libeufin-1.6.8/0000775000175000017500000000000015236145704013552 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/0000775000175000017500000000000015236145704016507 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/0000775000175000017500000000000015236145704017276 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/0000775000175000017500000000000015236145704020222 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/0000775000175000017500000000000015236145704021522 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/0000775000175000017500000000000015236145704022445 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/0000775000175000017500000000000015236145704024242 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/0000775000175000017500000000000015236145704025404 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/api/0000775000175000017500000000000015236145704026155 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/api/PreparedTransferApi.kt0000664000175000017500000001270115221677432032421 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.api import io.ktor.http.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import io.ktor.util.pipeline.* import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.nexus.NexusConfig import tech.libeufin.nexus.db.Database import tech.libeufin.nexus.db.TransferDAO.RegistrationResult import java.time.Instant import java.time.Duration fun Routing.preparedTransferAPI(db: Database, cfg: NexusConfig) = conditional(cfg.wireGatewayApiCfg) { get("/taler-prepared-transfer/config", { operationId = "getPreparedTransferConfig" description = "Get the configuration of the prepared transfer API" tags = listOf("Prepared Transfer") response { code(HttpStatusCode.OK) { description = "Configuration of the prepared transfer API"; body() } } }) { call.respond( PreparedTransferConfig( currency = cfg.currency, supported_formats = listOf(SubjectFormat.SIMPLE, SubjectFormat.CH_QR_BILL) ) ) } post("/taler-prepared-transfer/registration", { operationId = "registerTransfer" description = "Register a prepared transfer" tags = listOf("Prepared Transfer") request { body() } response { code(HttpStatusCode.OK) { description = "Registration successful"; body() } code(HttpStatusCode.Conflict) { description = "Reserve pub or subject derivation already used" } } }) { val req = call.receive(); if (!req.verify()) throw forbidden( "invalid signature", TalerErrorCode.BANK_BAD_SIGNATURE ) val iban = req.credit_account.expectIban().iban val reference = if (iban == cfg.ebics.account.iban) { null } else if (iban == cfg.ebics.qrIban) { subjectFmtQrBill(req.authorization_pub) } else { throw conflict( "Creditor account '${req.credit_account}' is not supported", TalerErrorCode.BANK_UNKNOWN_CREDITOR ) } when (val result = db.transfer.register( req.type, req.account_pub, req.authorization_pub, req.authorization_sig, req.recurrent, reference, Instant.now() )) { RegistrationResult.ReservePubReuse -> throw conflict( "reserve_pub used already", TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT ) RegistrationResult.SubjectReuse -> throw conflict( "subject derivation used already", TalerErrorCode.BANK_DERIVATION_REUSE ) RegistrationResult.Success -> { call.respond( SubjectResult( if (reference != null) { listOf(TransferSubject.QrBill(reference, req.credit_amount)) } else { listOf(TransferSubject.Simple(fmtIncomingSubject(IncomingType.map, req.authorization_pub), req.credit_amount)) }, TalerTimestamp.never() ) ) } } } post("/taler-prepared-transfer/unregistration", { operationId = "unregisterTransfer" description = "Unregister a prepared subject" tags = listOf("Prepared Transfer") response { code(HttpStatusCode.NoContent) { description = "Successfully unregistered" } code(HttpStatusCode.NotFound) { description = "Prepared transfer not found" } code(HttpStatusCode.Conflict) { description = "Invalid signature or timestamp too old" } } }) { val req = call.receive(); if (req.timestamp.instant.isBefore(Instant.now().minus(Duration.ofMinutes(15)))) throw conflict( "timestamp too old", TalerErrorCode.BANK_OLD_TIMESTAMP ) if (!req.verify()) throw forbidden( "invalid signature", TalerErrorCode.BANK_BAD_SIGNATURE ) if (db.transfer.unregister(req.authorization_pub, Instant.now())) { call.respond(HttpStatusCode.NoContent) } else { throw notFound( "Prepared transfer '${req.authorization_pub}' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) } } } libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/api/WireGatewayApi.kt0000664000175000017500000003337615204341712031403 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import io.ktor.util.pipeline.* import tech.libeufin.common.* import tech.libeufin.nexus.NexusConfig import tech.libeufin.nexus.checkCurrency import tech.libeufin.nexus.db.Database import tech.libeufin.nexus.db.ExchangeDAO import tech.libeufin.nexus.db.ExchangeDAO.TransferResult import tech.libeufin.nexus.db.PaymentDAO.IncomingRegistrationResult import tech.libeufin.nexus.iso20022.* import tech.libeufin.ebics.randEbicsId import java.time.Instant fun Routing.wireGatewayApi(db: Database, cfg: NexusConfig) = conditional(cfg.wireGatewayApiCfg) { get("/taler-wire-gateway/config", { operationId = "getWireGatewayConfig" description = "Get the configuration of the wire gateway" tags = listOf("Wire Gateway") response { code(HttpStatusCode.OK) { description = "Configuration of the wire gateway"; body() } } }) { call.respond( WireGatewayConfig( currency = cfg.currency, support_account_check = true ) ) } auth(cfg.wireGatewayApiCfg) { post("/taler-wire-gateway/transfer", { operationId = "createTransfer" description = "Initiate a wire transfer" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { body() } response { code(HttpStatusCode.OK) { description = "Transfer initiated successfully"; body() } code(HttpStatusCode.Conflict) { description = "Request UID or WTID already used" } } }) { val req = call.receive() cfg.checkCurrency(req.amount) req.credit_account.expectIbanFull() val endToEndId = randEbicsId() val res = db.exchange.transfer( req, endToEndId, Instant.now() ) when (res) { TransferResult.RequestUidReuse -> throw conflict( "request_uid used already", TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED ) TransferResult.WtidReuse -> throw conflict( "wtid used already", TalerErrorCode.BANK_TRANSFER_WTID_REUSED ) is TransferResult.Success -> call.respond( TransferResponse( timestamp = res.timestamp, row_id = res.id ) ) } } get("/taler-wire-gateway/transfers", { operationId = "listTransfers" description = "List wire transfers" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { queryParameter("start") { description = "Row ID to start from (legacy alias for offset)"; required = false } queryParameter("offset") { description = "Row ID to start from"; required = false } queryParameter("delta") { description = "Number of results to return (legacy alias for limit)"; required = false } queryParameter("limit") { description = "Number of results to return. Negative for descending order. Max 1024"; required = false } queryParameter("status") { description = "Filter by transfer status"; required = false } } response { code(HttpStatusCode.OK) { description = "List of transfers"; body() } code(HttpStatusCode.NoContent) { description = "No transfers found" } } }) { val params = TransferParams.extract(call.request.queryParameters) val items = db.exchange.pageTransfer(params) if (items.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(TransferList(items, cfg.ebics.payto)) } } get("/taler-wire-gateway/transfers/{ROW_ID}", { operationId = "getTransfer" description = "Get details of a specific wire transfer" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("ROW_ID") { description = "Row ID of the transfer" } } response { code(HttpStatusCode.OK) { description = "Transfer details"; body() } code(HttpStatusCode.NotFound) { description = "Transfer not found" } } }) { val id = call.longPath("ROW_ID") val transfer = db.exchange.getTransfer(id) ?: throw notFound( "Transfer '$id' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) call.respond(transfer) } suspend fun ApplicationCall.historyEndpoint( reduce: (List, String) -> Any, dbLambda: suspend ExchangeDAO.(HistoryParams) -> List ) { val params = HistoryParams.extract(this.request.queryParameters) val items = db.exchange.dbLambda(params) if (items.isEmpty()) { this.respond(HttpStatusCode.NoContent) } else { this.respond(reduce(items, cfg.ebics.payto)) } } get("/taler-wire-gateway/history/incoming", { operationId = "getIncomingHistory" description = "Get incoming transaction history" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { queryParameter("start") { description = "Row ID to start from (legacy alias for offset)"; required = false } queryParameter("offset") { description = "Row ID to start from"; required = false } queryParameter("delta") { description = "Number of results to return (legacy alias for limit)"; required = false } queryParameter("limit") { description = "Number of results to return. Negative for descending order. Max 1024"; required = false } queryParameter("long_poll_ms") { description = "Long-polling timeout in milliseconds (legacy alias for timeout_ms)"; required = false } queryParameter("timeout_ms") { description = "Long-polling timeout in milliseconds. Max 3600000 (1 hour)"; required = false } } response { code(HttpStatusCode.OK) { description = "Incoming transaction history"; body() } code(HttpStatusCode.NoContent) { description = "No incoming transactions found" } } }) { call.historyEndpoint(::IncomingHistory, ExchangeDAO::incomingHistory) } get("/taler-wire-gateway/history/outgoing", { operationId = "getOutgoingHistory" description = "Get outgoing transaction history" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { queryParameter("start") { description = "Row ID to start from (legacy alias for offset)"; required = false } queryParameter("offset") { description = "Row ID to start from"; required = false } queryParameter("delta") { description = "Number of results to return (legacy alias for limit)"; required = false } queryParameter("limit") { description = "Number of results to return. Negative for descending order. Max 1024"; required = false } queryParameter("long_poll_ms") { description = "Long-polling timeout in milliseconds (legacy alias for timeout_ms)"; required = false } queryParameter("timeout_ms") { description = "Long-polling timeout in milliseconds. Max 3600000 (1 hour)"; required = false } } response { code(HttpStatusCode.OK) { description = "Outgoing transaction history"; body() } code(HttpStatusCode.NoContent) { description = "No outgoing transactions found" } } }) { call.historyEndpoint(::OutgoingHistory, ExchangeDAO::outgoingHistory) } get("/taler-wire-gateway/account/check", { operationId = "checkAccount" description = "Check account status" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") response { code(HttpStatusCode.NotImplemented) { description = "Not implemented" } } }) { throw notImplemented() } suspend fun ApplicationCall.addIncoming( amount: TalerAmount, debitAccount: Payto, subject: String, metadata: IncomingSubject ) { cfg.checkCurrency(amount) val debitAccount = debitAccount.expectIban() val timestamp = Instant.now() val res = db.payment.registerTalerableIncoming( IncomingPayment( amount = amount, debtor = debitAccount, subject = subject, executionTime = timestamp, id = IncomingId(null, randEbicsId(), null) ), metadata ) when (res) { IncomingRegistrationResult.ReservePubReuse -> throw conflict( "reserve_pub used already", TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT ) IncomingRegistrationResult.MappingReuse -> throw conflict( "authorization_pub used already", TalerErrorCode.BANK_TRANSFER_MAPPING_REUSED ) IncomingRegistrationResult.UnknownMapping -> throw conflict( "authorization_pub unknown", TalerErrorCode.BANK_TRANSFER_MAPPING_UNKNOWN ) is IncomingRegistrationResult.Success -> respond( AddIncomingResponse( timestamp = TalerTimestamp(timestamp), row_id = res.id ) ) } } post("/taler-wire-gateway/admin/add-incoming", { operationId = "addIncoming" description = "Manually add an incoming transaction" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { body() } response { code(HttpStatusCode.OK) { description = "Incoming transaction added"; body() } code(HttpStatusCode.Conflict) { description = "Reserve pub already used" } } }) { val req = call.receive() call.addIncoming( amount = req.amount, debitAccount = req.debit_account, subject = "Manual incoming ${req.reserve_pub}", metadata = IncomingSubject.Reserve(req.reserve_pub) ) } post("/taler-wire-gateway/admin/add-kycauth", { operationId = "addKycauth" description = "Manually add a KYC auth incoming transaction" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { body() } response { code(HttpStatusCode.OK) { description = "KYC auth incoming transaction added"; body() } code(HttpStatusCode.Conflict) { description = "Reserve pub already used" } } }) { val req = call.receive() call.addIncoming( amount = req.amount, debitAccount = req.debit_account, subject = "Manual incoming KYC:${req.account_pub}", metadata = IncomingSubject.Kyc(req.account_pub) ) } post("/taler-wire-gateway/admin/add-mapped") { val req = call.receive() call.addIncoming( amount = req.amount, debitAccount = req.debit_account, subject = "Manual incoming MAP:${req.authorization_pub}", metadata = IncomingSubject.Map(req.authorization_pub) ) } } } libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/api/ObservabilityApi.kt0000664000175000017500000002003315204341712031753 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import io.ktor.util.pipeline.* import io.prometheus.metrics.core.metrics.* import io.prometheus.metrics.model.registry.PrometheusRegistry import io.prometheus.metrics.model.snapshots.Unit import io.prometheus.metrics.instrumentation.jvm.JvmMetrics; import io.prometheus.metrics.expositionformats.ExpositionFormats import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.nexus.* import tech.libeufin.nexus.db.* import tech.libeufin.nexus.db.KvDAO.* import tech.libeufin.nexus.db.ExchangeDAO.TransferResult import tech.libeufin.nexus.db.PaymentDAO.IncomingRegistrationResult import tech.libeufin.nexus.iso20022.* import tech.libeufin.ebics.randEbicsId import java.time.Instant import java.io.ByteArrayOutputStream object Metrics { @Volatile private var incomingTxTotal: Long = 0 @Volatile private var outgoingTxTotal: Long = 0 @Volatile private var incomingTalerTxTotal: Long = 0 @Volatile private var outgoingTalerTxTotal: Long = 0 @Volatile private var bouncedTotal: Long = 0 @Volatile private var initiatedStatus: Map = emptyMap() @Volatile private var submitStatus: TaskStatus = TaskStatus() @Volatile private var fetchStatus: TaskStatus = TaskStatus() init { // Register JVM metrics JvmMetrics.builder().register() // Register custom metrics CounterWithCallback.builder() .name("libeufin_nexus_tx_incoming_total") .help("Number of registered incoming transactions") .callback { it.call(incomingTxTotal.toDouble()) } .register() CounterWithCallback.builder() .name("libeufin_nexus_tx_outgoing_total") .help("Number of initiated outgoing transactions") .callback { it.call(outgoingTxTotal.toDouble()) } .register() CounterWithCallback.builder() .name("libeufin_nexus_tx_incoming_talerable_total") .help("Number of registered incoming talerable transactions") .callback { it.call(incomingTalerTxTotal.toDouble()) } .register() CounterWithCallback.builder() .name("libeufin_nexus_tx_outgoing_talerable_total") .help("Number of initiated outgoing talerable transactions") .callback { it.call(outgoingTalerTxTotal.toDouble()) } .register() CounterWithCallback.builder() .name("libeufin_nexus_tx_bounced_total") .help("Number of bounced transactions") .callback { it.call(bouncedTotal.toDouble()) } .register() GaugeWithCallback.builder() .name("libeufin_nexus_tx_initiated") .help("Status of initiated transaction") .labelNames("status") .callback { for ((label, count) in initiatedStatus) { it.call(count.toDouble(), label) } } .register() GaugeWithCallback.builder() .name("libeufin_nexus_task_execution_timestamp_seconds") .help("Status of initiated transaction") .unit(Unit.SECONDS) .labelNames("name") .callback { submitStatus.last_trial?.let { timestamp -> it.call(timestamp.getEpochSecond().toDouble(), "submit") } fetchStatus.last_trial?.let { timestamp -> it.call(timestamp.getEpochSecond().toDouble(), "fetch") } } .register() GaugeWithCallback.builder() .name("libeufin_nexus_task_success_timestamp_seconds") .help("Status of initiated transaction") .unit(Unit.SECONDS) .labelNames("name") .callback { submitStatus.last_successfull?.let { timestamp -> it.call(timestamp.getEpochSecond().toDouble(), "submit") } fetchStatus.last_successfull?.let { timestamp -> it.call(timestamp.getEpochSecond().toDouble(), "fetch") } } .register() } // Load metrics from the database suspend fun sync(db: Database) { db.serializable( """ SELECT (SELECT count(*) FROM incoming_transactions) AS incoming_tx_count, (SELECT count(*) FROM outgoing_transactions) AS outgoing_tx_count, (SELECT count(*) FROM talerable_incoming_transactions) AS incoming_talerable_tx_count, (SELECT count(*) FROM talerable_outgoing_transactions) AS outgoing_talerable_tx_count, (SELECT count(*) FROM bounced_transactions) AS bounced_tx_count, (SELECT value FROM kv WHERE key='$SUBMIT_TASK_KEY') AS submit_status, (SELECT value FROM kv WHERE key='$FETCH_TASK_KEY') AS fetch_status """ ) { one { incomingTxTotal = it.getLong("incoming_tx_count") outgoingTxTotal = it.getLong("outgoing_tx_count") incomingTalerTxTotal = it.getLong("incoming_talerable_tx_count") outgoingTalerTxTotal = it.getLong("outgoing_talerable_tx_count") bouncedTotal = it.getLong("bounced_tx_count") submitStatus = it.getJson("submit_status") ?: TaskStatus() fetchStatus = it.getJson("fetch_status") ?: TaskStatus() Unit } } db.serializable( """ SELECT count(*) as count, status FROM initiated_outgoing_transactions GROUP BY status """ ) { initiatedStatus = all { it.getString("status") to it.getLong("count") }.toMap() } } } fun Routing.observabilityApi(db: Database, cfg: NexusConfig) = conditional(cfg.observabilityApiCfg) { get("/taler-observability/config", { operationId = "getObservabilityConfig" description = "Get the configuration of the observability API" tags = listOf("Observability") response { code(HttpStatusCode.OK) { description = "Configuration of the observability API"; body() } } }) { call.respond(TalerObservabilityConfig()) } auth(cfg.observabilityApiCfg) { get("/taler-observability/metrics", { operationId = "getMetrics" description = "Get Prometheus metrics" tags = listOf("Observability") protected = true securitySchemeNames("bearerAuth", "basicAuth") response { code(HttpStatusCode.OK) { description = "Prometheus text format metrics" } } }) { Metrics.sync(db) val snapshot = PrometheusRegistry.defaultRegistry.scrape() val outputStream = ByteArrayOutputStream() ExpositionFormats.init().getPrometheusTextFormatWriter().write(outputStream, snapshot) call.respondText(outputStream.toString(Charsets.UTF_8), ContentType.parse("text/plain; version=0.0.4; charset=utf-8")) } } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/api/RevenueApi.kt0000664000175000017500000000655715204341712030565 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import tech.libeufin.common.HistoryParams import tech.libeufin.common.RevenueConfig import tech.libeufin.common.RevenueIncomingHistory import tech.libeufin.nexus.NexusConfig import tech.libeufin.nexus.db.Database fun Routing.revenueApi(db: Database, cfg: NexusConfig) = conditional(cfg.revenueApiCfg) { get("/taler-revenue/config", { operationId = "getRevenueConfig" description = "Get the configuration of the revenue API" tags = listOf("Revenue") response { code(HttpStatusCode.OK) { description = "Configuration of the revenue API"; body() } } }) { call.respond(RevenueConfig( currency = cfg.currency )) } auth(cfg.revenueApiCfg) { get("/taler-revenue/history", { operationId = "getRevenueHistory" description = "Get incoming revenue history" tags = listOf("Revenue") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { queryParameter("start") { description = "Row ID to start from (legacy alias for offset)"; required = false } queryParameter("offset") { description = "Row ID to start from"; required = false } queryParameter("delta") { description = "Number of results to return (legacy alias for limit)"; required = false } queryParameter("limit") { description = "Number of results to return. Negative for descending order. Max 1024"; required = false } queryParameter("long_poll_ms") { description = "Long-polling timeout in milliseconds (legacy alias for timeout_ms)"; required = false } queryParameter("timeout_ms") { description = "Long-polling timeout in milliseconds. Max 3600000 (1 hour)"; required = false } } response { code(HttpStatusCode.OK) { description = "Incoming revenue history"; body() } code(HttpStatusCode.NoContent) { description = "No revenue transactions found" } } }) { val params = HistoryParams.extract(call.request.queryParameters) val items = db.payment.revenueHistory(params) if (items.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(RevenueIncomingHistory(items, cfg.ebics.payto)) } } } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/api/helpers.kt0000664000175000017500000000300115122266731030147 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.api import io.ktor.http.* import io.ktor.server.response.* import io.ktor.server.routing.* import tech.libeufin.common.* import tech.libeufin.common.api.intercept import tech.libeufin.common.api.apiAuth import tech.libeufin.nexus.ApiConfig /** Apply authentication api configuration for a route */ fun Route.auth(cfg: ApiConfig?, callback: Route.() -> Unit): Route { val method = cfg?.authMethod if (method != null) { return apiAuth(method, callback) } else { return this } } /** Apply conditional api configuration for a route */ fun Route.conditional(cfg: ApiConfig?, callback: Route.() -> Unit): Route = intercept("Conditional", callback) { if (cfg == null) { throw notImplemented() } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/db/0000775000175000017500000000000015236145704025771 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt0000664000175000017500000002371215156463305030300 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.db import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.nexus.iso20022.IncomingPayment import tech.libeufin.nexus.iso20022.OutgoingPayment import java.sql.Types import java.time.Instant /** Data access logic for incoming & outgoing payments */ class PaymentDAO(private val db: Database) { /** Outgoing payments registration result */ data class OutgoingRegistrationResult( val id: Long, val initiated: Boolean, val new: Boolean ) /** Register an outgoing payment reconciling it with its initiated payment counterpart if present */ suspend fun registerOutgoing( payment: OutgoingPayment, wtid: ShortHashCode?, baseUrl: BaseURL?, metadata: String? ): OutgoingRegistrationResult = db.serializable( """ SELECT out_tx_id, out_initiated, out_found FROM register_outgoing((?,?)::taler_amount,(?,?)::taler_amount,?,?,?,?,?,?,?,?,?) """ ) { val executionTime = payment.executionTime.micros() bind(payment.amount) bind(payment.debitFee ?: TalerAmount.zero(db.currency)) bind(payment.subject) bind(executionTime) bind(payment.creditor?.toString()) bind(payment.id.endToEndId) bind(payment.id.msgId) bind(payment.id.acctSvcrRef) bind(wtid) bind(baseUrl?.url?.toString()) bind(metadata) one { OutgoingRegistrationResult( it.getLong("out_tx_id"), it.getBoolean("out_initiated"), !it.getBoolean("out_found") ) } } interface InResult { val new: Boolean val completed: Boolean val bounceId: String? } /** Incoming payments bounce registration result */ sealed interface IncomingBounceRegistrationResult { data class Success(val id: Long, override val bounceId: String, override val new: Boolean, override val completed: Boolean): IncomingBounceRegistrationResult, InResult data object Talerable: IncomingBounceRegistrationResult } /** Register an incoming payment and bounce it */ suspend fun registerMalformedIncoming( payment: IncomingPayment, bounceAmount: TalerAmount, bounceEndToEndId: String, timestamp: Instant, cause: String ): IncomingBounceRegistrationResult = db.serializable( """ SELECT out_found, out_tx_id, out_completed, out_bounce_id, out_talerable FROM register_and_bounce_incoming((?,?)::taler_amount,(?,?)::taler_amount,?,?,?,?,?,?,(?,?)::taler_amount,?,?, ?) """ ) { bind(payment.amount) bind(payment.creditFee ?: TalerAmount.zero(db.currency)) bind(payment.subject) bind(payment.executionTime) bind(payment.debtor?.toString()) bind(payment.id.uetr) bind(payment.id.txId) bind(payment.id.acctSvcrRef) bind(bounceAmount) bind(timestamp) bind(bounceEndToEndId) bind(cause) one { if (it.getBoolean("out_talerable")) { IncomingBounceRegistrationResult.Talerable } else { IncomingBounceRegistrationResult.Success( it.getLong("out_tx_id"), it.getString("out_bounce_id"), !it.getBoolean("out_found"), it.getBoolean("out_completed") ) } } } /** Incoming payments registration result */ sealed interface IncomingRegistrationResult { data class Success( val id: Long, override val new: Boolean, override val completed: Boolean, override val bounceId: String?, val pending: Boolean ): IncomingRegistrationResult, InResult data object ReservePubReuse: IncomingRegistrationResult data object MappingReuse: IncomingRegistrationResult data object UnknownMapping: IncomingRegistrationResult } /** Register an talerable incoming payment */ suspend fun registerTalerableIncoming( payment: IncomingPayment, metadata: IncomingSubject ): IncomingRegistrationResult = db.serializable( """ SELECT out_reserve_pub_reuse, out_mapping_reuse, out_unknown_mapping, out_found, out_completed, out_pending, out_tx_id, out_bounce_id FROM register_incoming((?,?)::taler_amount,(?,?)::taler_amount,?,?,?,?,?,?,?::taler_incoming_type,?,NULL) """ ) { bind(payment.amount) bind(payment.creditFee ?: TalerAmount.zero(db.currency)) bind(payment.subject) bind(payment.executionTime) bind(payment.debtor?.toString()) bind(payment.id.uetr) bind(payment.id.txId) bind(payment.id.acctSvcrRef) bind(metadata.type) bind(metadata.key) one { when { it.getBoolean("out_reserve_pub_reuse") -> IncomingRegistrationResult.ReservePubReuse it.getBoolean("out_mapping_reuse") -> IncomingRegistrationResult.MappingReuse it.getBoolean("out_unknown_mapping") -> IncomingRegistrationResult.UnknownMapping else -> IncomingRegistrationResult.Success( it.getLong("out_tx_id"), !it.getBoolean("out_found"), it.getBoolean("out_completed"), it.getString("out_bounce_id"), it.getBoolean("out_pending") ) } } } /** Register an QR-Bill incoming payment */ suspend fun registerQrBillIncoming( payment: IncomingPayment, reference: String ): IncomingRegistrationResult = db.serializable( """ SELECT out_reserve_pub_reuse, out_mapping_reuse, out_unknown_mapping, out_found, out_completed, out_pending, out_tx_id, out_bounce_id FROM register_incoming((?,?)::taler_amount,(?,?)::taler_amount,?,?,?,?,?,?,NULL,NULL,?) """ ) { bind(payment.amount) bind(payment.creditFee ?: TalerAmount.zero(db.currency)) bind(payment.subject) bind(payment.executionTime) bind(payment.debtor?.toString()) bind(payment.id.uetr) bind(payment.id.txId) bind(payment.id.acctSvcrRef) bind(reference) one { when { it.getBoolean("out_reserve_pub_reuse") -> IncomingRegistrationResult.ReservePubReuse it.getBoolean("out_mapping_reuse") -> IncomingRegistrationResult.MappingReuse it.getBoolean("out_unknown_mapping") -> IncomingRegistrationResult.UnknownMapping else -> IncomingRegistrationResult.Success( it.getLong("out_tx_id"), !it.getBoolean("out_found"), it.getBoolean("out_completed"), it.getString("out_bounce_id"), it.getBoolean("out_pending") ) } } } /** Register an incoming payment */ suspend fun registerIncoming( payment: IncomingPayment ): IncomingRegistrationResult.Success = db.serializable( """ SELECT out_found, out_completed, out_tx_id, out_bounce_id FROM register_incoming((?,?)::taler_amount,(?,?)::taler_amount,?,?,?,?,?,?,NULL,NULL,NULL) """ ) { bind(payment.amount) bind(payment.creditFee ?: TalerAmount.zero(db.currency)) bind(payment.subject) bind(payment.executionTime) bind(payment.debtor?.toString()) bind(payment.id.uetr) bind(payment.id.txId) bind(payment.id.acctSvcrRef) one { IncomingRegistrationResult.Success( it.getLong("out_tx_id"), !it.getBoolean("out_found"), it.getBoolean("out_completed"), it.getString("out_bounce_id"), false ) } } /** Query history of incoming transactions */ suspend fun revenueHistory( params: HistoryParams ): List = db.poolHistoryGlobal(params, db::listenRevenue, """ SELECT incoming_transaction_id ,execution_time ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,(credit_fee).val AS credit_fee_val ,(credit_fee).frac AS credit_fee_frac ,debit_payto ,subject FROM incoming_transactions WHERE debit_payto IS NOT NULL AND subject IS NOT NULL AND """, "incoming_transaction_id") { RevenueIncomingBankTransaction( row_id = it.getLong("incoming_transaction_id"), date = it.getTalerTimestamp("execution_time"), amount = it.getAmount("amount", db.currency), credit_fee = it.getAmount("credit_fee", db.currency).notZeroOrNull(), debit_account = it.getString("debit_payto"), subject = it.getString("subject") ) } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/db/KvDAO.kt0000664000175000017500000000620015122266731027231 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.db import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.nexus.iso20022.IncomingPayment import tech.libeufin.nexus.iso20022.OutgoingPayment import java.sql.* import java.time.Instant import kotlinx.serialization.Contextual import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.descriptors.PrimitiveKind import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encodeToString import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModule object InstantSerialize : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Instant", PrimitiveKind.LONG) override fun serialize(encoder: Encoder, value: Instant) = encoder.encodeLong(value.micros()) override fun deserialize(decoder: Decoder): Instant = decoder.decodeLong().asInstant() } val JSON = Json { this.serializersModule = SerializersModule { contextual(Instant::class) { InstantSerialize } } } inline fun ResultSet.getJson(name: String): T? { val value = this.getString(name) if (value == null) { return value } return JSON.decodeFromString(value) } /** Data access logic for key value */ class KvDAO( val db: Database) { /** Get current value for [key] */ suspend inline fun get(key: String): T? = db.serializable( "SELECT value FROM kv WHERE key=?" ) { bind(key) oneOrNull { it.getJson("value") } } /** Update a TaskStatus timestamp */ suspend fun updateTaskStatus(key: String, timestamp: Instant, success: Boolean) = db.serializable( if (success) { "INSERT INTO kv (key, value) VALUES (?, jsonb_build_object('last_successfull', ?, 'last_trial', ?)) ON CONFLICT (key) DO UPDATE SET value=EXCLUDED.value" } else { "INSERT INTO kv (key, value) VALUES (?, jsonb_build_object('last_trial', ?)) ON CONFLICT (key) DO UPDATE SET value=jsonb_set(EXCLUDED.value, '{last_trial}'::text[], to_jsonb(?))" } ) { bind(key) bind(timestamp) bind(timestamp) executeUpdate() } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/db/Database.kt0000664000175000017500000001102115156463305030031 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.db import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import org.slf4j.LoggerFactory import tech.libeufin.common.TalerAmount import tech.libeufin.common.TransferStatusState import tech.libeufin.common.IbanPayto import tech.libeufin.common.db.DatabaseConfig import tech.libeufin.common.db.DbPool import tech.libeufin.common.db.watchNotifications import tech.libeufin.ebics.EbicsDAO import java.time.Instant /** Batch of initiated outgoing payment to sent together */ data class PaymentBatch( val id: Long, val messageId: String, val creationDate: Instant, val sum: TalerAmount, val payments: List, ) /** Initiated outgoing transaction */ data class InitiatedPayment( val id: Long, val amount: TalerAmount, val subject: String, val creditor: IbanPayto, val initiationTime: Instant, val endToEndId: String ) enum class StatusUpdate { pending, transient_failure, permanent_failure, success } /** Outgoing transactions and batches submission status */ enum class SubmissionState { // Initiated but not yet submitted unsubmitted, // Submission failed, retry possible transient_failure, // Submission succeed, pending settltment pending, // Definitive failure, will never succeed permanent_failure, // Definitive success, booked and settled success, // Late failure after a success, happens when a payment is returned late_failure; companion object { val SETTLED = listOf(SubmissionState.success, SubmissionState.permanent_failure, SubmissionState.late_failure) val PENDING = listOf(SubmissionState.unsubmitted, SubmissionState.pending) } fun toTransferStatus(): TransferStatusState { return when (this) { SubmissionState.unsubmitted, SubmissionState.pending -> TransferStatusState.pending SubmissionState.transient_failure -> TransferStatusState.transient_failure SubmissionState.permanent_failure -> TransferStatusState.permanent_failure SubmissionState.success, SubmissionState.late_failure -> TransferStatusState.success } } } /** Collects database connection steps and any operation on the Nexus tables */ class Database(dbConfig: DatabaseConfig, val currency: String): DbPool(dbConfig, "libeufin_nexus") { val payment = PaymentDAO(this) val initiated = InitiatedDAO(this) val exchange = ExchangeDAO(this) val ebics = EbicsDAO(this) val list = ListDAO(this) val kv = KvDAO(this) val transfer = TransferDAO(this) private val outgoingTxFlows: MutableSharedFlow = MutableSharedFlow() private val incomingTxFlows: MutableSharedFlow = MutableSharedFlow() private val revenueTxFlows: MutableSharedFlow = MutableSharedFlow() init { watchNotifications(pgSource, "libeufin_nexus", LoggerFactory.getLogger("libeufin-nexus-db-watcher"), mapOf( "nexus_revenue_tx" to { val id = it.toLong() revenueTxFlows.emit(id) }, "nexus_outgoing_tx" to { val id = it.toLong() outgoingTxFlows.emit(id) }, "nexus_incoming_tx" to { val id = it.toLong() incomingTxFlows.emit(id) } )) } /** Listen for new taler outgoing transactions */ suspend fun listenOutgoing(lambda: suspend (Flow) -> R): R = lambda(outgoingTxFlows) /** Listen for new taler incoming transactions */ suspend fun listenIncoming(lambda: suspend (Flow) -> R): R = lambda(incomingTxFlows) /** Listen for new incoming transactions */ suspend fun listenRevenue(lambda: suspend (Flow) -> R): R = lambda(revenueTxFlows) }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/db/ExchangeDAO.kt0000664000175000017500000002160015156463305030377 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.db import tech.libeufin.common.* import tech.libeufin.common.db.* import java.time.Instant /** Data access logic for exchange specific logic */ class ExchangeDAO(private val db: Database) { /** Query history of taler incoming transactions */ suspend fun incomingHistory( params: HistoryParams ): List = db.poolHistoryGlobal(params, db::listenIncoming, """ SELECT incoming_transaction_id ,execution_time ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,(credit_fee).val AS credit_fee_val ,(credit_fee).frac AS credit_fee_frac ,debit_payto ,type ,metadata ,authorization_pub ,authorization_sig FROM talerable_incoming_transactions JOIN incoming_transactions USING(incoming_transaction_id) WHERE """, "incoming_transaction_id") { when (it.getEnum("type")) { IncomingType.reserve -> IncomingReserveTransaction( row_id = it.getLong("incoming_transaction_id"), date = it.getTalerTimestamp("execution_time"), amount = it.getAmount("amount", db.currency), credit_fee = it.getAmount("credit_fee", db.currency).notZeroOrNull(), debit_account = it.getString("debit_payto"), reserve_pub = EddsaPublicKey(it.getBytes("metadata")), authorization_pub = it.getOptKey("authorization_pub"), authorization_sig = it.getOptSig("authorization_sig") ) IncomingType.kyc -> IncomingKycAuthTransaction( row_id = it.getLong("incoming_transaction_id"), date = it.getTalerTimestamp("execution_time"), amount = it.getAmount("amount", db.currency), credit_fee = it.getAmount("credit_fee", db.currency).notZeroOrNull(), debit_account = it.getString("debit_payto"), account_pub = EddsaPublicKey(it.getBytes("metadata")), authorization_pub = it.getOptKey("authorization_pub"), authorization_sig = it.getOptSig("authorization_sig") ) IncomingType.map -> throw UnsupportedOperationException() } } /** Query exchange history of taler outgoing transactions */ suspend fun outgoingHistory( params: HistoryParams ): List = db.poolHistoryGlobal(params, db::listenOutgoing, """ SELECT outgoing_transaction_id ,execution_time ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,(debit_fee).val AS debit_fee_val ,(debit_fee).frac AS debit_fee_frac ,credit_payto ,wtid ,exchange_base_url ,metadata FROM talerable_outgoing_transactions JOIN outgoing_transactions USING(outgoing_transaction_id) WHERE """, "outgoing_transaction_id") { OutgoingTransaction( row_id = it.getLong("outgoing_transaction_id"), date = it.getTalerTimestamp("execution_time"), amount = it.getAmount("amount", db.currency), debit_fee = it.getAmount("debit_fee", db.currency).notZeroOrNull(), credit_account = it.getString("credit_payto"), wtid = ShortHashCode(it.getBytes("wtid")), exchange_base_url = it.getString("exchange_base_url"), metadata = it.getString("metadata"), ) } /** Result of taler transfer transaction creation */ sealed interface TransferResult { /** Transaction [id] and wire transfer [timestamp] */ data class Success(val id: Long, val timestamp: TalerTimestamp): TransferResult data object RequestUidReuse: TransferResult data object WtidReuse: TransferResult } /** Perform a Taler transfer */ suspend fun transfer( req: TransferRequest, endToEndId: String, timestamp: Instant ): TransferResult = db.serializable( """ SELECT out_request_uid_reuse ,out_wtid_reuse ,out_tx_row_id ,out_timestamp FROM taler_transfer ( ?, ?, ?, (?,?)::taler_amount, ?, ?, ?, ?, ? ) """ ) { val subject = fmtOutgoingSubject(req.wtid, req.exchange_base_url, req.metadata) bind(req.request_uid) bind(req.wtid) bind(subject) bind(req.amount) bind(req.exchange_base_url.toString()) bind(req.metadata) bind(req.credit_account.toString()) bind(endToEndId) bind(timestamp) one { when { it.getBoolean("out_request_uid_reuse") -> TransferResult.RequestUidReuse it.getBoolean("out_wtid_reuse") -> TransferResult.WtidReuse else -> TransferResult.Success( id = it.getLong("out_tx_row_id"), timestamp = it.getTalerTimestamp("out_timestamp") ) } } } /** Get status of transfer [id] */ suspend fun getTransfer( id: Long ): TransferStatus? = db.serializable( """ SELECT wtid ,exchange_base_url ,metadata ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,credit_payto ,initiation_time ,status ,status_msg FROM transfer_operations JOIN initiated_outgoing_transactions USING (initiated_outgoing_transaction_id) WHERE initiated_outgoing_transaction_id=? """ ) { bind(id) oneOrNull { TransferStatus( status = it.getEnum("status").toTransferStatus(), status_msg = it.getString("status_msg"), amount = it.getAmount("amount", db.currency), origin_exchange_url = it.getString("exchange_base_url"), metadata = it.getString("metadata"), wtid = ShortHashCode(it.getBytes("wtid")), credit_account = it.getString("credit_payto"), timestamp = it.getTalerTimestamp("initiation_time"), ) } } /** Get a page of transfers status */ suspend fun pageTransfer( params: TransferParams ): List = db.page( params.page, "initiated_outgoing_transaction_id", """ SELECT initiated_outgoing_transaction_id ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,status ,credit_payto ,initiation_time FROM transfer_operations JOIN initiated_outgoing_transactions USING (initiated_outgoing_transaction_id) WHERE ${ when (params.status) { null -> "" TransferStatusState.pending -> "(status=?::submission_state OR status=?::submission_state) AND" else -> "status=?::submission_state AND" } } """, { when (params.status) { null -> {} TransferStatusState.pending -> { bind(SubmissionState.pending) bind(SubmissionState.unsubmitted) } else -> { bind(params.status) } } } ) { TransferListStatus( row_id = it.getLong("initiated_outgoing_transaction_id"), status = it.getEnum("status").toTransferStatus(), amount = it.getAmount("amount", db.currency), credit_account = it.getString("credit_payto"), timestamp = it.getTalerTimestamp("initiation_time"), ) } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/db/TransferDAO.kt0000664000175000017500000000506515221677432030451 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.db import tech.libeufin.common.* import tech.libeufin.common.db.* import java.time.Instant /** Data access logic for transfer specific logic */ class TransferDAO(private val db: Database) { /** Result of prepared transfer registration */ sealed interface RegistrationResult { data object Success: RegistrationResult data object ReservePubReuse: RegistrationResult data object SubjectReuse: RegistrationResult } /** Register a prepared transfer */ suspend fun register( type: TransferType, accountPub: EddsaPublicKey, authPub: EddsaPublicKey, authSig: EddsaSignature, recurrent: Boolean, referenceNumber: String?, timestamp: Instant ): RegistrationResult = db.serializable( """ SELECT out_subject_reuse ,out_reserve_pub_reuse FROM register_prepared_transfers ( ?::taler_incoming_type, ?, ?, ?, ?, ?, ? ) """ ) { bind(type) bind(accountPub) bind(authPub) bind(authSig) bind(recurrent) bind(referenceNumber) bind(timestamp) one { when { it.getBoolean("out_subject_reuse") -> RegistrationResult.SubjectReuse it.getBoolean("out_reserve_pub_reuse") -> RegistrationResult.ReservePubReuse else -> RegistrationResult.Success } } } /** Unregister a prepared transfer */ suspend fun unregister( authorizationPub: EddsaPublicKey, timestamp: Instant ) = db.serializable( "SELECT out_found FROM delete_prepared_transfers(?,?)", { bind(authorizationPub) bind(timestamp) one { it.getBoolean(1) } } ) }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/db/ListDAO.kt0000664000175000017500000002111215156463305027566 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.db import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.nexus.iso20022.* import java.sql.Types import java.time.Instant import java.util.UUID /** Data access logic for metadata listing */ class ListDAO(private val db: Database) { /** List incoming transaction metadata for debugging */ suspend fun incoming(incomplete: Boolean): List = db.serializable( """ SELECT (incoming.amount).val AS amount_val ,(incoming.amount).frac AS amount_frac ,(credit_fee).val AS credit_fee_val ,(credit_fee).frac AS credit_fee_frac ,incoming.subject ,end_to_end_id AS bounced ,execution_time ,debit_payto ,type ,metadata ,uetr ,tx_id ,acct_svcr_ref ,talerable_incoming_transactions.authorization_pub as auth_pub ,pending_recurrent_incoming_transactions.authorization_pub as pending_pub FROM incoming_transactions AS incoming LEFT JOIN talerable_incoming_transactions USING (incoming_transaction_id) LEFT JOIN bounced_transactions USING (incoming_transaction_id) LEFT JOIN initiated_outgoing_transactions USING (initiated_outgoing_transaction_id) LEFT JOIN pending_recurrent_incoming_transactions USING (incoming_transaction_id) ${if (incomplete) { "WHERE debit_payto IS NULL OR incoming.subject IS NULL" } else { ""}} ORDER BY execution_time """ ) { all { val type = it.getOptEnum("type") val authPub = it.getOptKey("auth_pub") val pendingPub = it.getOptKey("pending_pub") val map = if (authPub != null) { " mapped by ${authPub}" } else { "" } IncomingTxMetadata( id = IncomingId( it.getObject("uetr") as UUID?, it.getString("tx_id"), it.getString("acct_svcr_ref"), ), date = it.getLong("execution_time").asInstant(), amount = it.getAmount("amount", db.currency), creditFee = it.getDecimal("credit_fee"), subject = it.getString("subject"), debtor = it.getString("debit_payto"), bounced = it.getString("bounced"), talerable = when (type) { null -> { if (pendingPub != null) { "pending mapped by $pendingPub" } else { null } } IncomingType.reserve -> "reserve ${EddsaPublicKey(it.getBytes("metadata"))}$map" IncomingType.kyc -> "kyc ${EddsaPublicKey(it.getBytes("metadata"))}$map" IncomingType.map -> throw UnsupportedOperationException() } ) } } /** List outgoing transaction metadata for debugging */ suspend fun outgoing(): List = db.serializable( """ SELECT (amount).val AS amount_val ,(amount).frac AS amount_frac ,subject ,execution_time ,credit_payto ,end_to_end_id ,acct_svcr_ref ,wtid ,exchange_base_url FROM outgoing_transactions LEFT JOIN talerable_outgoing_transactions using (outgoing_transaction_id) ORDER BY execution_time """ ) { all { OutgoingTxMetadata( id = OutgoingId( msgId = null, endToEndId = it.getString("end_to_end_id"), acctSvcrRef = it.getString("acct_svcr_ref"), ), date = it.getLong("execution_time").asInstant(), amount = it.getAmount("amount", db.currency), subject = it.getString("subject"), creditor = it.getString("credit_payto"), wtid = it.getBytes("wtid")?.run { ShortHashCode(this) }, exchangeBaseUrl = it.getString("exchange_base_url") ) } } /** List initiated transaction metadata for debugging */ suspend fun initiated(): List = db.serializable( """ SELECT (amount).val AS amount_val ,(amount).frac AS amount_frac ,subject ,initiation_time ,submission_date ,submission_counter ,credit_payto ,end_to_end_id ,message_id ,order_id ,initiated_outgoing_transactions.status ,initiated_outgoing_transactions.status_msg FROM initiated_outgoing_transactions LEFT JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) ORDER BY initiation_time """ ) { all { InitiatedTxMetadata( date = it.getLong("initiation_time").asInstant(), amount = it.getAmount("amount", db.currency), subject = it.getString("subject"), creditor = it.getString("credit_payto"), id = it.getString("end_to_end_id"), batch = it.getString("message_id"), batchOrder = it.getString("order_id"), status = it.getString("status"), msg = it.getString("status_msg"), submissionTime = it.getLong("submission_date").asInstant(), submissionCounter = it.getInt("submission_counter") ) } } /** List initiated transaction metadata pending acknowledgment for debugging */ suspend fun initiatedAck(): List = db.serializable( """ SELECT (amount).val AS amount_val ,(amount).frac AS amount_frac ,subject ,initiation_time ,credit_payto ,end_to_end_id ,initiated_outgoing_transaction_id FROM initiated_outgoing_transactions WHERE initiated_outgoing_batch_id IS NULL AND NOT awaiting_ack ORDER BY initiation_time """ ) { all { InitiatedTxMetadataAck( date = it.getLong("initiation_time").asInstant(), amount = it.getAmount("amount", db.currency), subject = it.getString("subject"), creditor = it.getString("credit_payto"), id = it.getString("end_to_end_id"), dbId = it.getLong("initiated_outgoing_transaction_id"), ) } } } /** Incoming transaction metadata for debugging */ data class IncomingTxMetadata( val id: IncomingId, val date: Instant, val amount: TalerAmount, val creditFee: DecimalNumber, val subject: String?, val debtor: String?, val talerable: String?, val bounced: String? ) /** Outgoing transaction metadata for debugging */ data class OutgoingTxMetadata( val id: OutgoingId, val date: Instant, val amount: TalerAmount, val subject: String?, val creditor: String?, val wtid: ShortHashCode?, val exchangeBaseUrl: String? ) /** Initiated metadata for debugging */ data class InitiatedTxMetadata( val date: Instant, val amount: TalerAmount, val subject: String, val creditor: String, val id: String, val batch: String?, val batchOrder: String?, val status: String, val msg: String?, val submissionTime: Instant, val submissionCounter: Int ) /** Initiated metadata for debugging */ data class InitiatedTxMetadataAck( val date: Instant, val amount: TalerAmount, val subject: String, val creditor: String, val dbId: Long, val id: String )libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt0000664000175000017500000003413615156463305030577 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.db import tech.libeufin.common.asInstant import tech.libeufin.common.db.* import tech.libeufin.common.micros import tech.libeufin.nexus.iso20022.* import java.time.Instant /** Data access logic for initiated outgoing payments */ class InitiatedDAO(private val db: Database) { private val UNSETTLED_FILTER = "status NOT IN (${SubmissionState.SETTLED.joinToString(",") { "'$it'" }})" private val PENDING_FILTER = "status IN (${SubmissionState.PENDING.joinToString(",") { "'$it'" }})" /** Outgoing payments initiation result */ sealed interface PaymentInitiationResult { data class Success(val id: Long): PaymentInitiationResult data object RequestUidReuse: PaymentInitiationResult } /** Initiate a new payment */ suspend fun create(payment: InitiatedPayment): PaymentInitiationResult = db.serializable( """ INSERT INTO initiated_outgoing_transactions ( amount ,subject ,credit_payto ,initiation_time ,end_to_end_id ) VALUES ((?,?)::taler_amount,?,?,?,?) RETURNING initiated_outgoing_transaction_id """ ) { // TODO check payto uri bind(payment.amount) bind(payment.subject) bind(payment.creditor.toString()) bind(payment.initiationTime) bind(payment.endToEndId) oneUniqueViolation(PaymentInitiationResult.RequestUidReuse) { PaymentInitiationResult.Success(it.getLong("initiated_outgoing_transaction_id")) } } /** Register submission success of order [orderId] for batch [id] at [timestamp] */ suspend fun batchSubmissionSuccess( id: Long, timestamp: Instant, orderId: String? ) = db.serializableTransaction { tx -> // Update batch status val updated = tx.withStatement( """ UPDATE initiated_outgoing_batches SET status = 'pending' ,submission_date = ? ,status_msg = NULL ,order_id = ? ,submission_counter = submission_counter + 1 WHERE initiated_outgoing_batch_id = ? AND order_id IS NULL """ ) { bind(timestamp) bind(orderId) bind(id) executeUpdate() } if (updated > 0) { // Update unsettled batch's transaction status tx.withStatement( """ UPDATE initiated_outgoing_transactions SET status = 'pending', status_msg = NULL WHERE initiated_outgoing_batch_id = ? AND $UNSETTLED_FILTER """ ) { bind(id) executeUpdate() } } } /** Register submission failure with [msg] for batch [id] at [timestamp]*/ suspend fun batchSubmissionFailure( id: Long, timestamp: Instant, msg: String?, permanent: Boolean = false ) = db.serializableTransaction { tx -> // Update batch status tx.withStatement( """ UPDATE initiated_outgoing_batches SET status = ?::submission_state ,submission_date = ? ,status_msg = ? ,submission_counter = submission_counter + 1 WHERE initiated_outgoing_batch_id = ? """ ) { if (permanent) { bind(StatusUpdate.permanent_failure) } else { bind(StatusUpdate.transient_failure) } bind(timestamp) bind(msg) bind(id) executeUpdate() } // Update unsettled batch's transaction status tx.withStatement( """ UPDATE initiated_outgoing_transactions SET status = ?::submission_state, status_msg = ? WHERE initiated_outgoing_batch_id = ? AND $UNSETTLED_FILTER """ ) { if (permanent) { bind(StatusUpdate.permanent_failure) } else { bind(StatusUpdate.transient_failure) } bind(msg) bind(id) executeUpdate() } } /** Register order step [msg] for [orderId] */ suspend fun orderStep(orderId: String, msg: String) = db.serializableTransaction { tx -> // Update pending batch status val batchId = tx.withStatement( """ UPDATE initiated_outgoing_batches SET status = 'pending', status_msg = ? WHERE order_id = ? AND $PENDING_FILTER RETURNING initiated_outgoing_batch_id """ ) { bind(msg) bind(orderId) oneOrNull { it.getLong(1) } } if (batchId != null) { // Update pending batch's transaction status tx.withStatement( """ UPDATE initiated_outgoing_transactions SET status = 'pending', status_msg = ? WHERE initiated_outgoing_batch_id = ? AND $PENDING_FILTER """ ) { bind(msg) bind(batchId) executeUpdate() } } } /** Register order success for [orderId] and return message_id if found */ suspend fun orderSuccess(orderId: String): String? = db.serializableTransaction { tx -> // Update batch status val result = tx.withStatement( """ UPDATE initiated_outgoing_batches SET status = 'success' WHERE order_id = ? RETURNING initiated_outgoing_batch_id, message_id """ ) { bind(orderId) oneOrNull { Pair( it.getLong("initiated_outgoing_batch_id"), it.getString("message_id") ) } } if (result == null) return@serializableTransaction null val (batchId, messageId) = result // Update unsettled batch's transaction status tx.withStatement( """ UPDATE initiated_outgoing_transactions SET status = 'pending' WHERE initiated_outgoing_batch_id = ? AND $UNSETTLED_FILTER """ ) { bind(batchId) executeUpdate() } messageId } /** Register order failure for [orderId] and return message_id and previous status_msg if found */ suspend fun orderFailure(orderId: String): Pair? = db.serializableTransaction { tx -> // Update batch status val result = tx.withStatement( """ UPDATE initiated_outgoing_batches SET status = 'permanent_failure' WHERE order_id = ? RETURNING initiated_outgoing_batch_id, message_id, status_msg """ ) { bind(orderId) oneOrNull { Triple( it.getLong("initiated_outgoing_batch_id"), it.getString("message_id"), it.getString("status_msg") ) } } if (result == null) return@serializableTransaction null val (batchId, messageId, msg) = result // Update batch's transaction status tx.withStatement( """ UPDATE initiated_outgoing_transactions SET status = 'permanent_failure' WHERE initiated_outgoing_batch_id = ? """ ) { bind(batchId) executeUpdate() } Pair(messageId, msg) } /** Register payment status [state] with [msg] for batch [msgId] */ suspend fun batchStatusUpdate(msgId: String, state: StatusUpdate, msg: String?) = db.serializable( "SELECT out_ok FROM batch_status_update(?,?::submission_state,?)" ) { bind(msgId) bind(state) bind(msg) one { it.getBoolean(1) } } /** Register payment status [state] with [msg] for transaction [endToEndId] in batch [msgId] */ suspend fun txStatusUpdate(endToEndId: String, msgId: String?, state: StatusUpdate, msg: String?) = db.serializable( "SELECT out_ok FROM tx_status_update(?,?,?::submission_state,?)" ) { bind(endToEndId) bind(msgId) bind(state) bind(msg) one { it.getBoolean(1) } } /** Unsettled initiated payment in batch [msgId] */ suspend fun unsettledTxInBatch(msgId: String, executionTime: Instant) = db.serializable( """ SELECT end_to_end_id ,(amount).val as amount_val ,(amount).frac as amount_frac ,subject ,credit_payto FROM initiated_outgoing_transactions JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) WHERE message_id = ? AND initiated_outgoing_transactions.$UNSETTLED_FILTER """ ) { bind(msgId) all { OutgoingPayment( id = OutgoingId( msgId = msgId, endToEndId = it.getString("end_to_end_id"), acctSvcrRef = null ), amount = it.getAmount("amount", db.currency), subject = it.getString("subject"), executionTime = executionTime, creditor = it.getIbanPayto("credit_payto") ) } } suspend fun ack(id: Long): Boolean { return db.serializable("UPDATE initiated_outgoing_transactions SET awaiting_ack=false WHERE initiated_outgoing_transaction_id = ?") { bind(id) executeUpdateCheck() } } /** Group unbatched transaction into a single batch */ suspend fun batch(timestamp: Instant, ebicsId: String, requireAck: Boolean) { db.serializable("SELECT FROM batch_outgoing_transactions(?, ?, ?)") { bind(timestamp) bind(ebicsId) bind(requireAck) executeQuery() } } /** List every initiated payment pending submission in the order they should be submitted */ suspend fun submittable(): List { val selectPart = """ SELECT initiated_outgoing_batch_id, message_id, creation_date, (sum).val as sum_val, (sum).frac as sum_frac FROM initiated_outgoing_batches """ return db.serializableTransaction { tx -> // We want to maximize the number of successfully submitted batches in the event // of a malformed transaction or a persistent error classified as transient. We send // the unsubmitted batches first, starting with the oldest by creation time. // This is the happy path, giving every batch a chance while being fair on the // basis of creation date. // Then we retry the failed batches, starting with the oldest by submission time. // This the bad path retrying each failed batch applying a rotation based on // resubmission time. val batches = tx.withStatement( """ ($selectPart WHERE status='unsubmitted' ORDER BY creation_date) UNION ALL ($selectPart WHERE status='transient_failure' ORDER BY submission_date) """ ) { all { PaymentBatch( id = it.getLong("initiated_outgoing_batch_id"), messageId = it.getString("message_id"), creationDate = it.getLong("creation_date").asInstant(), sum = it.getAmount("sum", db.currency), payments = emptyList() ) } }.associate { it.id to Pair(it, mutableListOf()) } // Then load transactions tx.withStatement( """ SELECT initiated_outgoing_transaction_id ,(amount).val as amount_val ,(amount).frac as amount_frac ,subject ,credit_payto ,initiated_outgoing_transactions.initiation_time ,end_to_end_id ,initiated_outgoing_batch_id FROM initiated_outgoing_transactions JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) WHERE initiated_outgoing_batches.status IN ('unsubmitted', 'transient_failure') """ ) { all { val payment = InitiatedPayment( id = it.getLong("initiated_outgoing_transaction_id"), amount = it.getAmount("amount", db.currency), creditor = it.getIbanPayto("credit_payto"), subject = it.getString("subject"), initiationTime = it.getLong("initiation_time").asInstant(), endToEndId = it.getString("end_to_end_id") ) val batchId = it.getLong("initiated_outgoing_batch_id") batches[batchId]!!.second.add(payment) Unit } } batches.values.map { (it, payments) -> it.copy(payments = payments) } } } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/Constants.kt0000664000175000017500000000156115122266731027721 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus // KV val CHECKPOINT_KEY = "checkpoint" val SUBMIT_TASK_KEY = "submit_task" val FETCH_TASK_KEY = "fetch_task"libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/Config.kt0000664000175000017500000001622115221677432027155 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus import tech.libeufin.common.* import tech.libeufin.common.db.DatabaseConfig import tech.libeufin.nexus.db.Database import tech.libeufin.ebics.EbicsKeysConfig import tech.libeufin.ebics.EbicsSetupConfig import tech.libeufin.ebics.EbicsHostConfig import java.nio.file.Path import java.time.Instant import org.slf4j.Logger import org.slf4j.LoggerFactory private val logger: Logger = LoggerFactory.getLogger("libeufin-config") val NEXUS_CONFIG_SOURCE = ConfigSource("libeufin", "libeufin-nexus", "libeufin-nexus") data class NexusIngestConfig( val accountType: AccountType, val ignoreTransactionsBefore: Instant, val ignoreBouncesBefore: Instant, val restrictionPaytoRegex: Regex?, val bounceDeduceFee: Boolean, val bounceFee: TalerAmount ) { companion object { fun default(accountType: AccountType, currency: String = "KUDOS") = NexusIngestConfig(accountType, Instant.MIN, Instant.MIN, null, false, TalerAmount.zero(currency)) } } class NexusFetchConfig(config: TalerConfig, currency: String) { private val section = config.section("nexus-fetch") val frequency = section.duration("frequency").require() val frequencyRaw = section.string("frequency").require() val checkpointTime = section.time("checkpoint_time_of_day").require() val ignoreTransactionsBefore = section.date("ignore_transactions_before").default(Instant.MIN) val ignoreBouncesBefore = section.date("ignore_bounces_before").default(Instant.MIN) val restrictionPaytoRegex = section.regex("restriction_payto_regex").orNull() val bounceDeduceFee = section.boolean("bounce_deduce_fee").default(false) val bounceFee = section.amount("bounce_fee", currency).default(TalerAmount.zero(currency)) } class NexusSubmitConfig(config: TalerConfig) { private val section = config.section("nexus-submit") val frequency = section.duration("frequency").require() val frequencyRaw = section.string("frequency").require() val requireAck = section.boolean("manual_ack").default(false) } class NexusSetupConfig(config: TalerConfig): EbicsSetupConfig { private val section = config.section("nexus-setup") override val bankAuthPubKey = section.hex("bank_authentication_pub_key_hash").orNull() override val bankEncPubKey = section.hex("bank_encryption_pub_key_hash").orNull() } class NexusHostConfig(sect: TalerConfigSection): EbicsHostConfig { /** The bank base URL */ override val baseUrl = sect.string("host_base_url").require() /** The bank EBICS host ID */ override val hostId = sect.string("host_id").require() /** EBICS user ID */ override val userId = sect.string("user_id").require() /** EBICS partner ID */ override val partnerId = sect.string("partner_id").require() } class NexusEbicsConfig( sect: TalerConfigSection, ): EbicsKeysConfig { val host by lazy { NexusHostConfig(sect) } /** Bank account metadata */ val account = IbanAccountMetadata( iban = sect.iban("iban").require(), bic = sect.string("bic").require(), name = sect.string("name").require() ) val qrIban = sect.iban("qr_iban").orNull() /** Bank account payto */ val payto = IbanPayto.build(account.iban.toString(), account.bic, account.name) val dialect = sect.map("bank_dialect", "bank dialect", mapOf( "postfinance" to Dialect.postfinance, "gls" to Dialect.gls, "maerki_baumann" to Dialect.maerki_baumann, "valiant" to Dialect.valiant, "raiffeisen" to Dialect.raiffeisen, )).require() /** Path where we store the bank public keys */ override val bankPublicKeysPath = sect.path("bank_public_keys_file").require() /** Path where we store our private keys */ override val clientPrivateKeysPath = sect.path("client_private_keys_file").require() } class ApiConfig(section: TalerConfigSection) { val authMethod = section.requireAuthMethod() } /** Configuration for libeufin-nexus */ class NexusConfig internal constructor (val cfg: TalerConfig) { private val sect = cfg.section("nexus-ebics") val dbCfg by lazy { cfg.dbConfig() } val serverCfg by lazy { cfg.loadServerConfig("nexus-httpd") } /** The bank's currency */ val currency = sect.string("currency").require() val accountType = sect.map("account_type", "account type", mapOf( "normal" to AccountType.normal, "exchange" to AccountType.exchange )).require() val fetch by lazy { NexusFetchConfig(cfg, currency) } val submit by lazy { NexusSubmitConfig(cfg) } val ebics by lazy { NexusEbicsConfig(sect) } val setup by lazy { NexusSetupConfig(cfg) } val ingest get() = NexusIngestConfig( accountType, fetch.ignoreTransactionsBefore, fetch.ignoreBouncesBefore, fetch.restrictionPaytoRegex, fetch.bounceDeduceFee, fetch.bounceFee ) val wireGatewayApiCfg = cfg.section("nexus-httpd-wire-gateway-api").apiConf() val revenueApiCfg = cfg.section("nexus-httpd-revenue-api").apiConf() val observabilityApiCfg = cfg.section("nexus-httpd-observability-api").apiConf() } fun NexusConfig.checkCurrency(amount: TalerAmount) { if (amount.currency != currency) throw badRequest( "Wrong currency: expected $currency got ${amount.currency}", TalerErrorCode.GENERIC_CURRENCY_MISMATCH ) } private fun TalerConfigSection.apiConf(): ApiConfig? { val enabled = boolean("enabled").require() return if (enabled) { return ApiConfig(this) } else { null } } enum class AccountType { normal, exchange } private fun TalerConfig.dbConfig(): DatabaseConfig { val sect = section("libeufin-nexusdb-postgres") val configOption = sect.string("config") return DatabaseConfig( dbConnStr = configOption.orNull() ?: section("nexus-postgres").string("config").orNull() ?: configOption.require(), sqlDir = sect.path("sql_dir").require() ) } /** Load nexus config at [configPath] */ fun nexusConfig(configPath: Path?): NexusConfig { val config = NEXUS_CONFIG_SOURCE.fromFile(configPath) return NexusConfig(config) } /** Load nexus db config at [configPath] */ fun dbConfig(configPath: Path?): DatabaseConfig = NEXUS_CONFIG_SOURCE.fromFile(configPath).dbConfig() /** Run [lambda] with access to a database conn pool */ suspend fun NexusConfig.withDb(lambda: suspend (Database, NexusConfig) -> Unit) { Database(dbCfg, currency).use { lambda(it, this) } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/0000775000175000017500000000000015236145704026153 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsFetch.kt0000664000175000017500000005553615221677432030532 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.parameters.arguments.* import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.* import com.github.ajalt.clikt.parameters.types.enum import kotlin.math.min import kotlinx.coroutines.* import kotlinx.serialization.Serializable import kotlinx.serialization.Contextual import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.db.* import tech.libeufin.nexus.db.PaymentDAO.* import tech.libeufin.nexus.iso20022.* import tech.libeufin.ebics.* import java.io.IOException import java.io.InputStream import java.time.* import org.slf4j.Logger import org.slf4j.LoggerFactory import java.time.temporal.* /** Register an outgoing [payment] into [db] */ suspend fun registerOutgoingPayment( db: Database, payment: OutgoingPayment ): OutgoingRegistrationResult { val metadata: Triple? = payment.subject?.let { runCatching { parseOutgoingSubject(it) }.getOrNull() } val result = db.payment.registerOutgoing(payment, metadata?.first, metadata?.second, metadata?.third) if (result.new) { if (result.initiated) logger.info("$payment") else logger.warn("$payment recovered") } else { logger.debug("{} already seen", payment) } return result } /** Register an outgoing [payment] into [db] */ suspend fun registerOutgoingBatch( db: Database, batch: OutgoingBatch ) { logger.info("BATCH ${batch.executionTime.fmtDate()} ${batch.msgId}") for (it in db.initiated.unsettledTxInBatch(batch.msgId, batch.executionTime)) { registerOutgoingPayment(db, it) } } /** * Register an incoming [payment] into [db] * Stores the payment into valid talerable ones or bounces it */ suspend fun registerIncomingPayment( db: Database, cfg: NexusIngestConfig, payment: IncomingPayment, ) { fun logRes(res: InResult, kind: String = "", suffix: String = "") { val fmt = buildString { append(payment) if (kind != "") { append(" ") append(kind) } if (res.new) { if (res.bounceId != null) { append(" bounced in ${res.bounceId}") } } else { if (res.completed) { append(" completed") if (res.bounceId != null) { append(" bounced in ${res.bounceId}") } } else { if (res.bounceId != null) { append(" already bounced in ${res.bounceId}") } } } if (suffix != "") { append(" ") append(suffix) } } if (res.completed || res.new) { logger.info(fmt) } else { logger.debug(fmt) } } suspend fun bounce(cause: String) { if (payment.id == null) { logger.debug("{} ignored: missing bank ID", payment) return } when (cfg.accountType) { AccountType.exchange -> { if (payment.executionTime < cfg.ignoreBouncesBefore) { val res = db.payment.registerIncoming(payment) logRes(res, suffix = "ignored bounce: $cause") } else { var bounceAmount = payment.amount if (payment.creditFee != null && cfg.bounceDeduceFee) { if (payment.creditFee > bounceAmount) { val res = db.payment.registerIncoming(payment) logRes(res, suffix = "skip bounce (transfer fee higher than amount): $cause") return } bounceAmount -= payment.creditFee } if (cfg.bounceFee > bounceAmount) { val res = db.payment.registerIncoming(payment) logRes(res, suffix = "skip bounce (bounce fee higher than amount): $cause") return } bounceAmount -= cfg.bounceFee val res = db.payment.registerMalformedIncoming( payment, bounceAmount, randEbicsId(), Instant.now(), cause ) when (res) { IncomingBounceRegistrationResult.Talerable -> logger.warn("{} tried to bounce a talerable transaction", payment) is IncomingBounceRegistrationResult.Success -> logRes(res, suffix=": $cause") } } } AccountType.normal -> { val res = db.payment.registerIncoming(payment) logRes(res) } } } // Check we have enough info to handle this transaction if (payment.debtor == null || payment.debtor.receiverName == null) { val res = db.payment.registerIncoming(payment) logRes(res, kind = "incomplete") return } if (cfg.restrictionPaytoRegex != null) { if (!cfg.restrictionPaytoRegex.matches(payment.debtor.toString())) { bounce("restricted account") return } } // Else we try to parse the incoming subject if (payment.subject != null && subjectIsQrBill(payment.subject)) { when (val res = db.payment.registerQrBillIncoming(payment, payment.subject)) { IncomingRegistrationResult.ReservePubReuse -> bounce("reverse pub reuse") IncomingRegistrationResult.MappingReuse -> bounce("mapping reuse") IncomingRegistrationResult.UnknownMapping -> bounce("unknown mapping") is IncomingRegistrationResult.Success -> logRes(res) } } else { runCatching { parseIncomingSubject(payment.subject) }.fold( onSuccess = { metadata -> if (metadata is IncomingSubject.AdminBalanceAdjust) { val res = db.payment.registerIncoming(payment) logRes(res, kind = "admin balance adjust") } else { when (val res = db.payment.registerTalerableIncoming(payment, metadata)) { IncomingRegistrationResult.ReservePubReuse -> bounce("reverse pub reuse") IncomingRegistrationResult.MappingReuse -> bounce("mapping reuse") IncomingRegistrationResult.UnknownMapping -> bounce("unknown mapping") is IncomingRegistrationResult.Success -> logRes(res) } } }, onFailure = { e -> bounce(e.fmt())} ) } } /** Register a [tx] notification into [db] */ suspend fun registerTransaction( db: Database, cfg: NexusIngestConfig, tx: TxNotification, ) { if (tx.executionTime < cfg.ignoreTransactionsBefore) { logger.debug("IGNORE {}", tx) } else { when (tx) { is IncomingPayment -> registerIncomingPayment(db, cfg, tx) is OutgoingPayment -> registerOutgoingPayment(db, tx) is OutgoingBatch -> registerOutgoingBatch(db, tx) is OutgoingReversal -> { logger.error("{}", tx) db.initiated.txStatusUpdate(tx.endToEndId, tx.msgId, StatusUpdate.permanent_failure, "Payment bounced: ${tx.reason}") } } } } /** Register a single EBICS [xml] txs [document] into [db] */ suspend fun registerTxs( db: Database, cfg: NexusConfig, xml: InputStream ): Int { var nbTx: Int = 0 parseTx(xml).forEach { accountTx -> if (accountTx.iban == cfg.ebics.account.iban.toString()) { require(accountTx.currency == null || accountTx.currency == cfg.currency) { "Expected transactions of currency ${cfg.currency} got ${accountTx.currency}" } accountTx.txs.forEach { tx -> when (tx) { is IncomingPayment -> require(tx.amount.currency == cfg.currency) { "Expected transactions of currency ${cfg.currency} got ${tx.amount.currency}" } is OutgoingPayment -> require(tx.amount.currency == cfg.currency) { "Expected transactions of currency ${cfg.currency} got ${tx.amount.currency}" } is OutgoingBatch, is OutgoingReversal -> {} } registerTransaction(db, cfg.ingest, tx) nbTx += 1 } } else { logger.debug("Skip transaction for unknown account ${accountTx.iban}") } } return nbTx } /** Register a single EBICS [xml] [document] into [db] */ suspend fun registerFile( db: Database, cfg: NexusConfig, xml: InputStream, doc: OrderDoc ) { when (doc) { OrderDoc.report, OrderDoc.statement, OrderDoc.notification -> { try { registerTxs(db, cfg, xml) } catch (e: Exception) { throw Exception("Ingesting transactions files failed", e) } } OrderDoc.acknowledgement -> { val acks = parseCustomerAck(xml) for (ack in acks) { when (ack.actionType) { HacAction.ORDER_HAC_FINAL_POS -> { logger.debug("{}", ack) db.initiated.orderSuccess(ack.orderId!!)?.let { messageId -> logger.info("Batch $messageId order ${ack.orderId} accepted at ${ack.timestamp.fmtDateTime()}") } } HacAction.ORDER_HAC_FINAL_NEG -> { logger.debug("{}", ack) db.initiated.orderFailure(ack.orderId!!)?.let { (messageId, msg) -> logger.error("Batch $messageId order ${ack.orderId} refused at ${ack.timestamp.fmtDateTime()}${if (msg != null) ": $msg" else ""}") } } else -> { logger.debug("{}", ack) if (ack.orderId != null) { db.initiated.orderStep(ack.orderId, ack.msg()) } } } } } OrderDoc.status -> { val msgStatus = parseCustomerPaymentStatusReport(xml) logger.debug("{}", msgStatus) if (msgStatus.code != null) { val msg = msgStatus.msg() val state = when (msgStatus.code) { ExternalPaymentGroupStatusCode.ACSC -> StatusUpdate.success ExternalPaymentGroupStatusCode.RJCT -> { logger.error("Batch ${msgStatus.id} failed: $msg") StatusUpdate.permanent_failure } else -> StatusUpdate.pending } db.initiated.batchStatusUpdate(msgStatus.id, state, msg) } for (pmtStatus in msgStatus.payments) { if (pmtStatus.id != "NOTPROVIDED") { logger.warn("Unexpected payment status for ${msgStatus.id}.${pmtStatus.id}") } else if (pmtStatus.code != null) { val msg = pmtStatus.msg() val state = when (pmtStatus.code) { ExternalPaymentGroupStatusCode.ACSC -> StatusUpdate.success ExternalPaymentGroupStatusCode.RJCT -> { logger.error("Batch ${msgStatus.id} failed: $msg") StatusUpdate.permanent_failure } else -> StatusUpdate.pending } db.initiated.batchStatusUpdate(msgStatus.id, state, msg) } for (txStatus in pmtStatus.transactions) { val msg = txStatus.msg() val state = when (txStatus.code) { ExternalPaymentTransactionStatusCode.RJCT, ExternalPaymentTransactionStatusCode.BLCK -> { logger.error("Transaction ${txStatus.endToEndId} failed: $msg") StatusUpdate.permanent_failure } else -> StatusUpdate.pending } db.initiated.txStatusUpdate(txStatus.endToEndId, null, state, msg) } } } } } /** Register an EBICS [payload] of [doc] into [db] */ private suspend fun registerPayload( db: Database, cfg: NexusConfig, payload: InputStream, doc: OrderDoc ) { // Unzip payload if necessary when (doc) { OrderDoc.status, OrderDoc.report, OrderDoc.statement, OrderDoc.notification -> { try { payload.unzipEach { fileName, xml -> logger.trace("parse $fileName") registerFile(db, cfg, xml, doc) } } catch (e: IOException) { throw Exception("Could not open any ZIP archive", e) } } OrderDoc.acknowledgement -> registerFile(db, cfg, payload, doc) } } /** * Fetch and register banking records from [orders] using EBICS [client] starting from [pinnedStart] * * If [pinnedStart] is null fetch new records. */ private suspend fun fetchEbicsDocuments( client: EbicsClient, db: Database, cfg: NexusConfig, orders: Collection, pinnedStart: Instant?, peek: Boolean ): Boolean { val lastExecutionTime: Instant? = pinnedStart var success = true for ((doc, orders) in orders.groupBy { it.doc() }) { if (doc == null) { logger.debug("Skip unsupported orders {}", orders) } else { if (lastExecutionTime == null) { logger.info("Fetching new '${doc.fullDescription()}'") } else { logger.info("Fetching '${doc.fullDescription()}' from timestamp: $lastExecutionTime") } for (order in orders) { try { client.download( order, lastExecutionTime, null, peek ) { payload -> registerPayload(db, cfg, payload, doc) } } catch (e: EbicsError.Code) { when (e.bankCode) { EbicsReturnCode.EBICS_NO_DOWNLOAD_DATA_AVAILABLE -> continue EbicsReturnCode.EBICS_AUTHORISATION_ORDER_IDENTIFIER_FAILED -> { e.fmtLog(logger) success = false continue } else -> throw e } } } } } return success } @Serializable data class Checkpoint( @Contextual val last_successfull: Instant? = null, @Contextual val last_trial: Instant? = null ) class EbicsFetch: EbicsCmd() { override fun help(context: Context) = "Downloads and parse EBICS files from the bank and register them into the database" private val documents: Set by argument( help = "Which documents should be fetched? If none are specified, all supported documents will be fetched", helpTags = OrderDoc.entries.associate { Pair(it.name, it.shortDescription()) }, ).enum().multiple().unique() private val pinnedStart by option( help = "Only supported in --transient mode, this option lets specify the earliest timestamp of the downloaded documents", metavar = "YYYY-MM-DD" ).convert { dateToInstant(it) } private val peek by option("--peek", help = "Only supported in --transient mode, do not consume fetched documents" ).flag() private val transientCheckpoint by option("--checkpoint", help = "Only supported in --transient mode, run a checkpoint" ).flag() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> val (clientKeys, bankKeys) = expectFullKeys(cfg.ebics) val client = EbicsClient( cfg.ebics.host, httpClient(), db.ebics, EbicsLogger(ebicsLog), clientKeys, bankKeys ) val docs = if (documents.isEmpty()) OrderDoc.entries else documents.toList() // EBICS order than should be fetched val selectedOrder = docs.flatMap { cfg.ebics.dialect.downloadDoc(it) } // Try to obtain real-time notification channel if not transient val wssNotification = if (transient) { logger.info("Transient mode: fetching once and returning") null } else { val tmp = listenForNotification(client) logger.info("Running with a frequency of ${cfg.fetch.frequencyRaw}") tmp } var lastFetch = Instant.EPOCH while (true) { val checkpoint = db.kv.get(CHECKPOINT_KEY) ?: TaskStatus() var nextFetch = lastFetch + cfg.fetch.frequency var nextCheckpoint = run { // We never ran, we must checkpoint now if (checkpoint.last_trial == null) { Instant.EPOCH } else { // We run today at checkpointTime val checkpointDate = OffsetDateTime.now().with(cfg.fetch.checkpointTime) val checkpointToday = checkpointDate.toInstant() // If we already ran today we ruAn tomorrow if (checkpoint.last_trial > checkpointToday) { checkpointDate.plusDays(1).toInstant() } else { checkpointToday } } } val now = Instant.now() var success: Boolean = true if ( // Run transient checkpoint at request (transient && transientCheckpoint) || // Or run recurrent checkpoint (!transient && now > nextCheckpoint) ) { logger.info("Running checkpoint") val since = if (transient && pinnedStart != null && (checkpoint.last_successfull == null || pinnedStart!!.isBefore(checkpoint.last_successfull))) { pinnedStart } else { checkpoint.last_successfull } success = try { /// We fetch HKD to only fetch supported EBICS orders and get the document versions val orders = client.download(EbicsOrder.V3.HKD) { stream -> val hkd = EbicsAdministrative.parseHKD(stream) val supportedOrder = hkd.partner.orders.map { it.order } logger.debug { val fmt = supportedOrder.map(EbicsOrder::description).joinToString(" ") "HKD: ${fmt}" } selectedOrder select supportedOrder } fetchEbicsDocuments(client, db, cfg, orders, since, transient && peek) } catch (e: Exception) { e.fmtLog(logger) false } db.kv.updateTaskStatus(CHECKPOINT_KEY, now, success) lastFetch = now } else if (transient || now > nextFetch) { if (!transient) logger.info("Running at frequency") success = try { /// We fetch HAA to only fetch pending & supported EBICS orders and get the document versions val orders = client.download(EbicsOrder.V3.HAA) { stream -> val haa = EbicsAdministrative.parseHAA(stream) logger.debug { val orders = haa.orders.map(EbicsOrder::description).joinToString(" ") "HAA: ${orders}" } selectedOrder select haa.orders } fetchEbicsDocuments(client, db, cfg, orders, if (transient) pinnedStart else null, transient && peek) } catch (e: Exception) { e.fmtLog(logger) false } lastFetch = now } db.kv.updateTaskStatus(SUBMIT_TASK_KEY, now, success) if (transient) throw ProgramResult(if (!success) 1 else 0) val delay = min(ChronoUnit.MILLIS.between(now, nextFetch), ChronoUnit.MILLIS.between(now, nextCheckpoint)) if (wssNotification == null) { delay(delay) } else { val notifications = withTimeoutOrNull(delay) { wssNotification.receive() } if (notifications != null) { // Only fetch requested and supported orders val orders = selectedOrder select notifications if (orders.isNotEmpty()) { logger.info("Running at real-time notifications reception") fetchEbicsDocuments(client, db, cfg, notifications, null, false) } } } } } } } libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/Manual.kt0000664000175000017500000001325315122266731027732 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.arguments.* import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.convert import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.* import com.github.ajalt.mordant.terminal.* import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.db.* import tech.libeufin.ebics.randEbicsId import tech.libeufin.nexus.iso20022.* import java.util.zip.* import java.time.Instant import java.io.* class ExportCmt: TalerCmd("export") { override fun help(context: Context) = "Export pending batches as pain001 messages" private val out by argument().outputStream() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> // Create and get pending batches db.initiated.batch(Instant.now(), randEbicsId(), cfg.submit.requireAck) val batches = db.initiated.submittable() var nbTx: Int = 0 ZipOutputStream(BufferedOutputStream(out)).use { zip -> val ebicsCfg = cfg.ebics val metadata = buildString { append("Exported ${batches.size} pain.001 files:") for (batch in batches) { nbTx = batch.payments.size val entry = ZipEntry("${batch.creationDate.toDateTimeFilePath()}-${batch.messageId}.xml") zip.putNextEntry(entry) val msg = batchToPain001Msg(ebicsCfg.account, batch) val xml = createPain001( msg = msg, dialect = ebicsCfg.dialect, instant = false ) zip.write(xml) append("\nbatch ${batch.messageId}:") for (tx in batch.payments) { append("\n- tx ${tx.endToEndId} ${tx.amount} ${tx.creditor.iban} '${tx.creditor.receiverName}'") } append("\n") } } zip.putNextEntry(ZipEntry("README.txt")) zip.write(metadata.toByteArray()) logger.info(metadata) } } } } class ImportCmt: TalerCmd("import") { override fun help(context: Context) = "Import EBICS camt files" private val sources by argument().inputStream().multiple(required = true) override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> for (source in sources) { var nbTx: Int = 0 source.use { xml -> nbTx += registerTxs(db, cfg, xml) } logger.info("Imported $nbTx transactions from $source") } } } } class StatusCmd: TalerCmd("status") { override fun help(context: Context) = "Change batches or transactions status" enum class Kind { batch, tx } private val kind by argument().enum() private val id by argument() private val status by argument().enum() private val msg by argument().optional() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> when (kind) { Kind.batch -> if (db.initiated.batchStatusUpdate(id, status, msg)) { logger.info("Updated batch '${id}' to ${status}") } else { throw Exception("Unknown batch '$id'") } Kind.tx -> if (db.initiated.txStatusUpdate(id, null, status, msg)) { logger.info("Updated tx '${id}' to ${status}") } else { throw Exception("Unknown tx '$id'") } } } } } class AckCmd: TalerCmd("ack") { override fun help(context: Context) = "Manually acknowledge the outgoing transaction for submission" private val ids by argument().long().multiple() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> for (id in ids) { if (db.initiated.ack(id)) { logger.info("Mark $id as acknowledge for submission") } else { logger.warn("Unknown transaction $id") } } } } } class ManualCmd : TalerCmd("manual") { init { subcommands(ExportCmt(), ImportCmt(), StatusCmd(), AckCmd()) } override fun help(context: Context) = "Manual management commands" override fun run() = Unit }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/InitiatePayment.kt0000664000175000017500000000563515122266731031626 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.convert import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.convert import com.github.ajalt.clikt.parameters.options.option import tech.libeufin.common.* import tech.libeufin.nexus.db.InitiatedPayment import tech.libeufin.nexus.nexusConfig import tech.libeufin.nexus.withDb import tech.libeufin.ebics.randEbicsId import java.time.Instant class InitiatePayment: TalerCmd() { override fun help(context: Context) = "Initiate an outgoing payment" private val amount by option( "--amount", help = "The amount to transfer, payto 'amount' parameter takes the precedence" ).convert { TalerAmount(it) } private val subject by option( "--subject", help = "The payment subject, payto 'message' parameter takes the precedence" ) private val endToEndId by option( "--end-to-end-id", "--request-uid", help = "The payment end-to-end UID" ) private val payto by argument( help = "The credited account IBAN payto URI" ).convert { Payto.parse(it).expectIban() } override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> val subject = requireNotNull(payto.message ?: subject) { "Missing subject" } val amount = requireNotNull(payto.amount ?: amount) { "Missing amount" } requireNotNull(payto.receiverName) { "Missing receiver name in creditor payto" } require(amount.currency == cfg.currency) { "Wrong currency: expected ${cfg.currency} got ${amount.currency}" } db.initiated.create( InitiatedPayment( id = -1, amount = amount, subject = subject, creditor = payto, initiationTime = Instant.now(), endToEndId = endToEndId ?: randEbicsId() ) ) } } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/Serve.kt0000664000175000017500000000474615122266731027610 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import tech.libeufin.common.TalerCmd import tech.libeufin.common.api.serve import tech.libeufin.nexus.nexusApi import tech.libeufin.nexus.nexusConfig import tech.libeufin.nexus.withDb class Serve : TalerCmd("serve") { override fun help(context: Context) = "Run libeufin-nexus HTTP server" private val check by option( help = "Check whether an API is in use (if it's useful to start the HTTP server). Exit with 0 if at least one API is enabled, otherwise 1" ).flag() override fun run() = cliCmd(logger) { val cfg = nexusConfig(config) if (check) { // Check if the server is to be started val apis = listOf( cfg.wireGatewayApiCfg to "Wire Gateway API", cfg.revenueApiCfg to "Revenue API" ) var startServer = false for ((api, name) in apis) { if (api != null) { startServer = true logger.info("$name is enabled: starting the server") } } if (!startServer) { logger.info("All APIs are disabled: not starting the server") throw ProgramResult(1) } else { throw ProgramResult(0) } } cfg.withDb { db, cfg -> serve(cfg.serverCfg, logger) { nexusApi(db, cfg) } } } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSubmit.kt0000664000175000017500000001353115221677432030731 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import kotlinx.coroutines.delay import tech.libeufin.common.* import tech.libeufin.ebics.* import tech.libeufin.nexus.* import tech.libeufin.nexus.db.* import tech.libeufin.nexus.iso20022.* import java.time.Instant import kotlin.time.toKotlinDuration fun batchToPain001Msg(account: IbanAccountMetadata, batch: PaymentBatch): Pain001Msg { return Pain001Msg( messageId = batch.messageId, timestamp = batch.creationDate, debtor = account, sum = batch.sum, txs = batch.payments.map { payment -> val payto = payment.creditor if (payto.receiverName == null) { logger.warn("Missing receiver-name for payto $payto") } Pain001Tx( creditor = IbanAccountMetadata( iban = payto.iban, bic = payto.bic, name = payto.receiverName ?: "Unknown" ), amount = payment.amount, subject = payment.subject, endToEndId = payment.endToEndId ) } ) } /** * Submit an initiated payments [batch] using [client]. * * Parse creditor IBAN account metadata then perform an EBICS direct credit * * Returns the orderID */ private suspend fun submitBatch( client: EbicsClient, order: EbicsOrder, batch: PaymentBatch, cfg: NexusConfig, instant: Boolean, ): String { val ebicsCfg = cfg.ebics val msg = batchToPain001Msg(ebicsCfg.account, batch) val xml = createPain001( msg = msg, dialect = ebicsCfg.dialect, instant = instant ) return client.upload(order, xml) } /** Submit all pending initiated payments using [client] */ private suspend fun submitAll(client: EbicsClient, requireAck: Boolean, cfg: NexusConfig, db: Database) { // Find a supported debit order var instantDebitOrder = cfg.ebics.dialect.instantDirectDebit() val debitOrder = cfg.ebics.dialect.directDebit() // Create batch if necessary db.initiated.batch(Instant.now(), randEbicsId(), requireAck) // Send submittable batches db.initiated.submittable().forEach { batch -> logger.debug("Submitting batch {}", batch.messageId) runCatching { if (instantDebitOrder != null) { try { return@runCatching submitBatch(client, instantDebitOrder!!, batch, cfg, true) } catch (e: EbicsError.Code) { // No longer try to submit using the instant method for now logger.debug("Failed to submit using instant credit order ${e.fmt()}") instantDebitOrder = null } } submitBatch(client, debitOrder, batch, cfg, false) }.fold( onSuccess = { orderId -> db.initiated.batchSubmissionSuccess(batch.id, Instant.now(), orderId) val transactions = batch.payments.joinToString(",") { it.endToEndId } if (instantDebitOrder == null) { logger.info("Batch ${batch.messageId} submitted as order $orderId: $transactions") } else { logger.info("Instant batch ${batch.messageId} submitted as order $orderId: $transactions") } }, onFailure = { e -> db.initiated.batchSubmissionFailure(batch.id, Instant.now(), e.message) logger.error("Batch ${batch.messageId} submission failure: ${e.fmt()}") throw e } ) } } class EbicsSubmit : EbicsCmd() { override fun help(context: Context) = "Submits pending initiated payments found in the database" override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> val (clientKeys, bankKeys) = expectFullKeys(cfg.ebics) val client = EbicsClient( cfg.ebics.host, httpClient(), db.ebics, EbicsLogger(ebicsLog), clientKeys, bankKeys ) if (transient) { logger.info("Transient mode: submitting what found and returning.") submitAll(client, cfg.submit.requireAck, cfg, db) } else { logger.debug("Running with a frequency of ${cfg.submit.frequencyRaw}") while (true) { val now = Instant.now(); val success = try { submitAll(client, cfg.submit.requireAck, cfg, db) true } catch (e: Exception) { e.fmtLog(logger) false } db.kv.updateTaskStatus(SUBMIT_TASK_KEY, now, success) // TODO take submitBatch taken time in the delay delay(cfg.submit.frequency.toKotlinDuration()) } } } } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/Testing.kt0000664000175000017500000002150315221677432030133 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.arguments.* import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.convert import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.required import com.github.ajalt.clikt.parameters.types.* import com.github.ajalt.mordant.terminal.* import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.iso20022.* import tech.libeufin.ebics.* import tech.libeufin.ebics.test.txCheck import java.util.zip.* import java.time.Instant import java.io.* class Wss : TalerCmd() { override fun help(context: Context) = "Listen to EBICS instant notification over websocket" private val ebicsLog by ebicsLogOption() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> val (clientKeys, bankKeys) = expectFullKeys(cfg.ebics) val client = EbicsClient( cfg.ebics.host, httpClient(), db.ebics, EbicsLogger(ebicsLog), clientKeys, bankKeys ) val wssNotifications = listenForNotification(client) if (wssNotifications != null) { while (true) { wssNotifications.receive() logger.debug("{}", wssNotifications) } } } } } class FakeIncoming : TalerCmd() { override fun help(context: Context) = "Genere a fake incoming payment" private val amount by option( "--amount", help = "The payment amount, credit-payto 'amount' parameter takes the precedence" ).convert { TalerAmount(it) } private val creditFee by option( "--credit-fee", help = "The payment credit fee" ).convert { TalerAmount(it) } private val subject by option( "--subject", help = "The payment subject, credit-payto 'message' parameter takes the precedence" ) private val chQrr by option( "--ch-qrr", help = "The payment reference, credit-payto 'ch-qrr' parameter takes the precedence" ) private val creditPayto by option( "--credit-payto", help = "The credited account IBAN payto URI" ).convert { Payto.parse(it).expectIban() } private val debitPayto by option( "--debit-payto", help = "The debited account IBAN payto URI" ).convert { Payto.parse(it).expectIban() } private val payto by argument( name = "deprecated", help = "deprecated" ).convert { Payto.parse(it).expectIban() }.optional() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> val amount = requireNotNull(creditPayto?.amount ?: payto?.amount ?: amount) { "Missing amount" } val subject = creditPayto?.message ?: payto?.message ?: subject val reference = creditPayto?.chQrr ?: payto?.chQrr ?: chQrr creditPayto?.let { if (reference != null) { require(it.iban == cfg.ebics.qrIban) { "Creditor must be the exchange QRR account expected ${cfg.ebics.account.iban} got ${it.iban}" } } else { require(it.iban == cfg.ebics.account.iban) { "Creditor must be the exchange expected ${cfg.ebics.account.iban} got ${it.iban}" } } } require(amount.currency == cfg.currency) { "Wrong currency: expected ${cfg.currency} got ${amount.currency}" } registerIncomingPayment( db, cfg.ingest, IncomingPayment( amount = amount, debtor = debitPayto ?: payto ?: IbanPayto.rand("Testing Account", Country.valueOf(cfg.ebics.account.iban.value.substring(0 until 2))), subject = reference ?: subject ?: "", creditFee = creditFee, executionTime = Instant.now(), id = IncomingId(null, randEbicsId(), null) ) ) } } } class TxCheck : TalerCmd() { override fun help(context: Context) = "Check transaction semantic" override fun run() = cliCmd(logger) { val nexusCgf = nexusConfig(config) val cfg = nexusCgf.ebics val (clientKeys, bankKeys) = expectFullKeys(cfg) val order = cfg.dialect.downloadDoc(OrderDoc.acknowledgement) val client = httpClient() val result = txCheck(client, cfg.host, clientKeys, bankKeys, order[0], cfg.dialect.directDebit()) println("$result") } } enum class ListKind { incoming, outgoing, initiated; fun description(): String = when (this) { incoming -> "Incoming transactions" outgoing -> "Outgoing transactions" initiated -> "Initiated transactions" } } class EbicsDownload : TalerCmd("ebics-btd") { override fun help(context: Context) = "Perform EBICS requests" private val type by option().default("BTD") private val name by option() private val scope by option() private val messageName by option() private val messageVersion by option() private val container by option() private val option by option() private val ebicsLog by ebicsLogOption() private val pinnedStart by option( help = "Constant YYYY-MM-DD date for the earliest document" + " to download (only consumed in --transient mode). The" + " latest document is always until the current time." ) private val peek by option( "--peek", help = "Do not consume fetched documents" ).flag() private val dryRun by option().flag() class DryRun : Exception() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> val (clientKeys, bankKeys) = expectFullKeys(cfg.ebics) val pinnedStartVal = pinnedStart val pinnedStartArg = if (pinnedStartVal != null) { logger.debug("Pinning start date to: $pinnedStartVal") dateToInstant(pinnedStartVal) } else null val client = EbicsClient( cfg.ebics.host, httpClient(), db.ebics, EbicsLogger(ebicsLog), clientKeys, bankKeys ) try { client.download( EbicsOrder.V3(type, name, scope, messageName, messageVersion, container, option), pinnedStartArg, null, peek ) { stream -> if (container == "ZIP") { stream.unzipEach { fileName, xmlContent -> println(fileName) println(xmlContent.readText()) } } else { println(stream.readText()) } if (dryRun) throw DryRun() } } catch (e: DryRun) { // We throw DryRun to not consume files while testing } } } } class IbanGen : CliktCommand("gen") { override fun help(context: Context) = "Generate fake IBANs for testing" private val country by option().enum().required() override fun run() { println(IBAN.rand(country)) } } class IbanCmd : CliktCommand("iban") { init { subcommands(IbanGen()) } override fun run() = Unit } class TestingCmd : CliktCommand("testing") { init { subcommands(IbanCmd(), FakeIncoming(), ListCmd(), EbicsDownload(), TxCheck(), Wss()) } override fun help(context: Context) = "Testing helper commands" override fun run() = Unit } libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/LibeufinNexus.kt0000664000175000017500000000403415122266731031272 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.versionOption import com.github.ajalt.clikt.parameters.types.path import tech.libeufin.common.* import tech.libeufin.nexus.NEXUS_CONFIG_SOURCE import org.slf4j.Logger import org.slf4j.LoggerFactory internal val logger: Logger = LoggerFactory.getLogger("libeufin-nexus") fun CliktCommand.ebicsLogOption() = option( "--debug-ebics", help = "Log EBICS transactions steps and payload at log_dir", metavar = "log_dir" ).path() fun CliktCommand.transientOption() = option( "--transient", help = "Execute once and return, ignoring the 'FREQUENCY' configuration value" ).flag(default = false) abstract class EbicsCmd(name: String? = null): TalerCmd(name) { val ebicsLog by ebicsLogOption() val transient by transientOption() } class LibeufinNexus : CliktCommand() { init { versionOption(VERSION) subcommands(DbInit(), EbicsSetup(), EbicsSubmit(), EbicsFetch(), Serve(), InitiatePayment(), ManualCmd(), ListCmd(), CliConfigCmd(NEXUS_CONFIG_SOURCE), TestingCmd()) } override fun run() = Unit }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/DbInit.kt0000664000175000017500000000312615122266731027664 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import tech.libeufin.common.TalerCmd import tech.libeufin.common.db.dbInit import tech.libeufin.common.db.pgDataSource import tech.libeufin.nexus.dbConfig class DbInit : TalerCmd("dbinit") { override fun help(context: Context) = "Initialize the libeufin-nexus database" private val reset by option( "--reset", "-r", help = "Reset database (DANGEROUS: All existing data is lost)" ).flag() override fun run() = cliCmd(logger) { val cfg = dbConfig(config) pgDataSource(cfg.dbConnStr).dbInit(cfg, "libeufin-nexus", reset) } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSetup.kt0000664000175000017500000002101215221677432030557 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import io.ktor.client.* import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.ebics.ClientPrivateKeysFile import tech.libeufin.ebics.BankPublicKeysFile import tech.libeufin.ebics.ebicsSetup import tech.libeufin.ebics.askUserToAcceptKeys import tech.libeufin.ebics.EbicsLogger import tech.libeufin.ebics.EbicsKeyMng import tech.libeufin.nexus.* import tech.libeufin.ebics.* import java.nio.file.FileAlreadyExistsException import java.nio.file.Path import java.nio.file.StandardOpenOption import java.time.Instant import kotlin.io.path.Path import kotlin.io.path.writeBytes fun expectFullKeys(cfg: EbicsKeysConfig): Pair = expectFullKeys(cfg, "libeufin-nexus ebics-setup") /** * CLI class implementing the "ebics-setup" subcommand. */ class EbicsSetup: TalerCmd() { override fun help(context: Context) = "Set up the EBICS subscriber" private val forceKeysResubmission by option( help = "Resubmits all the keys to the bank" ).flag(default = false) private val autoAcceptKeys by option( help = "Accepts the bank keys without interactively asking the user" ).flag(default = false) private val generateRegistrationPdf by option( help = "Generates the PDF with the client public keys to send to the bank" ).flag(default = false) private val ebicsLog by ebicsLogOption() /** * This function collects the main steps of setting up an EBICS access. */ override fun run() = cliCmd(logger) { val cfg = nexusConfig(config) val setupCfg = cfg.setup val client = httpClient() val ebicsLogger = EbicsLogger(ebicsLog) val ebics3 = when (cfg.ebics.dialect) { // TODO GLS needs EBICS 2.5 for key management Dialect.gls -> false else -> true } val (clientKeys, bankKeys) = ebicsSetup( client, ebicsLogger, cfg.ebics, cfg.ebics.host, cfg.setup, forceKeysResubmission, generateRegistrationPdf, autoAcceptKeys, ebics3 ) // Check account information logger.info("Doing administrative request HKD") cfg.withDb { db, _ -> EbicsClient( cfg.ebics.host, client, db.ebics, ebicsLogger, clientKeys, bankKeys ).download(EbicsOrder.V3.HKD) { stream -> val (partner, users) = EbicsAdministrative.parseHKD(stream) val user = users.find { it -> it.id == cfg.ebics.host.userId } // Debug logging logger.debug { buildString { if (partner.name != null || partner.accounts.isNotEmpty()) { append("Partner Info: ") if (partner.name != null) { append("'") append(partner.name) append("'") } for ((currency, iban, bic) in partner.accounts) { append(' ') append(currency) append('-') append(iban) append('-') append(bic) } append('\n') } append("Supported orders:\n") for ((order, description) in partner.orders) { append("- ") append(order.description()) append(": ") append(description) append('\n') } if (user != null) { append("Authorized orders:\n") for ((order) in partner.orders) { append("- ") append(order.description()) append('\n') } } } } // Check partner info match config if (partner.name != null && partner.name != cfg.ebics.account.name) logger.warn("Expected NAME '${cfg.ebics.account.name}' from config got '${partner.name}' from bank") val account = partner.accounts.find { it.iban == cfg.ebics.account.iban.toString() } if (account != null) { if (account.currency != null && account.currency != cfg.currency) logger.error("Expected CURRENCY '${cfg.currency}' from config got '${account.currency}' from bank") if (account.bic != cfg.ebics.account.bic) logger.error("Expected BIC '${cfg.ebics.account.bic}' from config got '${account.bic}' from bank") } else if (partner.accounts.isNotEmpty()) { val ibans = partner.accounts.map { it.iban }.joinToString(" ") logger.error("Expected IBAN ${cfg.ebics.account.iban} from config got $ibans from bank") } val instantDebitOrder = cfg.ebics.dialect.instantDirectDebit() val debitOrder = cfg.ebics.dialect.directDebit() val requireOrders = cfg.ebics.dialect.downloadOrders() val partnerOrders = partner.orders.map { it.order } // Check partner support for direct debit orders if (instantDebitOrder != null && instantDebitOrder !in partnerOrders) { logger.warn("Unsupported instant debit order: ${instantDebitOrder.description()}") } if (debitOrder !in partnerOrders) { logger.warn("Unsupported debit order: ${debitOrder.description()}") } // Check partner support required orders val unsupportedOrder = requireOrders subtract partnerOrders if (unsupportedOrder.isNotEmpty()) { logger.warn("Unsupported orders: {}", unsupportedOrder.map(EbicsOrder::description).joinToString(" ")) } if (user != null) { // Check user is authorized for direct debit orders if (instantDebitOrder != null && instantDebitOrder in partnerOrders && instantDebitOrder !in user.permissions) { logger.warn("Unauthorized instant debit order: ${instantDebitOrder.description()}") } if (debitOrder in partnerOrders && debitOrder !in user.permissions) { logger.warn("Unauthorized debit order: ${debitOrder.description()}") } // Check user is authorized for required orders val unauthorizedOrders = requireOrders subtract user.permissions subtract unsupportedOrder if (unauthorizedOrders.isNotEmpty()) { logger.warn("Unauthorized orders: {}", unauthorizedOrders.map(EbicsOrder::description).joinToString(" ")) } logger.info("Subscriber status: {}", user.status.description) } } } println("setup ready") } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/cli/List.kt0000664000175000017500000001405615140725607027434 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.arguments.* import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.convert import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.* import com.github.ajalt.mordant.terminal.* import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.iso20022.* import java.util.zip.* import java.time.Instant import java.io.* private fun fmtPayto(payto: String): String { try { val parsed = Payto.parse(payto).expectIban() return buildString { append(parsed.iban.toString()) if (parsed.bic != null) append(" ${parsed.bic}") if (parsed.receiverName != null) append(" ${parsed.receiverName}") } } catch (e: Exception) { return payto.removePrefix("payto://") } } class ListIncoming: TalerCmd("incoming") { override fun help(context: Context) = "List incoming transactions" private val incomplete by option( "--incomplete", help = "Only list transactions that are incomplete", ).flag() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> val txs = db.list.incoming(incomplete) for (tx in txs) { println(buildString{ if (tx.creditFee.isZero()) { append("${tx.date} ${tx.id} ${tx.amount}\n") } else { append("${tx.date} ${tx.id} ${tx.amount}-${tx.creditFee}\n") } if (tx.debtor != null) { append(" debtor: ${fmtPayto(tx.debtor)}\n") } if (tx.subject != null) { append(" subject: ${tx.subject}\n") } if (tx.talerable != null) { append(" talerable: ${tx.talerable}\n") } if (tx.bounced != null) { append(" bounced: ${tx.bounced}\n") } }) } } } } class ListOutgoing: TalerCmd("outgoing") { override fun help(context: Context) = "List outgoing transactions" override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> val txs = db.list.outgoing() for (tx in txs) { println(buildString{ append("${tx.date} ${tx.id} ${tx.amount}\n") if (tx.creditor != null) { append(" creditor: ${fmtPayto(tx.creditor)}\n") } append(" subject: ${tx.subject}\n") if (tx.wtid != null) { append(" talerable: ${tx.wtid} ${tx.exchangeBaseUrl}\n") } }) } } } } class ListInitiated: TalerCmd("initiated") { override fun help(context: Context) = "List initiated transactions" private val awaitingAck by option( "--ack", "--awaiting-ack", help = "Only list transactions awaiting manual acknowledgement", ).flag() override fun run() = cliCmd(logger) { nexusConfig(config).withDb { db, cfg -> if (awaitingAck) { val txs = db.list.initiatedAck() for (tx in txs) { println(buildString{ append("${tx.date} ${tx.id} ${tx.amount}\n") append(" creditor: ${fmtPayto(tx.creditor)}\n") append(" subject: ${tx.subject}\n") append(" ack: ${tx.dbId}") append('\n') }) } } else { val txs = db.list.initiated() for (tx in txs) { println(buildString{ append("${tx.date} ${tx.id} ${tx.amount}\n") append(" creditor: ${fmtPayto(tx.creditor)}\n") append(" subject: ${tx.subject}\n") if (tx.batch != null) { append(" batch: ${tx.batch}") if (tx.batchOrder != null) append(" ${tx.batchOrder}") append('\n') } if (tx.submissionCounter > 0) { append(" submission: ${tx.submissionTime} ${tx.submissionCounter}\n") } append(" status: ${tx.status}") if (tx.msg != null) { append(" ${tx.msg}") } append('\n') }) } } } } } class ListCmd: CliktCommand("list") { override fun help(context: Context) = "List nexus transactions" init { subcommands(ListIncoming(), ListOutgoing(), ListInitiated()) } override fun run() = Unit }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt0000664000175000017500000000605115221677432026634 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ /** * This file collects all the CLI subcommands and runs * them. The actual implementation of each subcommand is * kept in their respective files. */ package tech.libeufin.nexus import io.ktor.server.application.* import org.slf4j.Logger import org.slf4j.LoggerFactory import kotlinx.serialization.Serializable import kotlinx.serialization.Contextual import tech.libeufin.common.api.OpenApiInfo import tech.libeufin.common.api.talerApi import tech.libeufin.common.setupSecurityProperties import tech.libeufin.common.VERSION import tech.libeufin.nexus.api.revenueApi import tech.libeufin.nexus.api.preparedTransferAPI import tech.libeufin.nexus.api.wireGatewayApi import tech.libeufin.nexus.api.observabilityApi import tech.libeufin.nexus.cli.LibeufinNexus import tech.libeufin.nexus.db.Database import com.github.ajalt.clikt.core.main import tech.libeufin.common.IBAN import java.time.Instant /** Triple identifying one IBAN bank account */ data class IbanAccountMetadata( val iban: IBAN, val bic: String?, val name: String ) fun Application.nexusApi(db: Database, cfg: NexusConfig, serveSpec: Boolean = false) = talerApi( LoggerFactory.getLogger("libeufin-nexus-api"), OpenApiInfo( title = "LibEuFin Nexus API", version = VERSION, description = "Taler wire gateway, wire transfer gateway, revenue, and observability APIs for LibEuFin Nexus", securityConfig = { securityScheme("bearerAuth") { type = io.github.smiley4.ktoropenapi.config.AuthType.HTTP scheme = io.github.smiley4.ktoropenapi.config.AuthScheme.BEARER bearerFormat = "token" } securityScheme("basicAuth") { type = io.github.smiley4.ktoropenapi.config.AuthType.HTTP scheme = io.github.smiley4.ktoropenapi.config.AuthScheme.BASIC description = "HTTP Basic authentication, supported only on compatibility-enabled endpoints" } } ), serveSpec = serveSpec ) { wireGatewayApi(db, cfg) preparedTransferAPI(db, cfg) revenueApi(db, cfg) observabilityApi(db, cfg) } fun main(args: Array) { setupSecurityProperties() LibeufinNexus().main(args) } @Serializable data class TaskStatus( @Contextual val last_successfull: Instant? = null, @Contextual val last_trial: Instant? = null )libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/dialect.kt0000664000175000017500000000764615161724132027361 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus import tech.libeufin.ebics.* infix fun Collection.select(other: Collection): List = this.flatMap { filter -> other.filter { order -> filter.match(order) } } /** Supported EBICS standard */ enum class Standard { /// Swiss Payment Standards SIX, /// German Banking Industry Committee GBIC; fun downloadDoc(doc: OrderDoc): List = when (this) { SIX -> when (doc) { OrderDoc.acknowledgement -> listOf(EbicsOrder.V3.HAC) OrderDoc.status -> listOf(EbicsOrder.V3("BTD", "PSR", "CH", "pain.002", "10", "ZIP")) OrderDoc.report -> listOf(EbicsOrder.V3("BTD", "STM", "CH", "camt.052", "08", "ZIP")) OrderDoc.statement -> listOf(EbicsOrder.V3("BTD", "EOP", "CH", "camt.053", "08", "ZIP")) OrderDoc.notification -> listOf(EbicsOrder.V3("BTD", "REP", "CH", "camt.054", "08", "ZIP")) } GBIC -> when (doc) { OrderDoc.acknowledgement -> listOf(EbicsOrder.V3.HAC) OrderDoc.status -> listOf( EbicsOrder.V3("BTD", "REP", "DE", "pain.002", null, "ZIP", "SCI"), EbicsOrder.V3("BTD", "REP", "DE", "pain.002", null, "ZIP", "SCT") ) OrderDoc.report -> listOf(EbicsOrder.V3("BTD", "STM", "DE", "camt.052", null, "ZIP")) OrderDoc.statement -> listOf(EbicsOrder.V3("BTD", "EOP", "DE", "camt.053", null, "ZIP")) OrderDoc.notification -> listOf( EbicsOrder.V3("BTD", "STM", "DE", "camt.054", null, "ZIP"), EbicsOrder.V3("BTD", "STM", "DE", "camt.054", null, "ZIP", "SCI") ) } } fun directDebit(): EbicsOrder = when (this) { SIX -> EbicsOrder.V3("BTU", "MCT", "CH", "pain.001", "09") GBIC -> EbicsOrder.V3("BTU", "SCT", null, "pain.001") } fun instantDirectDebit(): EbicsOrder? = when (this) { SIX -> null GBIC -> EbicsOrder.V3("BTU", "SCI", "DE", "pain.001") } } /** Supported bank dialects */ enum class Dialect { valiant, raiffeisen, postfinance, gls, maerki_baumann; fun standard(): Standard = when (this) { valiant, postfinance, raiffeisen, maerki_baumann -> Standard.SIX gls -> Standard.GBIC } fun downloadDoc(doc: OrderDoc): List { if (this == maerki_baumann) throw IllegalArgumentException("Maerki Baumann does not have EBICS access") return this.standard().downloadDoc(doc) } fun directDebit(): EbicsOrder { if (this == maerki_baumann) throw IllegalArgumentException("Maerki Baumann does not have EBICS access") return this.standard().directDebit() } fun instantDirectDebit(): EbicsOrder? { if (this == maerki_baumann) throw IllegalArgumentException("Maerki Baumann does not have EBICS access") return this.standard().instantDirectDebit() } /** All orders required for a dialect implementation to work */ fun downloadOrders(): Set = ( // Administrative orders sequenceOf(EbicsOrder.V3.HAA, EbicsOrder.V3.HKD) // and documents orders + OrderDoc.entries.flatMap { downloadDoc(it) } ).toSet() }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/helpers.kt0000664000175000017500000000211315122266731027401 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter fun Instant.fmtDate(): String = DateTimeFormatter.ISO_LOCAL_DATE.withZone(ZoneId.of("UTC")).format(this) fun Instant.fmtDateTime(): String = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.of("UTC")).format(this) libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/0000775000175000017500000000000015236145704026564 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain001.kt0000664000175000017500000001275215221677432030305 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.iso20022 import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.ebics.XmlBuilder import java.time.Instant import java.time.ZoneId import java.time.ZonedDateTime import java.time.format.DateTimeFormatter /** String representation of a Taler [amount] compatible with EBICS */ fun getAmountNoCurrency(amount: TalerAmount): String { if (amount.isSubCent()) { throw Exception("Sub-cent amounts not supported") } return amount.number().toString() } /** pain.001 transaction metadata */ data class Pain001Tx( val creditor: IbanAccountMetadata, val amount: TalerAmount, val subject: String, val endToEndId: String ) /** pain.001 message metadata */ data class Pain001Msg( val messageId: String, val timestamp: Instant, val debtor: IbanAccountMetadata, val sum: TalerAmount, val txs: List ) /** Create a pain.001 XML document [msg] valid for [dialect] */ fun createPain001( msg: Pain001Msg, dialect: Dialect, instant: Boolean ): ByteArray { val version = "09" val suffix = when (dialect.standard()) { Standard.SIX -> ".ch.03" Standard.GBIC -> "" } val zonedTimestamp = ZonedDateTime.ofInstant(msg.timestamp, ZoneId.of("UTC")) val totalAmount = getAmountNoCurrency(msg.sum) return XmlBuilder.toBytes("Document") { attr("xmlns", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.$version") attr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") attr("xsi:schemaLocation", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.$version pain.001.001.$version$suffix.xsd") el("CstmrCdtTrfInitn") { el("GrpHdr") { // Used for idempotency as banks will refuse to process EBICS request with the same MsgId for a pre-agreed period // Used to uniquely identify batches of transactions in other files el("MsgId", msg.messageId) el("CreDtTm", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(zonedTimestamp)) el("NbOfTxs", msg.txs.size.toString()) el("CtrlSum", totalAmount) el("InitgPty/Nm", msg.debtor.name) /* TODO fail with GLS: ES_VERIFICATION IncorrectFileStructure - 'Signature verification' 'The file format is incomplete or invalid' el("InitnSrc") { el("Nm", "LibEuFin") el("Prvdr", "Taler Systems SA") el("Vrsn", VERSION) }*/ // LocalInstrument } el("PmtInf") { el("PmtInfId", "NOTPROVIDED") el("PmtMtd", "TRF") el("BtchBookg", "false") el("NbOfTxs", msg.txs.size.toString()) el("CtrlSum", totalAmount) if (dialect == Dialect.gls) { el("PmtTpInf") { el("SvcLvl/Cd", "SEPA") if (instant) { el("LclInstrm/Cd", "INST") } } } el("ReqdExctnDt/Dt", DateTimeFormatter.ISO_DATE.format(zonedTimestamp)) el("Dbtr/Nm", msg.debtor.name) el("DbtrAcct/Id/IBAN", msg.debtor.iban.toString()) el("DbtrAgt/FinInstnId") { if (msg.debtor.bic != null) { el("BICFI", msg.debtor.bic) } else { el("Othr/Id", "NOTPROVIDED") } } el("ChrgBr", "SLEV") for (tx in msg.txs) { el("CdtTrfTxInf") { el("PmtId") { el("InstrId", tx.endToEndId) // Used to uniquely identify transactions in other files el("EndToEndId", tx.endToEndId) } el("Amt/InstdAmt") { attr("Ccy", tx.amount.currency) text(getAmountNoCurrency(tx.amount)) } if (tx.creditor.bic != null) el("CdtrAgt/FinInstnId/BICFI", tx.creditor.bic) el("Cdtr") { el("Nm", tx.creditor.name) // Addr might become a requirement in the future /*el("PstlAdr") { el("TwnNm", "Bochum") el("Ctry", "DE") }*/ } el("CdtrAcct/Id/IBAN", tx.creditor.iban.toString()) el("RmtInf/Ustrd", tx.subject) } } } } } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/camt.kt0000664000175000017500000006073315122266731030057 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.iso20022 import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.ebics.XmlDestructor import java.io.InputStream import java.time.Instant import java.time.ZoneOffset import java.util.UUID import org.slf4j.Logger import org.slf4j.LoggerFactory private val logger: Logger = LoggerFactory.getLogger("libeufin-iso20022") sealed interface TxNotification { val executionTime: Instant } /** ID for incoming transactions */ data class IncomingId( /** ISO20022 UETR */ val uetr: UUID? = null, /** ISO20022 TxID */ val txId: String? = null, /** ISO20022 AcctSvcrRef */ val acctSvcrRef: String? = null, ) { constructor(uetr: String, txId: String?, acctSvcrRef: String?) : this(UUID.fromString(uetr), txId, acctSvcrRef); fun ref(): String = uetr?.toString() ?: txId ?: acctSvcrRef!! override fun toString(): String = buildString { append('(') if (uetr != null) { append("uetr=") append(uetr.toString()) } if (txId != null) { if (length != 1) append(" ") append("tx=") append(txId) } if (acctSvcrRef != null) { if (length != 1) append(" ") append("ref=") append(acctSvcrRef) } append(')') } } sealed interface OutId {} /** ID for outgoing transactions */ data class OutgoingId( /** * Unique msg ID generated by libeufin-nexus * ISO20022 MessageId **/ val msgId: String? = null, /** * Unique end-to-end ID generated by libeufin-nexus * ISO20022 EndToEndId or MessageId (retrocompatibility) **/ val endToEndId: String? = null, /** * Unique end-to-end ID generated by the bank * ISO20022 AcctSvcrRef **/ val acctSvcrRef: String? = null, ): OutId { fun ref(): String = endToEndId ?: acctSvcrRef ?: msgId!! override fun toString(): String = buildString { append('(') if (msgId != null && msgId != endToEndId) { append("msg=") append(msgId.toString()) } if (endToEndId != null) { if (length != 1) append(" ") append("e2e=") append(endToEndId) } if (acctSvcrRef != null) { if (length != 1) append(" ") append("ref=") append(acctSvcrRef) } append(')') } } /** ID for outgoing batches */ data class BatchId( /** * Unique msg ID generated by libeufin-nexus * ISO20022 MessageId **/ val msgId: String, /** * Unique end-to-end ID generated by the bank * ISO20022 AcctSvcrRef **/ val acctSvcrRef: String? = null, ): OutId { fun ref(): String = msgId override fun toString(): String = buildString { append("(msg=") append(msgId) if (acctSvcrRef != null) { if (length != 1) append(" ") append("ref=") append(acctSvcrRef) } append(')') } } /** ISO20022 incoming payment */ data class IncomingPayment( val id: IncomingId, val amount: TalerAmount, val creditFee: TalerAmount? = null, val subject: String?, override val executionTime: Instant, val debtor: IbanPayto? ): TxNotification { override fun toString(): String = buildString { append("IN ") append(executionTime.fmtDate()) append(" ") append(amount) if (creditFee != null) { append("-") append(creditFee) } append(" ") append(id) if (debtor != null) { append(" debtor=") append(debtor.fmt()) } if (subject != null) { append(" subject='") append(subject) append("'") } } } /** ISO20022 outgoing payment */ data class OutgoingPayment( val id: OutgoingId, val amount: TalerAmount, val debitFee: TalerAmount? = null, val subject: String?, override val executionTime: Instant, val creditor: IbanPayto? ): TxNotification { override fun toString(): String = buildString { append("OUT ") append(executionTime.fmtDate()) append(" ") append(amount) if (debitFee != null) { append("-") append(debitFee) } append(" ") append(id) if (creditor != null) { append(" creditor=") append(creditor.fmt()) } if (subject != null) { append(" subject='") append(subject) append("'") } } } /** ISO20022 outgoing batch */ data class OutgoingBatch( /** ISO20022 MessageId */ val msgId: String, override val executionTime: Instant, ): TxNotification { override fun toString(): String { return "BATCH ${executionTime.fmtDate()} $msgId" } } /** ISO20022 outgoing reversal */ data class OutgoingReversal( /** ISO20022 EndToEndId */ val endToEndId: String, /** ISO20022 MessageId */ val msgId: String? = null, val reason: String?, override val executionTime: Instant ): TxNotification { override fun toString(): String { val msgIdFmt = if (msgId == null) "" else "$msgId." return "BOUNCE ${executionTime.fmtDate()} $msgIdFmt$endToEndId: $reason" } } private class IncompleteTx(val msg: String): Exception(msg) private enum class Kind { CRDT, DBIT } /** Parse a payto */ private fun XmlDestructor.payto(prefix: String): IbanPayto? { return opt("RltdPties") { val iban = opt("${prefix}Acct")?.one("Id")?.opt("IBAN")?.text() if (iban != null) { val name = opt(prefix) { opt("Nm")?.text() ?: opt("Pty")?.one("Nm")?.text() } // TODO more performant option ibanPayto(iban, name) } else { null } } } /** Check if an entry status is BOOK */ private fun XmlDestructor.isBooked(): Boolean { // We check at the Sts or Sts/Cd level for retrocompatibility return one("Sts") { val status = opt("Cd")?.text() ?: text() status == "BOOK" } } /** Parse the instruction execution date */ private fun XmlDestructor.executionDate(): Instant { // Value date if present else booking date val date = opt("ValDt") ?: one("BookgDt") val parsed = date.opt("Dt") { date().atStartOfDay() } ?: date.one("DtTm") { dateTime() } return parsed.toInstant(ZoneOffset.UTC) } /** Parse batch message ID and transaction end-to-end ID as generated by libeufin-nexus */ private fun XmlDestructor.outgoingId(ref: String?): OutId = opt("Refs") { val endToEndId = opt("EndToEndId")?.text() val msgId = opt("MsgId")?.text() val ref = if (ref != "NOTPROVIDED") ref else null if (msgId != null && endToEndId == null) { // This is a batch representation BatchId(msgId, ref) } else if (endToEndId == "NOTPROVIDED") { // If not set use MsgId as end-to-end ID for retrocompatibility OutgoingId(msgId, msgId, ref) } else { OutgoingId(msgId, endToEndId, ref) } } ?: OutgoingId(acctSvcrRef = ref) /** Parse transaction ids as provided by bank*/ private fun XmlDestructor.incomingId(ref: String?): IncomingId = opt("Refs") { val uetr = opt("UETR")?.uuid() val txId = opt("TxId")?.text() IncomingId(uetr, txId, ref) } ?: IncomingId(acctSvcrRef = ref) /** Parse and format transaction return reasons */ private fun XmlDestructor.returnReason(): String = opt("RtrInf") { val code = one("Rsn").one("Cd").enum() val info = map("AddtlInf") { text() }.joinToString("") buildString { append("${code.isoCode} '${code.description}'") if (info.isNotEmpty()) { append(" - '$info'") } } } ?: opt("RmtInf") { map("Ustrd") { text() }.joinToString("") } ?: "" /** Parse amount */ private fun XmlDestructor.amount() = one("Amt") { val currency = attr("Ccy") val amount = text() val concat = if (amount.startsWith('.')) { "$currency:0$amount" } else { "$currency:$amount" } TalerAmount(concat) } data class ComplexAmount( // Transaction amount val amount: TalerAmount, // The applied fee private val fee: TalerAmount, ) { /// The fees to register in database fun fee(): TalerAmount? = if (fee.isZero()) { null } else { fee } /// Check that entry and tx amount are compatible and return the result fun resolve(child: ComplexAmount): ComplexAmount { // Most time transaction will match if (this.amount == child.amount && this.fee == child.fee) { return this } // Or one of the level is missing the fee if ( (child.amount > child.fee && child.amount - child.fee == this.amount) || this.amount - this.fee == child.amount ) { if (child.fee.isZero()) { return this } else { return child } } // Or the conversion information are only present at the entry layer if (child.amount.currency != this.amount.currency) { return this } throw Error("Amount mismatch, got ${this} in the entry and ${child} in the tx") } } private fun XmlDestructor.complexAmount(charges: List): ComplexAmount? { // Amount before charges var amount = opt("Amt") { val currency = attr("Ccy") // In case of fee overflow it's possible to have a negative amount here // We ignore this as it will be handled elsewhere correctly val amount = text().trimStart('-') TalerAmount("$currency:0$amount") } ?: return null var fee: TalerAmount = TalerAmount.zero(amount.currency) for (chr in charges) { if (chr.included && !chr.amount.isZero()) { fee += chr.amount if (chr.kind == Kind.DBIT) { if (chr.bearer == ChargeBearer.DEBT) { if (chr.amount > amount) { // This can happen when an incoming transaction fail because of debit fee amount = chr.amount - amount } else { amount -= chr.amount } } else if (chr.bearer == ChargeBearer.CRED) { amount += chr.amount } else { throw Error("Included charge ${chr.kind} with bearer ${chr.bearer}") } } } } return ComplexAmount(amount, fee) } /** Parse bank transaction code */ private fun XmlDestructor.bankTransactionCode(): BankTransactionCode { return one("BkTxCd").one("Domn") { val domain = one("Cd").enum() one("Fmly") { val family = one("Cd").enum() val subFamily = one("SubFmlyCd").enum() BankTransactionCode(domain, family, subFamily) } } } /** Parse optional bank transaction code */ private fun XmlDestructor.optBankTransactionCode(): BankTransactionCode? { return opt("BkTxCd")?.one("Domn") { val domain = one("Cd").enum() one("Fmly") { val family = one("Cd").enum() val subFamily = one("SubFmlyCd").enum() BankTransactionCode(domain, family, subFamily) } } } /** Parse transaction wire transfer subject */ private fun XmlDestructor.wireTransferSubject(): String? = opt("RmtInf") { map("Ustrd") { text() }.joinToString("").trim() } /** Parse account information */ private fun XmlDestructor.account(): Pair = one("Acct") { Pair( one("Id") { (opt("IBAN") ?: one("Othr").one("Id")).text() }, opt("Ccy")?.text() ) } private data class ChargeRecord( val amount: TalerAmount, val kind: Kind, val included: Boolean, val bearer: ChargeBearer ) private fun XmlDestructor.charges(): List = opt("Chrgs")?.map("Rcrd") { val amount = amount() val kind = opt("CdtDbtInd")?.enum() ?: Kind.CRDT val included = opt("ChrgInclInd")?.bool() ?: true // TODO not clear in spec val bearer = opt("Br")?.enum() ?: ChargeBearer.SHAR ChargeRecord(amount, kind, included, bearer) } ?: emptyList() data class AccountTransactions( val iban: String?, val currency: String?, val txs: List ) { companion object { internal fun fromParts(iban: String?, currency: String?, txsInfos: List): AccountTransactions { val txs = txsInfos.mapNotNull { try { it.parse() } catch (e: IncompleteTx) { // TODO: add more info in doc or in log message? logger.warn("skip incomplete tx: ${e.msg}") null } } return AccountTransactions(iban, currency, txs) } } } /** Parse camt.054 or camt.053 file */ fun parseTx(notifXml: InputStream): List { /* In ISO 20022 specifications, most fields are optional and the same information can be written several times in different places. For libeufin, we're only interested in a subset of the available values that can be found in both camt.052, camt.053 and camt.054. This function should not fail on legitimate files and should simply warn when available information are insufficient. EBICS and ISO20022 do not provide a perfect transaction identifier. The best is the UETR (unique end-to-end transaction reference), which is a universally unique identifier (UUID). However, it is not supplied by all banks. TxId (TransactionIdentification) is a unique identification as assigned by the first instructing agent. As its format is ambiguous, its uniqueness is not guaranteed by the standard, and it is only supposed to be unique for a “pre-agreed period”, whatever that means. These two identifiers are optional in the standard, but have the advantage of being unique and can be used to track a transaction between banks so we use them when available. It is also possible to use AccountServicerReference, which is a unique reference assigned by the account servicing institution. They can be present at several levels (batch level, transaction level, etc.) and are often optional. They also have the disadvantage of being known only by the account servicing institution. They should therefore only be used as a last resort. */ logger.trace("Parse transactions camt file") val accountTxs = mutableListOf() /** Common parsing logic for camt.052, camt.053 and camt.054 */ fun XmlDestructor.parseInner() { val (iban, currency) = account() val txInfos = mutableListOf() val batches = each("Ntry") { if (!isBooked()) return@each val entryCode = bankTransactionCode() val reversal = opt("RvslInd")?.text() == "true" val entryKind = opt("CdtDbtInd")?.enum(); val entryRef = opt("AcctSvcrRef")?.text() val bookDate = executionDate() val entryCharges = charges() val entryAmount = complexAmount(entryCharges)!! // When an entry only contain a single transactions information will sometimes only be stored at the entry level val tmp = opt("NtryDtls")?.map("TxDtls") { this } ?: return@each val unique = tmp.size == 1 for (it in tmp) {it.run { // Check information are present and coherent val kind = requireNotNull(opt("CdtDbtInd")?.enum() ?: entryKind) { "WTF" } // Sometimes the transaction level have a more precise bank transaction code val code = optBankTransactionCode() ?: entryCode // Amount val amount = if (unique) { // When unique the charges can be only at the entry level val txCharges = charges() val txAmount = complexAmount(if (txCharges.isEmpty()) entryCharges else txCharges) // Check coherence if (txAmount != null) entryAmount.resolve(txAmount) else entryAmount } else { // When many inner transaction the entry level is an aggregate of them // We only use the transaction level information requireNotNull(complexAmount(charges())) { "Missing tx amount" } } // We can only use the entry ref as the transaction ref if there is a single transaction in the batch val ref = opt("Refs")?.opt("AcctSvcrRef")?.text() ?: if (unique) entryRef else null if (code.isReversal() || reversal) { val outgoingId = outgoingId(ref) when (kind) { Kind.CRDT -> { val reason = returnReason() txInfos.add(TxInfo.CreditReversal( bookDate = bookDate, id = outgoingId, reason = reason, code = code )) } Kind.DBIT -> { val id = incomingId(ref) val subject = wireTransferSubject() val debtor = payto("Dbtr") val fee = amount.fee() txInfos.add(TxInfo.Credit( bookDate = bookDate, id = id, amount = amount.amount, subject = subject, debtor = debtor, code = code, creditFee = fee )) } } } else { val subject = wireTransferSubject() when (kind) { Kind.CRDT -> { val id = incomingId(ref) val debtor = payto("Dbtr") txInfos.add(TxInfo.Credit( bookDate = bookDate, id = id, amount = amount.amount, subject = subject, debtor = debtor, code = code, creditFee = amount.fee() )) } Kind.DBIT -> { val outgoingId = outgoingId(ref) val creditor = payto("Cdtr") txInfos.add(TxInfo.Debit( bookDate = bookDate, id = outgoingId, amount = amount.amount, subject = subject, creditor = creditor, code = code, debitFee = amount.fee() )) } } } }} } accountTxs.add(AccountTransactions.fromParts(iban, currency, txInfos)) } XmlDestructor.parse(notifXml, "Document") { // Camt.053 opt("BkToCstmrStmt")?.each("Stmt") { parseInner() } // Camt.052 opt("BkToCstmrAcctRpt")?.each("Rpt") { parseInner() } // Camt.054 opt("BkToCstmrDbtCdtNtfctn")?.each("Ntfctn") { parseInner() } } return accountTxs } sealed interface TxInfo { data class CreditReversal( val bookDate: Instant, val code: BankTransactionCode, val id: OutId, val reason: String ): TxInfo data class Credit( val bookDate: Instant, val code: BankTransactionCode, val id: IncomingId, val amount: TalerAmount, val creditFee: TalerAmount?, val subject: String?, val debtor: IbanPayto? ): TxInfo data class Debit( val bookDate: Instant, val code: BankTransactionCode, val id: OutId, val amount: TalerAmount, val debitFee: TalerAmount?, val subject: String?, val creditor: IbanPayto? ): TxInfo fun parse(): TxNotification { return when (this) { is TxInfo.CreditReversal -> { if (id !is OutgoingId || id.endToEndId == null) throw IncompleteTx("missing unique ID for Credit reversal $id") OutgoingReversal( endToEndId = id.endToEndId!!, msgId = id.msgId, reason = reason, executionTime = bookDate ) } is TxInfo.Credit -> { if (id.uetr == null && id.txId == null && id.acctSvcrRef == null) throw IncompleteTx("missing unique ID for Credit $id") IncomingPayment( amount = amount, creditFee = creditFee, id = id, debtor = debtor, executionTime = bookDate, subject = subject, ) } is TxInfo.Debit -> { when (id) { is OutgoingId -> { if (id.endToEndId == null && id.msgId == null && id.acctSvcrRef == null) { throw IncompleteTx("missing unique ID for Debit $id") } else { OutgoingPayment( id = OutgoingId( endToEndId = id.endToEndId, acctSvcrRef = id.acctSvcrRef, msgId = id.msgId, ), amount = amount, debitFee = debitFee, executionTime = bookDate, creditor = creditor, subject = subject ) } } is BatchId -> { OutgoingBatch( msgId = id.msgId, executionTime = bookDate, ) } } } } } } data class BankTransactionCode( val domain: ExternalBankTransactionDomainCode, val family: ExternalBankTransactionFamilyCode, val subFamily: ExternalBankTransactionSubFamilyCode ) { fun isReversal(): Boolean = REVERSAL_CODE.contains(subFamily) fun isPayment(): Boolean = domain == ExternalBankTransactionDomainCode.PMNT || subFamily == ExternalBankTransactionSubFamilyCode.PSTE override fun toString(): String = "${domain.name} ${family.name} ${subFamily.name} - '${domain.description}' '${family.description}' '${subFamily.description}'" companion object { private val REVERSAL_CODE = setOf( ExternalBankTransactionSubFamilyCode.RPCR, ExternalBankTransactionSubFamilyCode.RRTN, ExternalBankTransactionSubFamilyCode.PSTE, ) } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/Constants.kt0000664000175000017500000000315415122266731031101 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.iso20022 enum class HacAction(val description: String) { FILE_UPLOAD("File submitted to the bank"), FILE_DOWNLOAD("File downloaded from the bank"), ES_UPLOAD("Electronic signature submitted to the bank"), ES_DOWNLOAD("Electronic signature downloaded from the bank"), ES_VERIFICATION("Signature verification"), VEU_FORWARDING("Forwarding to EDS"), VEU_VERIFICATION("EDS signature verification"), VEU_VERIFICATION_END("VEU_VERIFICATION_END"), VEU_CANCEL_ORDER("Cancellation of EDS order"), ADDITIONAL("Additional information"), ORDER_HAC_FINAL_POS("HAC end of order (positive)"), ORDER_HAC_FINAL_NEG("HAC end of order (negative)"), // Not in the spec but Credit Suisse test suite use it ORDER_HAC_FINAL("HAC end of order") } enum class ChargeBearer(val description: String) { DEBT("BorneByDebtor"), CRED("BorneByCreditor"), SHAR("Shared"), SLEV("SLEV") }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/BankTransactionCode.kt0000664000175000017500000003023115122266731032775 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ // THIS FILE IS GENERATED, DO NOT EDIT package tech.libeufin.nexus.iso20022 enum class ExternalBankTransactionDomainCode(val description: String) { ACMT("Account Management"), CAMT("Cash Management"), CMDT("Commodities"), DERV("Derivatives"), FORX("Foreign Exchange"), LDAS("Loans, Deposits & Syndications"), PMET("Precious Metal"), PMNT("Payments"), SECU("Securities"), TRAD("Trade Services"), XTND("Extended Domain"), } enum class ExternalBankTransactionFamilyCode(val description: String) { ACCB("Account Balancing"), ACOP("Additional Miscellaneous Credit Operations"), ADOP("Additional Miscellaneous Debit Operations"), BLOC("Blocked Transactions"), CAPL("Cash Pooling"), CASH("Miscellaneous Securities Operations"), CCRD("Customer Card Transactions"), CLNC("Clean Collection"), CNTR("Counter Transactions"), COLC("Custody Collection"), COLL("Collateral Management"), CORP("Corporate Action"), CSLN("Consumer Loans"), CUST("Custody"), DCCT("Documentary Credit"), DLVR("Delivery"), DOCC("Documentary Collection"), DRFT("Drafts"), FTDP("Fixed Term Deposits"), FTLN("Fixed Term Loans"), FTUR("Futures"), FWRD("Forwards"), GUAR("Guarantees"), ICCN("Issued Cash Concentration Transactions"), ICDT("Issued Credit Transfers"), ICHQ("Issued Cheques"), IDDT("Issued Direct Debits"), IRCT("Issued Real-Time Credit Transfers"), LACK("Lack"), LBOX("Lockbox Transactions"), LFUT("Listed Derivatives - Futures"), LOCT("Stand-By Letter Of Credit"), LOPT("Listed Derivatives - Options"), MCOP("Miscellaneous Credit Operations"), MCRD("Merchant Card Transactions"), MDOP("Miscellaneous Debit Operations"), MGLN("Mortgage Loans"), NDFX("Non Deliverable"), NSET("Non Settled"), NTAV("Not Available"), NTDP("Notice Deposits"), NTLN("Notice Loans"), OBND("OTC Derivatives - Bonds"), OCRD("OTC Derivatives - Credit"), OEQT("OTC Derivatives - Equity"), OIRT("OTC Derivatives - Interest Rates"), OPCL("Opening & Closing"), OPTN("Options"), OSED("OTC Derivatives - Structured Exotic Derivatives"), OSWP("OTC Derivatives – Swaps"), OTHB("CSD Blocked transactions"), OTHR("Other"), RCCN("Received Cash Concentration Transactions"), RCDT("Received Credit Transfers"), RCHQ("Received Cheques"), RDDT("Received Direct Debits"), RRCT("Received Real-Time Credit Transfers"), SETT("Trade, Clearing and Settlement"), SPOT("Spots"), SWAP("Swaps"), SYDN("Syndications"), } enum class ExternalBankTransactionSubFamilyCode(val description: String) { ACCC("Account Closing"), ACCO("Account Opening"), ACCT("Account Transfer"), ACDT("ACH Credit"), ACOR("ACH Corporate Trade"), ADBT("ACH Debit"), ADJT("Adjustments (Generic)"), APAC("ACH Pre-Authorised"), ARET("ACH Return"), AREV("ACH Reversal"), ARPD("ARP Debit"), ASET("ACH Settlement"), ATXN("ACH Transaction"), AUTT("Automatic Transfer"), BBDD("SEPA B2B Direct Debit"), BCDP("Branch Deposit"), BCHQ("Bank Cheque"), BCKV("Back Value"), BCWD("Branch Withdrawl"), BFWD("Bond Forward"), BIDS("Repurchase Offer/Issuer Bid/Reverse Rights."), BKFE("Bank Fees"), BONU("Bonus Issue/Capitalisation Issue"), BOOK("Internal Book Transfer"), BPUT("Put Redemption"), BROK("Brokerage Fee"), BSBC("Sell Buy Back"), BSBO("Buy Sell Back"), CAJT("Credit Adjustments (Generic)"), CAPG("Capital Gains Distribution"), CASH("Cash Letter"), CCCH("Certified Customer Cheque"), CCHQ("Cheque"), CCIR("Cross Currency IRS"), CCPC("CCP Cleared Initial Margin"), CCPM("CCP Cleared Variation Margin"), CCSM("CCP Cleared Segregated Initial Margin"), CDIS("Controlled Disbursement"), CDPT("Cash Deposit"), CHAR("Charge/Fees"), CHKD("Check Deposit"), CHRG("Charges (Generic)"), CLAI("Compensation/Claims"), CLCQ("Circular Cheque"), CMBO("Corporate Mark Broker Owned"), CMCO("Corporate Mark Client Owned"), COME("Commission Excluding Taxes (Generic)"), COMI("Commission Including Taxes (Generic)"), COMM("Commission (Generic)"), COMT("Non Taxable Commissions (Generic)"), CONV("Conversion"), COVE("Cover Transaction"), CPEN("Cash Penalties"), CPRB("Corporate Rebate"), CQRV("Cheque Reversal"), CRCQ("Crossed Cheque"), CRDS("Credit DefaultSwap"), CROS("Cross Trade"), CRPR("Cross Product"), CRSP("Credit Support"), CRTL("Credit Line"), CSHA("Cash Letter Adjustment"), CSLI("Cash In Lieu"), CWDL("Cash Withdrawal"), DAJT("Debit Adjustments (Generic)"), DDFT("Discounted Draft"), DDWN("Drawdown"), DECR("Decrease in Value"), DMCG("Draft Maturity Change"), DMCT("Domestic Credit Transfer"), DPST("Deposit"), DRAW("Drawing"), DRIP("Dividend Reinvestment"), DSBR("Controlled Disbursement"), DTCH("Dutch Auction"), DVCA("Cash Dividend"), DVOP("Dividend Option"), ENCT("Nordic Payment Council Credit Transfer"), EQBO("Equity Mark Broker Owned"), EQCO("Equity Mark Client Owned"), EQPT("Equity Option"), EQUS("Equity Swap"), ERTA("Exchange Rate Adjustment"), ERWA("Lending Income"), ERWI("Borrowing Fee"), ESCT("SEPA Credit Transfer"), ESDD("SEPA Core Direct Debit"), EXOF("Exchange"), EXPT("Exotic Option"), EXRI("Call On Intermediate Securities"), EXTD("Exchange Traded Derivatives"), EXWA("Warrant Exercise/Warrant Conversion"), FCDP("Foreign Currencies Deposit"), FCTA("Factor Update"), FCWD("Foreign Currencies Withdrawal"), FEES("Fees (Generic)"), FICT("Financial Institution Credit Transfer"), FIDD("Financial Institution Direct Debit Payment"), FIOA("Financial Institution Own Account Transfer"), FIXI("Fixed Income"), FLTA("Float Adjustment"), FRZF("Freeze Of Funds"), FUCO("Futures Commission"), FUTU("Future Variation Margin"), FWBC("Forwards Broker Owned Collateral"), FWCC("Forwards Client Owned Collateral"), FWSB("MFA Segregated Broker Cash Collateral"), FWSC("MFA Segregated Client Cash Collateral"), GEN1("Withdrawal/Distribution"), GEN2("Deposit/Contribution"), IADD("Invoice Accepted with Differed Due Date"), INFD("Fixed Deposit Interest Amount"), INSP("Inspeci/Share Exchange"), INTR("Interest Payment"), ISSU("Depositary Receipt Issue"), LBCA("Credit Adjustment"), LBDP("Deposit"), LIQU("Liquidation Dividend / Liquidation Payment"), MARG("Margin Payments"), MBSB("Mortgage Back Segregated Broker Cash Collateral"), MBSC("Mortgage Back Segregated Client Cash Collateral"), MCAL("Full Call / Early Redemption"), MGCC("Margin Client Owned Cash Collateral"), MGSC("Initial Futures Margin Segregated Client Cash Collateral"), MIXD("Mixed Deposit"), MNFE("Management Fees"), MRGR("Merger"), MSCD("Miscellaneous Deposit"), NETT("Netting"), NPCC("Non Presented Circular Cheques"), NSYN("Non Syndicated"), NTAV("Not Available"), NWID("New issue distribution"), OCCC("Client owned OCC pledged collateral"), ODFT("Overdraft"), ODLT("Odd Lot Sale/Purchase"), OODD("One-Off Direct Debit"), OPBC("Option Broker Owned Collateral"), OPCC("Option Client Owned Collateral"), OPCQ("Open Cheque"), OPSB("OTC Option Segregated Broker Cash Collateral"), OPSC("OTC Option Segregated Client Cash Collateral"), OPTN("FX Option"), ORCQ("Order Cheque"), OTCC("OTC CCP"), OTCD("OTC Derivatives"), OTCG("OTC"), OTCN("OTC Non-CCP"), OTHR("Other"), OVCH("Overdraft Charge"), OWNE("External Account Transfer"), OWNI("Internal Account Transfer"), PADD("Pre-Authorised Direct Debit"), PAIR("Pair-Off"), PCAL("Partial Redemption With Reduction Of Nominal Value"), PLAC("Placement"), PMDD("Direct Debit"), PORT("Portfolio Move"), POSC("Credit Card Payment"), POSD("Point-of-Sale (POS) Payment - Debit Card"), PPAY("Principal Payment"), PRCT("Priority Credit Transfer"), PRDD("Reversal Due To Payment Reversal"), PRED("Partial Redemption Without Reduction Of Nominal Value"), PRII("Interest Payment with Principles"), PRIN("Interest Payment with Principles"), PRIO("Priority Issue"), PRUD("Principal Pay-Down/Pay-Up"), PSTE("Posting Error"), RCDD("Reversal Due To Payment Cancellation Request"), RCOV("Reversal due to a Cover Transaction Return"), REAA("Redemption Asset Allocation"), REDM("Final Maturity"), REPU("Repo"), RESI("Futures Residual Amount"), RHTS("Rights Issue/Subscription Rights/Rights Offer"), RIMB("Reimbursement (Generic)"), RNEW("Renewal"), RPBC("Bi-lateral repo broker owned collateral"), RPCC("Repo client owned collateral"), RPCR("Reversal Due To Payment Cancellation Request"), RPMT("Repayment"), RPSB("Bi-lateral Repo Segregated Broker Cash Collateral"), RPSC("Bi-lateral Repo Segregated Client Cash Collateral"), RRTN("Reversal Due To Payment Return"), RVPO("Reverse Repo"), RWPL("Redemption Withdrawing Plan"), SABG("Settlement Against Bank Guarantee"), SALA("Payroll/Salary Payment"), SBSC("Securities Buy Sell Sell Buy Back"), SCIE("Single Currency IRS Exotic"), SCIR("Single Currency IRS"), SCRP("Securities Cross Products"), SDVA("Same Day Value Credit Transfer"), SECB("Securities Borrowing"), SECL("Securities Lending"), SHBC("Broker owned collateral Short Sale"), SHCC("Client owned collateral Short Sale"), SHPR("Equity Premium Reserve"), SHSL("Short Sell"), SLBC("Lending Broker Owned Cash Collateral"), SLCC("Lending Client Owned Cash Collateral"), SLEB("Securities Lending And Borrowing"), SLOA("SecuredLoan"), SOSE("Settlement Of Sight Export Document"), SOSI("Settlement Of Sight Import Document"), SSPL("Subscription Savings Plan"), STAC("Settlement After Collection"), STAM("Settlement At Maturity"), STDO("Standing Order"), STLM("Settlement"), STLR("Settlement Under Reserve"), STOD("Bill of Exchange Settlement on Demand"), SUAA("Subscription Asset Allocation"), SUBS("Subscription"), SWAP("Swap Payment"), SWBC("Swap Broker Owned Collateral"), SWCC("Client Owned Collateral"), SWEP("Sweep"), SWFP("Final Payment"), SWIC("Switch"), SWPP("Partial Payment"), SWPT("Swaption"), SWRS("Reset Payment"), SWSB("ISDA/CSA Segregated Broker Cash Collateral"), SWSC("ISDA/CSA Segregated Client Cash Collateral"), SWUF("Upfront Payment"), SYND("Syndicated"), TAXE("Taxes (Generic)"), TBAC("TBA Closing"), TBAS("To Be Announced"), TBBC("TBA Broker owned cash collateral"), TBCC("TBA Client owned cash collateral"), TCDP("Travellers Cheques Deposit"), TCWD("Travellers Cheques Withdrawal"), TEND("Tender"), TOPG("Topping"), TOUT("Transfer Out"), TRAD("Trade"), TRCP("Treasury Cross Product"), TREC("Tax Reclaim"), TRFE("Transaction Fees"), TRIN("Transfer In"), TRPO("Triparty Repo"), TRVO("Triparty Reverse Repo"), TTLS("Treasury Tax And Loan Service"), TURN("Turnaround"), UDFT("Dishonoured/Unpaid Draft"), UNCO("Underwriting Commission"), UPCQ("Unpaid Cheque"), UPCT("Unpaid Card Transaction"), UPDD("Reversal Due To Return/Unpaid Direct Debit"), URCQ("Cheque Under Reserve"), URDD("Direct Debit Under Reserve"), VALD("Value Date"), VCOM("Credit Transfer With Agreed Commercial Information"), WITH("Withholding Tax"), XBCP("Cross-Border Credit Card Payment"), XBCQ("Foreign Cheque"), XBCT("Cross-Border Credit Transfer"), XBCW("Cross-Border Cash Withdrawal"), XBRD("Cross-Border"), XBSA("Cross-Border Payroll/Salary Payment"), XBST("Cross-Border Standing Order"), XCHC("Exchange Traded CCP"), XCHG("Exchange Traded"), XCHN("Exchange Traded Non-CCP"), XICT("Cross-Border Intra Company Transfer"), XPCQ("Unpaid Foreign Cheque"), XRCQ("Foreign Cheque Under Reserve"), XRTN("Cross Border Reversal Due to Payment Return"), YTDA("YTD Adjustment"), ZABA("Zero Balancing"), ACON("ACH Concentration"), BACT("Branch Account Transfer"), COAT("Corporate Own Account Transfer"), ICCT("Intra Company Transfer"), LBDB("Debit"), POSP("Point-of-Sale (POS) Payment"), SMCD("Smart-Card Payment"), SMRT("Smart-Card Payment"), XBDD("Cross-Border Direct Debit"), } libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/ExternalCodeSets.kt0000664000175000017500000013503315122266731032343 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ // THIS FILE IS GENERATED, DO NOT EDIT package tech.libeufin.nexus.iso20022 enum class ExternalStatusReasonCode(val isoCode: String, val description: String) { AB01("AbortedClearingTimeout", "Clearing process aborted due to timeout."), AB02("AbortedClearingFatalError", "Clearing process aborted due to a fatal error."), AB03("AbortedSettlementTimeout", "Settlement aborted due to timeout."), AB04("AbortedSettlementFatalError", "Settlement process aborted due to a fatal error."), AB05("TimeoutCreditorAgent", "Transaction stopped due to timeout at the Creditor Agent."), AB06("TimeoutInstructedAgent", "Transaction stopped due to timeout at the Instructed Agent."), AB07("OfflineAgent", "Agent of message is not online."), AB08("OfflineCreditorAgent", "Creditor Agent is not online."), AB09("ErrorCreditorAgent", "Transaction stopped due to error at the Creditor Agent."), AB10("ErrorInstructedAgent", "Transaction stopped due to error at the Instructed Agent."), AB11("TimeoutDebtorAgent", "Transaction stopped due to timeout at the Debtor Agent."), AB12("InvalidConcurrentBatch", "Duplicate Concurrent Batch Sequence number– for Settlement Instructions."), AB13("InvalidRoutingCodeUtilised", "Wrong Message Routing Type for Return-of-Funds."), AB15("InvalidAccountNumberForSettlementType", "Instruction may not be placed on the Continuous Processing Line settlement processor."), AB21("InvalidSettlementAgreementNumberSpecified", "Agreement number not valid (beneficiary)."), AB26("InvalidBatchSettlementInstruction", "Settlement Instruction does not exist."), AC01("IncorrectAccountNumber", "Account number is invalid or missing."), AC02("InvalidDebtorAccountNumber", "Debtor account number invalid or missing"), AC03("InvalidCreditorAccountNumber", "Creditor account number invalid or missing"), AC04("ClosedAccountNumber", "Account number specified has been closed on the bank of account's books."), AC05("ClosedDebtorAccountNumber", "Debtor account number closed"), AC06("BlockedAccount", "Account specified is blocked, prohibiting posting of transactions against it."), AC07("ClosedCreditorAccountNumber", "Creditor account number closed"), AC08("InvalidBranchCode", "Branch code is invalid or missing"), AC09("InvalidAccountCurrency", "Account currency is invalid or missing"), AC10("InvalidDebtorAccountCurrency", "Debtor account currency is invalid or missing"), AC11("InvalidCreditorAccountCurrency", "Creditor account currency is invalid or missing"), AC12("InvalidAccountType", "Account type missing or invalid."), AC13("InvalidDebtorAccountType", "Debtor account type missing or invalid"), AC14("InvalidCreditorAccountType", "Creditor account type missing or invalid"), AC15("AccountDetailsChanged", "The account details for the counterparty have changed."), AC16("CardNumberInvalid", "Credit or debit card number is invalid."), AEXR("AlreadyExpiredRTP", "Request-to-pay Expiry Date and Time has already passed."), AG01("TransactionForbidden", "Transaction forbidden on this type of account (formerly NoAgreement)"), AG02("InvalidBankOperationCode", "Bank Operation code specified in the message is not valid for receiver"), AG03("TransactionNotSupported", "Transaction type not supported/authorized on this account"), AG04("InvalidAgentCountry", "Agent country code is missing or invalid."), AG05("InvalidDebtorAgentCountry", "Debtor agent country code is missing or invalid"), AG06("InvalidCreditorAgentCountry", "Creditor agent country code is missing or invalid"), AG07("UnsuccesfulDirectDebit", "Debtor account cannot be debited for a generic reason."), AG08("InvalidAccessRights", "Transaction failed due to invalid or missing user or access right"), AG09("PaymentNotReceived", "Original payment never received."), AG10("AgentSuspended", "Agent of message is suspended from the Real Time Payment system."), AG11("CreditorAgentSuspended", "Creditor Agent of message is suspended from the Real Time Payment system."), AG12("NotAllowedBookTransfer", "Payment orders made by transferring funds from one account to another at the same financial institution (bank or payment institution) are not allowed."), AG13("ForbiddenReturnPayment", "Returned payments derived from previously returned transactions are not allowed."), AGNT("IncorrectAgent", "Agent in the payment workflow is incorrect"), ALAC("AlreadyAcceptedRTP", "Request-to-pay has already been accepted by the Debtor."), AM01("ZeroAmount", "Specified message amount is equal to zero"), AM02("NotAllowedAmount", "Specific transaction/message amount is greater than allowed maximum"), AM03("NotAllowedCurrency", "Specified message amount is an non processable currency outside of existing agreement"), AM04("InsufficientFunds", "Amount of funds available to cover specified message amount is insufficient."), AM05("Duplication", "Duplication"), AM06("TooLowAmount", "Specified transaction amount is less than agreed minimum."), AM07("BlockedAmount", "Amount specified in message has been blocked by regulatory authorities."), AM09("WrongAmount", "Amount received is not the amount agreed or expected"), AM10("InvalidControlSum", "Sum of instructed amounts does not equal the control sum."), AM11("InvalidTransactionCurrency", "Transaction currency is invalid or missing"), AM12("InvalidAmount", "Amount is invalid or missing"), AM13("AmountExceedsClearingSystemLimit", "Transaction amount exceeds limits set by clearing system"), AM14("AmountExceedsAgreedLimit", "Transaction amount exceeds limits agreed between bank and client"), AM15("AmountBelowClearingSystemMinimum", "Transaction amount below minimum set by clearing system"), AM16("InvalidGroupControlSum", "Control Sum at the Group level is invalid"), AM17("InvalidPaymentInfoControlSum", "Control Sum at the Payment Information level is invalid"), AM18("InvalidNumberOfTransactions", "Number of transactions is invalid or missing."), AM19("InvalidGroupNumberOfTransactions", "Number of transactions at the Group level is invalid or missing"), AM20("InvalidPaymentInfoNumberOfTransactions", "Number of transactions at the Payment Information level is invalid"), AM21("LimitExceeded", "Transaction amount exceeds limits agreed between bank and client."), AM22("ZeroAmountNotApplied", "Unable to apply zero amount to designated account. For example, where the rules of a service allow the use of zero amount payments, however the back-office system is unable to apply the funds to the account. If the rules of a service prohibit the use of zero amount payments, then code AM01 is used to report the error condition."), AM23("AmountExceedsSettlementLimit", "Transaction amount exceeds settlement limit."), AMSE("AttachmentMaximumSize", "Size of the attachment exceeds the allowed maximum."), APAR("AlreadyPaidRTP", "Request To Pay has already been paid by the Debtor."), ARFR("AlreadyRefusedRTP", "Request-to-pay has already been refused by the Debtor."), ARJR("AlreadyRejectedRTP", "Request-to-pay has already been rejected."), ATNS("AttachementsNotSupported", "Attachments to the request-to-pay are not supported."), BDAY("NotBusinessDay", "Settlement Cycle Day and Calendar day should be the same."), BE01("InconsistenWithEndCustomer", "Identification of end customer is not consistent with associated account number. (formerly CreditorConsistency)."), BE04("MissingCreditorAddress", "Specification of creditor's address, which is required for payment, is missing/not correct (formerly IncorrectCreditorAddress)."), BE05("UnrecognisedInitiatingParty", "Party who initiated the message is not recognised by the end customer"), BE06("UnknownEndCustomer", "End customer specified is not known at associated Sort/National Bank Code or does no longer exist in the books"), BE07("MissingDebtorAddress", "Specification of debtor's address, which is required for payment, is missing/not correct."), BE08("MissingDebtorName", "Debtor name is missing"), BE09("InvalidCountry", "Country code is missing or Invalid."), BE10("InvalidDebtorCountry", "Debtor country code is missing or invalid"), BE11("InvalidCreditorCountry", "Creditor country code is missing or invalid"), BE12("InvalidCountryOfResidence", "Country code of residence is missing or Invalid."), BE13("InvalidDebtorCountryOfResidence", "Country code of debtor's residence is missing or Invalid"), BE14("InvalidCreditorCountryOfResidence", "Country code of creditor's residence is missing or Invalid"), BE15("InvalidIdentificationCode", "Identification code missing or invalid."), BE16("InvalidDebtorIdentificationCode", "Debtor or Ultimate Debtor identification code missing or invalid"), BE17("InvalidCreditorIdentificationCode", "Creditor or Ultimate Creditor identification code missing or invalid"), BE18("InvalidContactDetails", "Contact details missing or invalid"), BE19("InvalidChargeBearerCode", "Charge bearer code for transaction type is invalid"), BE20("InvalidNameLength", "Name length exceeds local rules for payment type."), BE21("MissingName", "Name missing or invalid. Generic usage if cannot specifically identify debtor or creditor."), BE22("MissingCreditorName", "Creditor name is missing"), BE23("AccountProxyInvalid", "Phone number or email address, or any other proxy, used as the account proxy is unknown or invalid."), CERI("CheckERI", "Credit transfer is not tagged as an Extended Remittance Information (ERI) transaction but contains ERI."), CH03("RequestedExecutionDateOrRequestedCollectionDateTooFarInFuture", "Value in Requested Execution Date or Requested Collection Date is too far in the future"), CH04("RequestedExecutionDateOrRequestedCollectionDateTooFarInPast", "Value in Requested Execution Date or Requested Collection Date is too far in the past"), CH07("ElementIsNotToBeUsedAtB-andC-Level", "Element is not to be used at B- and C-Level"), CH09("MandateChangesNotAllowed", "Mandate changes are not allowed"), CH10("InformationOnMandateChangesMissing", "Information on mandate changes are missing"), CH11("CreditorIdentifierIncorrect", "Value in Creditor Identifier is incorrect"), CH12("CreditorIdentifierNotUnambiguouslyAtTransaction-Level", "Creditor Identifier is ambiguous at Transaction Level"), CH13("OriginalDebtorAccountIsNotToBeUsed", "Original Debtor Account is not to be used"), CH14("OriginalDebtorAgentIsNotToBeUsed", "Original Debtor Agent is not to be used"), CH15("ElementContentIncludesMoreThan140Characters", "Content Remittance Information/Structured includes more than 140 characters"), CH16("ElementContentFormallyIncorrect", "Content is incorrect"), CH17("ElementNotAdmitted", "Element is not allowed"), CH19("ValuesWillBeSetToNextTARGETday", "Values in Interbank Settlement Date or Requested Collection Date will be set to the next TARGET day"), CH20("DecimalPointsNotCompatibleWithCurrency", "Number of decimal points not compatible with the currency"), CH21("RequiredCompulsoryElementMissing", "Mandatory element is missing"), CH22("COREandB2BwithinOnemessage", "SDD CORE and B2B not permitted within one message"), CHCO("UnacceptedChargeCodeType", "Related to a Charge message to convey that the code in Charge Breakdown / Type / Code is not accepted by the receiving party."), CHQC("ChequeSettledOnCreditorAccount", "Cheque has been presented in cheque clearing and settled on the creditor’s account."), CHRG("UnderlyingChargeBearerWasNotDebt", "Related to a Charge message to convey that the charge bearer code used in the corresponding Payment message was not debt."), CN01("AuthorisationCancelled", "Authorisation is cancelled."), CNNS("CreditNotesNotSupported", "Credit notes are not supported."), CNOR("CreditorBankIsNotRegistered", "Creditor bank is not registered under this BIC in the CSM"), CURR("IncorrectCurrency", "Currency of the payment is incorrect"), CUST("RequestedByCustomer", "Cancellation requested by the Debtor"), DC02("SettlementNotReceived", "Rejection of a payment due to covering FI settlement not being received."), DNOR("DebtorBankIsNotRegistered", "Debtor bank is not registered under this BIC in the CSM"), DS01("ElectronicSignaturesCorrect", "The electronic signature(s) is/are correct"), DS02("OrderCancelled", "An authorized user has cancelled the order"), DS03("OrderNotCancelled", "The user’s attempt to cancel the order was not successful"), DS04("OrderRejected", "The order was rejected by the bank side (for reasons concerning content)"), DS05("OrderForwardedForPostprocessing", "The order was correct and could be forwarded for postprocessing"), DS06("TransferOrder", "The order was transferred to VEU"), DS07("ProcessingOK", "All actions concerning the order could be done by the EBICS bank server"), DS08("DecompressionError", "The decompression of the file was not successful"), DS09("DecryptionError", "The decryption of the file was not successful"), DS0A("DataSignRequested", "Data signature is required."), DS0B("UnknownDataSignFormat", "Data signature for the format is not available or invalid."), DS0C("SignerCertificateRevoked", "The signer certificate is revoked."), DS0D("SignerCertificateNotValid", "The signer certificate is not valid (revoked or not active)."), DS0E("IncorrectSignerCertificate", "The signer certificate is not present."), DS0F("SignerCertificationAuthoritySignerNotValid", "The authority of the signer certification sending the certificate is unknown."), DS0G("NotAllowedPayment", "Signer is not allowed to sign this operation type."), DS0H("NotAllowedAccount", "Signer is not allowed to sign for this account."), DS0K("NotAllowedNumberOfTransaction", "The number of transaction is over the number allowed for this signer."), DS10("Signer1CertificateRevoked", "The certificate is revoked for the first signer."), DS11("Signer1CertificateNotValid", "The certificate is not valid (revoked or not active) for the first signer."), DS12("IncorrectSigner1Certificate", "The certificate is not present for the first signer."), DS13("SignerCertificationAuthoritySigner1NotValid", "The authority of signer certification sending the certificate is unknown for the first signer."), DS14("UserDoesNotExist", "The user is unknown on the server"), DS15("IdenticalSignatureFound", "The same signature has already been sent to the bank"), DS16("PublicKeyVersionIncorrect", "The public key version is not correct. This code is returned when a customer sends signature files to the financial institution after conversion from an older program version (old ES format) to a new program version (new ES format) without having carried out re-initialisation with regard to a public key change."), DS17("DifferentOrderDataInSignatures", "Order data and signatures don’t match"), DS18("RepeatOrder", "File cannot be tested, the complete order has to be repeated. This code is returned in the event of a malfunction during the signature check, e.g. not enough storage space."), DS19("ElectronicSignatureRightsInsufficient", "The user’s rights (concerning his signature) are insufficient to execute the order"), DS20("Signer2CertificateRevoked", "The certificate is revoked for the second signer."), DS21("Signer2CertificateNotValid", "The certificate is not valid (revoked or not active) for the second signer."), DS22("IncorrectSigner2Certificate", "The certificate is not present for the second signer."), DS23("SignerCertificationAuthoritySigner2NotValid", "The authority of signer certification sending the certificate is unknown for the second signer."), DS24("WaitingTimeExpired", "Waiting time expired due to incomplete order"), DS25("OrderFileDeleted", "The order file was deleted by the bank server"), DS26("UserSignedMultipleTimes", "The same user has signed multiple times"), DS27("UserNotYetActivated", "The user is not yet activated (technically)"), DS28("ReturnForTechnicalReason", "Message routed to the wrong environment."), DT01("InvalidDate", "Invalid date (eg, wrong or missing settlement date)"), DT02("InvalidCreationDate", "Invalid creation date and time in Group Header (eg, historic date)"), DT03("InvalidNonProcessingDate", "Invalid non bank processing date (eg, weekend or local public holiday)"), DT04("FutureDateNotSupported", "Future date not supported"), DT05("InvalidCutOffDate", "Associated message, payment information block or transaction was received after agreed processing cut-off date, i.e., date in the past."), DT06("ExecutionDateChanged", "Execution Date has been modified in order for transaction to be processed"), DU01("DuplicateMessageID", "Message Identification is not unique."), DU02("DuplicatePaymentInformationID", "Payment Information Block is not unique."), DU03("DuplicateTransaction", "Transaction is not unique."), DU04("DuplicateEndToEndID", "End To End ID is not unique."), DU05("DuplicateInstructionID", "Instruction ID is not unique."), DUPL("DuplicatePaymentOrCharge", "Payment or charge is a duplicate of another payment or charge."), ED01("CorrespondentBankNotPossible", "Correspondent bank not possible."), ED03("BalanceInfoRequest", "Balance of payments complementary info is requested"), ED05("SettlementFailed", "Settlement of the transaction has failed."), ED06("SettlementSystemNotAvailable", "Interbank settlement system not available."), EDNA("ExecutionDateNotAccepted", "Requested execution date of the payment is not accepted."), EDTL("ExpiryDateTooLong", "Expiry date time of the request-to-pay is too far in the future."), EDTR("ExpiryDateTimeReached", "Expiry date time of the request-to-pay is already reached."), EOL1("EndOfLife", "Expiration of the payment authorisation due to no use for too long."), ERIN("ERIOptionNotSupported", "Extended Remittance Information (ERI) option is not supported."), FF01("InvalidFileFormat", "File Format incomplete or invalid"), FF02("SyntaxError", "Syntax error reason is provided as narrative information in the additional reason information."), FF03("InvalidPaymentTypeInformation", "Payment Type Information is missing or invalid."), FF04("InvalidServiceLevelCode", "Service Level code is missing or invalid"), FF05("InvalidLocalInstrumentCode", "Local Instrument code is missing or invalid"), FF06("InvalidCategoryPurposeCode", "Category Purpose code is missing or invalid"), FF07("InvalidPurpose", "Purpose is missing or invalid"), FF08("InvalidEndToEndId", "End to End Id missing or invalid"), FF09("InvalidChequeNumber", "Cheque number missing or invalid"), FF10("BankSystemProcessingError", "File or transaction cannot be processed due to technical issues at the bank side"), FF11("ClearingRequestAborted", "Clearing request rejected due it being subject to an abort operation."), FF12("OriginalTransactionNotEligibleForRequestedReturn", "Original payment is not eligible to be returned given its current status."), FF13("RequestForCancellationNotFound", "No record of request for cancellation found."), FOCR("FollowingCancellationRequest", "Return following a cancellation request."), FR01("Fraud", "Returned as a result of fraud."), FRAD("FraudulentOrigin", "Cancellation requested following a transaction that was originated fraudulently. The use of the FraudulentOrigin code should be governed by jurisdictions."), G000("PaymentTransferredAndTracked", "In an FI To FI Customer Credit Transfer: The Status Originator transferred the payment to the next Agent or to a Market Infrastructure. The payment transfer is tracked. No further updates will follow from the Status Originator."), G001("PaymentTransferredAndNotTracked", "In an FI To FI Customer Credit Transfer: The Status Originator transferred the payment to the next Agent or to a Market Infrastructure. The payment transfer is not tracked. No further updates will follow from the Status Originator."), G002("CreditDebitNotConfirmed", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account may not be confirmed same day. Update will follow from the Status Originator."), G003("CreditPendingDocuments", "In a FIToFI Customer Credit Transfer: Credit to creditor’s account is pending receipt of required documents. The Status Originator has requested creditor to provide additional documentation. Update will follow from the Status Originator."), G004("CreditPendingFunds", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account is pending, status Originator is waiting for funds provided via a cover. Update will follow from the Status Originator."), G005("DeliveredWithServiceLevel", "Payment has been delivered to creditor agent with service level."), G006("DeliveredWIthoutServiceLevel", "Payment has been delivered to creditor agent without service level."), ID01("CorrespondingOriginalFileStillNotSent", "Signature file was sent to the bank but the corresponding original file has not been sent yet."), IEDT("IncorrectExpiryDateTime", "Expiry date time of the request-to-pay is incorrect."), INAR("InvalidActivationReference", "Payer’s activation reference is invalid."), INDT("InvalidDetails", "Details not valid for this field."), IPNS("InstalmentPaymentsNotSupported", "Payments in instalments are not supported."), IRNR("InitialRTPNeverReceived", "No initial request-to-pay has been received."), ISWS("InvalidSettlementWindow", "Cannot schedule instruction for Night Window."), MD01("NoMandate", "No Mandate"), MD02("MissingMandatoryInformationInMandate", "Mandate related information data required by the scheme is missing."), MD05("CollectionNotDue", "Creditor or creditor's agent should not have collected the direct debit"), MD06("RefundRequestByEndCustomer", "Return of funds requested by end customer"), MD07("EndCustomerDeceased", "End customer is deceased."), MINF("MissingInformation", "Information missing for the field or cannot be empty."), MS02("NotSpecifiedReasonCustomerGenerated", "Reason has not been specified by end customer"), MS03("NotSpecifiedReasonAgentGenerated", "Reason has not been specified by agent."), NARR("Narrative", "Reason is provided as narrative information in the additional reason information."), NERI("NoERI", "Credit transfer is tagged as an Extended Remittance Information (ERI) transaction but does not contain ERI."), NOAR("NonAgreedRTP", "No existing agreement for receiving request-to-pay messages."), NOAS("NoAnswerFromCustomer", "No response from Beneficiary."), NOCM("NotCompliantGeneric", "Customer account is not compliant with regulatory requirements, for example FICA (in South Africa) or any other regulatory requirements which render an account inactive for certain processing."), NOFR("OutstandingFundingForSettlement", "Continuous Processing Line on Hold Instruction."), NOPG("NoPaymentGuarantee", "Requested payment guarantee (by Creditor) related to a request-to-pay cannot be provided."), NRCH("PayerOrPayerRTPSPNotReachable", "Recipient side of the request-to-pay (payer or its request-to-pay service provider) is not reachable."), OSNS("OptionalServiceNotSupported", "Requested optional service (for example instalment payments) is not supported."), PINS("TypeOfPaymentInstrumentNotSupported", "Type of payment requested in the request-to-pay is not supported by the payer."), RC01("BankIdentifierIncorrect", "Bank identifier code specified in the message has an incorrect format (formerly IncorrectFormatForRoutingCode)."), RC02("InvalidBankIdentifier", "Bank identifier is invalid or missing."), RC03("InvalidDebtorBankIdentifier", "Debtor bank identifier is invalid or missing"), RC04("InvalidCreditorBankIdentifier", "Creditor bank identifier is invalid or missing"), RC05("InvalidBICIdentifier", "BIC identifier is invalid or missing."), RC06("InvalidDebtorBICIdentifier", "Debtor BIC identifier is invalid or missing"), RC07("InvalidCreditorBICIdentifier", "Creditor BIC identifier is invalid or missing"), RC08("InvalidClearingSystemMemberIdentifier", "ClearingSystemMemberidentifier is invalid or missing."), RC09("InvalidDebtorClearingSystemMemberIdentifier", "Debtor ClearingSystemMember identifier is invalid or missing"), RC10("InvalidCreditorClearingSystemMemberIdentifier", "Creditor ClearingSystemMember identifier is invalid or missing"), RC11("InvalidIntermediaryAgent", "Intermediary Agent is invalid or missing"), RC12("MissingCreditorSchemeId", "Creditor Scheme Id is invalid or missing"), RC13("ParticipantNotAnActiveMemberofRTGS", "Originator not active any more."), RC15("ParticipantNotActiveMemberSettlementType", "Settlement agreement required."), RC16("ParticipantNotActiveMemberofSADCRTGS", "Participant blocked from SADC-RTGS."), RCON("RMessageConflict", "Conflict with R-Message"), RECI("ReceiverCustomerInformation", "Further information regarding the intended recipient."), REPR("RTPReceivedCanBeProcessed", "Request-to-pay has been received and can be processed further."), RF01("NotUniqueTransactionReference", "Transaction reference is not unique within the message."), RQNR("RequestNotRecognized", "Payer did not recognize the request from Payee Participant,"), RR01("MissingDebtorAccountOrIdentification", "Specification of the debtor’s account or unique identification needed for reasons of regulatory requirements is insufficient or missing"), RR02("MissingDebtorNameOrAddress", "Specification of the debtor’s name and/or address needed for regulatory requirements is insufficient or missing."), RR03("MissingCreditorNameOrAddress", "Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing."), RR04("RegulatoryReason", "Regulatory Reason"), RR05("RegulatoryInformationInvalid", "Regulatory or Central Bank Reporting information missing, incomplete or invalid."), RR06("TaxInformationInvalid", "Tax information missing, incomplete or invalid."), RR07("RemittanceInformationInvalid", "Remittance information structure does not comply with rules for payment type."), RR08("RemittanceInformationTruncated", "Remittance information truncated to comply with rules for payment type."), RR09("InvalidStructuredCreditorReference", "Structured creditor reference invalid or missing."), RR10("InvalidCharacterSet", "Character set supplied not valid for the country and payment type."), RR11("InvalidDebtorAgentServiceID", "Invalid or missing identification of a bank proprietary service."), RR12("InvalidPartyID", "Invalid or missing identification required within a particular country or payment type."), RTNS("RTPNotSupportedForDebtor", "Debtor does not support request-to-pay transactions."), RUTA("ReturnUponUnableToApply", "Return following investigation request and no remediation possible."), S000("ValidRequestForCancellationAcknowledged", "Request for Cancellation is acknowledged following validation."), S001("UETRFlaggedForCancellation", "Unique End-to-end Transaction Reference (UETR) relating to a payment has been identified as being associated with a Request for Cancellation."), S002("NetworkStopOfUETR", "Unique End-to-end Transaction Reference (UETR) relating to a payment has been prevent from traveling across a messaging network."), S003("RequestForCancellationForwarded", "Request for Cancellation has been forwarded to the payment processing/last payment processing agent."), S004("RequestForCancellationDeliveryAcknowledgement", "Request for Cancellation has been acknowledged as delivered to payment processing/last payment processing agent."), SBRN("SettlementBatchRemovalNotification", "Remove Concurrent Batch Processing Line on hold instruction."), SL01("SpecificServiceOfferedByDebtorAgent", "Due to specific service offered by the Debtor Agent."), SL02("SpecificServiceOfferedByCreditorAgent", "Due to specific service offered by the Creditor Agent."), SL03("ServiceofClearingSystem", "Due to a specific service offered by the clearing system."), SL11("CreditorNotOnWhitelistOfDebtor", "Whitelisting service offered by the Debtor Agent; Debtor has not included the Creditor on its “Whitelist” (yet). In the Whitelist the Debtor may list all allowed Creditors to debit Debtor bank account."), SL12("CreditorOnBlacklistOfDebtor", "Blacklisting service offered by the Debtor Agent; Debtor included the Creditor on his “Blacklist”. In the Blacklist the Debtor may list all Creditors not allowed to debit Debtor bank account."), SL13("MaximumNumberOfDirectDebitTransactionsExceeded", "Due to Maximum allowed Direct Debit Transactions per period service offered by the Debtor Agent."), SL14("MaximumDirectDebitTransactionAmountExceeded", "Due to Maximum allowed Direct Debit Transaction amount service offered by the Debtor Agent."), SL15("MaximumNumberOfCreditTransactionsExceeded", "Maximum number of credit transactions allowed by the account servicer per service period exceeded."), SL16("MaximumCreditTransactionsAmountExceeded", "Maximum total credit amount allowed by the account servicer per service period exceeded."), SL17("DebtorNotOnWhitelistOfCreditorSide", "Whitelisting service offered by payment system operator or financial institution. Debtor is not included on the Creditor side whitelist."), SL18("DebtorOnBlacklistOfCreditorSide", "Blacklisting service offered by payment system operator or financial institution. Debtor included on the Creditor side blacklist."), SNRD("ServiceNotRendered", "Services are not yet rendered by the Payee Participant (Creditor)."), SPII("RTPServiceProviderIdentifierIncorrect", "Identifier of the request-to-pay service provider is incorrect."), TA01("TransmissonAborted", "The transmission of the file was not successful – it had to be aborted (for technical reasons)"), TD01("NoDataAvailable", "There is no data available (for download)"), TD02("FileNonReadable", "The file cannot be read (e.g. unknown format)"), TD03("IncorrectFileStructure", "The file format is incomplete or invalid"), TK01("TokenInvalid", "Token is invalid."), TK02("SenderTokenNotFound", "Token used for the sender does not exist."), TK03("ReceiverTokenNotFound", "Token used for the receiver does not exist."), TK09("TokenMissing", "Token required for request is missing."), TKCM("TokenCounterpartyMismatch", "Token found with counterparty mismatch."), TKSG("TokenSingleUse", "Single Use Token already used."), TKSP("TokenSuspended", "Token found with suspended status."), TKVE("TokenValueLimitExceeded", "Token found with value limit rule violation."), TKXP("TokenExpired", "Token expired."), TM01("InvalidCutOffTime", "Associated message, payment information block, or transaction was received after agreed processing cut-off time."), TS01("TransmissionSuccessful", "The (technical) transmission of the file was successful."), TS04("TransferToSignByHand", "The order was transferred to pass by accompanying note signed by hand"), UCRD("UnknownCreditor", "Unknown Creditor."), UPAY("UnduePayment", "Payment is not justified."), } enum class ExternalPaymentGroupStatusCode(val isoCode: String, val description: String) { ACCC("AcceptedSettlementCompletedCreditorAccount", "Settlement on the creditor's account has been completed."), ACCP("AcceptedCustomerProfile", "Preceding check of technical validation was successful. Customer profile check was also successful."), ACSC("AcceptedSettlementCompletedDebitorAccount", "Settlement on the debtor's account has been completed."), ACSP("AcceptedSettlementInProcess", "All preceding checks such as technical validation and customer profile were successful and therefore the payment initiation has been accepted for execution."), ACTC("AcceptedTechnicalValidation", "Authentication and syntactical and semantical validation are successful"), ACWC("AcceptedWithChange", "Instruction is accepted but a change will be made, such as date or remittance not sent."), PART("PartiallyAccepted", "A number of transactions have been accepted, whereas another number of transactions have not yet achieved"), PDNG("Pending", "Payment initiation or individual transaction included in the payment initiation is pending. Further checks and status update will be performed."), RCVC("ReceivedVerificationCompleted", "Verification of Payee check have been applied to received transactions stating to be complete without mismatching data."), RCVD("Received", "Payment initiation has been received by the receiving agent"), RJCT("Rejected", "Payment initiation or individual transaction included in the payment initiation has been rejected."), RVCM("ReceivedVerificationCompletedWithMismatches", "Verification of Payee checks have been applied to received transactions stating to be complete containing mismatching data."), RVNC("ReceivedVerificationNotCompleted", "Verification of party check on transactions received is not yet completed."), } enum class ExternalPaymentTransactionStatusCode(val isoCode: String, val description: String) { ACCC("AcceptedSettlementCompletedCreditorAccount", "Settlement on the creditor's account has been completed."), ACCP("AcceptedCustomerProfile", "Preceding check of technical validation was successful. Customer profile check was also successful."), ACFC("AcceptedFundsChecked", "Preceding check of technical validation and customer profile was successful and an automatic funds check was positive."), ACFW("AcceptedFundsCheckedWaitingConfirmation", "Preceding check of technical validation and customer profile was successful, and an automatic funds check was positive, but an explicit confirmation by the initiating party is outstanding."), ACIS("AcceptedandChequeIssued", "Payment instruction to issue a cheque has been accepted, and the cheque has been issued but not yet been deposited or cleared."), ACPD("AcceptedClearingProcessed", "Status of transaction released from the Debtor Agent and accepted by the clearing."), ACSC("AcceptedSettlementCompletedDebitorAccount", "Settlement completed."), ACSP("AcceptedSettlementInProcess", "All preceding checks such as technical validation and customer profile were successful and therefore the payment instruction has been accepted for execution."), ACTC("AcceptedTechnicalValidation", "Authentication and syntactical and semantical validation are successful"), ACWC("AcceptedWithChange", "Instruction is accepted but a change will be made, such as date or remittance not sent."), ACWP("AcceptedWithoutPosting", "Payment instruction included in the credit transfer is accepted without being posted to the creditor customer’s account."), BLCK("Blocked", "Payment transaction previously reported with status 'ACWP' is blocked, for example, funds will neither be posted to the Creditor's account, nor be returned to the Debtor."), CANC("Cancelled", "Payment initiation has been successfully cancelled after having received a request for cancellation."), CPUC("CashPickedUpByCreditor", "Cash has been picked up by the Creditor."), PATC("PartiallyAcceptedTechnicalCorrect", "Payment initiation needs multiple authentications, where some but not yet all have been performed. Syntactical and semantical validations are successful."), PDNG("Pending", "Payment instruction is pending. Further checks and status update will be performed."), PRES("Presented", "Request for Payment has been presented to the Debtor."), RCVC("ReceivedVerificationCompleted", "Verification of Payee check has been applied to received transaction stating to be complete without mismatching data."), RCVD("Received", "Payment instruction has been received."), RJCT("Rejected", "Payment instruction has been rejected."), RVCM("ReceivedVerificationCompletedWithMismatches", "Verification of Payee checks have been applied to received transaction stating to be completed containing mismatching data."), RVMC("ReceivedVerificationCompletedMatchClosely", "Verification of Payee check has been applied to received transaction stating to be complete with data matching closely."), RVNA("ReceivedVerificationCompletedNotApplicable", "Verification of Payee check has been applied to received transaction stating to be complete with not applicable data."), RVNC("ReceivedVerificationNotCompleted", "Verification of party check on the transaction is not yet completed."), RVNM("ReceivedVerificationCompletedNoMatch", "Verification of Payee check has been applied to received transaction stating to be complete with mismatching data."), } enum class ExternalReturnReasonCode(val isoCode: String, val description: String) { AC01("IncorrectAccountNumber", "Format of the account number specified is not correct"), AC02("InvalidDebtorAccountNumber", "Debtor account number invalid or missing."), AC03("InvalidCreditorAccountNumber", "Wrong IBAN in SCT"), AC04("ClosedAccountNumber", "Account number specified has been closed on the bank of account's books"), AC06("BlockedAccount", "Account specified is blocked, prohibiting posting of transactions against it."), AC07("ClosedCreditorAccountNumber", "Creditor account number closed."), AC13("InvalidDebtorAccountType", "Debtor account type is missing or invalid"), AC14("InvalidAgent", "An agent in the payment chain is invalid."), AC15("AccountDetailsChanged", "Account details have changed."), AC16("AccountInSequestration", "Account is in sequestration."), AC17("AccountInLiquidation", "Account is in liquidation."), AG01("TransactionForbidden", "Transaction forbidden on this type of account (formerly NoAgreement)"), AG02("InvalidBankOperationCode", "Bank Operation code specified in the message is not valid for receiver"), AG07("UnsuccesfulDirectDebit", "Debtor account cannot be debited for a generic reason."), AGNT("IncorrectAgent", "Agent in the payment workflow is incorrect."), AM01("ZeroAmount", "Specified message amount is equal to zero"), AM02("NotAllowedAmount", "Specific transaction/message amount is greater than allowed maximum"), AM03("NotAllowedCurrency", "Specified message amount is an non processable currency outside of existing agreement"), AM04("InsufficientFunds", "Amount of funds available to cover specified message amount is insufficient."), AM05("Duplication", "Duplication"), AM06("TooLowAmount", "Specified transaction amount is less than agreed minimum."), AM07("BlockedAmount", "Amount specified in message has been blocked by regulatory authorities."), AM09("WrongAmount", "Amount received is not the amount agreed or expected"), AM10("InvalidControlSum", "Sum of instructed amounts does not equal the control sum."), ARDT("AlreadyReturnedTransaction", "Already returned original SCT"), BE01("InconsistenWithEndCustomer", "Identification of end customer is not consistent with associated account number, organisation ID or private ID."), BE04("MissingCreditorAddress", "Specification of creditor's address, which is required for payment, is missing/not correct (formerly IncorrectCreditorAddress)."), BE05("UnrecognisedInitiatingParty", "Party who initiated the message is not recognised by the end customer"), BE06("UnknownEndCustomer", "End customer specified is not known at associated Sort/National Bank Code or does no longer exist in the books"), BE07("MissingDebtorAddress", "Specification of debtor's address, which is required for payment, is missing/not correct."), BE08("BankError", "Returned as a result of a bank error."), BE10("InvalidDebtorCountry", "Debtor country code is missing or invalid."), BE11("InvalidCreditorCountry", "Creditor country code is missing or invalid."), BE16("InvalidDebtorIdentificationCode", "Debtor or Ultimate Debtor identification code missing or invalid."), BE17("InvalidCreditorIdentificationCode", "Creditor or Ultimate Creditor identification code missing or invalid."), CN01("AuthorisationCancelled", "Authorisation is cancelled."), CNOR("CreditorBankIsNotRegistered", "Creditor bank is not registered under this BIC in the CSM"), CNPC("CashNotPickedUp", "Cash not picked up by Creditor or cash could not be delivered to Creditor"), CURR("IncorrectCurrency", "Currency of the payment is incorrect"), CUST("RequestedByCustomer", "Cancellation requested by the Debtor"), DC04("NoCustomerCreditTransferReceived", "Return of Covering Settlement due to the underlying Credit Transfer details not being received."), DNOR("DebtorBankIsNotRegistered", "Debtor bank is not registered under this BIC in the CSM"), DS28("ReturnForTechnicalReason", "Return following technical problems resulting in erroneous transaction."), DT01("InvalidDate", "Invalid date (eg, wrong settlement date)"), DT02("ChequeExpired", "Cheque has been issued but not deposited and is considered expired."), DT04("FutureDateNotSupported", "Future date not supported."), DUPL("DuplicatePayment", "Payment is a duplicate of another payment."), ED01("CorrespondentBankNotPossible", "Correspondent bank not possible."), ED03("BalanceInfoRequest", "Balance of payments complementary info is requested"), ED05("SettlementFailed", "Settlement of the transaction has failed."), EMVL("EMVLiabilityShift", "The card payment is fraudulent and was not processed with EMV technology for an EMV card."), ERIN("ERIOptionNotSupported", "The Extended Remittance Information (ERI) option is not supported."), FF03("InvalidPaymentTypeInformation", "Payment Type Information is missing or invalid."), FF04("InvalidServiceLevelCode", "Service Level code is missing or invalid."), FF05("InvalidLocalInstrumentCode", "Local Instrument code is missing or invalid"), FF06("InvalidCategoryPurposeCode", "Category Purpose code is missing or invalid."), FF07("InvalidPurpose", "Purpose is missing or invalid."), FOCR("FollowingCancellationRequest", "Return following a cancellation request"), FR01("Fraud", "Returned as a result of fraud."), FRTR("FinalResponseMandateCancelled", "Final response/tracking is recalled as mandate is cancelled."), G004("CreditPendingFunds", "In a FIToFI Customer Credit Transfer: Credit to the creditor’s account is pending, status Originator is waiting for funds provided via a cover. Update will follow from the Status Originator."), MD01("NoMandate", "No Mandate"), MD02("MissingMandatoryInformationInMandate", "Mandate related information data required by the scheme is missing."), MD05("CollectionNotDue", "Creditor or creditor's agent should not have collected the direct debit."), MD06("RefundRequestByEndCustomer", "Return of funds requested by end customer"), MD07("EndCustomerDeceased", "End customer is deceased."), MS02("NotSpecifiedReasonCustomerGenerated", "Reason has not been specified by end customer"), MS03("NotSpecifiedReasonAgentGenerated", "Reason has not been specified by agent."), NARR("Narrative", "Reason is provided as narrative information in the additional reason information."), NOAS("NoAnswerFromCustomer", "No response from Beneficiary"), NOCM("NotCompliant", "Customer account is not compliant with regulatory requirements, for example FICA (in South Africa) or any other regulatory requirements which render an account inactive for certain processing."), NOOR("NoOriginalTransactionReceived", "Original SCT never received"), PINL("PINLiabilityShift", "The card payment is fraudulent (lost and stolen fraud) and was processed as EMV transaction without PIN verification."), RC01("BankIdentifierIncorrect", "Bank Identifier code specified in the message has an incorrect format (formerly IncorrectFormatForRoutingCode)."), RC03("InvalidDebtorBankIdentifier", "Debtor bank identifier is invalid or missing."), RC04("InvalidCreditorBankIdentifier", "Creditor bank identifier is invalid or missing."), RC07("InvalidCreditorBICIdentifier", "Incorrrect BIC of the beneficiary Bank in the SCTR"), RC08("InvalidClearingSystemMemberIdentifier", "ClearingSystemMemberidentifier is invalid or missing."), RC11("InvalidIntermediaryAgent", "Intermediary Agent is invalid or missing."), RF01("NotUniqueTransactionReference", "Transaction reference is not unique within the message."), RR01("MissingDebtorAccountOrIdentification", "Specification of the debtor’s account or unique identification needed for reasons of regulatory requirements is insufficient or missing"), RR02("MissingDebtorNameOrAddress", "Specification of the debtor’s name and/or address needed for regulatory requirements is insufficient or missing."), RR03("MissingCreditorNameOrAddress", "Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing."), RR04("RegulatoryReason", "Regulatory Reason"), RR05("RegulatoryInformationInvalid", "Regulatory or Central Bank Reporting information missing, incomplete or invalid."), RR06("TaxInformationInvalid", "Tax information missing, incomplete or invalid."), RR07("RemittanceInformationInvalid", "Remittance information structure does not comply with rules for payment type."), RR08("RemittanceInformationTruncated", "Remittance information truncated to comply with rules for payment type."), RR09("InvalidStructuredCreditorReference", "Structured creditor reference invalid or missing."), RR11("InvalidDebtorAgentServiceIdentification", "Invalid or missing identification of a bank proprietary service."), RR12("InvalidPartyIdentification", "Invalid or missing identification required within a particular country or payment type."), RUTA("ReturnUponUnableToApply", "Return following investigation request and no remediation possible."), SL01("SpecificServiceOfferedByDebtorAgent", "Due to specific service offered by the Debtor Agent"), SL02("SpecificServiceOfferedByCreditorAgent", "Due to specific service offered by the Creditor Agent"), SL11("CreditorNotOnWhitelistOfDebtor", "Whitelisting service offered by the Debtor Agent; Debtor has not included the Creditor on its “Whitelist” (yet). In the Whitelist the Debtor may list all allowed Creditors to debit Debtor bank account."), SL12("CreditorOnBlacklistOfDebtor", "Blacklisting service offered by the Debtor Agent; Debtor included the Creditor on his “Blacklist”. In the Blacklist the Debtor may list all Creditors not allowed to debit Debtor bank account."), SL13("MaximumNumberOfDirectDebitTransactionsExceeded", "Due to Maximum allowed Direct Debit Transactions per period service offered by the Debtor Agent."), SL14("MaximumDirectDebitTransactionAmountExceeded", "Due to Maximum allowed Direct Debit Transaction amount service offered by the Debtor Agent."), SP01("PaymentStopped", "Payment is stopped by account holder."), SP02("PreviouslyStopped", "Previously stopped by means of a stop payment advise."), SVNR("ServiceNotRendered", "The card payment is returned since a cash amount rendered was not correct or goods or a service was not rendered to the customer, e.g. in an e-commerce situation."), TM01("CutOffTime", "Associated message was received after agreed processing cut-off time."), TRAC("RemovedFromTracking", "Return following direct debit being removed from tracking process."), UPAY("UnduePayment", "Payment is not justified."), }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain002.kt0000664000175000017500000001127015122266731030274 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.iso20022 import tech.libeufin.nexus.* import tech.libeufin.ebics.XmlDestructor import java.io.InputStream private fun fmtMsg(code: String?, description: String?, reasons: List) = buildString { if (code != null) { append(code) append(" ") if (description != null) { append("'") append(description) append("'") } if (reasons.isNotEmpty()) { append(":") } } for (reason in reasons) { append(" ") if (reason.code != null) { append(reason.code.isoCode) append(" '") append(reason.code.description) append("'") } if (reason.information.isNotEmpty()) { if (reason.code != null) append(" ") append("'") append(reason.information) append("'") } } } data class MsgStatus( val id: String, val code: ExternalPaymentGroupStatusCode?, val reasons: List, val payments: List ) { fun msg() = fmtMsg(code?.isoCode, code?.description, reasons) override fun toString() = buildString { append(id) val msg = msg() if (msg.isNotEmpty()) { append(" ") append(msg) } for (pmt in payments) { append("\n>") append(pmt.id) val msg = pmt.msg() if (msg.isNotEmpty()) { append(" ") append(msg) } for (tx in pmt.transactions) { append("\n>>") if (tx.id != tx.endToEndId) { append(tx.id) append(" ") } append(tx.endToEndId) val msg = tx.msg() if (msg.isNotEmpty()) { append(" ") append(msg) } } } } } data class PmtStatus( val id: String, val code: ExternalPaymentGroupStatusCode?, val reasons: List, val transactions: List ) { fun msg() = fmtMsg(code?.isoCode, code?.description, reasons) } data class TxStatus( val id: String, val endToEndId: String, val code: ExternalPaymentTransactionStatusCode, val reasons: List ) { fun msg() = fmtMsg(code.isoCode, code.description, reasons) } data class Reason ( val code: ExternalStatusReasonCode?, val information: String ) /** Parse pain.002 XML file */ fun parseCustomerPaymentStatusReport(xml: InputStream): MsgStatus { fun XmlDestructor.reasons(): List { return map("StsRsnInf") { val code = opt("Rsn")?.one("Cd")?.enum() val info = map("AddtlInf") { text() }.joinToString("") Reason(code, info) } } return XmlDestructor.parse(xml, "Document") { one("CstmrPmtStsRpt") { val (id, code, reasons) = one("OrgnlGrpInfAndSts") { val id = one("OrgnlMsgId").text() val code = opt("GrpSts")?.enum() val reasons = reasons() Triple(id, code, reasons) } val payments = map("OrgnlPmtInfAndSts") { val id = one("OrgnlPmtInfId").text() val code = opt("PmtInfSts")?.enum() val reasons = reasons() val transactions = map("TxInfAndSts") { val id = one("OrgnlInstrId").text() val endToEndId = one("OrgnlEndToEndId").text() val code = one("TxSts").enum() val reasons = reasons() TxStatus(id, endToEndId, code, reasons) } PmtStatus(id, code, reasons, transactions) } MsgStatus(id, code, reasons, payments) } } }libeufin-1.6.8/libeufin-nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/hac.kt0000664000175000017500000000520515122266731027657 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.nexus.iso20022 import tech.libeufin.nexus.* import tech.libeufin.ebics.XmlDestructor import java.io.InputStream import java.time.Instant import java.time.ZoneOffset data class CustomerAck( val actionType: HacAction, val orderId: String?, val code: ExternalStatusReasonCode?, val info: String, val timestamp: Instant ) { fun msg(): String = buildString { append("$actionType") if (code != null) append(" ${code.isoCode}") append(" - '${actionType.description}'") if (code != null) append(" '${code.description}'") if (info != "") append(" - '$info'") } override fun toString(): String = buildString { append(timestamp.fmtDateTime()) if (orderId != null) append(" $orderId") append(" ${msg()}") } } /** Parse HAC pain.002 XML file */ fun parseCustomerAck(xml: InputStream): List { return XmlDestructor.parse(xml, "Document") { one("CstmrPmtStsRpt").map("OrgnlPmtInfAndSts") { val actionType = one("OrgnlPmtInfId").enum() one("StsRsnInf") { var timestamp: Instant? = null var orderId: String? = null one("Orgtr").one("Id").one("OrgId").each("Othr") { val value = one("Id") val key = one("SchmeNm").one("Prtry").text() when (key) { "TimeStamp" -> { timestamp = value.dateTime().toInstant(ZoneOffset.UTC) } "OrderID" -> orderId = value.text() } } val code = opt("Rsn")?.one("Cd")?.enum() val info = map("AddtlInf") { text() }.joinToString("") CustomerAck(actionType, orderId, code, info, requireNotNull(timestamp)) } } } }libeufin-1.6.8/libeufin-nexus/src/test/0000775000175000017500000000000015236145704020255 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/test/kotlin/0000775000175000017500000000000015236145704021555 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/src/test/kotlin/EbicsTest.kt0000664000175000017500000001370015122266731024001 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.w3c.dom.Document import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test import kotlinx.coroutines.runBlocking import io.ktor.http.* import io.ktor.http.content.* import org.junit.Test import tech.libeufin.nexus.cli.LibeufinNexus import tech.libeufin.nexus.* import tech.libeufin.common.* import tech.libeufin.common.test.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.ebics.test.* import tech.libeufin.ebics.* import kotlin.io.path.* import kotlin.test.* import java.time.LocalDate @OptIn(kotlin.io.path.ExperimentalPathApi::class) class EbicsTest { private val nexusCmd = LibeufinNexus() private val bank = EbicsState() private val args = "-L TRACE -c conf/fetch.conf" private fun ebicsSetup() { // Reset current keys val dir = Path("/tmp/ebics-test") dir.deleteRecursively() dir.createDirectories() // Set setup mock setMock(sequence { yield(bank::hev) yield(bank::ini) yield(bank::hia) yield(bank::hpb) yield(bank::hkd) yield(bank::receiptOk) }) // Run setup nexusCmd.succeed("ebics-setup $args --auto-accept-keys") } @Test fun setup() { ebicsSetup() } @Test fun fetchPinnedDate() = setup { db, _ -> ebicsSetup() suspend fun resetCheckpoint() { db.serializable("DELETE FROM kv WHERE key=?") { bind(CHECKPOINT_KEY) executeUpdate() } } // Default transient setMock(sequence { yield(bank::haa) yield(bank::receiptOk) yield(bank::btdNoData) }) nexusCmd.succeed("ebics-fetch $args --transient") // Pinned transient setMock(sequence { yield(bank::haa) yield(bank::receiptOk) yield(bank::btdNoDataPinned) }) nexusCmd.succeed("ebics-fetch $args --transient --pinned-start 2024-06-05") // Init checkpoint setMock(sequence { yield(bank::hkd) yield(bank::receiptOk) yield(bank::btdNoData) }) nexusCmd.succeed("ebics-fetch $args --transient --checkpoint") // Default checkpoint setMock(sequence { yield(bank::hkd) yield(bank::receiptOk) yield(bank::btdNoDataNow) }) nexusCmd.succeed("ebics-fetch $args --transient --checkpoint") // Pinned checkpoint setMock(sequence { yield(bank::hkd) yield(bank::receiptOk) yield(bank::btdNoDataPinned) }) nexusCmd.succeed("ebics-fetch $args --transient --checkpoint --pinned-start 2024-06-05") // Reset checkpoint resetCheckpoint() setMock(sequence { yield(bank::hkd) yield(bank::receiptOk) yield(bank::btdNoData) }) nexusCmd.succeed("ebics-fetch $args --transient --checkpoint") // Reset checkpoint pinned resetCheckpoint() setMock(sequence { yield(bank::hkd) yield(bank::receiptOk) yield(bank::btdNoDataPinned) }) nexusCmd.succeed("ebics-fetch $args --transient --checkpoint --pinned-start 2024-06-05") } @Test fun closePendingTransaction() = setup { db, _ -> ebicsSetup() // Failure before first segment setMock(sequence { // Failure to perform download yield(bank::failure) // Then continue yield(bank::haa) yield(bank::receiptOk) yield(bank::btdNoData) }) nexusCmd.fail("ebics-fetch $args --transient") nexusCmd.succeed("ebics-fetch $args --transient") // Compliant server setMock(sequence { yield(bank::haa) yield(bank::receiptOk) // Failure to perform download yield(bank::initializeTx) yield(bank::failure) // Retry fail once yield(bank::failure) // Retry fail twice yield(bank::failure) // Retry succeed yield(bank::receiptErr) // Then continue yield(bank::haa) yield(bank::receiptOk) yield(bank::btdNoData) }) nexusCmd.fail("ebics-fetch $args --transient") nexusCmd.fail("ebics-fetch $args --transient") nexusCmd.fail("ebics-fetch $args --transient") nexusCmd.succeed("ebics-fetch $args --transient") // Non compliant server setMock(sequence { yield(bank::haa) yield(bank::receiptOk) // Failure to perform download yield(bank::initializeTx) yield(bank::badRequest) // Retry fail yield(bank::failure) // Retry succeed yield(bank::badRequest) // Then continue yield(bank::haa) yield(bank::receiptOk) yield(bank::btdNoData) }) nexusCmd.fail("ebics-fetch $args --transient") nexusCmd.fail("ebics-fetch $args --transient") nexusCmd.succeed("ebics-fetch $args --transient") } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/bench.kt0000664000175000017500000002423215221677432023201 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import org.postgresql.jdbc.PgConnection import io.ktor.client.request.* import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.test.* import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.* import kotlin.math.max import java.util.UUID; import java.time.Instant class Bench { /** Generate [amount] rows to fill the database */ fun genData(conn: PgConnection, amount: Int) { val amount = max(amount, 10) val token32 = ByteArray(32) val token64 = ByteArray(64) val accountPubs = List(amount*2) { EddsaPublicKey.randEdsaKey() } conn.genData(amount, sequenceOf( "incoming_transactions(amount, subject, execution_time, debit_payto, uetr, tx_id, acct_svcr_ref)" to { val subject = if (it % 4 == 0) null else "subject ${it}" val debtor = if (it % 3 == 0) null else "debit_payto" if (it % 3 == 0) { "(20,0)\t$subject\t0\t$debtor\t${UUID.randomUUID()}\t\\N\t\\N\n" + "(21,0)\t$subject\t0\t$debtor\t\\N\tTX_ID${it*2}\t\\N\n" + "(22,0)\t$subject\t0\t$debtor\t\\N\t\\N\tREF${it*2}\n" } else if (it % 3 == 1) { "(30,0)\t$subject\t0\t$debtor\t${UUID.randomUUID()}\tTX_ID${it*2}\t\\N\n" + "(31,0)\t$subject\t0\t$debtor\t\\N\tTX_ID${it*2+1}\tREF${it*2}\n" + "(32,0)\t$subject\t0\t$debtor\t${UUID.randomUUID()}\t\\N\tREF${it*2+1}\n" } else { "(40,0)\t$subject\t0\t$debtor\t${UUID.randomUUID()}\tTX_ID${it*2}\tREF${it*2}\n" + "(41,0)\t$subject\t0\t$debtor\t${UUID.randomUUID()}\tTX_ID${it*2+1}\tREF${it*2+1}\n" } }, "outgoing_transactions(amount, subject, execution_time, credit_payto, end_to_end_id, acct_svcr_ref)" to { val subject = if (it % 4 == 0) null else "subject ${it}" val creditor = if (it % 3 == 0) null else "credit_payto" if (it % 2 == 0) { "(30,0)\t$subject\t0\t$creditor\t\\N\tREF${it*2}\n" + "(31,0)\t$subject\t0\t$creditor\tE2E_ID${it*2}\t\\N\n" } else { "(30,0)\t$subject\t0\t$creditor\tE2E_ID${it*2}\tREF${it*2}\n" + "(31,0)\t$subject\t0\t$creditor\tE2E_ID${it*2+1}\tREF${it*2+1}\n" } }, "initiated_outgoing_transactions(amount, subject, initiation_time, credit_payto, outgoing_transaction_id, end_to_end_id)" to { "(42,0)\tsubject\t0\tcredit_payto\t${it*2}\tE2E_ID$it\n" }, "prepared_transfers(type, account_pub, authorization_pub, authorization_sig, recurrent, reference_number, registered_at, incoming_transaction_id)" to { val type = if (it % 2 == 0) "reserve" else "kyc" val recurrent = if (it % 3 == 0) "true" else "false" val incoming_transaction_id = if (it % 5 == 0) "\\N" else "${it*2}" val reference_number = subjectFmtQrBill(accountPubs[it]) val pub = accountPubs[it].raw.encodeHex() val sig = token64.rand().encodeHex() "$type\t\\\\x$pub\t\\\\x$pub\t\\\\x$sig\t$recurrent\t$reference_number\t0\t$incoming_transaction_id\n" }, "pending_recurrent_incoming_transactions(incoming_transaction_id, authorization_pub)" to { val hex = accountPubs[it].raw.encodeHex() "${it*2}\t\\\\x$hex\n" }, "bounced_transactions(incoming_transaction_id, initiated_outgoing_transaction_id)" to { if (it % 10 == 0) { "${it/2}\t${it/3}\n" } else { "" } }, "talerable_incoming_transactions(type, metadata, incoming_transaction_id)" to { val hex = token32.rand().encodeHex() if (it % 2 == 0) { "reserve\t\\\\x$hex\t${it*2}\n" } else { "kyc\t\\\\x$hex\t${it*2}\n" } }, "talerable_outgoing_transactions(wtid, exchange_base_url, outgoing_transaction_id)" to { val hex = token32.rand().encodeHex() "\\\\x$hex\turl\t${it*2-1}\n" }, "transfer_operations(initiated_outgoing_transaction_id, request_uid, wtid, exchange_base_url)" to { val hex32 = token32.rand().encodeHex() val hex64 = token64.rand().encodeHex() "$it\t\\\\x$hex64\t\\\\x$hex32\turl\n" } )) } @Test fun benchDb() { val ingestCfg = NexusIngestConfig.default(AccountType.exchange) bench { AMOUNT -> serverSetup { db -> // Generate data db.conn { genData(it, AMOUNT) } val accountPubs = List(AMOUNT) { EddsaPublicKey.randEdsaKeyPair() } // Warm HTTP client client.getA("/taler-revenue/config").assertOk() // Register measureAction("register_in") { registerIn(db) } measureAction("register_incomplete_in") { registerIncompleteIn(db) } measureAction("register_completed_in") { registerCompletedIn(db) } measureAction("register_out") { registerOut(db) } measureAction("register_incomplete_out") { registerIncompleteOut(db) } measureAction("register_reserve") { talerableIn(db) } measureAction("register_prepared_reserve") { talerablePreparedIn(db) } measureAction("register_kyc") { talerableKycIn(db) } // Revenue API measureAction("transaction_revenue") { client.getA("/taler-revenue/history").assertOk() } // Wire gateway measureAction("wg_transfer") { client.postA("/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to "CHF:0.0001" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to grothoffPayto } }.assertOk() } measureAction("wg_transfer_get") { client.getA("/taler-wire-gateway/transfers/42").assertOk() } measureAction("wg_transfer_page") { client.getA("/taler-wire-gateway/transfers").assertOk() } measureAction("wg_transfer_page_filter") { client.getA("/taler-wire-gateway/transfers?status=success").assertNoContent() } measureAction("wg_add") { client.postA("/taler-wire-gateway/admin/add-incoming") { json { "amount" to "CHF:0.0001" "reserve_pub" to EddsaPublicKey.randEdsaKey() "debit_account" to grothoffPayto } }.assertOk() } measureAction("wg_incoming") { client.getA("/taler-wire-gateway/history/incoming") .assertOk() } measureAction("wg_outgoing") { client.getA("/taler-wire-gateway/history/outgoing") .assertOk() } // Wire transfer /*measureAction("wt_register") { val (priv, pub) = accountPubs[it] val valid_req = obj { "credit_account" to "payto://iban/CH7789144474425692816" "credit_amount" to "KUDOS:55" "type" to "reserve" "alg" to "EdDSA" "account_pub" to pub "authorization_pub" to pub "authorization_sig" to CryptoUtil.eddsaSign(pub.raw, priv) "recurrent" to false } client.post("/taler-prepared-transfer/registration") { json(valid_req) }.assertOkJson() client.post("/taler-prepared-transfer/registration") { json(valid_req) }.assertOkJson() } measureAction("wt_unregister") { val (priv, pub) = accountPubs[it] val now = Instant.now().toString() val valid_req = obj { "timestamp" to now "authorization_pub" to pub "authorization_sig" to CryptoUtil.eddsaSign(now.toByteArray(), priv) } client.post("/taler-prepared-transfer/unregistration") { json(valid_req) }.assertNoContent() client.post("/taler-prepared-transfer/unregistration") { json(valid_req) }.assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) }*/ // Observability /*measureAction("metrics") { client.get("/taler-observability/metrics") .assertOk() }*/ }} } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/PreparedTransferApiTest.kt0000664000175000017500000001661615221677432026672 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.* import java.time.Instant import kotlin.test.* class PreparedTransferApiTest { // GET /taler-prepared-transfer/config @Test fun config() = serverSetup { client.get("/taler-prepared-transfer/config").assertOkJson() } // POST /taler-prepared-transfer/registration @Test fun registration() = serverSetup { db -> val (priv, pub) = EddsaPublicKey.randEdsaKeyPair() val amount = TalerAmount("KUDOS:55") val valid_req = SubjectRequest( Payto.parse("payto://iban/CH7789144474425692816"), TransferType.reserve, false, amount, PublicKeyAlg.EdDSA, pub, pub, EddsaSignature.rand() ) val simple = listOf(TransferSubject.Simple("Taler MAP:$pub", amount)) val qrs = listOf(TransferSubject.QrBill(subjectFmtQrBill(pub), amount)) // Valid simple client.post("/taler-prepared-transfer/registration") { json(valid_req.sign(priv)) }.assertOkJson { assertEquals(it.subjects, simple) } // Idempotent simple client.post("/taler-prepared-transfer/registration") { json(valid_req.sign(priv)) }.assertOkJson { assertEquals(it.subjects, simple) } // Valid qr client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(credit_account=Payto.parse("payto://iban/CH4431999123000889012")).sign(priv)) }.assertOkJson { assertEquals(it.subjects, qrs) } // Idempotent qr client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(credit_account=Payto.parse("payto://iban/CH4431999123000889012")).sign(priv)) }.assertOkJson { assertEquals(it.subjects, qrs) } // Bad signature client.post("/taler-prepared-transfer/registration") { json(valid_req) }.assertForbidden(TalerErrorCode.BANK_BAD_SIGNATURE) // Unknown account client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(credit_account=Payto.parse(grothoffPayto)).sign(priv)) }.assertConflict(TalerErrorCode.BANK_UNKNOWN_CREDITOR) // Check authorization field in incoming history val (testPriv, testAuth) = EddsaPublicKey.randEdsaKeyPair() val testKey = EddsaPublicKey.randEdsaKey() val qr = subjectFmtQrBill(testAuth) client.post("/taler-prepared-transfer/registration") { json(valid_req.copy( credit_account=Payto.parse("payto://iban/CH4431999123000889012"), account_pub=testKey, authorization_pub=testAuth, recurrent=true ).sign(testPriv)) }.assertOkJson() val cfg = NexusIngestConfig.default(AccountType.exchange) registerIncomingPayment(db, cfg, genInPay(qr)) registerIncomingPayment(db, cfg, genInPay(qr)) registerIncomingPayment(db, cfg, genInPay(qr)) client.post("/taler-prepared-transfer/registration") { json(valid_req.copy( type=TransferType.kyc, account_pub=testKey, authorization_pub=testAuth, recurrent=true ).sign(testPriv)) }.assertOkJson() val otherPub = EddsaPublicKey.randEdsaKey() client.post("/taler-prepared-transfer/registration") { json(valid_req.copy( account_pub=otherPub, authorization_pub=testAuth, recurrent=true ).sign(testPriv)) }.assertOkJson() val lastPub = EddsaPublicKey.randEdsaKey() talerableIn(db, reserve_pub=lastPub) talerableKycIn(db, account_pub=lastPub) val history = client.getA("/taler-wire-gateway/history/incoming?limit=-5") .assertOkJson().incoming_transactions.map { when (it) { is IncomingKycAuthTransaction -> Pair(it.account_pub, it.authorization_pub) is IncomingReserveTransaction -> Pair(it.reserve_pub, it.authorization_pub) else -> throw UnsupportedOperationException() } } assertContentEquals(history, listOf( Pair(lastPub, null), Pair(lastPub, null), Pair(otherPub, testAuth), Pair(testKey, testAuth), Pair(testKey, testAuth) )) } // DELETE /taler-prepared-transfer/registration @Test fun unregistration() = serverSetup { val (priv, pub) = EddsaPublicKey.randEdsaKeyPair() val now = TalerTimestamp(Instant.now()) val req = Unregistration( now, pub, EddsaSignature.rand() ).sign(priv) // Unknown client.post("/taler-prepared-transfer/unregistration") { json(req) }.assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Know client.post("/taler-prepared-transfer/registration") { json(SubjectRequest( Payto.parse("payto://iban/CH7789144474425692816"), TransferType.reserve, false, TalerAmount("KUDOS:55"), PublicKeyAlg.EdDSA, pub, pub, EddsaSignature.rand() ).sign(priv)) }.assertOkJson() client.post("/taler-prepared-transfer/unregistration") { json(req) }.assertNoContent() // Idempotent client.post("/taler-prepared-transfer/unregistration") { json(req) }.assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Bad signature client.post("/taler-prepared-transfer/unregistration") { json(Unregistration( now, pub, EddsaSignature.rand() )) }.assertForbidden(TalerErrorCode.BANK_BAD_SIGNATURE) // Old timestamp client.post("/taler-prepared-transfer/unregistration") { json( Unregistration( TalerTimestamp(Instant.now().minusSeconds(1000000)), pub, EddsaSignature.rand() ).sign(priv) ) }.assertConflict(TalerErrorCode.BANK_OLD_TIMESTAMP) } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/RegistrationTest.kt0000664000175000017500000010601115122266731025424 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.* import tech.libeufin.nexus.db.* import tech.libeufin.nexus.iso20022.* import tech.libeufin.ebics.* import java.nio.file.Files import java.time.Instant import java.util.UUID import kotlin.io.path.* import kotlin.test.* /** End-to-end test for XML file registration */ class RegistrationTest { /** Register batches of initiated payments for reconcciliation */ suspend fun Database.batches(batches: Map>): List { val tmp = mutableListOf() for ((name, txs) in batches) { for (tx in txs) { initiated.create(tx) } this.initiated.batch(Instant.now(), name, false) val (batch) = this.initiated.submittable() this.initiated.batchSubmissionSuccess(batch.id, Instant.now(), name.replace("BATCH", "ORDER")) tmp.add(batch) } return tmp } /** Register an XML sample into the database */ suspend fun Database.register( cfg: NexusConfig, path: String, doc: OrderDoc ) { registerFile(this, cfg, Files.newInputStream(Path(path)), doc) } /** Check database content */ suspend fun Database.check( status: Map>>, incoming: List, outgoing: List, bounced: List ) { // Check batch status val batch_status = this.serializable( """ SELECT message_id, status FROM initiated_outgoing_batches ORDER BY initiated_outgoing_batch_id """ ) { all { Pair( it.getString("message_id"), it.getEnum("status") ) } } assertContentEquals(status.map { Pair(it.key, it.value.first) }, batch_status) // Check transactions status val batch_tx = this.serializable( """ SELECT message_id, end_to_end_id, initiated_outgoing_transactions.status FROM initiated_outgoing_transactions JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) ORDER BY initiated_outgoing_batch_id, initiated_outgoing_transaction_id """ ) { all { Triple( it.getString("message_id"), it.getString("end_to_end_id"), it.getEnum("status") ) }.groupBy( keySelector = { it.first }, valueTransform = { Pair(it.second, it.third) } ).mapValues { it.value.toMap() } } assertContentEquals(status.mapValues { it.value.second }.toList(), batch_tx.toList()) // Check incoming transactions val incoming_tx = this.serializable( """ SELECT uetr ,tx_id ,acct_svcr_ref ,(amount).val as amount_val ,(amount).frac AS amount_frac ,(credit_fee).val AS credit_fee_val ,(credit_fee).frac AS credit_fee_frac ,subject ,execution_time ,debit_payto FROM incoming_transactions ORDER BY incoming_transaction_id """ ) { all { IncomingPayment( id = IncomingId( it.getObject("uetr") as UUID?, it.getString("tx_id"), it.getString("acct_svcr_ref"), ), amount = it.getAmount("amount", this@check.currency), creditFee = it.getAmount("credit_fee", this@check.currency).notZeroOrNull(), subject = it.getString("subject"), executionTime = it.getLong("execution_time").asInstant(), debtor = it.getOptIbanPayto("debit_payto"), ) } } assertContentEquals(incoming, incoming_tx) // Check outgoing transactions val outgoing_tx = this.serializable( """ SELECT end_to_end_id ,acct_svcr_ref ,(amount).val as amount_val ,(amount).frac AS amount_frac ,(debit_fee).val AS debit_fee_val ,(debit_fee).frac AS debit_fee_frac ,subject ,execution_time ,credit_payto FROM outgoing_transactions ORDER BY outgoing_transaction_id """ ) { all { OutgoingPayment( id = OutgoingId(null, it.getString("end_to_end_id"), it.getString("acct_svcr_ref")), amount = it.getAmount("amount", this@check.currency), debitFee = it.getAmount("debit_fee", this@check.currency).notZeroOrNull(), subject = it.getString("subject"), executionTime = it.getLong("execution_time").asInstant(), creditor = it.getOptIbanPayto("credit_payto"), ) } } assertContentEquals(outgoing, outgoing_tx) // Check outgoing transactions val bounced_tx = this.serializable( """ SELECT end_to_end_id ,(amount).val as amount_val ,(amount).frac as amount_frac ,subject ,credit_payto FROM initiated_outgoing_transactions JOIN bounced_transactions USING (initiated_outgoing_transaction_id) """ ) { all { OutgoingPayment( id = OutgoingId(null, null, null), amount = it.getAmount("amount", this@check.currency), subject = it.getString("subject"), executionTime = Instant.EPOCH, creditor = it.getOptIbanPayto("credit_payto"), ) } } assertContentEquals(bounced, bounced_tx) } @Test fun pain001() = setup { db, cfg -> val (batch) = db.batches(mapOf( "MESSAGE_ID" to listOf( genInitPay( endToEndId = "TX_FIRST", amount = "EUR:42", subject = "Test 42", ), genInitPay( endToEndId = "TX_SECOND", amount = "EUR:5.11", subject = "Test 5.11", ), genInitPay( endToEndId = "TX_THIRD", amount = "EUR:0.21", subject = "Test 0.21", ), ), )) val msg = batchToPain001Msg(cfg.ebics.account, batch).copy(timestamp = dateToInstant("2024-09-09"),) for (dialect in Dialect.entries) { println(dialect) assertEquals( Path("sample/platform/${dialect}_pain001.xml").readText().replace("VERSION", VERSION), createPain001(msg, dialect, false).asUtf8() ) } } /** HAC order id test */ @Test fun hac() = setup { db, cfg -> db.batches(mapOf( "BATCH_SUCCESS" to listOf( genInitPay("BATCH_SUCCESS_0"), genInitPay("BATCH_SUCCESS_1"), ), "BATCH_FAILURE" to listOf( genInitPay("BATCH_FAILURE_0"), genInitPay("BATCH_FAILURE_1"), ) )) // Register HAC files db.register(cfg, "sample/platform/hac.xml", OrderDoc.acknowledgement) // Check state db.check( status = mapOf( "BATCH_SUCCESS" to Pair(SubmissionState.success, mapOf( "BATCH_SUCCESS_0" to SubmissionState.pending, "BATCH_SUCCESS_1" to SubmissionState.pending, )), "BATCH_FAILURE" to Pair(SubmissionState.permanent_failure, mapOf( "BATCH_FAILURE_0" to SubmissionState.permanent_failure, "BATCH_FAILURE_1" to SubmissionState.permanent_failure, )) ), incoming = emptyList(), outgoing = emptyList(), bounced = emptyList() ) } /** CreditSuisse dialect test */ @Test fun cs() = setup { db, cfg -> db.batches(mapOf( "05BD4C5B4A2649B5B08F6EF6A31F197A" to listOf( genInitPay("AQCXNCPWD8PHW5JTN65Y5XTF7R"), genInitPay("EE9SX76FC5YSC657EK3GMVZ9TC"), genInitPay("V5B3MXPEWES9VQW1JDRD6VAET4"), genInitPay("M9NGRCAC1FBX3ENX3XEDEPJ2JW"), ), )) // Register pain files db.register(cfg, "sample/platform/pain002_part.xml", OrderDoc.status) // Check state db.check( status = mapOf( "05BD4C5B4A2649B5B08F6EF6A31F197A" to Pair(SubmissionState.pending, mapOf( "AQCXNCPWD8PHW5JTN65Y5XTF7R" to SubmissionState.permanent_failure, "EE9SX76FC5YSC657EK3GMVZ9TC" to SubmissionState.permanent_failure, "V5B3MXPEWES9VQW1JDRD6VAET4" to SubmissionState.permanent_failure, "M9NGRCAC1FBX3ENX3XEDEPJ2JW" to SubmissionState.pending, )), ), incoming = emptyList(), outgoing = emptyList(), bounced = emptyList() ) } /** Valiant dialect test */ @Test fun valiant() = setup("valiant.conf") { db, cfg -> db.batches(mapOf( "MJDJO2BDDBL7YSL2P96SXHG3TQZEZQD26L" to listOf( genInitPay("4UWWIDGTEIGDU6Z721QE95PYJSIEA48PYE"), ), "5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U" to listOf( genInitPay("SKMU2891PAAYBDW22DBWX2W7KTFZ1CDFO8"), genInitPay("RC9YD301NZ17YKD6WDWLNOROFHIIN29VJN"), genInitPay("GKDGTHLB82X6XVHBJIJ1CK8MEGU9XJ2EL7"), genInitPay("PXCH2VVVTXEXBVDWICP23HZ4NV0H2CWW28"), ), "X166701F6RV59LP71RVWVIW9SV2AFZYLG4" to listOf( genInitPay("R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX"), ), "OLAMDPI6YPMNRZHQ5PQ6JCVUQV2AN5NW6P" to listOf( genInitPay("TU2WJ54DR9Z6HT5VE494BNH4EXUSM0DRF7"), ), "6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X" to listOf( genInitPay("02WDIX4J90Z1M1WNFHLNSXY59SHXQTQCMQ"), genInitPay("XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y"), genInitPay("GM8I8GIETR72LP6CFBGRBUDKNO2CEQBGOE") ), )) // Register camt files db.register(cfg, "sample/platform/valiant_camt052.xml", OrderDoc.report) // Check state db.check( status = mapOf( "MJDJO2BDDBL7YSL2P96SXHG3TQZEZQD26L" to Pair(SubmissionState.success, mapOf( "4UWWIDGTEIGDU6Z721QE95PYJSIEA48PYE" to SubmissionState.success )), "5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U" to Pair(SubmissionState.success, mapOf( "SKMU2891PAAYBDW22DBWX2W7KTFZ1CDFO8" to SubmissionState.success, "RC9YD301NZ17YKD6WDWLNOROFHIIN29VJN" to SubmissionState.success, "GKDGTHLB82X6XVHBJIJ1CK8MEGU9XJ2EL7" to SubmissionState.success, "PXCH2VVVTXEXBVDWICP23HZ4NV0H2CWW28" to SubmissionState.success )), "X166701F6RV59LP71RVWVIW9SV2AFZYLG4" to Pair(SubmissionState.success, mapOf( "R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX" to SubmissionState.late_failure )), "OLAMDPI6YPMNRZHQ5PQ6JCVUQV2AN5NW6P" to Pair(SubmissionState.success, mapOf( "TU2WJ54DR9Z6HT5VE494BNH4EXUSM0DRF7" to SubmissionState.success )), "6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X" to Pair(SubmissionState.success, mapOf( "02WDIX4J90Z1M1WNFHLNSXY59SHXQTQCMQ" to SubmissionState.success, "XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y" to SubmissionState.late_failure, "GM8I8GIETR72LP6CFBGRBUDKNO2CEQBGOE" to SubmissionState.success )), ), incoming = listOf( IncomingPayment( id = IncomingId(null, "51030655601.0001", "ZV20251030/514778/1"), amount = TalerAmount("CHF:0.85"), subject = "fun stuff", executionTime = dateToInstant("2025-10-30"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), ), IncomingPayment( id = IncomingId(null, "51030655601.0002", "ZV20251030/514779/1"), amount = TalerAmount("CHF:0.95"), subject = "Taler PC2MKG0B7CK32K1T7DP08P6E1B7FHB6HY6R Q0PT3VTPBPRPYM1B0", executionTime = dateToInstant("2025-10-30"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), ), IncomingPayment( id = IncomingId("7b76d488-05d5-44ab-9d77-31d4165ec158", "00204EQY370", "ZV20251118/685062/1"), amount = TalerAmount("CHF:4.55"), subject = "TEST", executionTime = dateToInstant("2025-11-18"), debtor = null ), ), outgoing = listOf( OutgoingPayment( id = OutgoingId(null, "4UWWIDGTEIGDU6Z721QE95PYJSIEA48PYE", "ZV20251030/511372/1"), amount = TalerAmount("CHF:0.1"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "single 2025-10-30T09:46:04.55293090 9Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "SKMU2891PAAYBDW22DBWX2W7KTFZ1CDFO8", "ZV20251030/511373/1"), amount = TalerAmount("CHF:0.1"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "multi 0 2025-10-30T09:46:10.3877961 30Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "RC9YD301NZ17YKD6WDWLNOROFHIIN29VJN", "ZV20251030/511373/2"), amount = TalerAmount("CHF:0.11"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "multi 1 2025-10-30T09:46:10.3877961 30Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "GKDGTHLB82X6XVHBJIJ1CK8MEGU9XJ2EL7", "ZV20251030/511373/3"), amount = TalerAmount("CHF:0.12"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "multi 2 2025-10-30T09:46:10.3877961 30Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "PXCH2VVVTXEXBVDWICP23HZ4NV0H2CWW28", "ZV20251030/511373/4"), amount = TalerAmount("CHF:0.13"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "multi 3 2025-10-30T09:46:10.3877961 30Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX", "ZV20251030/524078/1"), amount = TalerAmount("CHF:0.21"), creditor = ibanPayto("CH6208704048981247126", "John Smith"), subject = "bad name 2025-10-30T12:03:24.997478 811Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "02WDIX4J90Z1M1WNFHLNSXY59SHXQTQCMQ", "ZV20251030/524079/1"), amount = TalerAmount("CHF:0.1"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "single 2025-10-30T12:04:00.37042083 6Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y", "ZV20251030/524079/2"), amount = TalerAmount("CHF:0.21"), creditor = ibanPayto("CH6208704048981247126", "John Smith"), subject = "bad name 2025-10-30T12:03:53.042190 686Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "TU2WJ54DR9Z6HT5VE494BNH4EXUSM0DRF7", "ZV20251030/524077/1"), amount = TalerAmount("CHF:0.23"), debitFee = TalerAmount("CHF:5"), creditor = ibanPayto("DE48330605920000686018", "Christian Grothoff"), subject = "foreign iban 2025-10-30T12:03:44.0972 63765Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId(null, "GM8I8GIETR72LP6CFBGRBUDKNO2CEQBGOE", "ZV20251030/524080/1"), amount = TalerAmount("CHF:0.23"), debitFee = TalerAmount("CHF:5"), creditor = ibanPayto("DE48330605920000686018", "Christian Grothoff"), subject = "foreign iban 2025-10-30T12:03:58.0046 73747Z", executionTime = dateToInstant("2025-10-30") ), ), bounced = listOf( OutgoingPayment( id = OutgoingId(null, null, null), amount = TalerAmount("CHF:0.85"), subject = "bounce 51030655601.0001: missing reserve public key", executionTime = Instant.EPOCH, creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), ) ) } /** GLS dialect test */ @Test fun gls() = setup("gls.conf") { db, cfg -> db.batches(mapOf( "COMPAT_SUCCESS" to listOf( genInitPay("COMPAT_SUCCESS") ), "COMPAT_FAILURE" to listOf( genInitPay("COMPAT_FAILURE") ), "BATCH_SINGLE_SUCCESS" to listOf( genInitPay("FD622SMXKT5QWSAHDY0H8NYG3G"), ), // JEYMR3OYZTFM7505OWWENFPAH53LNOWJHS "BATCH_SINGLE_FAILURE" to listOf( genInitPay("DAFC3NEE4T48WVC560T76ABA2C"), ), "BATCH_SINGLE_RETURN" to listOf( genInitPay("KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5"), ), "BATCH_MANY_SUCCESS" to listOf( genInitPay("IVMIGCUIE7Q7VOF73R8GU3KGRYBZPAYC5V"), genInitPay("CDFN7I4FVIZ848DGDQ35DZ2K49H9EWXGAW"), genInitPay("35M1268GW5ZFHS5JCB41UKDQNPMD40T849"), genInitPay("HPOMV7A4E3P1TK9UZJS1WTM94A9V3X2SR1"), ), "BATCH_MANY_PART" to listOf( genInitPay("27SK3166EG36SJ7VP7VFYP0MW8"), genInitPay("KGTDBASWTJ6JM89WXD3Q5KFQC4"), genInitPay("8XK8Z7RAX224FGWK832FD40GYC"), ), // ZQOOPJC1DYBP52X119YGO6WMXU6NWIDPJK "BATCH_MANY_FAILURE" to listOf( genInitPay("4XTPKWE4A9V90PRQJCT8Z3MQZ8"), genInitPay("3VZZHVYJ6XP2SNPKWF4D4YVHNG"), ) )) // Register camt files db.register(cfg, "sample/platform/gls_camt052.xml", OrderDoc.report) db.register(cfg, "sample/platform/gls_camt053.xml", OrderDoc.statement) // TODO camt054 with missing id before and after // Check state db.check( status = mapOf( "COMPAT_SUCCESS" to Pair(SubmissionState.success, mapOf( "COMPAT_SUCCESS" to SubmissionState.success )), "COMPAT_FAILURE" to Pair(SubmissionState.pending, mapOf( "COMPAT_FAILURE" to SubmissionState.permanent_failure )), "BATCH_SINGLE_SUCCESS" to Pair(SubmissionState.success, mapOf( "FD622SMXKT5QWSAHDY0H8NYG3G" to SubmissionState.success )), "BATCH_SINGLE_FAILURE" to Pair(SubmissionState.pending, mapOf( // TODO success "DAFC3NEE4T48WVC560T76ABA2C" to SubmissionState.pending, // TODO failure )), "BATCH_SINGLE_RETURN" to Pair(SubmissionState.success, mapOf( "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5" to SubmissionState.late_failure, )), "BATCH_MANY_SUCCESS" to Pair(SubmissionState.success, mapOf( "IVMIGCUIE7Q7VOF73R8GU3KGRYBZPAYC5V" to SubmissionState.success, "CDFN7I4FVIZ848DGDQ35DZ2K49H9EWXGAW" to SubmissionState.success, "35M1268GW5ZFHS5JCB41UKDQNPMD40T849" to SubmissionState.success, "HPOMV7A4E3P1TK9UZJS1WTM94A9V3X2SR1" to SubmissionState.success, )), "BATCH_MANY_PART" to Pair(SubmissionState.success, mapOf( "27SK3166EG36SJ7VP7VFYP0MW8" to SubmissionState.success, "KGTDBASWTJ6JM89WXD3Q5KFQC4" to SubmissionState.permanent_failure, "8XK8Z7RAX224FGWK832FD40GYC" to SubmissionState.permanent_failure, )), "BATCH_MANY_FAILURE" to Pair(SubmissionState.pending, mapOf( // TODO success "4XTPKWE4A9V90PRQJCT8Z3MQZ8" to SubmissionState.pending, // TODO failure "3VZZHVYJ6XP2SNPKWF4D4YVHNG" to SubmissionState.pending, // TODO failure )) ), incoming = listOf( IncomingPayment( id = IncomingId(null, "BYLADEM1WOR-G2910276709458A2", "2024041210041357000"), amount = TalerAmount("EUR:3"), subject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", executionTime = dateToInstant("2024-04-12"), debtor = ibanPayto("DE84500105177118117964", "John Smith") ), ), outgoing = listOf( OutgoingPayment( id = OutgoingId(null, "COMPAT_SUCCESS", "2024041801514102000"), amount = TalerAmount("EUR:2"), subject = "TestABC123", executionTime = dateToInstant("2024-04-18"), creditor = ibanPayto("DE20500105172419259181", "John Smith") ), OutgoingPayment( id = OutgoingId(null, "FD622SMXKT5QWSAHDY0H8NYG3G", "2024090216552232000"), amount = TalerAmount("EUR:1.1"), subject = "single 2024-09-02T14:29:52.875253314Z", executionTime = dateToInstant("2024-09-02"), creditor = ibanPayto("DE89500105173198527518", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, "YF5QBARGQ0MNY0VK59S477VDG4", "2024041810552821000"), amount = TalerAmount("EUR:1.1"), subject = "Simple tx", executionTime = dateToInstant("2024-04-18"), creditor = ibanPayto("DE20500105172419259181", "John Smith") ), OutgoingPayment( id = OutgoingId(null, "IVMIGCUIE7Q7VOF73R8GU3KGRYBZPAYC5V", null), amount = TalerAmount("EUR:44"), subject = "init payment", executionTime = dateToInstant("2024-09-20"), creditor = ibanPayto("CH4189144589712575493", "Test") ), OutgoingPayment( id = OutgoingId(null, "CDFN7I4FVIZ848DGDQ35DZ2K49H9EWXGAW", null), amount = TalerAmount("EUR:44"), subject = "init payment", executionTime = dateToInstant("2024-09-20"), creditor = ibanPayto("CH4189144589712575493", "Test") ), OutgoingPayment( id = OutgoingId(null, "35M1268GW5ZFHS5JCB41UKDQNPMD40T849", null), amount = TalerAmount("EUR:44"), subject = "init payment", executionTime = dateToInstant("2024-09-20"), creditor = ibanPayto("CH4189144589712575493", "Test") ), OutgoingPayment( id = OutgoingId(null, "HPOMV7A4E3P1TK9UZJS1WTM94A9V3X2SR1", null), amount = TalerAmount("EUR:44"), subject = "init payment", executionTime = dateToInstant("2024-09-20"), creditor = ibanPayto("CH4189144589712575493", "Test") ), OutgoingPayment( id = OutgoingId(null, "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5", "2024092100252498000"), amount = TalerAmount("EUR:0.42"), subject = "This should fail because bad iban", executionTime = dateToInstant("2024-09-23"), creditor = ibanPayto("DE18500105173385245163", "John Smith") ), OutgoingPayment( id = OutgoingId(null, "27SK3166EG36SJ7VP7VFYP0MW8", null), amount = TalerAmount("EUR:44"), subject = "init payment", executionTime = dateToInstant("2024-09-04"), creditor = ibanPayto("CH4189144589712575493", "Test") ), ), bounced = emptyList() ) } /** Maerki Baumann dialect test */ @Test fun maerki_baumann() = setup("maerki_baumann.conf") { db, cfg -> db.batches(mapOf( "BATCH_SINGLE_REPORTING" to listOf( genInitPay("5IBJZOWESQGPCSOXSNNBBY49ZURI5W7Q4H"), genInitPay("XZ15UR0XU52QWI7Q4XB88EDS44PLH7DYXH"), genInitPay("A09R35EW0359SZ51464E7TC37A0P2CBK04"), genInitPay("UYXZ78LE9KAIMBY6UNXFYT1K8KNY8VLZLT"), ), )) // Register camt files db.register(cfg, "sample/platform/maerki_baumann_camt053.xml", OrderDoc.statement) // Check state db.check( status = mapOf( "BATCH_SINGLE_REPORTING" to Pair(SubmissionState.success, mapOf( "5IBJZOWESQGPCSOXSNNBBY49ZURI5W7Q4H" to SubmissionState.success, "XZ15UR0XU52QWI7Q4XB88EDS44PLH7DYXH" to SubmissionState.success, "A09R35EW0359SZ51464E7TC37A0P2CBK04" to SubmissionState.success, "UYXZ78LE9KAIMBY6UNXFYT1K8KNY8VLZLT" to SubmissionState.success, )), ), incoming = listOf( IncomingPayment( id = IncomingId("adbe4a5a-6cea-4263-b259-8ab964561a32", "41103099704.0002", "ZV20241104/765446/1"), amount = TalerAmount("CHF:1"), creditFee = TalerAmount("CHF:0.2"), subject = "SFHP6H24C16A5J05Q3FJW2XN1PB3EK70ZPY 5SJ30ADGY68FWN68G", executionTime = dateToInstant("2024-11-04"), debtor = ibanPayto("CH7389144832588726658", "Mr Test") ), IncomingPayment( id = IncomingId("7371795e-62fa-42dd-93b7-da89cc120faa", "41103099704.0003", "ZV20241104/765447/1"), amount = TalerAmount("CHF:1"), creditFee = TalerAmount("CHF:0.2"), subject = "Random subject", executionTime = dateToInstant("2024-11-04"), debtor = ibanPayto("CH7389144832588726658", "Mr Test") ), IncomingPayment( id = IncomingId(null, "50523424675.0001", "ZV20250523/851716/1"), amount = TalerAmount("CHF:0.5"), creditFee = TalerAmount("CHF:0.2"), subject = null, executionTime = dateToInstant("2025-05-23"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), IncomingPayment( id = IncomingId("f203fbb4-6e13-4c78-9b2a-d852fea6374a", "41202060702.0001", "ZV20241202/778108/1"), amount = TalerAmount("CHF:0.05"), creditFee = TalerAmount("CHF:0.2"), subject = "mini", executionTime = dateToInstant("2024-12-02"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), IncomingPayment( id = IncomingId("81b0d8c6-a677-4577-b75e-a639dcc03681", "41120636093.0001", "ZV20241121/773118/1"), amount = TalerAmount("CHF:0.1"), creditFee = TalerAmount("CHF:0.2"), subject = "small transfer test", executionTime = dateToInstant("2024-11-21"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), IncomingPayment( id = IncomingId(null, null, "ZV20250114/796191/1"), amount = TalerAmount("CHF:3003"), subject = "Fix bad payment by MB.", executionTime = dateToInstant("2025-01-27"), debtor = null ), IncomingPayment( id = IncomingId(null, "F000787951230001", "ZV20250526/852733/1"), amount = TalerAmount("CHF:1.38"), creditFee = TalerAmount("CHF:0.2"), subject = "Taler XT3D9MADR4V85JBWX47SMJFDQD2FDZDHHPH8R25YDG1KNVTSEH6G", executionTime = dateToInstant("2025-05-26"), debtor = ibanPayto("DE20500105172419259181", "Mr German") ), ), outgoing = listOf( OutgoingPayment( id = OutgoingId(null, "5IBJZOWESQGPCSOXSNNBBY49ZURI5W7Q4H", "ZV20241121/773541/1"), amount = TalerAmount("CHF:0.1"), subject = "multi 0 2024-11-21T15:21:59.8859234 63Z", executionTime = dateToInstant("2024-11-27"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, "XZ15UR0XU52QWI7Q4XB88EDS44PLH7DYXH", "ZV20241121/773541/4"), amount = TalerAmount("CHF:0.13"), subject = "multi 3 2024-11-21T15:21:59.8859234 63Z", executionTime = dateToInstant("2024-11-27"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, "A09R35EW0359SZ51464E7TC37A0P2CBK04", "ZV20241121/773541/3"), amount = TalerAmount("CHF:0.12"), subject = "multi 2 2024-11-21T15:21:59.8859234 63Z", executionTime = dateToInstant("2024-11-27"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, "UYXZ78LE9KAIMBY6UNXFYT1K8KNY8VLZLT", "ZV20241121/773541/2"), amount = TalerAmount("CHF:0.11"), subject = "multi 1 2024-11-21T15:21:59.8859234 63Z", executionTime = dateToInstant("2024-11-27"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, null, "GB20241220/205792/1"), amount = TalerAmount("CHF:3000"), subject = null, executionTime = dateToInstant("2024-12-20"), creditor = null ), ), bounced = listOf( OutgoingPayment( id = OutgoingId(null, null, null), amount = TalerAmount("CHF:1"), subject = "bounce 7371795e-62fa-42dd-93b7-da89cc120faa: missing reserve public key", executionTime = Instant.EPOCH, creditor = ibanPayto("CH7389144832588726658", "Mr Test") ), OutgoingPayment( id = OutgoingId(null, null, null), amount = TalerAmount("CHF:0.5"), subject = "bounce 50523424675.0001: missing subject", executionTime = Instant.EPOCH, creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, null, null), amount = TalerAmount("CHF:0.05"), subject = "bounce f203fbb4-6e13-4c78-9b2a-d852fea6374a: missing reserve public key", executionTime = Instant.EPOCH, creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, null, null), amount = TalerAmount("CHF:0.1"), subject = "bounce 81b0d8c6-a677-4577-b75e-a639dcc03681: missing reserve public key", executionTime = Instant.EPOCH, creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, null, null), amount = TalerAmount("CHF:1.38"), subject = "bounce F000787951230001: restricted account", executionTime = Instant.EPOCH, creditor = ibanPayto("DE20500105172419259181", "Mr German") ) ) ) } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/Iso20022Test.kt0000664000175000017500000010346415221677432024107 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.iso20022.* import tech.libeufin.ebics.* import kotlin.io.path.* import kotlin.test.* import java.time.Instant class Iso20022Test { @Test fun pain001() { val creditor = IbanAccountMetadata( iban = IBAN.parse("CH4189144589712575493"), bic = null, name = "Test" ) val msg = Pain001Msg( messageId = "MESSAGE_ID", timestamp = dateToInstant("2024-09-09"), debtor = IbanAccountMetadata( iban = IBAN.parse("CH7789144474425692816"), bic = "BIC", name = "myname" ), sum = TalerAmount("CHF:47.32"), txs = listOf( Pain001Tx( creditor = creditor, amount = TalerAmount("CHF:42"), subject = "Test 42", endToEndId = "TX_FIRST" ), Pain001Tx( creditor = creditor, amount = TalerAmount("CHF:5.11"), subject = "Test 5.11", endToEndId = "TX_SECOND" ), Pain001Tx( creditor = creditor, amount = TalerAmount("CHF:0.21"), subject = "Test 0.21", endToEndId = "TX_THIRD" ) ) ) for (dialect in Dialect.entries) { assertEquals( Path("sample/platform/${dialect}_pain001.xml").readText().replace("VERSION", VERSION), createPain001(msg, dialect, false).asUtf8() ) } } @Test fun hac() { assertContentEquals( parseCustomerAck(Path("sample/platform/hac.xml").inputStream()), listOf( CustomerAck( actionType = HacAction.FILE_DOWNLOAD, orderId = null, code = ExternalStatusReasonCode.TS01, info = "", timestamp = dateTimeToInstant("2024-09-02T15:47:30.350Z") ), CustomerAck( actionType = HacAction.FILE_UPLOAD, orderId = "ORDER_SUCCESS", code = ExternalStatusReasonCode.TS01, info = "", timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") ), CustomerAck( actionType = HacAction.ES_VERIFICATION, orderId = "ORDER_SUCCESS", code = ExternalStatusReasonCode.DS01, info = "", timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") ), CustomerAck( actionType = HacAction.ORDER_HAC_FINAL_POS, orderId = "ORDER_SUCCESS", code = null, info = "Some multiline info", timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") ), CustomerAck( actionType = HacAction.FILE_DOWNLOAD, orderId = null, code = ExternalStatusReasonCode.TD01, info = "", timestamp = dateTimeToInstant("2024-09-02T15:47:31.754Z") ), CustomerAck( actionType = HacAction.FILE_UPLOAD, orderId = "ORDER_FAILURE", code = ExternalStatusReasonCode.TS01, info = "", timestamp = dateTimeToInstant("2024-08-23T15:34:11.987") ), CustomerAck( actionType = HacAction.ES_VERIFICATION, orderId = "ORDER_FAILURE", code = ExternalStatusReasonCode.TD03, info = "", timestamp = dateTimeToInstant("2024-08-23T15:34:13.307") ), CustomerAck( actionType = HacAction.ORDER_HAC_FINAL_NEG, orderId = "ORDER_FAILURE", code = null, info = "", timestamp = dateTimeToInstant("2024-08-23T15:34:13.307") ), ) ) } @Test fun postfinance_camt054() { assertContentEquals( parseTx(Path("sample/platform/postfinance_camt054.xml").inputStream()), listOf(AccountTransactions( iban = "CH9289144596463965762", currency = "CHF", txs = listOf( OutgoingPayment( id = OutgoingId("ZS1PGNTSV0ZNDFAJBBWWB8015G", "ZS1PGNTSV0ZNDFAJBBWWB8015G", null), amount = TalerAmount("CHF:3.00"), subject = null, executionTime = dateToInstant("2024-01-15"), creditor = null ), IncomingPayment( id = IncomingId("62e2b511-7313-4ccd-8d40-c9d8e612cd71", null, "231121CH0AZWCR9T"), amount = TalerAmount("CHF:10"), subject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YBG", executionTime = dateToInstant("2023-12-19"), debtor = ibanPayto("CH7389144832588726658", "Mr Test") ), IncomingPayment( id = IncomingId("62e2b511-7313-4ccd-8d40-c9d8e612cd71", null, "231121CH0AZWCVR1"), amount = TalerAmount("CHF:2.53"), subject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YB", executionTime = dateToInstant("2023-12-19"), debtor = ibanPayto("CH7389144832588726658", "Mr Test") ), OutgoingReversal( endToEndId = "50820f78-9024-44ff-978d-63a18c", msgId = "50820f78-9024-44ff-978d-63a18c", reason = "", executionTime = dateToInstant("2024-01-15") ), OutgoingBatch( msgId = "ZS1PGNTSV0ZNDFAJBBWWB8015G", executionTime = dateToInstant("2024-01-15") ) ) )) ) } @Test fun postfinance_camt053() { assertContentEquals( parseTx(Path("sample/platform/postfinance_camt053.xml").inputStream()), listOf(AccountTransactions( iban = "CH9289144596463965762", currency = "CHF", txs = listOf( OutgoingReversal( endToEndId = "889d1a80-1267-49bd-8fcc-85701a", msgId = "889d1a80-1267-49bd-8fcc-85701a", reason = "InconsistenWithEndCustomer 'Identification of end customer is not consistent with associated account number, organisation ID or private ID.' - 'more info here ...'", executionTime = dateToInstant("2023-11-22") ), OutgoingReversal( endToEndId = "4cc61cc7-6230-49c2-b5e2-b40bbb", msgId = "4cc61cc7-6230-49c2-b5e2-b40bbb", reason = "MissingCreditorNameOrAddress 'Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing.' - 'more info here ...'", executionTime = dateToInstant("2023-11-22") ), OutgoingBatch( msgId = "EB4D22D428214261B2B3012D2A8CEC36", executionTime = dateToInstant("2024-08-26") ) ) )) ) } @Test fun valiant_camt052() { assertContentEquals( parseTx(Path("sample/platform/valiant_camt052.xml").inputStream()), listOf(AccountTransactions( iban = "CH7389144832588726658", currency = "CHF", txs = listOf( OutgoingPayment( id = OutgoingId("MJDJO2BDDBL7YSL2P96SXHG3TQZEZQD26L", "4UWWIDGTEIGDU6Z721QE95PYJSIEA48PYE", "ZV20251030/511372/1"), amount = TalerAmount("CHF:0.1"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "single 2025-10-30T09:46:04.55293090 9Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId("5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", "SKMU2891PAAYBDW22DBWX2W7KTFZ1CDFO8", "ZV20251030/511373/1"), amount = TalerAmount("CHF:0.1"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "multi 0 2025-10-30T09:46:10.3877961 30Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId("5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", "RC9YD301NZ17YKD6WDWLNOROFHIIN29VJN", "ZV20251030/511373/2"), amount = TalerAmount("CHF:0.11"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "multi 1 2025-10-30T09:46:10.3877961 30Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId("5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", "GKDGTHLB82X6XVHBJIJ1CK8MEGU9XJ2EL7", "ZV20251030/511373/3"), amount = TalerAmount("CHF:0.12"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "multi 2 2025-10-30T09:46:10.3877961 30Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId("5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", "PXCH2VVVTXEXBVDWICP23HZ4NV0H2CWW28", "ZV20251030/511373/4"), amount = TalerAmount("CHF:0.13"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "multi 3 2025-10-30T09:46:10.3877961 30Z", executionTime = dateToInstant("2025-10-30") ), IncomingPayment( id = IncomingId(null, "51030655601.0001", "ZV20251030/514778/1"), amount = TalerAmount("CHF:0.85"), subject = "fun stuff", executionTime = dateToInstant("2025-10-30"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), ), IncomingPayment( id = IncomingId(null, "51030655601.0002", "ZV20251030/514779/1"), amount = TalerAmount("CHF:0.95"), subject = "Taler PC2MKG0B7CK32K1T7DP08P6E1B7FHB6HY6R Q0PT3VTPBPRPYM1B0", executionTime = dateToInstant("2025-10-30"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), ), OutgoingPayment( id = OutgoingId("X166701F6RV59LP71RVWVIW9SV2AFZYLG4", "R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX", "ZV20251030/524078/1"), amount = TalerAmount("CHF:0.21"), creditor = ibanPayto("CH6208704048981247126", "John Smith"), subject = "bad name 2025-10-30T12:03:24.997478 811Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId("6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X", "02WDIX4J90Z1M1WNFHLNSXY59SHXQTQCMQ", "ZV20251030/524079/1"), amount = TalerAmount("CHF:0.1"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), subject = "single 2025-10-30T12:04:00.37042083 6Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId("6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X", "XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y", "ZV20251030/524079/2"), amount = TalerAmount("CHF:0.21"), creditor = ibanPayto("CH6208704048981247126", "John Smith"), subject = "bad name 2025-10-30T12:03:53.042190 686Z", executionTime = dateToInstant("2025-10-30") ), OutgoingReversal( endToEndId = "XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y", reason = "Error msg in german", executionTime = dateToInstant("2025-10-30") ), OutgoingReversal( endToEndId = "R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX", reason = "Error msg in german", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId("OLAMDPI6YPMNRZHQ5PQ6JCVUQV2AN5NW6P", "TU2WJ54DR9Z6HT5VE494BNH4EXUSM0DRF7", "ZV20251030/524077/1"), amount = TalerAmount("CHF:0.23"), debitFee = TalerAmount("CHF:5"), creditor = ibanPayto("DE48330605920000686018", "Christian Grothoff"), subject = "foreign iban 2025-10-30T12:03:44.0972 63765Z", executionTime = dateToInstant("2025-10-30") ), OutgoingPayment( id = OutgoingId("6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X", "GM8I8GIETR72LP6CFBGRBUDKNO2CEQBGOE", "ZV20251030/524080/1"), amount = TalerAmount("CHF:0.23"), debitFee = TalerAmount("CHF:5"), creditor = ibanPayto("DE48330605920000686018", "Christian Grothoff"), subject = "foreign iban 2025-10-30T12:03:58.0046 73747Z", executionTime = dateToInstant("2025-10-30") ), IncomingPayment( id = IncomingId("7b76d488-05d5-44ab-9d77-31d4165ec158", "00204EQY370", "ZV20251118/685062/1"), amount = TalerAmount("CHF:4.55"), subject = "TEST", executionTime = dateToInstant("2025-11-18"), debtor = null ), ) )) ) } @Test fun raiffeisen_camt053() { assertContentEquals( parseTx(Path("sample/platform/raiffeisen_camt053.xml").inputStream()), listOf(AccountTransactions( iban = "CH7389144832588726658", currency = null, txs = listOf( IncomingPayment( id = IncomingId(null, null, "A200020494367552"), amount = TalerAmount("CHF:20000"), subject = "1. TZ 2025", executionTime = dateToInstant("2025-12-23"), debtor = ibanPayto("CH7389144832588726658", "KANTON BERN") ), OutgoingPayment( id = OutgoingId(null, null, "19868398389"), amount = TalerAmount("CHF:15"), executionTime = dateToInstant("2025-12-31"), subject = null, creditor = null ), OutgoingPayment( id = OutgoingId(null, null, "19890406743"), amount = TalerAmount("CHF:2"), executionTime = dateToInstant("2025-12-31"), subject = null, creditor = null ), OutgoingPayment( id = OutgoingId(null, null, "19885172770"), amount = TalerAmount("CHF:3"), executionTime = dateToInstant("2025-12-31"), subject = null, creditor = null ), ) )) ) } @Test fun gls_camt052() { assertContentEquals( parseTx(Path("sample/platform/gls_camt052.xml").inputStream()), listOf(AccountTransactions( iban = "DE84500105177118117964", currency = "EUR", txs = listOf( OutgoingPayment( id = OutgoingId("COMPAT_SUCCESS", "COMPAT_SUCCESS", "2024041801514102000"), amount = TalerAmount("EUR:2"), subject = "TestABC123", executionTime = dateToInstant("2024-04-18"), creditor = ibanPayto("DE20500105172419259181", "John Smith") ), OutgoingReversal( endToEndId = "8XK8Z7RAX224FGWK832FD40GYC", reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN fehlerhaft und ungültig'", executionTime = dateToInstant("2024-09-05") ), IncomingPayment( id = IncomingId(null, "BYLADEM1WOR-G2910276709458A2", "2024041210041357000"), amount = TalerAmount("EUR:3"), subject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", executionTime = dateToInstant("2024-04-12"), debtor = ibanPayto("DE84500105177118117964", "John Smith") ), OutgoingReversal( endToEndId = "COMPAT_FAILURE", reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN ...'", executionTime = dateToInstant("2024-04-12") ), OutgoingPayment( id = OutgoingId("BATCH_SINGLE_SUCCESS", "FD622SMXKT5QWSAHDY0H8NYG3G", "2024090216552232000"), amount = TalerAmount("EUR:1.1"), subject = "single 2024-09-02T14:29:52.875253314Z", executionTime = dateToInstant("2024-09-02"), creditor = ibanPayto("DE89500105173198527518", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId("YF5QBARGQ0MNY0VK59S477VDG4", "YF5QBARGQ0MNY0VK59S477VDG4", "2024041810552821000"), amount = TalerAmount("EUR:1.1"), subject = "Simple tx", executionTime = dateToInstant("2024-04-18"), creditor = ibanPayto("DE20500105172419259181", "John Smith") ), OutgoingBatch( msgId = "BATCH_MANY_SUCCESS", executionTime = dateToInstant("2024-09-20"), ), OutgoingPayment( id = OutgoingId("BATCH_SINGLE_RETURN", "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5", "2024092100252498000"), amount = TalerAmount("EUR:0.42"), subject = "This should fail because bad iban", executionTime = dateToInstant("2024-09-23"), creditor = ibanPayto("DE18500105173385245163", "John Smith") ), OutgoingReversal( endToEndId = "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5", reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN fehlerhaft und ungültig'", executionTime = dateToInstant("2024-09-24") ), ) )) ) } @Test fun gls_camt053() { assertContentEquals( parseTx(Path("sample/platform/gls_camt053.xml").inputStream()), listOf(AccountTransactions( iban = "DE84500105177118117964", currency = "EUR", txs = listOf( OutgoingPayment( id = OutgoingId("COMPAT_SUCCESS", "COMPAT_SUCCESS", "2024041801514102000"), amount = TalerAmount("EUR:2"), subject = "TestABC123", executionTime = dateToInstant("2024-04-18"), creditor = ibanPayto("DE20500105172419259181", "John Smith") ), OutgoingReversal( endToEndId = "KGTDBASWTJ6JM89WXD3Q5KFQC4", reason = "Retoure aus SEPA Überweisung multi line", executionTime = dateToInstant("2024-09-04") ), OutgoingBatch( msgId = "BATCH_MANY_PART", executionTime = dateToInstant("2024-09-04") ), IncomingPayment( id = IncomingId(null, "BYLADEM1WOR-G2910276709458A2", "2024041210041357000"), amount = TalerAmount("EUR:3"), subject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", executionTime = dateToInstant("2024-04-12"), debtor = ibanPayto("DE84500105177118117964", "John Smith") ), OutgoingReversal( endToEndId = "COMPAT_FAILURE", reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN ...'", executionTime = dateToInstant("2024-04-12") ), OutgoingPayment( id = OutgoingId("BATCH_SINGLE_SUCCESS", "FD622SMXKT5QWSAHDY0H8NYG3G", "2024090216552232000"), amount = TalerAmount("EUR:1.1"), subject = "single 2024-09-02T14:29:52.875253314Z", executionTime = dateToInstant("2024-09-02"), creditor = ibanPayto("DE89500105173198527518", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId("YF5QBARGQ0MNY0VK59S477VDG4", "YF5QBARGQ0MNY0VK59S477VDG4", "2024041810552821000"), amount = TalerAmount("EUR:1.1"), subject = "Simple tx", executionTime = dateToInstant("2024-04-18"), creditor = ibanPayto("DE20500105172419259181", "John Smith") ), )) ) ) } @Test fun gls_camt054() { assertContentEquals( parseTx(Path("sample/platform/gls_camt054.xml").inputStream()), listOf(AccountTransactions( iban = "DE84500105177118117964", currency = "EUR", txs = listOf( IncomingPayment( id = IncomingId(null, "IS11PGENODEFF2DA8899900378806", null), amount = TalerAmount("EUR:2.5"), subject = "Test ICT", executionTime = dateToInstant("2024-05-05"), debtor = ibanPayto("DE84500105177118117964", "Mr Test") ) ) )) ) } @Test fun maerki_baumann_camt053() { assertContentEquals( parseTx(Path("sample/platform/maerki_baumann_camt053.xml").inputStream()), listOf(AccountTransactions( iban = "CH7389144832588726658", currency = "CHF", txs = listOf( IncomingPayment( id = IncomingId("adbe4a5a-6cea-4263-b259-8ab964561a32", "41103099704.0002", "ZV20241104/765446/1"), amount = TalerAmount("CHF:1"), creditFee = TalerAmount("CHF:0.2"), subject = "SFHP6H24C16A5J05Q3FJW2XN1PB3EK70ZPY 5SJ30ADGY68FWN68G", executionTime = dateToInstant("2024-11-04"), debtor = ibanPayto("CH7389144832588726658", "Mr Test") ), IncomingPayment( id = IncomingId("7371795e-62fa-42dd-93b7-da89cc120faa", "41103099704.0003", "ZV20241104/765447/1"), amount = TalerAmount("CHF:1"), creditFee = TalerAmount("CHF:0.2"), subject = "Random subject", executionTime = dateToInstant("2024-11-04"), debtor = ibanPayto("CH7389144832588726658", "Mr Test") ), IncomingPayment( id = IncomingId(null, "50523424675.0001", "ZV20250523/851716/1"), amount = TalerAmount("CHF:0.5"), creditFee = TalerAmount("CHF:0.2"), subject = null, executionTime = dateToInstant("2025-05-23"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId("BATCH_SINGLE_REPORTING", "5IBJZOWESQGPCSOXSNNBBY49ZURI5W7Q4H", "ZV20241121/773541/1"), amount = TalerAmount("CHF:0.1"), subject = "multi 0 2024-11-21T15:21:59.8859234 63Z", executionTime = dateToInstant("2024-11-27"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId("BATCH_SINGLE_REPORTING", "XZ15UR0XU52QWI7Q4XB88EDS44PLH7DYXH", "ZV20241121/773541/4"), amount = TalerAmount("CHF:0.13"), subject = "multi 3 2024-11-21T15:21:59.8859234 63Z", executionTime = dateToInstant("2024-11-27"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId("BATCH_SINGLE_REPORTING", "A09R35EW0359SZ51464E7TC37A0P2CBK04", "ZV20241121/773541/3"), amount = TalerAmount("CHF:0.12"), subject = "multi 2 2024-11-21T15:21:59.8859234 63Z", executionTime = dateToInstant("2024-11-27"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId("BATCH_SINGLE_REPORTING", "UYXZ78LE9KAIMBY6UNXFYT1K8KNY8VLZLT", "ZV20241121/773541/2"), amount = TalerAmount("CHF:0.11"), subject = "multi 1 2024-11-21T15:21:59.8859234 63Z", executionTime = dateToInstant("2024-11-27"), creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), IncomingPayment( id = IncomingId("f203fbb4-6e13-4c78-9b2a-d852fea6374a", "41202060702.0001", "ZV20241202/778108/1"), amount = TalerAmount("CHF:0.05"), creditFee = TalerAmount("CHF:0.2"), subject = "mini", executionTime = dateToInstant("2024-12-02"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), IncomingPayment( id = IncomingId("81b0d8c6-a677-4577-b75e-a639dcc03681", "41120636093.0001", "ZV20241121/773118/1"), amount = TalerAmount("CHF:0.1"), creditFee = TalerAmount("CHF:0.2"), subject = "small transfer test", executionTime = dateToInstant("2024-11-21"), debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") ), OutgoingPayment( id = OutgoingId(null, null, "GB20241220/205792/1"), amount = TalerAmount("CHF:3000"), subject = null, executionTime = dateToInstant("2024-12-20"), creditor = null ), IncomingPayment( id = IncomingId(null, null, "ZV20250114/796191/1"), amount = TalerAmount("CHF:3003"), subject = "Fix bad payment by MB.", executionTime = dateToInstant("2025-01-27"), debtor = null ), IncomingPayment( id = IncomingId(null, "F000787951230001", "ZV20250526/852733/1"), amount = TalerAmount("CHF:1.38"), creditFee = TalerAmount("CHF:0.2"), subject = "Taler XT3D9MADR4V85JBWX47SMJFDQD2FDZDHHPH8R25YDG1KNVTSEH6G", executionTime = dateToInstant("2025-05-26"), debtor = ibanPayto("DE20500105172419259181", "Mr German") ), ) )) ) } @Test fun pain002() { assertEquals( parseCustomerPaymentStatusReport(Path("sample/platform/pain002_part.xml").inputStream()), MsgStatus( id = "05BD4C5B4A2649B5B08F6EF6A31F197A", code = ExternalPaymentGroupStatusCode.PART, reasons = emptyList(), payments = listOf( PmtStatus( id = "NOTPROVIDED", code = ExternalPaymentGroupStatusCode.PART, reasons = listOf( Reason( code = ExternalStatusReasonCode.DT06, information = "Due date is not a working day. Order will be executed on the next working day" ) ), transactions = listOf( TxStatus( id = "AQCXNCPWD8PHW5JTN65Y5XTF7R", endToEndId = "AQCXNCPWD8PHW5JTN65Y5XTF7R", code = ExternalPaymentTransactionStatusCode.RJCT, reasons = listOf( Reason( code = ExternalStatusReasonCode.AC04, information = "Error message" ) ) ), TxStatus( id = "EE9SX76FC5YSC657EK3GMVZ9TC", endToEndId = "EE9SX76FC5YSC657EK3GMVZ9TC", code = ExternalPaymentTransactionStatusCode.RJCT, reasons = listOf( Reason( code = ExternalStatusReasonCode.MS03, information = "Error message" ) ) ), TxStatus( id = "V5B3MXPEWES9VQW1JDRD6VAET4", endToEndId = "V5B3MXPEWES9VQW1JDRD6VAET4", code = ExternalPaymentTransactionStatusCode.RJCT, reasons = listOf( Reason( code = ExternalStatusReasonCode.RR02, information = "Error message" ) ) ) ) ) ) ) ) assertEquals( parseCustomerPaymentStatusReport(Path("sample/platform/pain002_accp.xml").inputStream()), MsgStatus( id = "5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", code = ExternalPaymentGroupStatusCode.ACCP, reasons = listOf( Reason( code = null, information = "PN10630020F0297329.20251030104613.EBTUAAAC.PN1.0002372" ) ), payments = emptyList() ) ) } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/CliTest.kt0000664000175000017500000000557615156463305023502 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.asUtf8 import tech.libeufin.nexus.* import tech.libeufin.ebics.* import tech.libeufin.nexus.cli.LibeufinNexus import java.io.ByteArrayOutputStream import java.io.PrintStream import kotlin.io.path.* import kotlin.test.Test import kotlin.test.assertEquals val nexusCmd = LibeufinNexus() fun CliktCommand.testErr(cmd: String, msg: String) { val prevOut = System.err val tmpOut = ByteArrayOutputStream() System.setErr(PrintStream(tmpOut)) val result = test(cmd) System.setErr(prevOut) val tmpStr = tmpOut.asUtf8() println(tmpStr) assertEquals(1, result.statusCode, "'$cmd' should have failed") val line = tmpStr.substringAfterLast(" - ").trimEnd('\n') println(line) assertEquals(msg, line) } class CliTest { /** Test server check */ @Test fun serveCheck() { val confs = listOf( "mini" to 1, "test" to 0 ) for ((conf, statusCode) in confs) { val result = nexusCmd.test("serve --check -c conf/$conf.conf") assertEquals(statusCode, result.statusCode) } } /** Test list cmds */ @Test fun listCheck() = setup { db, _ -> fun check() { for (list in listOf("incoming", "outgoing", "initiated", "initiated --awaiting-ack")) { val result = nexusCmd.test("list $list -c conf/test.conf") assertEquals(0, result.statusCode) } } // Check empty check() // Check with transactions registerIn(db) registerOut(db) check() // Check with taler transactions talerableOut(db) talerableIn(db) talerableCompletedIn(db) talerableKycIn(db) talerablePreparedIn(db) talerablePreparedCompletedIn(db) check() // Check with incomplete registerIncompleteIn(db) talerableIncompleteIn(db) registerIncompleteOut(db) talerablePreparedIncompleteIn(db) check() } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/ObservabilityTest.kt0000664000175000017500000000245115122266731025573 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import io.ktor.client.request.* import org.junit.Test import tech.libeufin.common.TalerObservabilityConfig import tech.libeufin.common.assertOkJson import tech.libeufin.common.assertOk class ObservabilityApiTest { // GET /taler-observability/config @Test fun config() = serverSetup { client.get("/taler-observability/config").assertOkJson() } // GET /taler-observability/metrics @Test fun metrics() = serverSetup { db -> client.getA("/taler-observability/metrics").assertOk() } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/DatabaseTest.kt0000664000175000017500000014600215161724132024457 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.nexus.AccountType import tech.libeufin.nexus.NexusIngestConfig import tech.libeufin.nexus.iso20022.* import tech.libeufin.nexus.cli.* import tech.libeufin.nexus.db.* import tech.libeufin.nexus.db.PaymentDAO.* import tech.libeufin.nexus.db.InitiatedDAO.* import tech.libeufin.nexus.db.TransferDAO.* import tech.libeufin.ebics.* import java.time.Instant import java.util.UUID; import kotlin.test.* suspend fun Database.checkInCount(nbIncoming: Int, nbBounce: Int, nbTalerable: Int) = serializable( """ SELECT (SELECT count(*) FROM incoming_transactions) AS incoming, (SELECT count(*) FROM bounced_transactions) AS bounce, (SELECT count(*) FROM talerable_incoming_transactions) AS talerable; """ ) { one { assertEquals( Triple(nbIncoming, nbBounce, nbTalerable), Triple(it.getInt("incoming"), it.getInt("bounce"), it.getInt("talerable")) ) } } suspend fun Database.checkOutCount(nbIncoming: Int, nbTalerable: Int) = serializable( """ SELECT (SELECT count(*) FROM outgoing_transactions) AS incoming, (SELECT count(*) FROM talerable_outgoing_transactions) AS talerable; """ ) { one { assertEquals( Pair(nbIncoming, nbTalerable), Pair(it.getInt("incoming"), it.getInt("talerable")) ) } } sealed interface Status { data object Simple : Status data object Pending : Status data object Bounced : Status data object Incomplete : Status data class Reserve(val key: EddsaPublicKey) : Status data class Kyc(val key: EddsaPublicKey) : Status } suspend fun Database.checkIn(vararg expected: Status) { val current = this.serializable( """ SELECT pending_recurrent_incoming_transactions.authorization_pub IS NOT NULL, initiated_outgoing_transaction_id IS NOT NULL, debit_payto IS NULL OR subject IS NULL, type, metadata FROM incoming_transactions LEFT JOIN talerable_incoming_transactions USING (incoming_transaction_id) LEFT JOIN pending_recurrent_incoming_transactions USING (incoming_transaction_id) LEFT JOIN bounced_transactions USING (incoming_transaction_id) ORDER BY incoming_transaction_id """ ) { all { if (it.getBoolean(1)) { Status.Pending } else if (it.getBoolean(2)) { Status.Bounced } else if (it.getBoolean(3)) { Status.Incomplete } else { when (it.getOptEnum(4)) { null -> Status.Simple TransferType.reserve -> Status.Reserve(EddsaPublicKey(it.getBytes(5))) TransferType.kyc -> Status.Kyc(EddsaPublicKey(it.getBytes(5))) } } }.toList() } assertContentEquals(listOf(*expected), current) } class OutgoingPaymentsTest { @Test fun register() = setup { db, _ -> // Register initiated transaction for (subject in sequenceOf( "initiated by nexus", "${ShortHashCode.rand()} https://exchange.com/" )) { val pay = genOutPay(subject) assertIs( db.initiated.create(genInitPay(pay.id.endToEndId!!, subject)) ) val first = registerOutgoingPayment(db, pay) assertEquals(OutgoingRegistrationResult(id = first.id, initiated = true, new = true), first) assertEquals( OutgoingRegistrationResult(id = first.id, initiated = true, new = false), registerOutgoingPayment(db, pay) ) val refOnly = pay.copy(id = OutgoingId(null, null, acctSvcrRef = pay.id.endToEndId)) val second = registerOutgoingPayment(db, refOnly) assertEquals(OutgoingRegistrationResult(id = first.id + 1, initiated = false, new = true), second) assertEquals( OutgoingRegistrationResult(id = second.id, initiated = false, new = false), registerOutgoingPayment(db, refOnly) ) } db.checkOutCount(nbIncoming = 4, nbTalerable = 1) // Register unknown for (subject in sequenceOf( "not initiated by nexus", "${ShortHashCode.rand()} https://exchange.com/" )) { val pay = genOutPay(subject) val first = registerOutgoingPayment(db, pay) assertEquals(OutgoingRegistrationResult(id = first.id, initiated = false, new = true), first) assertEquals( OutgoingRegistrationResult(id = first.id, initiated = false, new = false), registerOutgoingPayment(db, pay) ) } db.checkOutCount(nbIncoming = 6, nbTalerable = 2) // Register wtid reuse val wtid = ShortHashCode.rand() for (subject in sequenceOf( "$wtid https://exchange.com/", "$wtid https://exchange.com/" )) { val pay = genOutPay(subject) val first = registerOutgoingPayment(db, pay) assertEquals(OutgoingRegistrationResult(id = first.id, initiated = false, new = true), first) assertEquals( OutgoingRegistrationResult(id = first.id, initiated = false, new = false), db.payment.registerOutgoing(pay, null, null, null) ) } db.checkOutCount(nbIncoming = 8, nbTalerable = 3) } @Test fun registerBatch() = setup { db, _ -> // Init batch val wtid = ShortHashCode.rand() for (subject in sequenceOf( "initiated by nexus", "${ShortHashCode.rand()} https://exchange.com/", "$wtid https://exchange.com/", "$wtid https://exchange.com/" )) { assertIs( db.initiated.create(genInitPay(randEbicsId(), subject=subject)) ) } db.initiated.batch(Instant.now(), "BATCH", false) // Register batch registerOutgoingBatch(db, OutgoingBatch("BATCH", Instant.now())); db.checkOutCount(nbIncoming = 4, nbTalerable = 2) // Test manual ack val txs = List(3) { nb -> assertIs( db.initiated.create(genInitPay(randEbicsId(), subject="tx $nb")) ).id } // Check not sent without ack db.initiated.batch(Instant.now(), "BATCH_MANUAL", true) registerOutgoingBatch(db, OutgoingBatch("BATCH_MANUAL", Instant.now())); db.checkOutCount(nbIncoming = 4, nbTalerable = 2) // Check sent with ack for (tx in txs) { db.initiated.ack(tx) } db.initiated.batch(Instant.now(), "BATCH_MANUAL", true) registerOutgoingBatch(db, OutgoingBatch("BATCH_MANUAL", Instant.now())); db.checkOutCount(nbIncoming = 7, nbTalerable = 2) } } class IncomingPaymentsTest { // Tests creating and bouncing incoming payments in one DB transaction @Test fun bounce() = setup { db, _ -> // creating and bouncing one incoming transaction. val payment = genInPay("incoming and bounced") val id = randEbicsId() db.payment.registerMalformedIncoming( payment, TalerAmount("KUDOS:2.53"), id, Instant.now(), "manual bounce" ).run { assertIs(this) assertTrue(new) assertEquals(id, bounceId) } db.payment.registerMalformedIncoming( payment, TalerAmount("KUDOS:2.53"), randEbicsId(), Instant.now(), "manual bounce" ).run { assertIs(this) assertFalse(new) assertEquals(id, bounceId) } db.conn { // Checking one incoming got created val checkIncoming = it.talerStatement(""" SELECT (amount).val as amount_value, (amount).frac as amount_frac FROM incoming_transactions WHERE incoming_transaction_id = 1 """).executeQuery() assertTrue(checkIncoming.next()) assertEquals(payment.amount.value, checkIncoming.getLong("amount_value")) assertEquals(payment.amount.frac, checkIncoming.getInt("amount_frac")) // Checking the bounced table got its row. val checkBounced = it.talerStatement(""" SELECT 1 FROM bounced_transactions WHERE incoming_transaction_id = 1 AND initiated_outgoing_transaction_id = 1 """).executeQuery() assertTrue(checkBounced.next()) // check the related initiated payment exists. val checkInitiated = it.talerStatement(""" SELECT (amount).val as amount_value ,(amount).frac as amount_frac FROM initiated_outgoing_transactions WHERE initiated_outgoing_transaction_id = 1 """).executeQuery() assertTrue(checkInitiated.next()) assertEquals( 53000000, checkInitiated.getInt("amount_frac") ) assertEquals( 2, checkInitiated.getInt("amount_value") ) } } // Test creating an incoming reserve transaction without and ID and reconcile it later again @Test fun simple() = setup { db, _ -> val cfg = NexusIngestConfig.default(AccountType.exchange) val subject = "test" // Register val incoming = genInPay(subject) registerIncomingPayment(db, cfg, incoming) db.checkIn(Status.Bounced) // Idempotent registerIncomingPayment(db, cfg, incoming) db.checkIn(Status.Bounced) // No key reuse registerIncomingPayment(db, cfg, genInPay(subject, "KUDOS:9")) registerIncomingPayment(db, cfg, genInPay("another $subject")) db.checkIn(Status.Bounced, Status.Bounced, Status.Bounced) // Admin balance adjust is ignored registerIncomingPayment(db, cfg, genInPay("ADMIN BALANCE ADJUST")) db.checkIn(Status.Bounced, Status.Bounced, Status.Bounced, Status.Simple) val original = genInPay("test 2") val incomplete = original.copy(subject = null, debtor = null) // Register incomplete transaction registerIncomingPayment(db, cfg, incomplete) db.checkIn(Status.Bounced, Status.Bounced, Status.Bounced, Status.Simple, Status.Incomplete) // Idempotent registerIncomingPayment(db, cfg, incomplete) db.checkIn(Status.Bounced, Status.Bounced, Status.Bounced, Status.Simple, Status.Incomplete) // Recover info when complete registerIncomingPayment(db, cfg, original) db.checkIn(Status.Bounced, Status.Bounced, Status.Bounced, Status.Simple, Status.Bounced) } // Test creating an incoming reserve taler transaction without and ID and reconcile it later again @Test fun talerable() = setup { db, _ -> val cfg = NexusIngestConfig.default(AccountType.exchange) val key = EddsaPublicKey.randEdsaKey() val subject = "test with $key reserve pub" // Register val incoming = genInPay(subject) registerIncomingPayment(db, cfg, incoming) db.checkIn(Status.Reserve(key)) // Idempotent registerIncomingPayment(db, cfg, incoming) db.checkIn(Status.Reserve(key)) // Key reuse is bounced registerIncomingPayment(db, cfg, genInPay(subject, "KUDOS:9")) registerIncomingPayment(db, cfg, genInPay("another $subject")) db.checkIn(Status.Reserve(key), Status.Bounced, Status.Bounced) // Admin balance adjust is ignored registerIncomingPayment(db, cfg, genInPay("ADMIN BALANCE ADJUST")) db.checkIn(Status.Reserve(key), Status.Bounced, Status.Bounced, Status.Simple) val newKey = EddsaPublicKey.randEdsaKey() val original = genInPay("test 2 with $newKey reserve pub") val incomplete = original.copy(subject = null, debtor = null) // Register incomplete transaction registerIncomingPayment(db, cfg, incomplete) db.checkIn(Status.Reserve(key), Status.Bounced, Status.Bounced, Status.Simple, Status.Incomplete) // Idempotent registerIncomingPayment(db, cfg, incomplete) db.checkIn(Status.Reserve(key), Status.Bounced, Status.Bounced, Status.Simple, Status.Incomplete) // Recover info when complete registerIncomingPayment(db, cfg, original) db.checkIn(Status.Reserve(key), Status.Bounced, Status.Bounced, Status.Simple, Status.Reserve(newKey)) } // Test creating an mapped reserve taler transaction without and ID and reconcile it later again @Test fun mapping() = setup { db, _ -> val cfg = NexusIngestConfig.default(AccountType.exchange) val firstKey = EddsaPublicKey.randEdsaKey() val authPub = EddsaPublicKey.randEdsaKey() val sig = EddsaSignature.rand() val referenceNumber = subjectFmtQrBill(authPub) val subject = "test with MAP:$authPub auth pub" assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = firstKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = true ) ) // Register val incoming = genInPay(subject) registerIncomingPayment(db, cfg, incoming) db.checkIn(Status.Reserve(firstKey)) // Idempotent registerIncomingPayment(db, cfg, incoming) db.checkIn(Status.Reserve(firstKey)) // Admin balance adjust is ignored registerIncomingPayment(db, cfg, genInPay("ADMIN BALANCE ADJUST")) db.checkIn(Status.Reserve(firstKey), Status.Simple) val original = genInPay("test 2 for $subject") val incomplete = original.copy(subject = null, debtor = null) // Register incomplete transaction registerIncomingPayment(db, cfg, incomplete) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Incomplete) // Idempotent registerIncomingPayment(db, cfg, incomplete) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Incomplete) // Recover info when complete registerIncomingPayment(db, cfg, original) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Pending) val secondKey = EddsaPublicKey.randEdsaKey() assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = secondKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = true ) ) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Reserve(secondKey)) // Key reuse is pending registerIncomingPayment(db, cfg, genInPay(subject, "KUDOS:9")) registerIncomingPayment(db, cfg, genInPay("another $subject")) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Reserve(secondKey), Status.Pending, Status.Pending) // Finish pending val thirdKey = EddsaPublicKey.randEdsaKey() assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = thirdKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = true ) ) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Reserve(secondKey), Status.Reserve(thirdKey), Status.Pending) } // Test creating an mapped reserve taler transaction without and ID and reconcile it later again @Test fun reference() = setup { db, _ -> val cfg = NexusIngestConfig.default(AccountType.exchange) val firstKey = EddsaPublicKey.randEdsaKey() val authPub = EddsaPublicKey.randEdsaKey() val sig = EddsaSignature.rand() val referenceNumber = subjectFmtQrBill(authPub) assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = firstKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = true ) ) // Register val incoming = genInPay(referenceNumber) registerIncomingPayment(db, cfg, incoming) db.checkIn(Status.Reserve(firstKey)) // Idempotent registerIncomingPayment(db, cfg, incoming) db.checkIn(Status.Reserve(firstKey)) // Admin balance adjust is ignored registerIncomingPayment(db, cfg, genInPay("ADMIN BALANCE ADJUST")) db.checkIn(Status.Reserve(firstKey), Status.Simple) val original = genInPay(referenceNumber) val incomplete = original.copy(subject = null, debtor = null) // Register incomplete transaction registerIncomingPayment(db, cfg, incomplete) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Incomplete) // Idempotent registerIncomingPayment(db, cfg, incomplete) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Incomplete) // Recover info when complete registerIncomingPayment(db, cfg, original) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Pending) val secondKey = EddsaPublicKey.randEdsaKey() assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = secondKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = true ) ) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Reserve(secondKey)) // Key reuse is pending registerIncomingPayment(db, cfg, genInPay(referenceNumber, "KUDOS:9")) registerIncomingPayment(db, cfg, genInPay(referenceNumber)) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Reserve(secondKey), Status.Pending, Status.Pending) // Finish pending val thirdKey = EddsaPublicKey.randEdsaKey() assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = thirdKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = true ) ) db.checkIn(Status.Reserve(firstKey), Status.Simple, Status.Reserve(secondKey), Status.Reserve(thirdKey), Status.Pending) } @Test fun recoverInfo() = setup { db, _ -> val cfg = NexusIngestConfig.default(AccountType.exchange) suspend fun Database.checkContent(payment: IncomingPayment) = serializable( """ SELECT uetr IS NOT DISTINCT FROM ? AND tx_id IS NOT DISTINCT FROM ? AND acct_svcr_ref IS NOT DISTINCT FROM ? AND subject IS NOT DISTINCT FROM ? AND debit_payto IS NOT DISTINCT FROM ? FROM incoming_transactions ORDER BY incoming_transaction_id DESC LIMIT 1 """ ) { bind(payment.id.uetr) bind(payment.id.txId) bind(payment.id.acctSvcrRef) bind(payment.subject) bind(payment.debtor?.toString()) one { assertTrue(it.getBoolean(1)) } } // Non talerable for ((index, partialId) in sequenceOf( IncomingId(UUID.randomUUID(), null, null), IncomingId(null, randEbicsId(), null), IncomingId(null, null, randEbicsId()), ).withIndex()) { val payment = genInPay("subject") // Register minimal val partialPayment = payment.copy(id = partialId, subject = null, debtor = null) registerIncomingPayment(db, cfg, partialPayment) db.checkContent(partialPayment) db.checkInCount(index + 1, index, 0) // Recover ID val fullId = IncomingId( partialId.uetr ?: UUID.randomUUID(), partialId.txId ?: randEbicsId(), partialId.acctSvcrRef ?: randEbicsId() ) val idPayment = partialPayment.copy(id = fullId) registerIncomingPayment(db, cfg, idPayment) db.checkContent(idPayment) db.checkInCount(index + 1, index, 0) // Recover subject & debtor val fullPayment = payment.copy(id = fullId) registerIncomingPayment(db, cfg, fullPayment) db.checkContent(fullPayment) db.checkInCount(index + 1, index + 1, 0) } // Talerable for ((index, partialId) in sequenceOf( IncomingId(UUID.randomUUID(), null, null), IncomingId(null, randEbicsId(), null), IncomingId(null, null, randEbicsId()), ).withIndex()) { val payment = genInPay("test with ${EddsaPublicKey.randEdsaKey()} reserve pub") // Register minimal val partialPayment = payment.copy(id = partialId, subject = null, debtor = null) registerIncomingPayment(db, cfg, partialPayment) db.checkContent(partialPayment) db.checkInCount(index + 4, 3, index) // Recover ID val fullId = IncomingId( partialId.uetr ?: UUID.randomUUID(), partialId.txId ?: randEbicsId(), partialId.acctSvcrRef ?: randEbicsId() ) val idPayment = partialPayment.copy(id = fullId) registerIncomingPayment(db, cfg, idPayment) db.checkContent(idPayment) db.checkInCount(index + 4, 3, index) // Recover subject & debtor val fullPayment = payment.copy(id = fullId) registerIncomingPayment(db, cfg, fullPayment) db.checkContent(fullPayment) db.checkInCount(index + 4, 3, index + 1) } } @Test fun horror() = setup { db, _ -> val cfg = NexusIngestConfig.default(AccountType.exchange) // Check we do not bounce already registered talerable transaction val key = EddsaPublicKey.randEdsaKey() val talerablePayment = genInPay("test with $key reserve pub") registerIncomingPayment(db, cfg, talerablePayment) db.payment.registerMalformedIncoming( talerablePayment, TalerAmount("KUDOS:2.53"), randEbicsId(), Instant.now(), "manual bounce" ).run { assertEquals(IncomingBounceRegistrationResult.Talerable, this) } registerIncomingPayment(db, cfg, talerablePayment.copy(subject=null)) registerIncomingPayment(db, cfg, talerablePayment) registerIncomingPayment(db, cfg, talerablePayment.copy(subject=null)) db.checkIn(Status.Reserve(key)) // Check we do not register as talerable bounced transaction val newKey = EddsaPublicKey.randEdsaKey() val bouncedPayment = genInPay("bounced $key") registerIncomingPayment(db, cfg, bouncedPayment.copy(subject=null)) registerIncomingPayment(db, cfg, bouncedPayment) registerIncomingPayment(db, cfg, bouncedPayment.copy(subject=null)) registerIncomingPayment(db, cfg, bouncedPayment) db.checkIn(Status.Reserve(key), Status.Bounced) } } class PaymentInitiationsTest { // Test skipping transaction based on config @Test fun skipping() = setup("skip.conf") { db, cfg -> suspend fun checkCount(nbTxs: Int, nbBounce: Int) { db.serializable( """ SELECT (SELECT count(*) FROM incoming_transactions) + (SELECT count(*) FROM outgoing_transactions) AS transactions, (SELECT count(*) FROM bounced_transactions) AS bounce """ ) { one { assertEquals( Pair(nbTxs, nbBounce), Pair(it.getInt("transactions"), it.getInt("bounce")) ) } } } suspend fun ingest(executionTime: Instant) { for (tx in sequenceOf( genInPay("test at $executionTime", executionTime = executionTime), genOutPay("test at $executionTime", executionTime = executionTime) )) { registerTransaction(db, cfg.ingest, tx) } } assertEquals(cfg.fetch.ignoreTransactionsBefore, dateToInstant("2024-04-04")) assertEquals(cfg.fetch.ignoreBouncesBefore, dateToInstant("2024-06-12")) // No transaction at the beginning checkCount(0, 0) // Skipped transactions ingest(cfg.fetch.ignoreTransactionsBefore.minusMillis(10)) checkCount(0, 0) // Skipped bounces ingest(cfg.fetch.ignoreTransactionsBefore) ingest(cfg.fetch.ignoreTransactionsBefore.plusMillis(10)) ingest(cfg.fetch.ignoreBouncesBefore.minusMillis(10)) checkCount(6, 0) // Bounces ingest(cfg.fetch.ignoreBouncesBefore) ingest(cfg.fetch.ignoreBouncesBefore.plusMillis(10)) checkCount(10, 2) } @Test fun status() = setup { db, _ -> suspend fun checkPart( batchId: Long, batchStatus: SubmissionState, batchMsg: String?, txStatus: SubmissionState, txMsg: String?, settledStatus: SubmissionState, settledMsg: String?, ) { // Check batch status val msgId = db.serializable( """ SELECT message_id, status, status_msg FROM initiated_outgoing_batches WHERE initiated_outgoing_batch_id=? """ ) { bind(batchId) one { val msgId = it.getString("message_id") assertEquals( batchStatus to batchMsg, it.getEnum("status") to it.getString("status_msg"), msgId ) msgId } } // Check tx status db.serializable( """ SELECT end_to_end_id, status, status_msg FROM initiated_outgoing_transactions WHERE initiated_outgoing_batch_id=? """ ) { bind(batchId) all { val endToEndId = it.getString("end_to_end_id") val expected = when (endToEndId) { "TX" -> Pair(txStatus, txMsg) "TX_SETTLED" -> Pair(settledStatus, settledMsg) else -> throw Exception("Unexpected tx $endToEndId") } assertEquals( expected, it.getEnum("status") to it.getString("status_msg"), "$msgId.$endToEndId" ) } } } suspend fun checkBatch(batchId: Long, status: SubmissionState, msg: String?, txStatus: SubmissionState? = null) { val txStatus = txStatus ?: status checkPart(batchId, status, msg, txStatus, msg, txStatus, msg) } suspend fun checkOrder(orderId: String, status: SubmissionState, msg: String?, txStatus: SubmissionState? = null) { val batchId = db.serializable( "SELECT initiated_outgoing_batch_id FROM initiated_outgoing_batches WHERE order_id=?" ) { bind(orderId) one { it.getLong("initiated_outgoing_batch_id") } } checkBatch(batchId, status, msg, txStatus) } suspend fun test(lambda: suspend (Long) -> Unit) { // Reset DB db.conn { conn -> conn.execSQLUpdate("DELETE FROM initiated_outgoing_transactions"); conn.execSQLUpdate("DELETE FROM initiated_outgoing_batches"); } // Create a test batch with three transactions for (id in sequenceOf("TX", "TX_SETTLED")) { assertIs( db.initiated.create(genInitPay(id)) ) } db.initiated.batch(Instant.now(), "BATCH", false) // Create witness transactions and batch for (id in sequenceOf("WITNESS_1", "WITNESS_2")) { assertIs( db.initiated.create(genInitPay(id)) ) } db.initiated.batch(Instant.now(), "BATCH_WITNESS", false) for (id in sequenceOf("WITNESS_3", "WITNESS_4")) { assertIs( db.initiated.create(genInitPay(id)) ) } // Check everything is unsubmitted db.serializable( """ SELECT (SELECT bool_and(status = 'unsubmitted') FROM initiated_outgoing_batches) AND (SELECT bool_and(status = 'unsubmitted') FROM initiated_outgoing_transactions) """ ) { one { assertTrue(it.getBoolean(1)) } } // Run test lambda(db.initiated.submittable().find { it.messageId == "BATCH" }!!.id) // Check witness status is unaltered db.serializable( """ SELECT (SELECT bool_and(status = 'unsubmitted') FROM initiated_outgoing_batches WHERE message_id != 'BATCH') AND (SELECT bool_and(initiated_outgoing_transactions.status = 'unsubmitted') FROM initiated_outgoing_transactions JOIN initiated_outgoing_batches USING (initiated_outgoing_batch_id) WHERE message_id != 'BATCH') """ ) { one { assertTrue(it.getBoolean(1)) } } } // Submission retry status test { batchId -> db.initiated.batchSubmissionFailure(batchId, Instant.now(), "First failure") checkBatch(batchId, SubmissionState.transient_failure, "First failure") db.initiated.batchSubmissionFailure(batchId, Instant.now(), "Second failure") checkBatch(batchId, SubmissionState.transient_failure, "Second failure") db.initiated.batchSubmissionSuccess(batchId, Instant.now(), "ORDER") checkOrder("ORDER", SubmissionState.pending, null) db.initiated.batchSubmissionSuccess(batchId, Instant.now(), "ORDER") checkOrder("ORDER", SubmissionState.pending, null) db.initiated.orderStep("ORDER", "step msg") checkOrder("ORDER", SubmissionState.pending, "step msg") db.initiated.orderStep("ORDER", "success msg") checkOrder("ORDER", SubmissionState.pending, "success msg") db.initiated.orderSuccess("ORDER") checkOrder("ORDER", SubmissionState.success, "success msg", SubmissionState.pending) db.initiated.orderStep("ORDER", "late msg") checkOrder("ORDER", SubmissionState.success, "success msg", SubmissionState.pending) } // Order step message on failure test { batchId -> db.initiated.batchSubmissionSuccess(batchId, Instant.now(), "ORDER") checkOrder("ORDER", SubmissionState.pending, null) db.initiated.orderStep("ORDER", "step msg") checkOrder("ORDER", SubmissionState.pending, "step msg") db.initiated.orderStep("ORDER", "failure msg") checkOrder("ORDER", SubmissionState.pending, "failure msg") assertEquals("failure msg", db.initiated.orderFailure("ORDER")!!.second) checkOrder("ORDER", SubmissionState.permanent_failure, "failure msg") db.initiated.orderStep("ORDER", "late msg") checkOrder("ORDER", SubmissionState.permanent_failure, "failure msg") } // Payment & batch status test { batchId -> checkBatch(batchId, SubmissionState.unsubmitted, null) db.initiated.batchStatusUpdate("BATCH", StatusUpdate.pending, "progress") checkBatch(batchId, SubmissionState.pending, "progress") db.initiated.txStatusUpdate("TX_SETTLED", null, StatusUpdate.success, "success") checkPart(batchId, SubmissionState.pending, "progress", SubmissionState.pending, "progress", SubmissionState.success, "success") db.initiated.batchStatusUpdate("BATCH", StatusUpdate.transient_failure, "waiting") checkPart(batchId, SubmissionState.transient_failure, "waiting", SubmissionState.transient_failure, "waiting", SubmissionState.success, "success") db.initiated.txStatusUpdate("TX", "BATCH", StatusUpdate.permanent_failure, "failure") checkPart(batchId, SubmissionState.success, null, SubmissionState.permanent_failure, "failure", SubmissionState.success, "success") db.initiated.txStatusUpdate("TX_SETTLED", "BATCH", StatusUpdate.permanent_failure, "late") checkPart(batchId, SubmissionState.success, null, SubmissionState.permanent_failure, "failure", SubmissionState.late_failure, "late") } // Registration test { batchId -> checkBatch(batchId, SubmissionState.unsubmitted, null) registerOutgoingPayment(db, genOutPay("", endToEndId = "TX_SETTLED")) checkPart(batchId, SubmissionState.unsubmitted, null, SubmissionState.unsubmitted, null, SubmissionState.success, null) registerOutgoingPayment(db, genOutPay("", endToEndId = "TX", msgId = "BATCH")) checkPart(batchId, SubmissionState.success, null, SubmissionState.success, null, SubmissionState.success, null) } // Transaction failure take over batch failures test { batchId -> checkBatch(batchId, SubmissionState.unsubmitted, null) db.initiated.batchStatusUpdate("BATCH", StatusUpdate.permanent_failure, "batch") checkPart(batchId, SubmissionState.permanent_failure, "batch", SubmissionState.permanent_failure, "batch", SubmissionState.permanent_failure, "batch") db.initiated.txStatusUpdate("TX", "BATCH", StatusUpdate.permanent_failure, "tx") db.initiated.batchStatusUpdate("BATCH", StatusUpdate.permanent_failure, "batch2") checkPart(batchId, SubmissionState.permanent_failure, "batch", SubmissionState.permanent_failure, "tx", SubmissionState.permanent_failure, "batch") } // Unknown order and batch db.initiated.batchSubmissionSuccess(42, Instant.now(), "ORDER_X") db.initiated.batchSubmissionFailure(42, Instant.now(), null) db.initiated.orderStep("ORDER_X", "msg") db.initiated.batchStatusUpdate("BATCH_X", StatusUpdate.success, null) db.initiated.txStatusUpdate("TX_X", "BATCH_X", StatusUpdate.success, "msg") assertNull(db.initiated.orderSuccess("ORDER_X")) assertNull(db.initiated.orderFailure("ORDER_X")) } @Test fun submittable() = setup { db, _ -> repeat(6) { assertIs( db.initiated.create(genInitPay("PAY$it")) ) db.initiated.batch(Instant.now(), "BATCH$it", false) } suspend fun checkIds(vararg ids: String) { assertEquals( listOf(*ids), db.initiated.submittable().flatMap { it.payments.map { it.endToEndId } } ) } checkIds("PAY0", "PAY1", "PAY2", "PAY3", "PAY4", "PAY5") // Check submitted not submitable db.initiated.batchSubmissionSuccess(1, Instant.now(), "ORDER1") checkIds("PAY1", "PAY2", "PAY3", "PAY4", "PAY5") // Check transient failure submitable last db.initiated.batchSubmissionFailure(2, Instant.now(), "Failure") checkIds("PAY2", "PAY3", "PAY4", "PAY5", "PAY1") // Check persistent failure not submitable db.initiated.batchSubmissionSuccess(4, Instant.now(), "ORDER3") db.initiated.orderFailure("ORDER3") checkIds("PAY2", "PAY4", "PAY5", "PAY1") db.initiated.batchSubmissionSuccess(5, Instant.now(), "ORDER4") db.initiated.orderFailure("ORDER4") checkIds("PAY2", "PAY5", "PAY1") // Check rotation db.initiated.batchSubmissionFailure(3, Instant.now(), "Failure") checkIds("PAY5", "PAY1", "PAY2") db.initiated.batchSubmissionFailure(6, Instant.now(), "Failure") checkIds("PAY1", "PAY2", "PAY5") db.initiated.batchSubmissionFailure(2, Instant.now(), "Failure") checkIds("PAY2", "PAY5", "PAY1") } // TODO test for unsettledTxInBatch } class EbicsTxTest { // Test pending transaction's id @Test fun pending() = setup { db, _ -> val ids = setOf("first", "second", "third") for (id in ids) { db.ebics.register(id) } repeat(ids.size) { val id = db.ebics.first() assert(ids.contains(id)) db.ebics.remove(id!!) } assertNull(db.ebics.first()) } } class TransferTest { suspend fun Database.mapTx(authPub: EddsaPublicKey) = this.payment.registerTalerableIncoming( genInPay("subject"), IncomingSubject.Map(authPub) ) suspend fun Database.qrTx(reference: String) = this.payment.registerQrBillIncoming( genInPay(reference), reference ) @Test fun registration() = setup { db, cfg -> val now = Instant.now() val accountPub = EddsaPublicKey.randEdsaKey() val authPub = EddsaPublicKey.randEdsaKey() val sig = EddsaSignature.rand() val referenceNumber = subjectFmtQrBill(authPub) // Register assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = accountPub, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = now, recurrent = false ) ) // Idempotent assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = accountPub, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = now, recurrent = false ) ) // Reference number reuse assertEquals( RegistrationResult.SubjectReuse, db.transfer.register( type = TransferType.reserve, accountPub = accountPub, authPub = EddsaPublicKey.randEdsaKey(), authSig = sig, referenceNumber = referenceNumber, timestamp = now, recurrent = false ) ) // Auth pub reuse replace existing one assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = accountPub, authPub = authPub, authSig = sig, referenceNumber = "032847109247158302947510329", timestamp = now, recurrent = false ) ) // Reserve pub reuse assertEquals( RegistrationResult.ReservePubReuse, db.transfer.register( type = TransferType.reserve, accountPub = accountPub, authPub = EddsaPublicKey.randEdsaKey(), authSig = sig, referenceNumber = "032847109247158302947510330", timestamp = now, recurrent = true ) ) // Non recurrent accept one then bounce assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = accountPub, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = now, recurrent = false ) ) assertEquals( IncomingRegistrationResult.Success(1, true, false, null, false), db.mapTx(authPub) ) db.checkIn( Status.Reserve(accountPub) ) assertEquals( IncomingRegistrationResult.MappingReuse, db.mapTx(authPub) ) // Recurrent accept one and delay val newKey = EddsaPublicKey.randEdsaKey() assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = newKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = now, recurrent = true ) ) assertEquals( IncomingRegistrationResult.Success(2, true, false, null, false), db.mapTx(authPub) ) assertEquals( IncomingRegistrationResult.Success(3, true, false, null, true), db.mapTx(authPub) ) assertEquals( IncomingRegistrationResult.Success(4, true, false, null, true), db.mapTx(authPub) ) assertEquals( IncomingRegistrationResult.Success(5, true, false, null, true), db.mapTx(authPub) ) assertEquals( IncomingRegistrationResult.Success(6, true, false, null, true), db.mapTx(authPub) ) db.checkIn( Status.Reserve(accountPub), Status.Reserve(newKey), Status.Pending, Status.Pending, Status.Pending, Status.Pending ) // Complete pending on recurrent update val kycKey = EddsaPublicKey.randEdsaKey() assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.kyc, accountPub = kycKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = now, recurrent = true ) ) assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = kycKey, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = now, recurrent = true ) ) db.checkIn( Status.Reserve(accountPub), Status.Reserve(newKey), Status.Kyc(kycKey), Status.Reserve(kycKey), Status.Pending, Status.Pending, ) // Kyc key reuse keep pending ones registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), genInPay(fmtIncomingSubject(IncomingType.kyc, kycKey))) db.checkIn( Status.Reserve(accountPub), Status.Reserve(newKey), Status.Kyc(kycKey), Status.Reserve(kycKey), Status.Pending, Status.Pending, Status.Kyc(kycKey) ) // Switching to non recurrent cancel pending val lastAccountPub = EddsaPublicKey.randEdsaKey() val lastAuthPub = EddsaPublicKey.randEdsaKey() val lastReferenceNumber = subjectFmtQrBill(lastAuthPub) assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = lastAccountPub, authPub = lastAuthPub, authSig = sig, referenceNumber = lastReferenceNumber, timestamp = now, recurrent = true ) ) assertEquals( IncomingRegistrationResult.Success(8, true, false, null, false), db.mapTx(lastAuthPub) ) assertEquals( IncomingRegistrationResult.Success(9, true, false, null, true), db.mapTx(lastAuthPub) ) assertEquals( IncomingRegistrationResult.Success(10, true, false, null, true), db.mapTx(lastAuthPub) ) db.checkIn( Status.Reserve(accountPub), Status.Reserve(newKey), Status.Kyc(kycKey), Status.Reserve(kycKey), Status.Pending, Status.Pending, Status.Kyc(kycKey), Status.Reserve(lastAccountPub), Status.Pending, Status.Pending, ) assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.kyc, accountPub = lastAccountPub, authPub = lastAuthPub, authSig = sig, referenceNumber = lastReferenceNumber, timestamp = now, recurrent = false ) ) db.checkIn( Status.Reserve(accountPub), Status.Reserve(newKey), Status.Kyc(kycKey), Status.Reserve(kycKey), Status.Pending, Status.Pending, Status.Kyc(kycKey), Status.Reserve(lastAccountPub), Status.Bounced, Status.Bounced, ) } @Test fun delete() = setup { db, _ -> val authPub = EddsaPublicKey.randEdsaKey() val sig = EddsaSignature.rand() val referenceNumber = subjectFmtQrBill(authPub) val payto = IbanPayto.rand("Sir Florian") val amount = TalerAmount("KUDOS:2.53") // Unknown assertFalse(db.transfer.unregister(authPub, Instant.now())) // Unused assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = authPub, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = false ) ) assertTrue(db.transfer.unregister(authPub, Instant.now())) assertFalse(db.transfer.unregister(authPub, Instant.now())) assertEquals( IncomingRegistrationResult.UnknownMapping, db.mapTx(authPub) ) assertEquals( IncomingRegistrationResult.UnknownMapping, db.qrTx(referenceNumber) ) // Register after deletion is idempotent if already known assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = authPub, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = false ) ) val cfg = NexusIngestConfig.default(AccountType.exchange) val payment = genInPay(referenceNumber) assertEquals(IncomingRegistrationResult.Success(1, true, false, null, false), db.payment.registerQrBillIncoming(payment, referenceNumber)) assertEquals(IncomingRegistrationResult.Success(1, false, false, null, false), db.payment.registerQrBillIncoming(payment, referenceNumber)) db.checkIn(Status.Reserve(authPub)) assertTrue(db.transfer.unregister(authPub, Instant.now())) registerIncomingPayment(db, cfg, payment) assertEquals(IncomingRegistrationResult.Success(1, false, false, null, false), db.payment.registerQrBillIncoming(payment, referenceNumber)) db.checkIn(Status.Reserve(authPub)) // Test mapped transfers behavior after deletion assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.kyc, accountPub = authPub, authPub = authPub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = true ) ) // First is registered assertEquals( IncomingRegistrationResult.Success(2, true, false, null, false), db.qrTx(referenceNumber) ) // Other are pending assertEquals( IncomingRegistrationResult.Success(3, true, false, null, true), db.qrTx(referenceNumber) ) assertEquals( IncomingRegistrationResult.Success(4, true, false, null, true), db.mapTx(authPub) ) db.checkIn(Status.Reserve(authPub), Status.Kyc(authPub), Status.Pending, Status.Pending) assertTrue(db.transfer.unregister(authPub, Instant.now())) db.checkIn(Status.Reserve(authPub), Status.Kyc(authPub), Status.Bounced, Status.Bounced) assertEquals( IncomingRegistrationResult.UnknownMapping, db.mapTx(authPub) ) assertEquals( IncomingRegistrationResult.UnknownMapping, db.qrTx(referenceNumber) ) } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/OpenApiTest.kt0000664000175000017500000000412015204341712024275 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.junit.Test import sun.misc.Unsafe import tech.libeufin.common.* import tech.libeufin.nexus.db.Database import tech.libeufin.nexus.nexusApi import tech.libeufin.nexus.nexusConfig import java.io.File import kotlin.io.path.Path import kotlin.test.* class OpenApiTest { private fun fakeDatabase(): Database { val field = Unsafe::class.java.getDeclaredField("theUnsafe") field.isAccessible = true val unsafe = field.get(null) as Unsafe return unsafe.allocateInstance(Database::class.java) as Database } @Test fun generateSpec() { val cfg = nexusConfig(Path("conf/test.conf")) testApplication { application { nexusApi(fakeDatabase(), cfg, serveSpec = true) } val resp = client.get("/openapi.yaml") resp.assertOk() val spec = resp.bodyAsText() assertTrue(spec.contains("openapi: 3.1.0"), "Response should be a valid OpenAPI spec") assertTrue(spec.contains("LibEuFin Nexus API"), "Spec should contain the API title") val outFile = File("build/openapi.yaml") outFile.writeText(spec) println("OpenAPI spec written to ${outFile.absolutePath}") } } } libeufin-1.6.8/libeufin-nexus/src/test/kotlin/routines.kt0000664000175000017500000000534615122266731023773 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.http.* import io.ktor.server.testing.* import tech.libeufin.common.TalerErrorCode import tech.libeufin.common.assertBadRequest import tech.libeufin.common.assertUnauthorized import tech.libeufin.common.test.abstractHistoryRoutine // Test endpoint is correctly authenticated suspend fun ApplicationTestBuilder.authRoutine( method: HttpMethod, path: String, token: Boolean = true ) { // No header client.request(path) { this.method = method }.assertUnauthorized(TalerErrorCode.GENERIC_PARAMETER_MISSING) // Bad header client.request(path) { this.method = method headers[HttpHeaders.Authorization] = "WTF" }.assertBadRequest(TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED) // Wrong scheme if (token) { client.request(path) { this.method = method headers[HttpHeaders.Authorization] = "Basic bad-token" }.assertUnauthorized(TalerErrorCode.GENERIC_UNAUTHORIZED) } else { client.request(path) { this.method = method headers[HttpHeaders.Authorization] = "Bearer bad-token" }.assertUnauthorized(TalerErrorCode.GENERIC_UNAUTHORIZED) } // Bad token if (token) { client.request(path) { this.method = method headers[HttpHeaders.Authorization] = "Bearer bad-token" }.assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) } else { client.request(path) { this.method = method basicAuth("username", "bad-password") }.assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) } } suspend inline fun ApplicationTestBuilder.historyRoutine( url: String, crossinline ids: (B) -> List, registered: List Unit>, ignored: List Unit> = listOf(), polling: Boolean = true ) { abstractHistoryRoutine(ids, registered, ignored, polling) { params: String -> client.getA("$url?$params") } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/WireGatewayApiTest.kt0000664000175000017500000004267615221677432025660 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.http.* import io.ktor.server.testing.* import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.nexus.cli.registerOutgoingPayment import tech.libeufin.ebics.randEbicsId import java.time.Instant import kotlin.test.* class WireGatewayApiTest { // GET /taler-wire-gateway/config @Test fun config() = serverSetup { client.get("/taler-wire-gateway/config").assertOk() } // POST /taler-wire-gateway/transfer @Test fun transfer() = serverSetup { val valid_req = obj { "request_uid" to HashCode.rand() "amount" to "CHF:55" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to grothoffPayto } authRoutine(HttpMethod.Post, "/taler-wire-gateway/transfer") // Check OK client.postA("/taler-wire-gateway/transfer") { json(valid_req) }.assertOk() // check idempotency client.postA("/taler-wire-gateway/transfer") { json(valid_req) }.assertOk() val with_metadata = obj(valid_req) { "request_uid" to HashCode.rand() "metadata" to "ID" "wtid" to ShortHashCode.rand() } client.postA("/taler-wire-gateway/transfer") { json(with_metadata) }.assertOk() client.postA("/taler-wire-gateway/transfer") { json(with_metadata) }.assertOk() // Malformed metadata listOf("bad_id", "bad id", "bad@id.com", "A".repeat(41)).forEach { client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to HashCode.rand() "metadata" to it "wtid" to ShortHashCode.rand() } }.assertBadRequest() } // Trigger conflict due to reused request_uid client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "wtid" to ShortHashCode.rand() "exchange_base_url" to "http://different-exchange.example.com/" } }.assertConflict(TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED) // Trigger conflict due to reused wtid client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to HashCode.rand() } }.assertConflict(TalerErrorCode.BANK_TRANSFER_WTID_REUSED) // Currency mismatch client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "amount" to "EUR:33" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Bad BASE32 wtid client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "wtid" to "I love chocolate" } }.assertBadRequest() // Bad BASE32 len wtid client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "wtid" to Base32Crockford.encode(ByteArray(31).rand()) } }.assertBadRequest() // Bad BASE32 request_uid client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to "I love chocolate" } }.assertBadRequest() // Bad BASE32 len wtid client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to Base32Crockford.encode(ByteArray(65).rand()) } }.assertBadRequest() // Missing receiver-name client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "credit_account" to "payto://iban/CH7389144832588726658" } }.assertBadRequest() // Bad payto kind client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "credit_account" to "payto://x-taler-bank/bank.hostname.test/bar?receiver-name=Mr+Tom" } }.assertBadRequest() // Bad baseURL for (bad in sequenceOf("not-a-url", "file://not.http.com/", "no.transport.com/", "https://not.a/base/url")) { client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "exchange_base_url" to bad } }.assertBadRequest() } } // GET /taler-wire-gateway/transfers/{ROW_ID} @Test fun transferById() = serverSetup { val wtid = ShortHashCode.rand() val valid_req = obj { "request_uid" to HashCode.rand() "amount" to "CHF:55" "exchange_base_url" to "http://exchange.example.com/" "wtid" to wtid "credit_account" to grothoffPayto } authRoutine(HttpMethod.Get, "/taler-wire-gateway/transfers/1") val resp = client.postA("/taler-wire-gateway/transfer") { json(valid_req) }.assertOkJson() // Check OK client.getA("/taler-wire-gateway/transfers/${resp.row_id}") .assertOkJson { tx -> assertEquals(TransferStatusState.pending, tx.status) assertEquals(TalerAmount("CHF:55"), tx.amount) assertEquals("http://exchange.example.com/", tx.origin_exchange_url) assertNull(tx.metadata) assertEquals(wtid, tx.wtid) assertEquals(resp.timestamp, tx.timestamp) } client.postA("/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to HashCode.rand() "metadata" to "ID" "wtid" to ShortHashCode.rand() } }.assertOkJson { client.getA("/taler-wire-gateway/transfers/${it.row_id}") .assertOkJson { tx -> assertEquals(tx.metadata, "ID") } } // Check unknown transaction client.getA("/taler-wire-gateway/transfers/42") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } // GET /accounts/{USERNAME}/taler-wire-gateway/transfers @Test fun transferPage() = serverSetup { db -> authRoutine(HttpMethod.Get, "/taler-wire-gateway/transfers") client.getA("/taler-wire-gateway/transfers").assertNoContent() repeat(6) { client.postA("/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to "CHF:55" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to grothoffPayto } }.assertOkJson() db.initiated.batch(Instant.now(), randEbicsId(), false) } client.getA("/taler-wire-gateway/transfers") .assertOkJson { assertEquals(6, it.transfers.size) assertEquals( it, client.getA("/taler-wire-gateway/transfers?status=pending").assertOkJson() ) } client.getA("/taler-wire-gateway/transfers?status=success").assertNoContent() db.initiated.batchSubmissionSuccess(1, Instant.now(), "ORDER1") db.initiated.batchSubmissionFailure(2, Instant.now(), "Failure") db.initiated.batchSubmissionFailure(3, Instant.now(), "Failure") client.getA("/taler-wire-gateway/transfers?status=transient_failure").assertOkJson { assertEquals(2, it.transfers.size) } client.getA("/taler-wire-gateway/transfers?status=pending").assertOkJson { assertEquals(4, it.transfers.size) } } // GET /taler-wire-gateway/history/incoming @Test fun historyIncoming() = serverSetup { db -> authRoutine(HttpMethod.Get, "/taler-wire-gateway/history/incoming") historyRoutine( url = "/taler-wire-gateway/history/incoming", ids = { it.incoming_transactions.map { it.row_id } }, registered = listOf( // Reserve transactions using clean add incoming logic { addIncoming("CHF:12") }, // Reserve transactions using raw bank transaction logic { talerableIn(db) }, { talerableCompletedIn(db) }, { talerablePreparedIn(db) }, { talerablePreparedCompletedIn(db) }, // KYC transactions using clean add incoming logic { addKyc("CHF:12") }, // KYC transactions using raw bank transaction logic { talerableKycIn(db) }, ), ignored = listOf( // Ignore malformed incoming transaction { registerIn(db) }, // Ignore malformed incomplete { registerIncompleteIn(db) }, // Ignore malformed completed { registerCompletedIn(db) }, // Ignore incompleted { talerableIncompleteIn(db) }, // Ignore outgoing transaction { talerableOut(db) }, // Ignore prepared incomplete { talerablePreparedIncompleteIn(db) }, ) ) } // GET /taler-wire-gateway/history/outgoing @Test fun historyOutgoing() = serverSetup { db -> authRoutine(HttpMethod.Get, "/taler-wire-gateway/history/outgoing") historyRoutine( url = "/taler-wire-gateway/history/outgoing", ids = { it.outgoing_transactions.map { it.row_id } }, registered = listOf( // Transfer using raw bank transaction logic { talerableOut(db) }, // And with metadata { talerableOut(db, "CON.ID") } ), ignored = listOf( // Ignore pending transfers { transfer() }, // Ignore manual incoming transaction { talerableIn(db) }, // Ignore malformed incoming transaction { registerIn(db) }, // Ignore malformed outgoing transaction { registerOutgoingPayment(db, genOutPay("ignored")) }, ) ) println(client.getA("/taler-wire-gateway/history/outgoing?limit=2") .assertOkJson() .outgoing_transactions .map { it.amount.toString() to it.metadata }) assertContentEquals( client.getA("/taler-wire-gateway/history/outgoing?limit=2") .assertOkJson() .outgoing_transactions .map { it.amount.toString() to it.metadata } ,listOf( "CHF:44" to null, "CHF:44" to "CON.ID", ) ) } suspend fun ApplicationTestBuilder.talerAddIncomingRoutine(type: IncomingType) { val (path, key) = when (type) { IncomingType.reserve -> Pair("add-incoming", "reserve_pub") IncomingType.kyc -> Pair("add-kycauth", "account_pub") IncomingType.map -> Pair("add-mapped", "authorization_pub") } val (priv, pub) = EddsaPublicKey.randEdsaKeyPair() client.post("/taler-prepared-transfer/registration") { json(SubjectRequest( Payto.parse("payto://iban/CH7789144474425692816"), TransferType.reserve, false, TalerAmount("CHF:44"), PublicKeyAlg.EdDSA, pub, pub, EddsaSignature.rand() ).sign(priv)) }.assertOkJson() val valid_req = obj { "amount" to "CHF:44" key to pub "debit_account" to grothoffPayto } authRoutine(HttpMethod.Post, "/taler-wire-gateway/admin/$path") // Check OK client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) }.assertOk() when (type) { IncomingType.reserve -> { // Trigger conflict due to reused reserve_pub client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) }.assertConflict(TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT) } IncomingType.kyc -> { // Non conflict on reuse client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) }.assertOk() } IncomingType.map -> { // Trigger conflict due to reused authorization_pub client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) }.assertConflict(TalerErrorCode.BANK_TRANSFER_MAPPING_REUSED) // Trigger conflict due to unknown authorization_pub client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) { key to EddsaPublicKey.randEdsaKey() } }.assertConflict(TalerErrorCode.BANK_TRANSFER_MAPPING_UNKNOWN) } } // Currency mismatch client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) { "amount" to "EUR:33" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Bad BASE32 reserve_pub client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) { key to "I love chocolate" } }.assertBadRequest() // Bad BASE32 len reserve_pub client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) { key to Base32Crockford.encode(ByteArray(31).rand()) } }.assertBadRequest() // Bad payto kind client.postA("/taler-wire-gateway/admin/$path") { json(valid_req) { "debit_account" to "payto://x-taler-bank/bank.hostname.test/bar" } }.assertBadRequest() } // POST /taler-wire-gateway/admin/add-incoming @Test fun addIncoming() = serverSetup { talerAddIncomingRoutine(IncomingType.reserve) } // POST /taler-wire-gateway/admin/add-kycauth @Test fun addKycAuth() = serverSetup { talerAddIncomingRoutine(IncomingType.kyc) } // POST /taler-wire-gateway/admin/add-mapped @Test fun addMapped() = serverSetup { talerAddIncomingRoutine(IncomingType.map) } @Test fun addIncomingMix() = serverSetup { db -> addIncoming("CHF:1") addKyc("CHF:2") talerableIn(db, amount = "CHF:3") talerableKycIn(db, amount = "CHF:4") talerablePreparedIn(db, amount = "CHF:5") client.getA("/taler-wire-gateway/history/incoming?limit=25").assertOkJson { assertEquals(5, it.incoming_transactions.size) it.incoming_transactions.forEachIndexed { i, tx -> assertEquals(TalerAmount("CHF:${i+1}"), tx.amount) if (i % 2 == 1) { val tmp = assertIs(tx) if (i < 4) { assertNull(tmp.authorization_pub) assertNull(tmp.authorization_sig) } else { assertNotNull(tmp.authorization_pub) assertNotNull(tmp.authorization_sig) } } else { val tmp = assertIs(tx) if (i < 4) { assertNull(tmp.authorization_pub) assertNull(tmp.authorization_sig) } else { assertNotNull(tmp.authorization_pub) assertNotNull(tmp.authorization_sig) } } } } } // POST /taler-wire-gateway/account/check @Test fun accountCheck() = serverSetup { client.getA("/taler-wire-gateway/account/check").assertNotImplemented() } @Test fun noApi() = serverSetup("mini.conf") { client.get("/taler-wire-gateway/config").assertNotImplemented() } @Test fun auth() = serverSetup("auth.conf") { authRoutine(HttpMethod.Get, "/taler-wire-gateway/history/incoming", false) client.get("/taler-wire-gateway/history/incoming") { basicAuth("username", "password") }.assertNoContent() } }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/helpers.kt0000664000175000017500000002471215156463305023566 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import kotlinx.coroutines.runBlocking import tech.libeufin.common.* import tech.libeufin.common.db.dbInit import tech.libeufin.common.db.pgDataSource import tech.libeufin.ebics.* import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.registerIncomingPayment import tech.libeufin.nexus.cli.registerOutgoingPayment import tech.libeufin.nexus.db.Database import tech.libeufin.nexus.db.InitiatedPayment import tech.libeufin.nexus.db.TransferDAO.RegistrationResult import tech.libeufin.nexus.iso20022.* import java.time.Instant import kotlin.io.path.Path import kotlin.test.assertEquals fun conf( conf: String = "test.conf", lambda: suspend (NexusConfig) -> Unit ) = runBlocking { val cfg = nexusConfig(Path("conf/$conf")) lambda(cfg) } fun setup( conf: String = "test.conf", lambda: suspend (Database, NexusConfig) -> Unit ) = conf(conf) { cfg -> pgDataSource(cfg.dbCfg.dbConnStr).dbInit(cfg.dbCfg, "libeufin-nexus", true) cfg.withDb(lambda) } fun serverSetup( conf: String = "test.conf", lambda: suspend ApplicationTestBuilder.(Database) -> Unit ) = setup(conf) { db, cfg -> testApplication { application { nexusApi(db, cfg) } lambda(db) } } const val grothoffPayto = "payto://iban/CH4189144589712575493?receiver-name=Grothoff%20Hans" val clientKeys = generateNewKeys() /** Generates a payment initiation, given its subject */ fun genInitPay( endToEndId: String, subject: String = "init payment", amount: String = "KUDOS:44", creditor: IbanPayto = ibanPayto("CH4189144589712575493", "Test") ) = InitiatedPayment( id = -1, amount = TalerAmount(amount), creditor = creditor, subject = subject, initiationTime = Instant.now(), endToEndId = endToEndId ) /** Generates an incoming payment, given its subject */ fun genInPay( subject: String, amount: String = "KUDOS:44", executionTime: Instant = Instant.now() ) = IncomingPayment( amount = TalerAmount(amount), debtor = ibanPayto("DE84500105177118117964", "John Smith"), subject = subject, executionTime = executionTime, id = IncomingId(null, randEbicsId(), null) ) /** Generates an outgoing payment, given its subject and end-to-end ID */ fun genOutPay( subject: String, endToEndId: String? = null, msgId: String? = null, executionTime: Instant = Instant.now() ) = OutgoingPayment( id = OutgoingId(msgId, endToEndId ?: randEbicsId(), null), amount = TalerAmount(44, 0, "KUDOS"), creditor = ibanPayto("CH4189144589712575493", "Test"), subject = subject, executionTime = executionTime, ) /** Perform a taler outgoing transaction */ suspend fun ApplicationTestBuilder.transfer() { client.postA("/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to "CHF:55" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to grothoffPayto } }.assertOk() } /** Perform a taler incoming transaction of [amount] from merchant to exchange */ suspend fun ApplicationTestBuilder.addIncoming(amount: String) { client.postA("/taler-wire-gateway/admin/add-incoming") { json { "amount" to TalerAmount(amount) "reserve_pub" to EddsaPublicKey.randEdsaKey() "debit_account" to grothoffPayto } }.assertOk() } /** Perform a taler kyc transaction of [amount] from merchant to exchange */ suspend fun ApplicationTestBuilder.addKyc(amount: String) { client.postA("/taler-wire-gateway/admin/add-kycauth") { json { "amount" to TalerAmount(amount) "account_pub" to EddsaPublicKey.randEdsaKey() "debit_account" to grothoffPayto } }.assertOk() } /** Register a talerable outgoing transaction */ suspend fun talerableOut(db: Database, metadata: String? = null) { val wtid = EddsaPublicKey.randEdsaKey() registerOutgoingPayment(db, genOutPay(fmtOutgoingSubject(wtid, BaseURL.parse("http://exchange.example.com/"), metadata))) } /** Register a talerable reserve incoming transaction */ suspend fun talerableIn( db: Database, amount: String = "CHF:44", reserve_pub: EddsaPublicKey = EddsaPublicKey.randEdsaKey() ) { registerIncomingPayment( db, NexusIngestConfig.default(AccountType.exchange), genInPay("test with $reserve_pub reserve pub", amount) ) } private suspend fun prepare(db: Database): String { val pub = EddsaPublicKey.randEdsaKey() val sig = EddsaSignature.rand() val referenceNumber = subjectFmtQrBill(pub) assertEquals( RegistrationResult.Success, db.transfer.register( type = TransferType.reserve, accountPub = pub, authPub = pub, authSig = sig, referenceNumber = referenceNumber, timestamp = Instant.now(), recurrent = false ) ) return referenceNumber } /** Register a talerable reserve prepared incoming transaction */ suspend fun talerablePreparedIn(db: Database, amount: String = "CHF:44") { val referenceNumber = prepare(db) registerIncomingPayment( db, NexusIngestConfig.default(AccountType.exchange), genInPay(referenceNumber, amount) ) } /** Register an incomplete talerable reserve prepared incoming transaction */ suspend fun talerablePreparedIncompleteIn(db: Database, amount: String = "CHF:44") { val referenceNumber = prepare(db) val incomplete = genInPay(referenceNumber).copy(subject = null, debtor = null) registerIncomingPayment( db, NexusIngestConfig.default(AccountType.exchange), incomplete ) } /** Register a completed talerable reserve prepared incoming transaction */ suspend fun talerablePreparedCompletedIn(db: Database, amount: String = "CHF:44") { val referenceNumber = prepare(db) val original = genInPay(referenceNumber, amount) val incomplete = original.copy(subject = null, debtor = null) registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), incomplete) registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), original) } /** Register an incomplete talerable reserve incoming transaction */ suspend fun talerableIncompleteIn(db: Database) { val reserve_pub = EddsaPublicKey.randEdsaKey() val incomplete = genInPay("test with $reserve_pub reserve pub").copy(subject = null, debtor = null) registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), incomplete) } /** Register a completed talerable reserve incoming transaction */ suspend fun talerableCompletedIn(db: Database) { val reserve_pub = EddsaPublicKey.randEdsaKey() val original = genInPay("test with $reserve_pub reserve pub") val incomplete = original.copy(subject = null, debtor = null) registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), incomplete) registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), original) } /** Register a talerable KYC incoming transaction */ suspend fun talerableKycIn( db: Database, amount: String = "CHF:44", account_pub: EddsaPublicKey = EddsaPublicKey.randEdsaKey() ) { registerIncomingPayment( db, NexusIngestConfig.default(AccountType.exchange), genInPay("test with KYC:$account_pub account pub", amount) ) } /** Register an incoming transaction */ suspend fun registerIn(db: Database) { registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), genInPay("ignored")) } /** Register an incomplete incoming transaction */ suspend fun registerIncompleteIn(db: Database) { val incomplete = genInPay("ignored").copy(subject = null, debtor = null) registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), incomplete) } /** Register a completed incoming transaction */ suspend fun registerCompletedIn(db: Database) { val original = genInPay("ignored") val incomplete = original.copy(subject = null, debtor = null) registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), incomplete) registerIncomingPayment(db, NexusIngestConfig.default(AccountType.exchange), original) } /** Register an outgoing transaction */ suspend fun registerOut(db: Database) { registerOutgoingPayment(db, genOutPay("ignored")) } /** Register an incomplete outgoing transaction */ suspend fun registerIncompleteOut(db: Database) { val original = genOutPay("ignored") val incomplete = original.copy(id = OutgoingId(null, null, original.id.endToEndId), creditor = null) registerOutgoingPayment(db, incomplete) } /* ----- Auth ----- */ /** Auto auth get request */ suspend inline fun HttpClient.getA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { return get(url) { auth() builder(this) } } /** Auto auth post request */ suspend inline fun HttpClient.postA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { return post(url) { auth() builder(this) } } /** Auto auth patch request */ suspend inline fun HttpClient.patchA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { return patch(url) { auth() builder(this) } } /** Auto auth delete request */ suspend inline fun HttpClient.deleteA(url: String, builder: HttpRequestBuilder.() -> Unit = {}): HttpResponse { return delete(url) { auth() builder(this) } } fun HttpRequestBuilder.auth() { headers[HttpHeaders.Authorization] = "Bearer secret-token" }libeufin-1.6.8/libeufin-nexus/src/test/kotlin/RevenueApiTest.kt0000664000175000017500000000460315156463305025024 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import io.ktor.client.request.* import org.junit.Test import tech.libeufin.common.RevenueIncomingHistory import tech.libeufin.common.assertNotImplemented import tech.libeufin.common.assertOk class RevenueApiTest { // GET /taler-revenue/config @Test fun config() = serverSetup { client.get("/taler-revenue/config").assertOk() } // GET /taler-revenue/history @Test fun history() = serverSetup { db -> authRoutine(HttpMethod.Get, "/taler-revenue/history") historyRoutine( url = "/taler-revenue/history", ids = { it.incoming_transactions.map { it.row_id } }, registered = listOf( // Transactions using clean transfer logic { talerableIn(db) }, { talerableCompletedIn(db) }, { talerablePreparedIn(db) }, { talerablePreparedCompletedIn(db) }, // Common credit transactions { registerIn(db) }, { registerCompletedIn(db) } ), ignored = listOf( // Ignore debit transactions { talerableOut(db) }, // Ignore incomplete { registerIncompleteIn(db) }, { talerableIncompleteIn(db) }, { talerablePreparedIncompleteIn(db) }, ) ) } @Test fun noApi() = serverSetup("mini.conf") { client.getA("/taler-revenue/config").assertNotImplemented() } @Test fun auth() = serverSetup("auth.conf") { authRoutine(HttpMethod.Get, "/taler-revenue/history") } }libeufin-1.6.8/libeufin-nexus/build.gradle0000664000175000017500000000505315204341712020761 0ustar grothoffgrothoffplugins { id("kotlin") id("application") id("com.gradleup.shadow") version "$shadow_version" id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version" } version = rootProject.version java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } compileKotlin.kotlinOptions.jvmTarget = "17" compileTestKotlin.kotlinOptions.jvmTarget = "17" sourceSets.main.java.srcDirs = ["src/main/kotlin"] dependencies { // Core language libraries implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") implementation(project(":libeufin-common")) implementation(project(":libeufin-ebics")) // Metrics implementation("io.prometheus:prometheus-metrics-core:$prometheus_version") implementation("io.prometheus:prometheus-metrics-instrumentation-jvm:$prometheus_version") implementation("io.prometheus:prometheus-metrics-exposition-formats:$prometheus_version") // Command line parsing implementation("com.github.ajalt.clikt:clikt:$clikt_version") implementation("org.postgresql:postgresql:$postgres_version") // Ktor client library implementation("io.ktor:ktor-server-core:$ktor_version") implementation("io.ktor:ktor-client-cio:$ktor_version") implementation("io.ktor:ktor-client-websockets:$ktor_version") // UNIX domain sockets support (used to connect to PostgreSQL) implementation("com.kohlschutter.junixsocket:junixsocket-core:$junixsocket_version") // Serialization implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") // OpenAPI spec generation implementation("io.github.smiley4:ktor-openapi:5.6.0") implementation("io.github.smiley4:schema-kenerator-core:2.6.0") // Unit testing testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version") testImplementation("io.ktor:ktor-server-test-host:$ktor_version") testImplementation("io.ktor:ktor-server-cio:$ktor_version") } application { mainClass = "tech.libeufin.nexus.MainKt" } shadowJar { version = "" minimize { // Kotlin serialization exclude(dependency("io.ktor:ktor-serialization-kotlinx-json:.*")) // Postgres unix socket driver exclude(dependency("com.kohlschutter.junixsocket:junixsocket-core:.*")) // CIO engine exclude(dependency("io.ktor:ktor-client-cio:.*")) // Crypto exclude(dependency("org.bouncycastle:.*")) // CLI exclude(dependency("com.github.ajalt.mordant:mordant:.*")) // PDF exclude(dependency("com.itextpdf:itext-core:.*")) } }libeufin-1.6.8/libeufin-nexus/codegen.py0000775000175000017500000001153515122266731020473 0ustar grothoffgrothoff#!/usr/bin/python3 # Update EBICS constants file using latest external code sets files from io import BytesIO from zipfile import ZipFile import polars as pl import requests def iso20022codegenExternalCodeSet(): # Get XLSX zip file from server r = requests.get( "https://www.iso20022.org/sites/default/files/media/file/ExternalCodeSets_XLSX.zip" ) assert r.status_code == 200 # Unzip the XLSX file zip = ZipFile(BytesIO(r.content)) files = zip.namelist() assert len(files) == 1 bytes = zip.read(files[0]) # Parse excel df = pl.read_excel(bytes, sheet_name="AllCodeSets") def extractCodeSet(setName: str, className: str) -> str: out = f"enum class {className}(val isoCode: String, val description: String) {{" for row in ( df.filter(pl.col("Code Set") == setName).sort("Code Value").rows(named=True) ): (value, isoCode, description) = ( row["Code Value"], row["Code Name"], row["Code Definition"].split("\n", 1)[0].strip().replace("_x000D_", ""), ) out += f'\n\t{value}("{isoCode}", "{description}"),' out += "\n}" return out # Write kotlin file kt = f"""/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ // THIS FILE IS GENERATED, DO NOT EDIT package tech.libeufin.nexus.iso20022 {extractCodeSet("ExternalStatusReason1Code", "ExternalStatusReasonCode")} {extractCodeSet("ExternalPaymentGroupStatus1Code", "ExternalPaymentGroupStatusCode")} {extractCodeSet("ExternalPaymentTransactionStatus1Code", "ExternalPaymentTransactionStatusCode")} {extractCodeSet("ExternalReturnReason1Code", "ExternalReturnReasonCode")} """ with open( "src/main/kotlin/tech/libeufin/nexus/iso20022/ExternalCodeSets.kt", "w" ) as file1: file1.write(kt) def iso20022codegenBankTransactionCode(): # Get XLSX zip file from server r = requests.get( "https://www.iso20022.org/sites/default/files/media/file/BTC_Codification_21March2024.xlsx" ) assert r.status_code == 200 # Get the XLSX file bytes = r.content # Parse excel df = pl.read_excel( bytes, sheet_name="BTC_Codification", read_options={"header_row": 2}, ).rename(lambda name: name.splitlines()[0]) def extractCodeSet(setName: str, className: str) -> str: out = f"enum class {className}(val description: String) {{" codeName = f"{setName} Code" for row in ( df.group_by(codeName) .agg(pl.col(setName).unique().sort()) .sort(codeName) .rows(named=True) ): if len(row[setName]) > 1: print(row) (code, description) = ( row[codeName].strip().replace("\xa0", ""), row[setName][0].strip(), ) out += f'\n\t{code}("{description}"),' out += "\n}" return out # Write kotlin file kt = f"""/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ // THIS FILE IS GENERATED, DO NOT EDIT package tech.libeufin.nexus.iso20022 {extractCodeSet("Domain", "ExternalBankTransactionDomainCode")} {extractCodeSet("Family", "ExternalBankTransactionFamilyCode")} {extractCodeSet("SubFamily", "ExternalBankTransactionSubFamilyCode")} """ with open( "src/main/kotlin/tech/libeufin/nexus/iso20022/BankTransactionCode.kt", "w" ) as file1: file1.write(kt) iso20022codegenExternalCodeSet() iso20022codegenBankTransactionCode() libeufin-1.6.8/libeufin-nexus/sample/0000775000175000017500000000000015236145704017770 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/sample/platform/0000775000175000017500000000000015236145704021614 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/sample/platform/postfinance_camt053.xml0000664000175000017500000001407415122266731026107 0ustar grothoffgrothoff CH9289144596463965762 CHF 1.00 CRDT true BOOK
2023-11-22
32632000B04CYPIK PMNT ICDT RRTN 889d1a80-1267-49bd-8fcc-85701a 231122CH0B04CYPI NOTPROVIDED NOTPROVIDED NOTPROVIDED 3e53516e-c0d3-450d-b6fc-69161ebe5942 1.00 CRDT PMNT ICDT RRTN BE01 more info here ...
1.00 CRDT true BOOK
2023-11-22
32632000B04KLEEK PMNT ICDT RRTN 4cc61cc7-6230-49c2-b5e2-b40bbb 231122CH0B04KLEE NOTPROVIDED NOTPROVIDED NOTPROVIDED 635d1493-cf6c-4ece-91b9-926daf2d4213 1.00 CRDT PMNT ICDT RRTN RR03 more info here ...
406.00 DBIT false BOOK
2024-08-26
PMNT ICDT AUTT EB4D22D428214261B2B3012D2A8CEC36 NOTPROVIDED fe4ba22a-8fc4-4f9b-80fc-12c4157a90bc 406.00 DBIT PMNT ICDT AUTT EZAG ISO 20022 BULK ORDER E-FINANCE NOTPROVIDED EB4D22D428214261B2B3012D2A8CEC36
libeufin-1.6.8/libeufin-nexus/sample/platform/postfinance_pain001.xml0000664000175000017500000000321315122266731026074 0ustar grothoffgrothoffMESSAGE_ID2024-09-09T00:00:00Z347.32mynameNOTPROVIDEDTRFfalse347.32
2024-09-09Z
mynameCH7789144474425692816BICSLEVTX_FIRSTTX_FIRST42TestCH4189144589712575493Test 42TX_SECONDTX_SECOND5.11TestCH4189144589712575493Test 5.11TX_THIRDTX_THIRD0.21TestCH4189144589712575493Test 0.21
libeufin-1.6.8/libeufin-nexus/sample/platform/maerki_baumann_pain001.xml0000664000175000017500000000321315122266731026534 0ustar grothoffgrothoffMESSAGE_ID2024-09-09T00:00:00Z347.32mynameNOTPROVIDEDTRFfalse347.32
2024-09-09Z
mynameCH7789144474425692816BICSLEVTX_FIRSTTX_FIRST42TestCH4189144589712575493Test 42TX_SECONDTX_SECOND5.11TestCH4189144589712575493Test 5.11TX_THIRDTX_THIRD0.21TestCH4189144589712575493Test 0.21
libeufin-1.6.8/libeufin-nexus/sample/platform/raiffeisen_pain001.xml0000664000175000017500000000321315161724132025673 0ustar grothoffgrothoffMESSAGE_ID2024-09-09T00:00:00Z347.32mynameNOTPROVIDEDTRFfalse347.32
2024-09-09Z
mynameCH7789144474425692816BICSLEVTX_FIRSTTX_FIRST42TestCH4189144589712575493Test 42TX_SECONDTX_SECOND5.11TestCH4189144589712575493Test 5.11TX_THIRDTX_THIRD0.21TestCH4189144589712575493Test 0.21
libeufin-1.6.8/libeufin-nexus/sample/platform/raiffeisen_camt053.xml0000664000175000017500000001564315161724132025711 0ustar grothoffgrothoff M/20574741277/CA 2025-09-26T00:54:24+02:00 1 true SPS/1.7/PROD M/20574741277/CAl 268 2025-09-26T00:54:24+02:00 2025-09-25T00:00:00+02:00 2025-09-26T00:00:00+02:00 CH7389144832588726658 Taler Operations AG Raiffeisenbank Seeland OPBD 458.16 CRDT
2025-09-25
CLBD 458.16 CRDT
2025-09-25
CLAV 458.16 CRDT
2025-09-25
20000 CRDT BOOK
2025-12-23
2025-12-23
A200020494367552 PMNT RCDT DMCT 1000 1 A200020494367552 01-470006005102602025 430002300186732025 20000 CRDT KANTON BERN Munsterplatz 12 3011 Bern CH CH7389144832588726658 POFICHBE PostFinance Nordring 8 3030 Bern CH 1. TZ 2025
15 DBIT BOOK
2025-12-30
2025-12-31
19868398389 ACMT MDOP FEES 8002 1 19868398389 15 DBIT Gebührenbelastung Kontoführung 01.10.2025 - 31.12.2025
2 DBIT BOOK
2025-12-31
2025-12-31
19890406743 ACMT MDOP FEES 8002 1 19890406743 2 DBIT Gebührenbelastung Belege und Auszüge 01.10.2025 - 31.12.2025
3 DBIT BOOK
2025-12-31
2025-12-31
19885172770 ACMT MDOP FEES 8002 1 19885172770 3 DBIT Gebührenbelastung Versand und Verpackung 01.10.2025 - 31.12.2025
libeufin-1.6.8/libeufin-nexus/sample/platform/hac.xml0000664000175000017500000001630415122266731023073 0ustar grothoffgrothoff FILE_DOWNLOAD 2024-09-02T15:47:30.350Z TimeStamp TS01 FILE_UPLOAD ORDER_SUCCESS OrderID 2024-09-02T20:48:43.153Z TimeStamp TS01 ES_VERIFICATION ORDER_SUCCESS OrderID 2024-09-02T20:48:43.153Z TimeStamp DS01 ORDER_HAC_FINAL_POS ORDER_SUCCESS OrderID 2024-09-02T20:48:43.153Z TimeStamp Some multiline info FILE_DOWNLOAD 2024-09-02T15:47:31.754Z TimeStamp TD01 FILE_UPLOAD ORDER_FAILURE OrderID 2024-08-23T15:34:11.987Z TimeStamp TS01 ES_VERIFICATION ORDER_FAILURE OrderID 2024-08-23T15:34:13.307Z TimeStamp TD03 ORDER_HAC_FINAL_NEG ORDER_FAILURE OrderID 2024-08-23T15:34:13.307Z TimeStamp libeufin-1.6.8/libeufin-nexus/sample/platform/pain002_part.xml0000664000175000017500000000421715122266731024537 0ustar grothoffgrothoff 05BD4C5B4A2649B5B08F6EF6A31F197A PART NOTPROVIDED PART DT06 Due date is not a working day. Order will be executed on the next working day AQCXNCPWD8PHW5JTN65Y5XTF7R AQCXNCPWD8PHW5JTN65Y5XTF7R RJCT AC04 Error message EE9SX76FC5YSC657EK3GMVZ9TC EE9SX76FC5YSC657EK3GMVZ9TC RJCT MS03 Error message V5B3MXPEWES9VQW1JDRD6VAET4 V5B3MXPEWES9VQW1JDRD6VAET4 RJCT RR02 Error message libeufin-1.6.8/libeufin-nexus/sample/platform/valiant_pain001.xml0000664000175000017500000000321315122266731025221 0ustar grothoffgrothoffMESSAGE_ID2024-09-09T00:00:00Z347.32mynameNOTPROVIDEDTRFfalse347.32
2024-09-09Z
mynameCH7789144474425692816BICSLEVTX_FIRSTTX_FIRST42TestCH4189144589712575493Test 42TX_SECONDTX_SECOND5.11TestCH4189144589712575493Test 5.11TX_THIRDTX_THIRD0.21TestCH4189144589712575493Test 0.21
libeufin-1.6.8/libeufin-nexus/sample/platform/gls_camt052.xml0000664000175000017500000004770215122266731024366 0ustar grothoffgrothoff DE84500105177118117964 EUR 2.00 DBIT BOOK
2024-04-18
2024041801514102000 PMNT ICDT ESCT COMPAT_SUCCESS NOTPROVIDED NOTPROVIDED 2024041785403105090200000010000001 2.00 PMNT ICDT ESCT NTRF+177+08381 DK Mr Test DE84500105177118117964 John Smith DE20500105172419259181 BYLADEM1WOR TestABC123 Überweisungsauftrag
1.10 CRDT BOOK
2024-09-05
2024-09-05
2024090509342698000 PMNT ICDT RRTN NRTI+159+00931 DK 8XK8Z7RAX224FGWK832FD40GYC 2024090455250415090200000010000003 1.10 PMNT ICDT RRTN NRTI+159+00931 DK Florian Dold DE89500105171325381664 John Smith DE18500105173385245163 Retoure SEPA multi line 116 DK GENODEM1GLS AC01 IBAN fehlerhaft und ungültig Retouren
3.00 CRDT BOOK
2024-04-12
2024041210041357000 PMNT RCDT ESCT NOTPROVIDED BYLADEM1WOR-G2910276709458A2 3.00 PMNT RCDT ESCT John Smith DE84500105177118117964 Mr Test DE20500105172419259181 BYLADEM1WOR Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,- Überweisungsgutschr.
1.10 CRDT BOOK
2024-04-12
2024041210041357000 PMNT ICDT RRTN COMPAT_FAILURE 2024042288942205090200000010000001 1.10 PMNT ICDT RRTN John Smith DE84500105177118117964 Mr Test DE20500105172419259181 116 DK GENODEM1GLS AC01 IBAN ... Überweisungsgutschr.
1.10 DBIT BOOK
2024-09-02
2024-09-02
2024090216552232000 PMNT ICDT ESCT NTRF+177+08381 DK BATCH_SINGLE_SUCCESS NOTPROVIDED FD622SMXKT5QWSAHDY0H8NYG3G 2024090252501131090200000010000001 1.10 PMNT ICDT ESCT NTRF+177+08381 DK Florian Dold DE89500105171325381664 Grothoff Hans DE89500105173198527518 GENODEM1GLS single 2024-09-02T14:29:52.875253314Z Überweisungsauftrag
1.10 DBIT BOOK
2024-04-18
2024-04-18
2024041810552821000 PMNT ICDT ESCT NTRF+177+08381 DK YF5QBARGQ0MNY0VK59S477VDG4 NOTPROVIDED NOTPROVIDED 2024041885917775090200000010000001 1.10 PMNT ICDT ESCT NTRF+177+08381 DK Mr Test DE84500105177118117964 John Smith DE20500105172419259181 INGDDEFFXXX Simple tx Überweisungsauftrag
0.46 DBIT BOOK
2024-09-20
2024-09-20
2024092019251584000 PMNT ICDT ESCT NTRF+191+08381 DK BATCH_MANY_SUCCESS NOTPROVIDED 0.46 PMNT ICDT ESCT NTRF+191+08381 DK Florian Dold DE89500105171325381664 SEPA Sammel-Ueberweisung mit 4 Ueberweisungen MSG-ID: BATCH_MANY_SUCCESS Sammelüberweisung
0.42 DBIT BOOK
2024-09-23
2024-09-23
2024092100252498000 PMNT ICDT ESCT NTRF+177+08381 DK BATCH_SINGLE_RETURN NOTPROVIDED KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5 2024092374955203090200000010000001 0.42 PMNT ICDT ESCT NTRF+177+08381 DK Florian Dold DE89500105171325381664 John Smith DE18500105173385245163 INGDDEFFXXX This should fail because bad iban Überweisungsauftrag
0.42 CRDT BOOK
2024-09-24
2024-09-24
2024092409341766000 PMNT ICDT RRTN NRTI+159+00931 DK KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5 2024092374955203090200000010000001 0.42 PMNT ICDT RRTN NRTI+159+00931 DK Florian Dold DE89500105171325381664 John Smith DE18500105173385245163 Retoure ... 116 DK GENODEM1GLS AC01 IBAN fehlerhaft und ungültig Retouren
libeufin-1.6.8/libeufin-nexus/sample/platform/gls_camt053.xml0000664000175000017500000003616215122266731024365 0ustar grothoffgrothoff DE84500105177118117964 EUR 2.00 DBIT BOOK
2024-04-18
2024041801514102000 PMNT ICDT ESCT COMPAT_SUCCESS NOTPROVIDED NOTPROVIDED 2024041785403105090200000010000001 2.00 PMNT ICDT ESCT NTRF+177+08381 DK Mr Test DE84500105177118117964 John Smith DE20500105172419259181 BYLADEM1WOR TestABC123 Überweisungsauftrag
1.10 CRDT true BOOK
2024-09-04
2024-09-04
2024090413252540000 ACMT ACOP PSTE NRTI+899+08381 DK KGTDBASWTJ6JM89WXD3Q5KFQC4 2024090455250415090200000010000002 1.10 ACMT ACOP PSTE NRTI+899+08381 DK Florian Dold DE54430609674049078800 Florian Dold DE89500105171325381664 GENODEM1GLS Retoure aus SEPA Überweisung multi line Storno
3.30 DBIT BOOK
2024-09-04
2024-09-04
2024090413252541000 PMNT ICDT ESCT NTRF+191+08381 DK BATCH_MANY_PART NOTPROVIDED 3.30 PMNT ICDT ESCT NTRF+191+08381 DK Florian Dold DE89500105171325381664 SEPA Sammel-Ueberweisung mit 3 Ueberweisungen MSG-ID: IP5QN7GOBZDJLKXDGQGD5AYS3WLSBEIY6U Sammelüberweisung
3.00 CRDT BOOK
2024-04-12
2024041210041357000 PMNT RCDT ESCT NOTPROVIDED BYLADEM1WOR-G2910276709458A2 3.00 PMNT RCDT ESCT John Smith DE84500105177118117964 Mr Test DE20500105172419259181 BYLADEM1WOR Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,- Überweisungsgutschr.
1.10 CRDT BOOK
2024-04-12
2024041210041357000 PMNT ICDT RRTN COMPAT_FAILURE 2024042288942205090200000010000001 1.10 PMNT ICDT RRTN John Smith DE84500105177118117964 Mr Test DE20500105172419259181 BYLADEM1WOR 116 DK GENODEM1GLS AC01 IBAN ... Überweisungsgutschr.
1.10 DBIT BOOK
2024-09-02
2024-09-02
2024090216552232000 PMNT ICDT ESCT NTRF+177+08381 DK BATCH_SINGLE_SUCCESS NOTPROVIDED FD622SMXKT5QWSAHDY0H8NYG3G 2024090252501131090200000010000001 1.10 PMNT ICDT ESCT NTRF+177+08381 DK Florian Dold DE89500105171325381664 Grothoff Hans DE89500105173198527518 GENODEM1GLS single 2024-09-02T14:29:52.875253314Z Überweisungsauftrag
1.10 DBIT BOOK
2024-04-18
2024-04-18
2024041810552821000 PMNT ICDT ESCT NTRF+177+08381 DK YF5QBARGQ0MNY0VK59S477VDG4 NOTPROVIDED NOTPROVIDED 2024041885917775090200000010000001 1.10 PMNT ICDT ESCT NTRF+177+08381 DK Mr Test DE84500105177118117964 John Smith DE20500105172419259181 INGDDEFFXXX Simple tx Überweisungsauftrag
libeufin-1.6.8/libeufin-nexus/sample/platform/maerki_baumann_camt053.xml0000664000175000017500000011073215122266731026545 0ustar grothoffgrothoff 2024111201095780 2024-11-12T17:10:27+01:00 1 true CH7389144832588726658 CHF .8 CRDT false BOOK
2024-11-04
2024-11-04
PMNT RCDT OTHR 1 .8 CRDT ZV20241104/765446/1 NOTPROVIDED adbe4a5a-6cea-4263-b259-8ab964561a32 41103099704.0002 .8 CRDT 1 1 .2 DBIT true PT inc.paym.exp
CRED
0 CRDT SHAR
Mr Test CH7389144832588726658 CHSIC 087042 SFHP6H24C16A5J05Q3FJW2XN1PB3EK70ZPY 5SJ30ADGY68FWN68G Bank clearing payment Grothoff Hans
Bank clearing payment Grothoff Hans
.8 CRDT false BOOK
2024-11-04
2024-11-04
PMNT RCDT OTHR 1 .8 CRDT ZV20241104/765447/1 NOTPROVIDED 7371795e-62fa-42dd-93b7-da89cc120faa 41103099704.0003 .8 CRDT 1 1 .2 DBIT true PT inc.paym.exp
CRED
Mr Test CH7389144832588726658 CHSIC 087042 Random subject Bank clearing payment Grothoff Hans
Bank clearing payment Grothoff Hans
.3 CRDT false BOOK
2025-05-23
2025-05-23
ZV20250523/851716 PMNT RCDT OTHR 1 .3 CRDT ZV20250523/851716/1 NOTPROVIDED 50523424675.0001 .3 CRDT .5 .5 .2 DBIT true PT inc.paym.exp
CRED
Grothoff Hans CH7389144832588726658 CHSIC 087042 Bank clearing payment Grothoff Hans
Bank clearing payment Grothoff Hans
.1 DBIT false BOOK
2024-11-27
2024-11-27
PMNT ICDT OTHR BATCH_SINGLE_REPORTING ZV20241121/773541/1 NOTPROVIDED 5IBJZOWESQGPCSOXSNNBBY49ZURI5W7Q4H 5IBJZOWESQGPCSOXSNNBBY49ZURI5W7Q4H 30c030ad-01cc-4cbf-b2d4-428cccaa1a85 .1 DBIT Grothoff Hans CH7389144832588726658 multi 0 2024-11-21T15:21:59.8859234 63Z PAIN-Auftrag Grothoff Hans PAIN-Auftrag Grothoff Hans
.13 DBIT false BOOK
2024-11-27
2024-11-27
PMNT ICDT OTHR 1 .13 DBIT BATCH_SINGLE_REPORTING ZV20241121/773541/4 NOTPROVIDED XZ15UR0XU52QWI7Q4XB88EDS44PLH7DYXH XZ15UR0XU52QWI7Q4XB88EDS44PLH7DYXH b14d4554-49a0-4c99-a49e-5ebb4fa177d1 .13 DBIT .13 .13 Grothoff Hans CH7389144832588726658 multi 3 2024-11-21T15:21:59.8859234 63Z PAIN-Auftrag Grothoff Hans PAIN-Auftrag Grothoff Hans
.12 DBIT false BOOK
2024-11-27
2024-11-27
PMNT ICDT OTHR 1 .12 DBIT BATCH_SINGLE_REPORTING ZV20241121/773541/3 NOTPROVIDED A09R35EW0359SZ51464E7TC37A0P2CBK04 A09R35EW0359SZ51464E7TC37A0P2CBK04 fa3869de-e29b-4163-9ffa-b9c6d6b70d25 .12 DBIT .12 .12 Grothoff Hans CH7389144832588726658 multi 2 2024-11-21T15:21:59.8859234 63Z PAIN-Auftrag Grothoff Hans PAIN-Auftrag Grothoff Hans
.11 DBIT false BOOK
2024-11-27
2024-11-27
PMNT ICDT OTHR 1 .11 DBIT BATCH_SINGLE_REPORTING ZV20241121/773541/2 NOTPROVIDED UYXZ78LE9KAIMBY6UNXFYT1K8KNY8VLZLT UYXZ78LE9KAIMBY6UNXFYT1K8KNY8VLZLT 93b01b18-36f6-4e42-a3bf-e4341b7e64cf .11 DBIT .11 .11 Grothoff Hans CH7389144832588726658 multi 1 2024-11-21T15:21:59.8859234 63Z PAIN-Auftrag Grothoff Hans PAIN-Auftrag Grothoff Hans
.15 DBIT true BOOK
2024-12-02
2024-12-02
PMNT RCDT CAJT .2 .2 DBIT true PT inc.paym.exp
DEBT
1 .15 DBIT ZV20241202/778108/1 NOTPROVIDED f203fbb4-6e13-4c78-9b2a-d852fea6374a 41202060702.0001 -.15 DBIT .05 .05 Grothoff Hans CH7389144832588726658 CHSIC 087042 mini Bank clearing payment Grothoff Hans Bank clearing payment Grothoff Hans
.1 DBIT true BOOK
2024-11-21
2024-11-21
PMNT RCDT CAJT .2 .2 DBIT true PT inc.paym.exp
DEBT
1 .1 DBIT ZV20241121/773118/1 NOTPROVIDED 81b0d8c6-a677-4577-b75e-a639dcc03681 41120636093.0001 -.1 DBIT .1 .1 Grothoff Hans CH7389144832588726658 small transfer test Bank clearing payment Grothoff Hans Bank clearing payment Grothoff Hans
3000 DBIT false BOOK
2024-12-20
2024-12-20
PMNT ICDT OTHR 1 3000 DBIT GB20241220/205792/1 NOTPROVIDED NOTPROVIDED 3000 DBIT 3000 3000 all-in one fee all-in one fee
3003 CRDT false BOOK
2025-01-27
2025-01-27
PMNT RCDT OTHR 1 3003 CRDT ZV20250114/796191/1 NOTPROVIDED 3003 CRDT 3003 3003 Fix bad payment by MB. Transfer Taler Operations AG Transfer Taler Operations AG
1.18 CRDT false BOOK
2025-05-26
2025-05-26
ZV20250526/852733 PMNT RCDT OTHR 1 1.18 CRDT ZV20250526/852733/1 6b515f17ecc9408191f7b9b1d755faf7 F000787951230001 1.18 CRDT 1.5 1.5 CHF EUR .917876 .2 DBIT true PT inc.paym.exp
CRED
Mr German DE20500105172419259181 CHSIC 083077 Taler XT3D9MADR4V85JBWX47SMJFDQD2FDZDHHPH8R25YDG1KNVTSEH6G
libeufin-1.6.8/libeufin-nexus/sample/platform/valiant_camt052.xml0000664000175000017500000011474715122266731025243 0ustar grothoffgrothoff CH7389144832588726658 CHF .1 DBIT false BOOK
2025-10-30
2025-10-30
ZV20251030/511372 PMNT ICDT CHRG 1 .1 DBIT MJDJO2BDDBL7YSL2P96SXHG3TQZEZQD26L ZV20251030/511372/1 NOTPROVIDED 4UWWIDGTEIGDU6Z721QE95PYJSIEA48PYE 4UWWIDGTEIGDU6Z721QE95PYJSIEA48PYE .1 DBIT .1 .1 Grothoff Hans CH7389144832588726658 single 2025-10-30T09:46:04.55293090 9Z Vergütung Vergütung
.46 DBIT false BOOK
2025-10-30
2025-10-30
ZV20251030/511373 PMNT ICDT CHRG 4 .46 DBIT 5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U ZV20251030/511373/1 NOTPROVIDED SKMU2891PAAYBDW22DBWX2W7KTFZ1CDFO8 SKMU2891PAAYBDW22DBWX2W7KTFZ1CDFO8 .1 DBIT .1 .1 Grothoff Hans CH7389144832588726658 multi 0 2025-10-30T09:46:10.3877961 30Z Vergütung 5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U ZV20251030/511373/2 NOTPROVIDED RC9YD301NZ17YKD6WDWLNOROFHIIN29VJN RC9YD301NZ17YKD6WDWLNOROFHIIN29VJN .11 DBIT .11 .11 Grothoff Hans CH7389144832588726658 multi 1 2025-10-30T09:46:10.3877961 30Z Vergütung 5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U ZV20251030/511373/3 NOTPROVIDED GKDGTHLB82X6XVHBJIJ1CK8MEGU9XJ2EL7 GKDGTHLB82X6XVHBJIJ1CK8MEGU9XJ2EL7 .12 DBIT .12 .12 Grothoff Hans CH7389144832588726658 multi 2 2025-10-30T09:46:10.3877961 30Z Vergütung 5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U ZV20251030/511373/4 NOTPROVIDED PXCH2VVVTXEXBVDWICP23HZ4NV0H2CWW28 PXCH2VVVTXEXBVDWICP23HZ4NV0H2CWW28 .13 DBIT .13 .13 Grothoff Hans CH7389144832588726658 multi 3 2025-10-30T09:46:10.3877961 30Z Vergütung Vergütung
.85 CRDT false BOOK
2025-10-30
2025-10-30
ZV20251030/514778 PMNT RCDT OTHR 1 .85 CRDT ZV20251030/514778/1 NOTPROVIDED 51030655601.0001 .85 CRDT .85 .85 Grothoff Hans CH7389144832588726658 CHSIC 087042 fun stuff Vergütung Vergütung
.95 CRDT false BOOK
2025-10-30
2025-10-30
ZV20251030/514779 PMNT RCDT OTHR 1 .95 CRDT ZV20251030/514779/1 NOTPROVIDED 51030655601.0002 .95 CRDT .95 .95 Grothoff Hans CH7389144832588726658 CHSIC 087042 Taler PC2MKG0B7CK32K1T7DP08P6E1B7FHB6HY6R Q0PT3VTPBPRPYM1B0 Vergütung Vergütung
.21 DBIT false BOOK
2025-10-30
2025-10-30
ZV20251030/524078 PMNT ICDT OTHR 1 .21 DBIT X166701F6RV59LP71RVWVIW9SV2AFZYLG4 ZV20251030/524078/1 NOTPROVIDED R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX .21 DBIT .21 .21 John Smith CH6208704048981247126 AEK BANK 1826 Genossenschaft Hofstettenstrasse 2 3601 Thun bad name 2025-10-30T12:03:24.997478 811Z Vergütung Vergütung
.31 DBIT false BOOK
2025-10-30
2025-10-30
ZV20251030/524079 PMNT ICDT OTHR 2 .31 DBIT 6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X ZV20251030/524079/1 NOTPROVIDED 02WDIX4J90Z1M1WNFHLNSXY59SHXQTQCMQ 02WDIX4J90Z1M1WNFHLNSXY59SHXQTQCMQ .1 DBIT .1 .1 Grothoff Hans CH7389144832588726658 single 2025-10-30T12:04:00.37042083 6Z Vergütung 6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X ZV20251030/524079/2 NOTPROVIDED XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y .21 DBIT .21 .21 John Smith CH6208704048981247126 bad name 2025-10-30T12:03:53.042190 686Z Vergütung Vergütung
.21 CRDT false BOOK
2025-10-30
2025-10-30
ZV20251030/525730 PMNT ICDT RRTN 1 .21 CRDT ZV20251030/525730/1 XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y 51030658148.0001 .21 CRDT .21 .21 AEK BANK 1826 GENOSSENSCHAFT HOFSTETTENSTRASSE 2 3602 THUN SWITZERLAND VERD Finanzas AG 3011 Bern Error msg in german Vergütung Vergütung
.21 CRDT false BOOK
2025-10-30
2025-10-30
ZV20251030/525968 PMNT ICDT RRTN 1 .21 CRDT ZV20251030/525968/1 R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX 51030658165.0001 .21 CRDT .21 .21 Error msg in german Vergütung Vergütung
5.23 DBIT false BOOK
2025-10-30
2025-10-30
ZV20251030/524077 PMNT ICDT OTHR 5 5 DBIT true ZV-Ausland.Zlg
DEBT
1 5.23 DBIT OLAMDPI6YPMNRZHQ5PQ6JCVUQV2AN5NW6P ZV20251030/524077/1 NOTPROVIDED TU2WJ54DR9Z6HT5VE494BNH4EXUSM0DRF7 TU2WJ54DR9Z6HT5VE494BNH4EXUSM0DRF7 5.23 DBIT .23 .23 Christian Grothoff DE48330605920000686018 GENODED1SPW foreign iban 2025-10-30T12:03:44.0972 63765Z Vergütung Vergütung
5.23 DBIT false BOOK
2025-10-30
2025-10-30
ZV20251030/524080 PMNT ICDT OTHR 5 5 DBIT true ZV-Ausland.Zlg
DEBT
1 5.23 DBIT 6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X ZV20251030/524080/1 NOTPROVIDED GM8I8GIETR72LP6CFBGRBUDKNO2CEQBGOE GM8I8GIETR72LP6CFBGRBUDKNO2CEQBGOE 5.23 DBIT .23 .23 Christian Grothoff DE48330605920000686018 GENODED1SPW foreign iban 2025-10-30T12:03:58.0046 73747Z Vergütung Vergütung
4.55 CRDT false BOOK
2025-11-18
2025-11-18
ZV20251118/685062 PMNT RCDT DMCT 1 4.55 CRDT ZV20251118/685062/1 NOTPROVIDED 7b76d488-05d5-44ab-9d77-31d4165ec158 00204EQY370 4.55 CRDT 5 5 CHF EUR .911064 0 CRDT SHA 1/HANS GROTHOFF 2/BRUENNMATTEN 20 3/CH/2563 IPSACH VERD Finanzas AG 3011 Bern TEST Gutschrift Gutschrift
libeufin-1.6.8/libeufin-nexus/sample/platform/postfinance_camt054.xml0000664000175000017500000002046715122266731026113 0ustar grothoffgrothoff 20240115375204422237387 CH9289144596463965762 CHF 3.00 DBIT false BOOK
2024-01-15
01542000B8GTEONK PMNT ICDT DMCT ZS1PGNTSV0ZNDFAJBBWWB8015G NOTPROVIDED NOTPROVIDED NOTPROVIDED NOTPROVIDED 3.00 DBIT LASTSCHRIFT ...
12.53 false BOOK
2023-12-19
35332000B4R5BCIU PMNT RCDT AUTT 231121CH0AZWCR9T NOTPROVIDED 62e2b511-7313-4ccd-8d40-c9d8e612cd71 10.00 CRDT PMNT RCDT ATXN Mr Test CH7389144832588726658 CH9289144596463965762 G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ 7JVGV543XZCB27YBG 231121CH0AZWCVR1 NOTPROVIDED 62e2b511-7313-4ccd-8d40-c9d8e612cd71 2.53 CRDT PMNT RCDT ATXN Mr Test CH7389144832588726658 G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ 7JVGV543XZCB27YB SAMMELGUTSCHRIFT FÜR KONTO: ...
1.00 CRDT true BOOK
2024-01-15
01542000B8K95YTK PMNT ICDT RRTN 50820f78-9024-44ff-978d-63a18c NOTPROVIDED 1.00 CRDT RETOURE IHRER ZAHLUNG VOM 15.01.2024 ... GRUND: KEINE UEBEREINSTIMMUNG VON KONTONUMMER UND KONTOINHABER
406.00 DBIT false BOOK
2024-01-15
PMNT ICDT AUTT ZS1PGNTSV0ZNDFAJBBWWB8015G NOTPROVIDED c810f027-08f8-44ad-bf53-647ae3fc349f 406.00 DBIT
libeufin-1.6.8/libeufin-nexus/sample/platform/gls_camt054.xml0000664000175000017500000000540115122266731024356 0ustar grothoffgrothoff IS11PGENODEFF2DA8899900378806 DE84500105177118117964 EUR 2.50 CRDT BOOK
2024-05-05
PMNT RRCT ESCT NOTPROVIDED IS11PGENODEFF2DA8899900378806 Mr Test DE84500105177118117964 John Smith DE20500105172419259181 BYLADEM1WOR GENODEM1GLS Test ICT
libeufin-1.6.8/libeufin-nexus/sample/platform/pain002_accp.xml0000664000175000017500000000154215122266731024475 0ustar grothoffgrothoff pain.002/20251030/104854310674000 2025-10-30T10:48:54+01:00 VABECH22XXX 5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U pain.001 ACCP PN10630020F0297329.20251030104613.EBTUAAAC.PN1.0002372 libeufin-1.6.8/libeufin-nexus/sample/platform/gls_pain001.xml0000664000175000017500000000327015122266731024353 0ustar grothoffgrothoffMESSAGE_ID2024-09-09T00:00:00Z347.32mynameNOTPROVIDEDTRFfalse347.32SEPA
2024-09-09Z
mynameCH7789144474425692816BICSLEVTX_FIRSTTX_FIRST42TestCH4189144589712575493Test 42TX_SECONDTX_SECOND5.11TestCH4189144589712575493Test 5.11TX_THIRDTX_THIRD0.21TestCH4189144589712575493Test 0.21
libeufin-1.6.8/libeufin-nexus/conf/0000775000175000017500000000000015236145704017434 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-nexus/conf/gls.conf0000664000175000017500000000061315122266731021066 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = EUR HOST_BASE_URL = https://ebics.multivia-suite.de/ebicsweb/ebicsweb BANK_DIALECT = gls BANK_PUBLIC_KEYS_FILE = test/tmp/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = test/tmp/client-keys.json HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 IBAN = DE84500105177118117964 BIC = BIC NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufinchecklibeufin-1.6.8/libeufin-nexus/conf/mini.conf0000664000175000017500000000061515122266731021237 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = CHF BANK_DIALECT = postfinance HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_PUBLIC_KEYS_FILE = test/tmp/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = test/tmp/client-keys.json IBAN = CH7789144474425692816 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 BIC = BIC NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufinchecklibeufin-1.6.8/libeufin-nexus/conf/valiant.conf0000664000175000017500000000062315122266731021740 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = CHF HOST_BASE_URL = https://www.ebics.swisscom.com/ebics-server/ebics.aspx BANK_DIALECT = valiant BANK_PUBLIC_KEYS_FILE = test/tmp/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = test/tmp/client-keys.json HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 IBAN = CH7389144832588726658 BIC = BIC NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufinchecklibeufin-1.6.8/libeufin-nexus/conf/fetch.conf0000664000175000017500000000061115122266731021370 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = CHF BANK_DIALECT = postfinance HOST_BASE_URL = http://localhost:8080/ebicsweb BANK_PUBLIC_KEYS_FILE = /tmp/ebics-test/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = /tmp/ebics-test/client-keys.json IBAN = CH7789144474425692816 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 BIC = BIC NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufinchecklibeufin-1.6.8/libeufin-nexus/conf/maerki_baumann.conf0000664000175000017500000000045015122266731023251 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = CHF BANK_DIALECT = maerki_baumann HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 IBAN = CH7389144832588726658 BIC = BIC NAME = myname [nexus-fetch] RESTRICTION_PAYTO_REGEX = payto://iban/CH.* [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufinchecklibeufin-1.6.8/libeufin-nexus/conf/test.conf0000664000175000017500000000123215221677432021262 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = CHF BANK_DIALECT = postfinance HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_PUBLIC_KEYS_FILE = test/tmp/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = test/tmp/client-keys.json IBAN = CH7789144474425692816 QR_IBAN = CH4431999123000889012 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 BIC = BIC NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck [nexus-httpd-wire-gateway-api] ENABLED = YES AUTH_METHOD = bearer TOKEN = secret-token [nexus-httpd-revenue-api] ENABLED = YES AUTH_METHOD = bearer TOKEN = secret-token [nexus-httpd-observability-api] ENABLED = YES AUTH_METHOD = nonelibeufin-1.6.8/libeufin-nexus/conf/auth.conf0000664000175000017500000000122315156463305021243 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = CHF BANK_DIALECT = postfinance HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_PUBLIC_KEYS_FILE = test/tmp/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = test/tmp/client-keys.json IBAN = CH7789144474425692816 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 BIC = BIC NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck [nexus-httpd-wire-gateway-api] ENABLED = YES AUTH_METHOD = basic USERNAME = username PASSWORD = password [nexus-httpd-wire-transfer-gateway-api] ENABLED = YES [nexus-httpd-revenue-api] ENABLED = YES AUTH_METHOD = bearer-token AUTH_BEARER_TOKEN = secret-tokenlibeufin-1.6.8/libeufin-nexus/conf/skip.conf0000664000175000017500000000075115122266731021252 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = KUDOS BANK_DIALECT = postfinance HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_PUBLIC_KEYS_FILE = test/tmp/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = test/tmp/client-keys.json IBAN = CH7789144474425692816 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 BIC = BIC NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck [nexus-fetch] IGNORE_TRANSACTIONS_BEFORE = 2024-04-04 IGNORE_BOUNCES_BEFORE = 2024-06-12libeufin-1.6.8/doc/0000775000175000017500000000000015236145704014317 5ustar grothoffgrothofflibeufin-1.6.8/doc/prebuilt/0000775000175000017500000000000015236145704016145 5ustar grothoffgrothofflibeufin-1.6.8/doc/prebuilt/man/0000775000175000017500000000000015236145704016720 5ustar grothoffgrothofflibeufin-1.6.8/doc/prebuilt/man/libeufin-ebisync.10000664000175000017500000001600615236113377022235 0ustar grothoffgrothoff.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "LIBEUFIN-EBISYNC" "1" "Aug 09, 2026" "1.0" "GNU Taler" .SH NAME libeufin-ebisync \- service to synchronize files via EBICS .SH SYNOPSIS .sp \fBlibeufin\-ebisync\fP [\fB\-h\fP\ |\ \fB\-\-help\fP] [\fB\-\-version\fP] COMMAND [ARGS...] .sp Subcommands: \fBdbinit\fP, \fBsetup\fP, \fBfetch\fP, \fBserve\fP, \fBconfig\fP .SH DESCRIPTION .sp \fBlibeufin\-ebisync\fP is a program that provides a service to synchronize ISO20022 files through the EBICS protocol .sp Its options are as follows: .INDENT 0.0 .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .TP \fB–version\fP Print version information. .UNINDENT .sp The interaction model is as follows: .INDENT 0.0 .IP \(bu 2 Configure the database with commands \fBdbinit\fP\&. .IP \(bu 2 Setup EBICS access with commands \fBsetup\fP\&. Setting the access means to share the client keys with the bank and downloading the bank keys .IP \(bu 2 After a successful setup, the subcommand \fBfetch\fP can be run to respectively download files. .UNINDENT .sp The following sections describe each command in detail. .SS dbinit .sp This command defines the database schema for LibEuFin EbiSync. It is mandatory to run this command before invoking the \fBsetup\fP command. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-r\fP | \fB\-\-reset\fP Reset database (DANGEROUS: All existing data is lost) .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS setup .sp This command creates the client keys, if they aren\(aqt found already on the disk, and sends them to the bank if they were not sent yet. In case of sending, it ejects the PDF document that contains the keys fingerprints, so that the user can send it to the bank to confirm their keys. The process continues by checking if the bank keys exist already on disk, and proceeds with downloading them in case they are not. It checks then if the bank keys were accepted by the user; if yes, the setup terminates, otherwise it interactively asks the user to mark the keys as accepted. By accepting the bank keys, the setup terminates successfully. .sp It is mandatory to run this command before invoking the \fBfetch\fP command. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-force\-keys\-resubmission\fP Resubmits all the keys to the bank. .TP \fB\-\-auto\-accept\-keys\fP Accepts the bank keys without interactively asking the user. .TP \fB\-\-generate\-registration\-pdf\fP Generates the PDF with the client keys fingerprints, if the keys have the submitted state. That\(aqs useful in case the PDF went lost after the first submission and the user needs a new PDF. .TP \fB\-\-debug\-ebics\fP Log EBICS transactions steps and payload at log_dir. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS fetch .sp This subcommand fetches ISO20022 files from the bank and store them at a configured destination. .sp Fetches of new documents are executed at \(aqFREQUENCY\(aq or any time a real\-time EBICS notification is received. Every day, a checkpoint is performed, during which all documents since the last checkpoint are fetched. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-transient\fP Execute once and return, ignoring the \(aqFREQUENCY\(aq configuration value. .TP \fB\-\-pinned\-start\fP \fIYYYY\-MM\-DD\fP Only supported in \-\-transient mode, this option lets specify the earliest timestamp of the downloaded documents. .TP \fB\-\-peek\fP Only supported in \-\-transient mode, do not consume fetched documents. .TP \fB\-\-checkpoint\fP Only supported in \-\-transient mode, run a checkpoint. .TP \fB\-\-debug\-ebics\fP \fIlog_dir\fP Log EBICS transactions steps and payload at log_dir. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS serve .sp This command starts the HTTP server. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-check\fP Check whether an API is in use (if it\(aqs useful to start the HTTP server). Exit with 0 if at least one API is enabled, otherwise 1. .TP \fB\-\-debug\-ebics\fP \fIlog_dir\fP Log EBICS transactions steps and payload at log_dir. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config .sp This command inspect or change the configuration. .INDENT 0.0 .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .sp Subcommands: \fBget\fP, \fBdump\fP, \fBpathsub\fP .SS config get .sp This command lookup config value. .sp It takes two arguments, the section name and the option name .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-f\fP | \fB\-\-filename\fP Interpret value as path with dollar\-expansion. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config dump .sp This command dump the configuration. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config pathsub .sp This command substitute variables in a path. .sp It takes one argument, a path expression. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SH SEE ALSO .sp libeufin\-ebisync.conf(5) .SH BUGS .sp Report bugs by using \X'tty: link https://bugs.taler.net'\fI\%https://bugs.taler.net\fP\X'tty: link' or by sending electronic mail to <\X'tty: link mailto:taler@gnu.org'\fI\%taler@gnu.org\fP\X'tty: link'>. .SH AUTHOR GNU Taler contributors .SH COPYRIGHT 2014-2025 Taler Systems SA (GPLv3+ or GFDL 1.3+) .\" Generated by docutils manpage writer. . libeufin-1.6.8/doc/prebuilt/man/libeufin-nexus.conf.50000664000175000017500000002574015236113377022700 0ustar grothoffgrothoff.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "LIBEUFIN-NEXUS.CONF" "5" "Aug 09, 2026" "1.0" "GNU Taler" .SH NAME libeufin-nexus.conf \- LibEuFin Nexus configuration file .SH DESCRIPTION .sp The configuration file is line\-oriented. Blank lines and whitespace at the beginning and end of a line are ignored. Comments start with \fB#\fP or \fB%\fP in the first column (after any beginning\-of\-line whitespace) and go to the end of the line. .sp The file is split into sections. Every section begins with \fB[SECTIONNAME]\fP and contains a number of options of the form \fBOPTION=VALUE\fP\&. There may be whitespace around the \fB=\fP (equal sign). Section names and options are \fIcase\-insensitive\fP\&. .sp The values, however, are \fIcase\-sensitive\fP\&. In particular, boolean values are one of \fBYES\fP or \fBNO\fP\&. Values can include whitespace by surrounding the entire value with \fB\(dq\fP (double quote). Note, however, that there are no escape characters in such strings; all characters between the double quotes (including other double quotes) are taken verbatim. .sp Values that represent a time duration are represented as a series of one or more \fBNUMBER UNIT\fP pairs, e.g. \fB60 s\fP, \fB4 weeks 1 day\fP, \fB5 years 2 minutes\fP\&. .sp Values that represent an amount are in the usual amount syntax: \fBCURRENCY:VALUE.FRACTION\fP, e.g. \fBEUR:1.50\fP\&. The \fBFRACTION\fP portion may extend up to 8 places. .sp Values that represent filenames can begin with a \fB/bin/sh\fP\-like variable reference. This can be simple, such as \fB$TMPDIR/foo\fP, or complex, such as \fB${TMPDIR:\-${TMP:\-/tmp}}/foo\fP\&. The variables are expanded either using key\-values from the \fB[PATHS]\fP section (see below) or from the environment (\fBgetenv()\fP). The values from \fB[PATHS]\fP take precedence over those from the environment. If the variable name is found in neither \fB[PATHS]\fP nor the environment, a warning is printed and the value is left unchanged. Variables (including those from the environment) are expanded recursively, so if \fBFOO=$BAR\fP and \fBBAR=buzz\fP then the result is \fBFOO=buzz\fP\&. Recursion is bounded to at most 128 levels to avoid undefined behavior for mutually recursive expansions like if \fBBAR=$FOO\fP in the example above. .sp The \fB[PATHS]\fP section is special in that it contains paths that can be referenced using \fB$\fP in other configuration values that specify \fIfilenames\fP\&. Note that configuration options that are not specifically retrieved by the application as \fIfilenames\fP will not see “$”\-expressions expanded. To expand \fB$\fP\-expressions when using \fBtaler\-config\fP, you must pass the \fB\-f\fP command\-line option. .sp The system automatically pre\-populates the \fB[PATHS]\fP section with a few values at run\-time (in addition to the values that are in the actual configuration file and automatically overwriting those values if they are present). These automatically generated values refer to installation properties from \X'tty: link https://www.gnu.org/prep/standards/html_node/Directory-Variables.html'\fI\%GNU autoconf\fP\X'tty: link'\&. The values are usually dependent on an \fBINSTALL_PREFIX\fP which is determined by the \fB\-\-prefix\fP option given to configure. The canonical values are: .INDENT 0.0 .IP \(bu 2 LIBEXECDIR = $INSTALL_PREFIX/taler/libexec/ .IP \(bu 2 DOCDIR = $INSTALL_PREFIX/share/doc/taler/ .IP \(bu 2 ICONDIR = $INSTALL_PREFIX/share/icons/ .IP \(bu 2 LOCALEDIR = $INSTALL_PREFIX/share/locale/ .IP \(bu 2 PREFIX = $INSTALL_PREFIX/ .IP \(bu 2 BINDIR = $INSTALL_PREFIX/bin/ .IP \(bu 2 LIBDIR = $INSTALL_PREFIX/lib/taler/ .IP \(bu 2 DATADIR = $INSTALL_PREFIX/share/taler/ .UNINDENT .sp Note that on some platforms, the given paths may differ depending on how the system was compiled or installed, the above are just the canonical locations of the various resources. These automatically generated values are never written to disk. .sp Files containing default values for many of the options described below are installed under \fB$LIBEUFIN_NEXUS_PREFIX/share/libeufin\-nexus/config.d/\fP\&. The configuration file given with \fB\-c\fP to Taler binaries overrides these defaults. .sp A configuration file may include another, by using the \fB@INLINE@\fP directive, for example, in \fBmain.conf\fP, you could write \fB@INLINE@ sub.conf\fP to include the entirety of \fBsub.conf\fP at that point in \fBmain.conf\fP\&. .SS EBICS OPTIONS .sp The following options are from the “[nexus\-ebics]” section. .INDENT 0.0 .TP .B CURRENCY Name of the currency, e.g.\ “EUR” for Euro. .TP .B HOST_BASE_URL URL of the EBICS server .TP .B HOST_ID EBICS specific: name of the EBICS host .TP .B USER_ID EBICS specific: user ID of the EBICS subscriber. This value must be assigned by the bank after having activated a new EBICS subscriber. .TP .B PARTNER_ID EBICS specific: partner ID of the EBICS subscriber. This value must be assigned by the bank after having activated a new EBICS subscriber. .TP .B IBAN IBAN of the bank account that is associated with the EBICS subscriber. .TP .B BIC BIC of the bank account that is associated with the EBICS subscriber. .TP .B QR_IBAN QR IBAN of a QR virtual bank account linked to the configured bank account that can be used for QR BILL .TP .B NAME Legal entity that is associated with the EBICS subscriber. .TP .B BANK_PUBLIC_KEYS_FILE Filesystem location where Nexus should store the bank public keys. .TP .B CLIENT_PRIVATE_KEYS_FILE Filesystem location where Nexus should store the subscriber private keys. .TP .B BANK_DIALECT Name of the following combination: EBICS version and ISO20022 recommendations that Nexus would honor in the communication with the bank. Currently only the \fBpostfinance\fP, \fBgls\fP, \fBraiffeisen\fP, \fBmaerki_baumann\fP or \fBvaliant\fP dialects is supported. .TP .B ACCOUNT_TYPE Specify the account type and therefore the indexing behavior. This can either can be \fBnormal\fP or \fBexchange\fP\&. Exchange accounts bounce invalid incoming Taler transactions. .UNINDENT .SS EBICS SETUP OPTIONS .sp The following configuration value(s) belong to the “[nexus\-setup]” section. .INDENT 0.0 .TP .B BANK_ENCRYPTION_PUB_KEY_HASH Bank encryption public key hash. .TP .B BANK_AUTHENTICATION_PUB_KEY_HASH Bank authentication public key hash. .UNINDENT .SS EBICS SUBMIT OPTIONS .sp The following configuration value(s) belong to the “[nexus\-submit]” section. .INDENT 0.0 .TP .B FREQUENCY Duration value to instruct the \fBebics\-submit\fP subcommand how much to wait before checking the database again to find new unsubmitted payments. .TP .B MANUAL_ACK Wether to wait for manual acknowledgement before submiting transactions. .UNINDENT .SS EBICS FETCH OPTIONS .sp The following configuration value(s) belong to the “[nexus\-fetch]” section. .INDENT 0.0 .TP .B FREQUENCY Duration value to instruct the \fBebics\-fetch\fP subcommand how often it should download from the bank. .TP .B CHECKPOINT_TIME_OF_DAY At what time HH:MM of day should \fBebics\-fetch\fP perform a checkpoint. .TP .B IGNORE_TRANSACTIONS_BEFORE Ignore all transactions before a certain YYYY\-MM\-DD date, useful when you want to use an existing account with old transactions that should not be bounced. .TP .B IGNORE_BOUNCES_BEFORE Ignore all malformed transactions prior to a certain YYYY\-MM\-DD date, useful when you want to import old transactions without bouncing the malformed ones a second time. .TP .B BOUNCE_DEDUCE_FEE Whether to deduce the fee paid by the exchange account from the bounced amount. .TP .B BOUNCE_FEE An additional fee to deduce from the bounced amount. .TP .B RESTRICTION_PAYTO_REGEX Bounce transactions coming from account not matching this regex. .UNINDENT .SS HTTP SERVER OPTIONS .sp The following configuration value(s) belong to the “[nexus\-httpd]” section. .INDENT 0.0 .TP .B SERVE This can either be \fBtcp\fP or \fBunix\fP\&. .TP .B PORT Port on which the HTTP server listens, e.g.\ 9967. Only used if \fBSERVE\fP is \fBtcp\fP\&. .TP .B BIND_TO Which IP address should we bind to? E.g. \fB127.0.0.1\fP or \fB::1\(ga\(gafor loopback. Can also be given as a hostname. Only used if \(ga\(gaSERVE\fP is \fBtcp\fP\&. .TP .B UNIXPATH Which unix domain path should we bind to? Only used if \fBSERVE\fP is \fBunix\fP\&. .UNINDENT .SS HTTP WIRE GATEWAY API OPTIONS .sp The following configuration value(s) belong to the “[nexus\-httpd\-wire\-gateway\-api]” section. .INDENT 0.0 .TP .B ENABLED Whether to serve the Wire Gateway API and the Prepared Transfer API. .UNINDENT .INDENT 0.0 .TP .B AUTH_METHOD Authentication scheme, this can either be \fBbasic\fP, \fBbearer\fP or \fBnone\fP\&. .TP .B USERNAME User name for \fBbasic\fP authentication scheme. .TP .B PASSWORD Password for \fBbasic\fP authentication scheme. .TP .B TOKEN Token for \fBbearer\fP authentication scheme. .UNINDENT .SS HTTP REVENUE API OPTIONS .sp The following configuration value(s) belong to the “[nexus\-httpd\-revenue\-api]” section. .INDENT 0.0 .TP .B ENABLED Whether to serve the Revenue API. .UNINDENT .INDENT 0.0 .TP .B AUTH_METHOD Authentication scheme, this can either be \fBbasic\fP, \fBbearer\fP or \fBnone\fP\&. .TP .B USERNAME User name for \fBbasic\fP authentication scheme. .TP .B PASSWORD Password for \fBbasic\fP authentication scheme. .TP .B TOKEN Token for \fBbearer\fP authentication scheme. .UNINDENT .SS HTTP OBSERVABILITY API OPTIONS .sp The following configuration value(s) belong to the “[nexus\-httpd\-observability\-api]” section. .INDENT 0.0 .TP .B ENABLED Whether to serve the Observability API. .UNINDENT .INDENT 0.0 .TP .B AUTH_METHOD Authentication scheme, this can either be \fBbasic\fP, \fBbearer\fP or \fBnone\fP\&. .TP .B USERNAME User name for \fBbasic\fP authentication scheme. .TP .B PASSWORD Password for \fBbasic\fP authentication scheme. .TP .B TOKEN Token for \fBbearer\fP authentication scheme. .UNINDENT .SS DATABASE OPTIONS .sp Setting the database belongs to the “[libeufin\-nexusdb\-postgres]” section and the following value. .INDENT 0.0 .TP .B CONFIG PostgreSQL connection string. .TP .B SQL_DIR Where are the SQL files to setup our tables? .UNINDENT .SH SEE ALSO .sp libeufin\-nexus(1) .SH BUGS .sp Report bugs by using \X'tty: link https://bugs.taler.net/'\fI\%https://bugs.taler.net/\fP\X'tty: link' or by sending electronic mail to <\X'tty: link mailto:taler@gnu.org'\fI\%taler@gnu.org\fP\X'tty: link'>. .SH AUTHOR GNU Taler contributors .SH COPYRIGHT 2014-2025 Taler Systems SA (GPLv3+ or GFDL 1.3+) .\" Generated by docutils manpage writer. . libeufin-1.6.8/doc/prebuilt/man/libeufin-nexus.10000664000175000017500000003026415236113377021745 0ustar grothoffgrothoff.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "LIBEUFIN-NEXUS" "1" "Aug 09, 2026" "1.0" "GNU Taler" .SH NAME libeufin-nexus \- service to interface to various bank access APIs .SH SYNOPSIS .sp \fBlibeufin\-nexus\fP [\fB\-h\fP\ |\ \fB\-\-help\fP] [\fB\-\-version\fP] COMMAND [ARGS...] .sp Subcommands: \fBdbinit\fP, \fBebics\-setup\fP, \fBebics\-submit\fP, \fBebics\-fetch\fP, \fBserve\fP, \fBinitiate\-payment\fP, \fBmanual\fP, \fBlist\fP, \fBconfig\fP .SH DESCRIPTION .sp \fBlibeufin\-nexus\fP is a program that provides a service to interface to various bank access APIs .sp Its options are as follows: .INDENT 0.0 .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .TP \fB–version\fP Print version information. .UNINDENT .sp The interaction model is as follows: .INDENT 0.0 .IP \(bu 2 Configure the database with commands \fBdbinit\fP\&. .IP \(bu 2 Setup EBICS access with commands \fBebics\-setup\fP\&. Setting the access means to share the client keys with the bank and downloading the bank keys .IP \(bu 2 After a successful setup, the subcommands \fBebics\-submit\fP and \fBebics\-fetch\fP can be run to respectively send payments and download the bank account history. .IP \(bu 2 Start the HTTP server with command \fBserve\fP\&. Let this run in a shell, writing logs to stderr. .UNINDENT .sp The following sections describe each command in detail. .SS dbinit .sp This command defines the database schema for LibEuFin Nexus. It is mandatory to run this command before invoking the \fBebics\-setup\fP or \fBserve\fP commands. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-r\fP | \fB\-\-reset\fP Reset database (DANGEROUS: All existing data is lost) .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS ebics\-setup .sp This command creates the client keys, if they aren\(aqt found already on the disk, and sends them to the bank if they were not sent yet. In case of sending, it ejects the PDF document that contains the keys fingerprints, so that the user can send it to the bank to confirm their keys. The process continues by checking if the bank keys exist already on disk, and proceeds with downloading them in case they are not. It checks then if the bank keys were accepted by the user; if yes, the setup terminates, otherwise it interactively asks the user to mark the keys as accepted. By accepting the bank keys, the setup terminates successfully. .sp It is mandatory to run this command before invoking the \fBebics\-fetch\fP or \fBebics\-submit\fP commands. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-force\-keys\-resubmission\fP Resubmits all the keys to the bank. .TP \fB\-\-auto\-accept\-keys\fP Accepts the bank keys without interactively asking the user. .TP \fB\-\-generate\-registration\-pdf\fP Generates the PDF with the client keys fingerprints, if the keys have the submitted state. That\(aqs useful in case the PDF went lost after the first submission and the user needs a new PDF. .TP \fB\-\-debug\-ebics\fP Log EBICS transactions steps and payload at log_dir. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS ebics\-submit .sp This subcommand submits EBICS files to the bank. It submits pending outgoing payments. Outgoing payment status is fetched by ebics\-fetch. .sp Submits are executed at \(aqFREQUENCY\(aq. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-transient\fP Execute once and return, ignoring the \(aqFREQUENCY\(aq configuration value. .TP \fB\-\-debug\-ebics\fP \fIlog_dir\fP Log EBICS transactions steps and payload at log_dir. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS ebics\-fetch .sp This subcommand fetches EBICS files from the bank. Incoming payments are recorded and the status of outgoing payments is updated. .sp If ACCOUNT_TYPE is \fBexchange\fP, incoming payments with an invalid Taler subject are bounced. Bounces are submitted by ebics\-submit. .sp Fetches of new documents are executed at \(aqFREQUENCY\(aq or any time a real\-time EBICS notification is received. Every day, a checkpoint is performed, during which all documents since the last checkpoint are fetched. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-transient\fP Execute once and return, ignoring the \(aqFREQUENCY\(aq configuration value. .TP \fB\-\-pinned\-start\fP \fIYYYY\-MM\-DD\fP Only supported in \-\-transient mode, this option lets specify the earliest timestamp of the downloaded documents. .TP \fB\-\-peek\fP Only supported in \-\-transient mode, do not consume fetched documents. .TP \fB\-\-checkpoint\fP Only supported in \-\-transient mode, run a checkpoint. .TP \fB\-\-debug\-ebics\fP \fIlog_dir\fP Log EBICS transactions steps and payload at log_dir. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS serve .sp This command starts the HTTP server. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-check\fP Check whether an API is in use (if it\(aqs useful to start the HTTP server). Exit with 0 if at least one API is enabled, otherwise 1. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS initiate\-payment .sp This subcommand initiates an outgoing payment. The pending payment is stored in the database and will be performed the next time \fBebics\-submit\fP run. .sp It takes one argument, the creditor IBAN payto URI, which must contain a \(aqreceiver\-name\(aq and may contain an \(aqamount\(aq and a \(aqmessage\(aq if they have not been defined using CLI options. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-amount\fP \fIAMOUNT\fP The amount to transfer, payto \(aqamount\(aq parameter takes the precedence .TP \fB\-\-subject\fP \fITEXT\fP The payment subject, payto \(aqmessage\(aq parameter takes the precedence .TP \fB\-\-request\-uid\fP \fITEXT\fP The payment request UID, will be randomly generated if missing. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS manual .sp Manual management commands. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .sp Subcommands: \fBexport\fP, \fBimport\fP, \fBstatus\fP, \fBack\fP .SS manual export .sp Export pending batches as pain001 messages. .sp It takes one argument, the path where to write the zip export. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS manual import .sp Import EBICS camt files. .sp It takes multiple arguments, the paths to XML files to import. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS manual status .sp Change batches or transactions status. .sp It takes four arguments: the element kind, the element id, the new status and an optional status message. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS manual ack .sp Manually acknowledge the outgoing transaction for submission. .sp It takes many transactions as arguments. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS list .sp List nexus transactions. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .sp Subcommands: \fBincoming\fP, \fBoutgoing\fP, \fBinitiated\fP .SS list incoming .sp List incoming transactions. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-incomplete\fP Only list transactions that are incomplete .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS list outgoing .sp List outgoing transactions. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS list initiated .sp List initiated transactions. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-ack\fP | \fB\-\-awaiting\-ack\fP Only list transactions awaiting manual acknowledgement. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config .sp This command inspect or change the configuration. .INDENT 0.0 .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .sp Subcommands: \fBget\fP, \fBdump\fP, \fBpathsub\fP .SS config get .sp This command lookup config value. .sp It takes two arguments, the section name and the option name .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-f\fP | \fB\-\-filename\fP Interpret value as path with dollar\-expansion. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config dump .sp This command dump the configuration. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config pathsub .sp This command substitute variables in a path. .sp It takes one argument, a path expression. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SH SEE ALSO .sp libeufin\-nexus.conf(5) .SH BUGS .sp Report bugs by using \X'tty: link https://bugs.taler.net'\fI\%https://bugs.taler.net\fP\X'tty: link' or by sending electronic mail to <\X'tty: link mailto:taler@gnu.org'\fI\%taler@gnu.org\fP\X'tty: link'>. .SH AUTHOR GNU Taler contributors .SH COPYRIGHT 2014-2025 Taler Systems SA (GPLv3+ or GFDL 1.3+) .\" Generated by docutils manpage writer. . libeufin-1.6.8/doc/prebuilt/man/libeufin-bank.10000664000175000017500000001777315236113377021530 0ustar grothoffgrothoff.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "LIBEUFIN-BANK" "1" "Aug 09, 2026" "1.0" "GNU Taler" .SH NAME libeufin-bank \- implementation of a regional currency bank .SH SYNOPSIS .sp \fBlibeufin\-bank\fP [\fB\-h\fP\ |\ \fB\-\-help\fP] [\fB\-\-version\fP] COMMAND [ARGS...] .sp Subcommands: \fBdbinit\fP, \fBpasswd\fP, \fBcreate\-token\fP, \fBserve\fP, \fBcreate\-account\fP, \fBedit\-account\fP, \fBgc\fP, \fBbench\-pwh\fP, \fBconfig\fP .SH DESCRIPTION .sp \fBlibeufin\-bank\fP is a program that implements a simple core banking system with account and REST APIs, including REST APIs for a Web interface and REST APIs to interact with GNU Taler components. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .TP \fB–version\fP Print version information. .UNINDENT .sp The interaction model is as follows: .INDENT 0.0 .IP \(bu 2 Configure the database with commands \fBdbinit\fP\&. .IP \(bu 2 Set admin account password with commands \fBpasswd\fP\&. .IP \(bu 2 Start the HTTP server with command \fBserve\fP\&. Let this run in a shell, writing logs to stderr. .UNINDENT .sp The following sections describe each command in detail. .SS dbinit .sp This command defines the database schema for LibEuFin Bank. It is mandatory to run this command before invoking the \fBpasswd\fP or \fBserve\fP commands. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-r\fP | \fB\-\-reset\fP Reset database (DANGEROUS: All existing data is lost) .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS passwd .sp This command change any account password. .sp It takes two arguments, the account username and the account new password. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS create\-token .sp Create authentication token for a userword. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-u\fP | \fB\-\-user\fP | \fB\-\-username\fP \fIUSERNAME\fP Account username. .TP \fB\-s\fP | \fB\-\-scope\fP \fISCOPE\fP Scope for the token. .TP \fB\-d\fP | \fB\-\-duration\fP \fIforever|MICROS\fP Custom token validity duration. .TP \fB\-\-description\fP \fIDESCRIPTION\fP Optional token description. .TP \fB\-\-refreshable\fP Make the token refreshable into a new token. .TP \fB\-\-current\-token\fP \fITOKEN\fP Current token to reuse if still valid. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS serve .sp This command starts the HTTP server. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS create\-account .sp This command create a bank account and prints its payto://\-URI to STDOUT. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-u\fP | \fB\-\-user\fP | \fB\-\-username\fP \fIUSERNAME\fP Account unique username. .TP \fB\-p\fP | \fB\-\-password\fP \fIPASSWORD\fP Account password used for authentication. .TP \fB\-\-name\fP \fINAME\fP Legal name of the account owner. .TP \fB\-\-public\fP Make this account visible to anyone. .TP \fB\-\-exchange\fP Make this account a taler exchange. .TP \fB\-\-email\fP \fIEMAIL\fP E\-Mail address used for TAN transmission. .TP \fB\-\-phone\fP \fIPHONE_NUMBER\fP Phone number used for TAN transmission. .TP \fB\-\-cashout_payto_uri\fP \fIPAYTO_URI\fP Payto URI of a fiant account who receive cashout amount. .TP \fB\-\-payto_uri\fP \fIPAYTO_URI\fP Payto URI of this account. .TP \fB\-\-debit_threshold\fP \fIAMOUNT\fP Max debit allowed for this account. .TP \fB\-\-tan_channel\fP \fITAN_CHANNEL\fP Enables 2FA and set the TAN channel used for challenges. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS edit\-account .sp This command edit an existing account. .sp It takes one argument, the account username. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-\-name\fP \fINAME\fP Legal name of the account owner. .TP \fB\-\-public\fP \fItrue|false\fP Make this account visible to anyone. .TP \fB\-\-email\fP \fIEMAIL\fP E\-Mail address used for TAN transmission. .TP \fB\-\-phone\fP \fIPHONE_NUMBER\fP Phone number used for TAN transmission. .TP \fB\-\-cashout_payto_uri\fP \fIPAYTO_URI\fP Payto URI of this account. .TP \fB\-\-debit_threshold\fP \fIAMOUNT\fP Max debit allowed for this account. .TP \fB\-\-tan_channel\fP \fITAN_CHANNEL\fP Enables 2FA and set the TAN channel used for challenges. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS gc .sp This command performs garbage collection: abort expired operations and clean expired data. .sp Its options are as follows: .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config .sp This command inspect or change the configuration. .INDENT 0.0 .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .sp Subcommands: \fBget\fP, \fBdump\fP, \fBpathsub\fP .SS config get .sp This command lookup config value. .sp It takes two arguments, the section name and the option name .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-f\fP | \fB\-\-filename\fP Interpret value as path with dollar\-expansion. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config dump .sp This command dump the configuration. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SS config pathsub .sp This command substitute variables in a path. .sp It takes one argument, a path expression. .INDENT 0.0 .TP \fB\-c\fP | \fB\-\-config\fP \fIconfig_file\fP Specifies the configuration file. .TP \fB\-L\fP | \fB\-\-log\fP \fILOGLEVEL\fP Configure logging to use LOGLEVEL. .TP \fB\-h\fP | \fB\-\-help\fP Print short help on options. .UNINDENT .SH SEE ALSO .sp libeufin\-bank.conf(5) .SH BUGS .sp Report bugs by using \X'tty: link https://bugs.taler.net'\fI\%https://bugs.taler.net\fP\X'tty: link' or by sending electronic mail to <\X'tty: link mailto:taler@gnu.org'\fI\%taler@gnu.org\fP\X'tty: link'>. .SH AUTHOR GNU Taler contributors .SH COPYRIGHT 2014-2025 Taler Systems SA (GPLv3+ or GFDL 1.3+) .\" Generated by docutils manpage writer. . libeufin-1.6.8/doc/prebuilt/man/libeufin-ebisync.conf.50000664000175000017500000002032115236113377023160 0ustar grothoffgrothoff.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "LIBEUFIN-EBISYNC.CONF" "5" "Aug 09, 2026" "1.0" "GNU Taler" .SH NAME libeufin-ebisync.conf \- LibEuFin EbiSync configuration file .SH DESCRIPTION .sp The configuration file is line\-oriented. Blank lines and whitespace at the beginning and end of a line are ignored. Comments start with \fB#\fP or \fB%\fP in the first column (after any beginning\-of\-line whitespace) and go to the end of the line. .sp The file is split into sections. Every section begins with \fB[SECTIONNAME]\fP and contains a number of options of the form \fBOPTION=VALUE\fP\&. There may be whitespace around the \fB=\fP (equal sign). Section names and options are \fIcase\-insensitive\fP\&. .sp The values, however, are \fIcase\-sensitive\fP\&. In particular, boolean values are one of \fBYES\fP or \fBNO\fP\&. Values can include whitespace by surrounding the entire value with \fB\(dq\fP (double quote). Note, however, that there are no escape characters in such strings; all characters between the double quotes (including other double quotes) are taken verbatim. .sp Values that represent a time duration are represented as a series of one or more \fBNUMBER UNIT\fP pairs, e.g. \fB60 s\fP, \fB4 weeks 1 day\fP, \fB5 years 2 minutes\fP\&. .sp Values that represent an amount are in the usual amount syntax: \fBCURRENCY:VALUE.FRACTION\fP, e.g. \fBEUR:1.50\fP\&. The \fBFRACTION\fP portion may extend up to 8 places. .sp Values that represent filenames can begin with a \fB/bin/sh\fP\-like variable reference. This can be simple, such as \fB$TMPDIR/foo\fP, or complex, such as \fB${TMPDIR:\-${TMP:\-/tmp}}/foo\fP\&. The variables are expanded either using key\-values from the \fB[PATHS]\fP section (see below) or from the environment (\fBgetenv()\fP). The values from \fB[PATHS]\fP take precedence over those from the environment. If the variable name is found in neither \fB[PATHS]\fP nor the environment, a warning is printed and the value is left unchanged. Variables (including those from the environment) are expanded recursively, so if \fBFOO=$BAR\fP and \fBBAR=buzz\fP then the result is \fBFOO=buzz\fP\&. Recursion is bounded to at most 128 levels to avoid undefined behavior for mutually recursive expansions like if \fBBAR=$FOO\fP in the example above. .sp The \fB[PATHS]\fP section is special in that it contains paths that can be referenced using \fB$\fP in other configuration values that specify \fIfilenames\fP\&. Note that configuration options that are not specifically retrieved by the application as \fIfilenames\fP will not see “$”\-expressions expanded. To expand \fB$\fP\-expressions when using \fBtaler\-config\fP, you must pass the \fB\-f\fP command\-line option. .sp The system automatically pre\-populates the \fB[PATHS]\fP section with a few values at run\-time (in addition to the values that are in the actual configuration file and automatically overwriting those values if they are present). These automatically generated values refer to installation properties from \X'tty: link https://www.gnu.org/prep/standards/html_node/Directory-Variables.html'\fI\%GNU autoconf\fP\X'tty: link'\&. The values are usually dependent on an \fBINSTALL_PREFIX\fP which is determined by the \fB\-\-prefix\fP option given to configure. The canonical values are: .INDENT 0.0 .IP \(bu 2 LIBEXECDIR = $INSTALL_PREFIX/taler/libexec/ .IP \(bu 2 DOCDIR = $INSTALL_PREFIX/share/doc/taler/ .IP \(bu 2 ICONDIR = $INSTALL_PREFIX/share/icons/ .IP \(bu 2 LOCALEDIR = $INSTALL_PREFIX/share/locale/ .IP \(bu 2 PREFIX = $INSTALL_PREFIX/ .IP \(bu 2 BINDIR = $INSTALL_PREFIX/bin/ .IP \(bu 2 LIBDIR = $INSTALL_PREFIX/lib/taler/ .IP \(bu 2 DATADIR = $INSTALL_PREFIX/share/taler/ .UNINDENT .sp Note that on some platforms, the given paths may differ depending on how the system was compiled or installed, the above are just the canonical locations of the various resources. These automatically generated values are never written to disk. .sp Files containing default values for many of the options described below are installed under \fB$LIBEUFIN_EBISYNC_PREFIX/share/libeufin\-ebisync/config.d/\fP\&. The configuration file given with \fB\-c\fP to Taler binaries overrides these defaults. .sp A configuration file may include another, by using the \fB@INLINE@\fP directive, for example, in \fBmain.conf\fP, you could write \fB@INLINE@ sub.conf\fP to include the entirety of \fBsub.conf\fP at that point in \fBmain.conf\fP\&. .SS GLOBAL OPTIONS .sp The following options are from the “[ebisync]” section. .INDENT 0.0 .TP .B HOST_BASE_URL URL of the EBICS server .TP .B HOST_ID EBICS specific: name of the EBICS host .TP .B USER_ID EBICS specific: user ID of the EBICS subscriber. This value must be assigned by the bank after having activated a new EBICS subscriber. .TP .B PARTNER_ID EBICS specific: partner ID of the EBICS subscriber. This value must be assigned by the bank after having activated a new EBICS subscriber. .TP .B BANK_PUBLIC_KEYS_FILE Filesystem location where EbiSync should store the bank public keys. .TP .B CLIENT_PRIVATE_KEYS_FILE Filesystem location where EbiSync should store the subscriber private keys. .UNINDENT .SS SETUP OPTIONS .sp The following configuration value(s) belong to the “[ebisync\-setup]” section. .INDENT 0.0 .TP .B BANK_ENCRYPTION_PUB_KEY_HASH Bank encryption public key hash. .TP .B BANK_AUTHENTICATION_PUB_KEY_HASH Bank authentication public key hash. .UNINDENT .SS FETCH OPTIONS .sp The following configuration value(s) belong to the “[ebisync\-fetch]” section. .INDENT 0.0 .TP .B FREQUENCY Duration value to instruct the \fBfetch\fP subcommand how often it should download from the bank. .TP .B CHECKPOINT_TIME_OF_DAY At what time HH:MM of day should \fBfetch\fP perform a checkpoint. .TP .B DESTINATION Where should the ebics file be stored? This can either be \fBazure\-blob\-storage\fP or \fBnone\fP\&. .TP .B AZURE_API_URL Azure API account base url .TP .B AZURE_ACCOUNT_NAME Azure API account name .TP .B AZURE_ACCOUNT_KEY Azure API account key .TP .B AZURE_COUNTAINER Which Azure Blob Storage container to use .UNINDENT .SS SUBMIT OPTIONS .sp The following configuration value(s) belong to the “[ebisync\-submit]” section. .INDENT 0.0 .TP .B SOURCE Where does the ebics file come from? This can either be \fBebisync\-api\fP or \fBnone\fP .TP .B AUTH_METHOD Authentication scheme for api sources, this can either be \fBbasic\fP, \fBbearer\fP or \fBnone\fP\&. .TP .B USERNAME User name for \fBbasic\fP authentication scheme. .TP .B PASSWORD Password for \fBbasic\fP authentication scheme. .TP .B TOKEN Token for \fBbearer\fP authentication scheme. .UNINDENT .SS HTTP SERVER OPTIONS .sp The following configuration value(s) belong to the “[ebisync\-httpd]” section. .INDENT 0.0 .TP .B SERVE This can either be \fBtcp\fP or \fBunix\fP\&. .TP .B PORT Port on which the HTTP server listens, e.g.\ 9967. Only used if \fBSERVE\fP is \fBtcp\fP\&. .TP .B BIND_TO Which IP address should we bind to? E.g. \fB127.0.0.1\fP or \fB::1\(ga\(gafor loopback. Can also be given as a hostname. Only used if \(ga\(gaSERVE\fP is \fBtcp\fP\&. .TP .B UNIXPATH Which unix domain path should we bind to? Only used if \fBSERVE\fP is \fBunix\fP\&. .UNINDENT .SS DATABASE OPTIONS .sp Setting the database belongs to the “[ebisyncdb\-postgres]” section and the following value. .SH SEE ALSO .sp libeufin\-ebisync(1) .SH BUGS .sp Report bugs by using \X'tty: link https://bugs.taler.net/'\fI\%https://bugs.taler.net/\fP\X'tty: link' or by sending electronic mail to <\X'tty: link mailto:taler@gnu.org'\fI\%taler@gnu.org\fP\X'tty: link'>. .SH AUTHOR GNU Taler contributors .SH COPYRIGHT 2014-2025 Taler Systems SA (GPLv3+ or GFDL 1.3+) .\" Generated by docutils manpage writer. . libeufin-1.6.8/doc/prebuilt/man/libeufin-bank.conf.50000664000175000017500000002343715236113377022452 0ustar grothoffgrothoff.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "LIBEUFIN-BANK.CONF" "5" "Aug 09, 2026" "1.0" "GNU Taler" .SH NAME libeufin-bank.conf \- LibEuFin Bank configuration file .SH DESCRIPTION .sp The configuration file is line\-oriented. Blank lines and whitespace at the beginning and end of a line are ignored. Comments start with \fB#\fP or \fB%\fP in the first column (after any beginning\-of\-line whitespace) and go to the end of the line. .sp The file is split into sections. Every section begins with \fB[SECTIONNAME]\fP and contains a number of options of the form \fBOPTION=VALUE\fP\&. There may be whitespace around the \fB=\fP (equal sign). Section names and options are \fIcase\-insensitive\fP\&. .sp The values, however, are \fIcase\-sensitive\fP\&. In particular, boolean values are one of \fBYES\fP or \fBNO\fP\&. Values can include whitespace by surrounding the entire value with \fB\(dq\fP (double quote). Note, however, that there are no escape characters in such strings; all characters between the double quotes (including other double quotes) are taken verbatim. .sp Values that represent a time duration are represented as a series of one or more \fBNUMBER UNIT\fP pairs, e.g. \fB60 s\fP, \fB4 weeks 1 day\fP, \fB5 years 2 minutes\fP\&. .sp Values that represent an amount are in the usual amount syntax: \fBCURRENCY:VALUE.FRACTION\fP, e.g. \fBEUR:1.50\fP\&. The \fBFRACTION\fP portion may extend up to 8 places. .sp Values that represent filenames can begin with a \fB/bin/sh\fP\-like variable reference. This can be simple, such as \fB$TMPDIR/foo\fP, or complex, such as \fB${TMPDIR:\-${TMP:\-/tmp}}/foo\fP\&. The variables are expanded either using key\-values from the \fB[PATHS]\fP section (see below) or from the environment (\fBgetenv()\fP). The values from \fB[PATHS]\fP take precedence over those from the environment. If the variable name is found in neither \fB[PATHS]\fP nor the environment, a warning is printed and the value is left unchanged. Variables (including those from the environment) are expanded recursively, so if \fBFOO=$BAR\fP and \fBBAR=buzz\fP then the result is \fBFOO=buzz\fP\&. Recursion is bounded to at most 128 levels to avoid undefined behavior for mutually recursive expansions like if \fBBAR=$FOO\fP in the example above. .sp The \fB[PATHS]\fP section is special in that it contains paths that can be referenced using \fB$\fP in other configuration values that specify \fIfilenames\fP\&. Note that configuration options that are not specifically retrieved by the application as \fIfilenames\fP will not see “$”\-expressions expanded. To expand \fB$\fP\-expressions when using \fBtaler\-config\fP, you must pass the \fB\-f\fP command\-line option. .sp The system automatically pre\-populates the \fB[PATHS]\fP section with a few values at run\-time (in addition to the values that are in the actual configuration file and automatically overwriting those values if they are present). These automatically generated values refer to installation properties from \X'tty: link https://www.gnu.org/prep/standards/html_node/Directory-Variables.html'\fI\%GNU autoconf\fP\X'tty: link'\&. The values are usually dependent on an \fBINSTALL_PREFIX\fP which is determined by the \fB\-\-prefix\fP option given to configure. The canonical values are: .INDENT 0.0 .IP \(bu 2 LIBEXECDIR = $INSTALL_PREFIX/taler/libexec/ .IP \(bu 2 DOCDIR = $INSTALL_PREFIX/share/doc/taler/ .IP \(bu 2 ICONDIR = $INSTALL_PREFIX/share/icons/ .IP \(bu 2 LOCALEDIR = $INSTALL_PREFIX/share/locale/ .IP \(bu 2 PREFIX = $INSTALL_PREFIX/ .IP \(bu 2 BINDIR = $INSTALL_PREFIX/bin/ .IP \(bu 2 LIBDIR = $INSTALL_PREFIX/lib/taler/ .IP \(bu 2 DATADIR = $INSTALL_PREFIX/share/taler/ .UNINDENT .sp Note that on some platforms, the given paths may differ depending on how the system was compiled or installed, the above are just the canonical locations of the various resources. These automatically generated values are never written to disk. .sp Files containing default values for many of the options described below are installed under \fB$LIBEUFIN_BANK_PREFIX/share/libeufin\-bank/config.d/\fP\&. The configuration file given with \fB\-c\fP to Taler binaries overrides these defaults. .sp A configuration file may include another, by using the \fB@INLINE@\fP directive, for example, in \fBmain.conf\fP, you could write \fB@INLINE@ sub.conf\fP to include the entirety of \fBsub.conf\fP at that point in \fBmain.conf\fP\&. .SS GLOBAL OPTIONS .sp The following options are from the “[libeufin\-bank]” section. .INDENT 0.0 .TP .B CURRENCY Internal currency of the libeufin\-bank, e.g.\ “EUR” for Euro. .TP .B WIRE_TYPE Supported payment target type, this can either be \fBiban\fP or \fBx\-taler\-bank\fP .TP .B IBAN_PAYTO_BIC Bank BIC used in generated iban payto URI. Required if \fBWIRE_TYPE\(ga\(gais \(ga\(gaiban\fP .TP .B X_TALER_BANK_PAYTO_HOSTNAME Bank hostname used in generated x\-taler\-bank payto URI. Required if \fBWIRE_TYPE\(ga\(gais \(ga\(gax\-taler\-bank\fP .TP .B NAME Bank display name, used in webui and TAN messages. Defaults to \fBTaler Bank\fP if not specified. .TP .B BASE_URL The advertised base URL .TP .B WIRE_TRANSFER_FEES Wire transfer execution fees. Only applies to bank transactions and withdrawals. Defaults to \fBCURRENCY:0\fP if not specified. .TP .B MIN_WIRE_TRANSFER_AMOUNT Minimum wire transfer amount allowed. Only applies to bank transactions and withdrawals. Defaults to no limit. .TP .B MAX_WIRE_TRANSFER_AMOUNT Maximum wire transfer amount allowed. Only applies to bank transactions and withdrawals. Defaults to no limit. .TP .B DEFAULT_DEBT_LIMIT Default debt limit for newly created accounts. Defaults to \fBCURRENCY:0\fP if not specified. .TP .B REGISTRATION_BONUS Value of the registration bonus for new users. Defaults to \fBCURRENCY:0\fP if not specified. .TP .B ALLOW_REGISTRATION Whether anyone can create a new account or whether this action is reserved for the admin. Defaults to \fBNO\fP if not specified. .TP .B ALLOW_ACCOUNT_DELETION Whether anyone can delete its account or whether this action is reserved for the admin. Defaults to \fBNO\fP if not specified. .TP .B ALLOW_EDIT_NAME Whether anyone can edit their legal name or whether this action is reserved for the admin. Defaults to \fBNO\fP if not specified. .TP .B ALLOW_EDIT_CASHOUT_PAYTO_URI Whether anyone can edit their cashout account or whether this action is reserved for the admin. Defaults to \fBNO\fP if not specified. .TP .B ALLOW_CONVERSION Whether regional currency conversion is enabled. Defaults to \fBNO\fP if not specified. .TP .B FIAT_CURRENCY External currency used during cashin and cashout. Only used if \fBALLOW_CONVERSION\fP is \fBYES\fP\&. .TP .B TAN_SMS Path to TAN challenge transmission script via sms. If not specified, this TAN channel will not be supported. Only used if \fBALLOW_CONVERSION\fP is \fBYES\fP\&. .TP .B TAN_EMAIL Path to TAN challenge transmission script via email. If not specified, this TAN channel will not be supported. Only used if \fBALLOW_CONVERSION\fP is \fBYES\fP\&. .TP .B TAN_SMS_ENV Environment variables for the sms TAN script as a single\-line JSON object Only used if \fBTAN_SMS\fP is set. .TP .B TAN_EMAIL_ENV Environment variables for the email TAN script as a single\-line JSON object Only used if \fBTAN_EMAIL\fP is set. .TP .B SERVE This can either be \fBtcp\fP or \fBunix\fP\&. .TP .B PORT Port on which the HTTP server listens, e.g.\ 9967. Only used if \fBSERVE\fP is \fBtcp\fP\&. .TP .B BIND_TO Which IP address should we bind to? E.g. \fB127.0.0.1\fP or \fB::1\(ga\(gafor loopback. Can also be given as a hostname. Only used if \(ga\(gaSERVE\fP is \fBtcp\fP\&. .TP .B UNIXPATH Which unix domain path should we bind to? Only used if \fBSERVE\fP is \fBunix\fP\&. .TP .B SUGGESTED_WITHDRAWAL_EXCHANGE Exchange that is suggested to wallets when withdrawing .TP .B PWD_HASH_ALGORITHM Password hash algorithm, this can only be \fBbcrypt\fP .TP .B PWD_HASH_CONFIG Password hash algorithm configuration as a single\-line JSON object When \fBPWD_HASH_ALGORITHM\fP is \fBbcrypt\fP you can configure \fBcost\fP .TP .B PWD_CHECK Whether to check password quality Unstable flag, will become a non configurable default in a future version .TP .B PWD_AUTH_COMPAT Whether to allow password auth everywhere Unstable flag, will become a non configurable default in a future version .TP .B GC_ABORT_AFTER Time after which pending operations are aborted during garbage collection .TP .B GC_CLEAN_AFTER Time after which aborted operations and expired items are deleted during garbage collection .TP .B GC_DELETE_AFTER Time after which all bank transactions, operations and deleted accounts are deleted during garbage collection .UNINDENT .SS DATABASE OPTIONS .sp Setting the database belongs to the “[libeufin\-bankdb\-postgres]” section and the following value. .INDENT 0.0 .TP .B CONFIG PostgreSQL connection string. .TP .B SQL_DIR Where are the SQL files to setup our tables? .UNINDENT .SH SEE ALSO .sp libeufin\-bank(1). .SH BUGS .sp Report bugs by using \X'tty: link https://bugs.taler.net/'\fI\%https://bugs.taler.net/\fP\X'tty: link' or by sending electronic mail to <\X'tty: link mailto:taler@gnu.org'\fI\%taler@gnu.org\fP\X'tty: link'>. .SH AUTHOR GNU Taler contributors .SH COPYRIGHT 2014-2025 Taler Systems SA (GPLv3+ or GFDL 1.3+) .\" Generated by docutils manpage writer. . libeufin-1.6.8/.gitmodules0000644000175000017500000000050414757402655015734 0ustar grothoffgrothoff[submodule "build-system/taler-build-scripts"] path = build-system/taler-build-scripts url = ../build-common.git [submodule "contrib/wallet-core"] path = contrib/wallet-core url = ../taler-typescript-core.git branch = prebuilt [submodule "doc/prebuilt"] path = doc/prebuilt url = ../taler-docs.git branch = prebuilt libeufin-1.6.8/libeufin-bank/0000775000175000017500000000000015236145704016260 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/0000775000175000017500000000000015236145704017047 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/0000775000175000017500000000000015236145704017773 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/0000775000175000017500000000000015236145704021273 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/0000775000175000017500000000000015236145704022216 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/0000775000175000017500000000000015236145704024013 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/0000775000175000017500000000000015236145704024726 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/api/0000775000175000017500000000000015236145704025477 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/api/PreparedTransferApi.kt0000664000175000017500000001252515221677432031747 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.api import io.ktor.http.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import io.ktor.util.pipeline.* import tech.libeufin.bank.* import tech.libeufin.bank.auth.pathUsername import tech.libeufin.bank.db.Database import tech.libeufin.bank.db.TransferDAO.RegistrationResult import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import java.time.Instant import java.time.Duration fun Routing.preparedTransferApi(db: Database, cfg: BankConfig) { get("/taler-prepared-transfer/config", { operationId = "getPreparedTransferConfig" description = "Get the configuration of the prepared transfer API" tags = listOf("Prepared Transfer") request { pathParameter("USERNAME") { description = "Account username" } } response { code(HttpStatusCode.OK) { description = "Configuration of the prepared transfer API"; body() } } }) { call.respond( PreparedTransferConfig( currency = cfg.regionalCurrency, supported_formats = listOf(SubjectFormat.SIMPLE) ) ) } post("/taler-prepared-transfer/registration", { operationId = "registerTransfer" description = "Register a prepared transfer" tags = listOf("Prepared Transfer") request { body() } response { code(HttpStatusCode.OK) { description = "Registration successful"; body() } code(HttpStatusCode.Conflict) { description = "Reserve pub or subject derivation already used" } } }) { val req = call.receive() cfg.checkRegionalCurrency(req.credit_amount) if (!req.verify()) throw forbidden( "invalid signature", TalerErrorCode.BANK_BAD_SIGNATURE ) when (val result = db.transfer.register( req.credit_account, req.type, req.account_pub, req.authorization_pub, req.authorization_sig, req.recurrent, req.credit_amount, Instant.now() )) { RegistrationResult.NotExchange -> throw notExchange(req.credit_account.canonical) RegistrationResult.ReservePubReuse -> throw conflict( "reserve_pub used already", TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT ) RegistrationResult.UnknownCreditor -> throw unknownCreditorAccount(req.credit_account.canonical) is RegistrationResult.Success -> { val subjects = mutableListOf() if (result.uuid != null) subjects.add(TransferSubject.Uri(cfg.talerWithdrawUri(result.uuid), req.credit_amount)) subjects.add(TransferSubject.Simple(fmtIncomingSubject(IncomingType.map, req.authorization_pub), req.credit_amount)) call.respond( SubjectResult( subjects, TalerTimestamp.never() ) ) } } } post("/taler-prepared-transfer/unregistration", { operationId = "unregisterTransfer" description = "Unregister a prepared subject" tags = listOf("Prepared Transfer") response { code(HttpStatusCode.NoContent) { description = "Successfully unregistered" } code(HttpStatusCode.NotFound) { description = "Prepared transfer not found" } code(HttpStatusCode.Conflict) { description = "Invalid signature or timestamp too old" } } }) { val req = call.receive(); logger.error("${req.nbo().joinToString(", ") { (it.toInt() and 0xFF).toString() }}") if (req.timestamp.instant.isBefore(Instant.now().minus(Duration.ofMinutes(15)))) throw conflict( "timestamp too old", TalerErrorCode.BANK_OLD_TIMESTAMP ) if (!req.verify()) throw forbidden( "invalid signature", TalerErrorCode.BANK_BAD_SIGNATURE ) if (db.transfer.unregister(req.authorization_pub, Instant.now())) { call.respond(HttpStatusCode.NoContent) } else { throw notFound( "Prepared transfer '${req.authorization_pub}' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) } } } libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/api/BankIntegrationApi.kt0000664000175000017500000002013715204341712031543 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ /* This file contains the Taler Integration API endpoints, * that are typically requested by wallets. */ package tech.libeufin.bank.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import tech.libeufin.bank.* import tech.libeufin.bank.db.AbortResult import tech.libeufin.bank.db.Database import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalSelectionResult import tech.libeufin.common.* fun Routing.bankIntegrationApi(db: Database, ctx: BankConfig) { get("/taler-integration/config", { operationId = "getIntegrationConfig" description = "Get bank integration configuration" tags = listOf("Bank Integration") response { code(HttpStatusCode.OK) { description = "Integration configuration"; body() } } }) { call.respond(TalerIntegrationConfigResponse( currency = ctx.regionalCurrency, currency_specification = ctx.regionalCurrencySpec )) } // Note: wopid acts as an authentication token. get("/taler-integration/withdrawal-operation/{wopid}", { operationId = "getIntegrationWithdrawalStatus" description = "Get withdrawal operation status" tags = listOf("Bank Integration") request { pathParameter("wopid") { description = "Withdrawal operation ID" } queryParameter("timeout_ms") { description = "Timeout for long polling in milliseconds (default: 0, no long polling)" required = false } queryParameter("old_state") { description = "Previous state for long polling (pending, aborted, selected, confirmed). Default: pending" required = false } } response { code(HttpStatusCode.OK) { description = "Withdrawal operation status"; body() } code(HttpStatusCode.NotFound) { description = "Withdrawal operation not found" } } }) { val uuid = call.uuidPath("wopid") val params = StatusParams.extract(call.request.queryParameters) val op = db.withdrawal.pollStatus( uuid, params, ctx.wireMethod, ctx.maxAmount )?.copy( card_fees = ctx.wireTransferFees, min_amount = ctx.minAmount ) ?: throw notFound( "Withdrawal operation '$uuid' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) call.respond(op.copy( suggested_exchange = ctx.suggestedWithdrawalExchange, confirm_transfer_url = if (op.status == WithdrawalStatus.pending || op.status == WithdrawalStatus.selected) ctx.withdrawConfirmUrl(uuid) else null )) } post("/taler-integration/withdrawal-operation/{wopid}", { operationId = "selectWithdrawalExchange" description = "Select exchange and reserve for withdrawal" tags = listOf("Bank Integration") request { pathParameter("wopid") { description = "Withdrawal operation ID" } body() } response { code(HttpStatusCode.OK) { description = "Exchange selected"; body() } code(HttpStatusCode.NotFound) { description = "Withdrawal operation not found" } code(HttpStatusCode.Conflict) { description = "Operation conflict" } } }) { val uuid = call.uuidPath("wopid") val req = call.receive() req.amount?.run(ctx::checkRegionalCurrency) val res = db.withdrawal.setDetails( uuid, req.selected_exchange, req.reserve_pub, req.amount, ctx.wireTransferFees, ctx.minAmount, ctx.maxAmount ) when (res) { WithdrawalSelectionResult.UnknownOperation -> throw notFound( "Withdrawal operation '$uuid' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) WithdrawalSelectionResult.AlreadySelected -> throw conflict( "Cannot select different exchange and reserve pub. under the same withdrawal operation", TalerErrorCode.BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT ) WithdrawalSelectionResult.ReservePubReuse -> throw conflict( "Reserve pub already used", TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT ) WithdrawalSelectionResult.UnknownAccount -> throw conflict( "Account ${req.selected_exchange} not found", TalerErrorCode.BANK_UNKNOWN_ACCOUNT ) WithdrawalSelectionResult.AccountIsNotExchange -> throw notExchange(req.selected_exchange.toString()) WithdrawalSelectionResult.AmountDiffers -> throw conflict( "Given amount is different from the current", TalerErrorCode.BANK_AMOUNT_DIFFERS ) WithdrawalSelectionResult.BalanceInsufficient -> throw conflict( "Insufficient funds", TalerErrorCode.BANK_UNALLOWED_DEBIT ) WithdrawalSelectionResult.BadAmount -> throw conflict( "Amount either to high or too low", TalerErrorCode.BANK_UNALLOWED_DEBIT ) WithdrawalSelectionResult.AlreadyAborted -> throw conflict( "Cannot update an aborted withdrawal", TalerErrorCode.BANK_UPDATE_ABORT_CONFLICT ) is WithdrawalSelectionResult.Success -> { call.respond(BankWithdrawalOperationPostResponse( transfer_done = res.status == WithdrawalStatus.confirmed, status = res.status, confirm_transfer_url = if (res.status == WithdrawalStatus.pending || res.status == WithdrawalStatus.selected) ctx.withdrawConfirmUrl(uuid) else null )) } } } post("/taler-integration/withdrawal-operation/{wopid}/abort", { operationId = "abortIntegrationWithdrawal" description = "Abort a withdrawal operation" tags = listOf("Bank Integration") request { pathParameter("wopid") { description = "Withdrawal operation ID" } } response { code(HttpStatusCode.NoContent) { description = "Withdrawal aborted successfully" } code(HttpStatusCode.NotFound) { description = "Withdrawal operation not found" } code(HttpStatusCode.Conflict) { description = "Cannot abort confirmed withdrawal" } } }) { val uuid = call.uuidPath("wopid") when (db.withdrawal.abort(uuid)) { AbortResult.UnknownOperation -> throw notFound( "Withdrawal operation '$uuid' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) AbortResult.AlreadyConfirmed -> throw conflict( "Cannot abort confirmed withdrawal", TalerErrorCode.BANK_ABORT_CONFIRM_CONFLICT ) AbortResult.Success -> call.respond(HttpStatusCode.NoContent) } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/api/ConversionApi.kt0000664000175000017500000004236515204341712030620 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import tech.libeufin.bank.* import tech.libeufin.bank.auth.* import tech.libeufin.bank.db.ConversionDAO import tech.libeufin.bank.db.ConversionDAO.ConversionResult import tech.libeufin.bank.db.Database import tech.libeufin.common.* private suspend fun ApplicationCall.config(db: Database, cfg: BankConfig) { respond( ConversionConfig( regional_currency = cfg.regionalCurrency, regional_currency_specification = cfg.regionalCurrencySpec, fiat_currency = cfg.fiatCurrency!!, fiat_currency_specification = cfg.fiatCurrencySpec!!, conversion_rate = db.conversion.getDefaultRate() ) ) } private suspend fun ApplicationCall.setGlobal(db: Database, cfg: BankConfig) { val req = receive() req.check(cfg) db.conversion.updateConfig(req) respond(HttpStatusCode.NoContent) } fun Routing.conversionApi(db: Database, cfg: BankConfig) = conditional(cfg.allowConversion) { get("/conversion-info/config", { operationId = "getConversionConfig" description = "Get conversion configuration" tags = listOf("Conversion") response { code(HttpStatusCode.OK) { description = "Conversion configuration"; body() } } }) { call.config(db, cfg) } get("/conversion-rate-classes/{CLASS_ID}/conversion-info/config", { operationId = "getConversionConfigForClass" description = "Get conversion configuration for a rate class" tags = listOf("Conversion") request { pathParameter("CLASS_ID") { description = "Conversion rate class ID" } } response { code(HttpStatusCode.OK) { description = "Conversion configuration for rate class"; body() } } }) { call.config(db, cfg) } get("/accounts/{USERNAME}/conversion-info/config", { operationId = "getConversionConfigForAccount" description = "Get conversion configuration for an account" tags = listOf("Conversion") request { pathParameter("USERNAME") { description = "Account username" } } response { code(HttpStatusCode.OK) { description = "Conversion configuration for account"; body() } } }) { call.config(db, cfg) } authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat) { post("/conversion-info/conversion-rate", { operationId = "setGlobalConversionRate" description = "Set global conversion rate" tags = listOf("Conversion") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { body() } response { code(HttpStatusCode.NoContent) { description = "Conversion rate updated" } } }) { call.setGlobal(db, cfg) } post("/accounts/{USERNAME}/conversion-info/conversion-rate", { operationId = "setAccountConversionRate" description = "Set conversion rate for an account" tags = listOf("Conversion") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.NoContent) { description = "Conversion rate updated" } } }) { call.setGlobal(db, cfg) } post("/conversion-rate-classes/{CLASS_ID}/conversion-info/conversion-rate", { operationId = "setClassConversionRate" description = "Set conversion rate for a rate class" tags = listOf("Conversion") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("CLASS_ID") { description = "Conversion rate class ID" } body() } response { code(HttpStatusCode.NoContent) { description = "Conversion rate updated" } } }) { call.setGlobal(db, cfg) } } suspend fun ApplicationCall.convert( input: TalerAmount, conversion: suspend ConversionDAO.(TalerAmount) -> ConversionResult, output: (TalerAmount) -> ConversionResponse ) { when (val res = db.conversion.(conversion)(input)) { is ConversionResult.Success -> respond(output(res.converted)) ConversionResult.ToSmall -> throw conflict( "$input is too small to be converted", TalerErrorCode.BANK_BAD_CONVERSION ) ConversionResult.IsExchange -> throw conflict( "exchange accounts cannot cashout", TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE ) ConversionResult.NotExchange -> throw conflict( "only exchange accounts can cashin", TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE ) } } get("/conversion-info/rate", { operationId = "getDefaultConversionRate" description = "Get default conversion rate" tags = listOf("Conversion") response { code(HttpStatusCode.OK) { description = "Default conversion rate"; body() } } }) { call.respond(db.conversion.getDefaultRate()) } get("/conversion-info/cashout-rate", { operationId = "getDefaultCashoutRate" description = "Calculate cashout conversion rate" tags = listOf("Conversion") request { queryParameter("amount_debit") { description = "Amount to convert from regional currency (mutually exclusive with amount_credit)" required = false } queryParameter("amount_credit") { description = "Amount to convert to fiat currency (mutually exclusive with amount_debit)" required = false } } response { code(HttpStatusCode.OK) { description = "Cashout conversion result"; body() } } }) { val params = RateParams.extract(call.request.queryParameters) params.debit?.let { cfg.checkRegionalCurrency(it) } params.credit?.let { cfg.checkFiatCurrency(it) } if (params.debit != null) { call.convert(params.debit, ConversionDAO::defaultToCashout) { ConversionResponse(params.debit, it) } } else { call.convert(params.credit!!, ConversionDAO::defaultFromCashout) { ConversionResponse(it, params.credit) } } } get("/conversion-info/cashin-rate", { operationId = "getDefaultCashinRate" description = "Calculate cashin conversion rate" tags = listOf("Conversion") request { queryParameter("amount_debit") { description = "Amount to convert from fiat currency (mutually exclusive with amount_credit)" required = false } queryParameter("amount_credit") { description = "Amount to convert to regional currency (mutually exclusive with amount_debit)" required = false } } response { code(HttpStatusCode.OK) { description = "Cashin conversion result"; body() } } }) { val params = RateParams.extract(call.request.queryParameters) params.debit?.let { cfg.checkFiatCurrency(it) } params.credit?.let { cfg.checkRegionalCurrency(it) } if (params.debit != null) { call.convert(params.debit, ConversionDAO::defaultToCashin) { ConversionResponse(params.debit, it) } } else { call.convert(params.credit!!, ConversionDAO::defaultFromCashin) { ConversionResponse(it, params.credit) } } } authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat) { get("/conversion-rate-classes/{CLASS_ID}/conversion-info/rate", { operationId = "getClassConversionRate" description = "Get conversion rate for a rate class" tags = listOf("Conversion") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("CLASS_ID") { description = "Conversion rate class ID" } } response { code(HttpStatusCode.OK) { description = "Class conversion rate"; body() } } }) { val id = call.longPath("CLASS_ID") val rate = db.conversion.getClassRate(id) call.respond(rate) } get("/conversion-rate-classes/{CLASS_ID}/conversion-info/cashout-rate", { operationId = "getClassCashoutRate" description = "Calculate cashout conversion rate for a rate class" tags = listOf("Conversion") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("CLASS_ID") { description = "Conversion rate class ID" } queryParameter("amount_debit") { description = "Amount to convert from regional currency (mutually exclusive with amount_credit)" required = false } queryParameter("amount_credit") { description = "Amount to convert to fiat currency (mutually exclusive with amount_debit)" required = false } } response { code(HttpStatusCode.OK) { description = "Class cashout conversion result"; body() } } }) { val id = call.longPath("CLASS_ID") val params = RateParams.extract(call.request.queryParameters) params.debit?.let { cfg.checkRegionalCurrency(it) } params.credit?.let { cfg.checkFiatCurrency(it) } if (params.debit != null) { call.convert(params.debit, { classToCashout(id, it) }) { ConversionResponse(params.debit, it) } } else { call.convert(params.credit!!, { classFromCashout(id, it) }) { ConversionResponse(it, params.credit) } } } get("/conversion-rate-classes/{CLASS_ID}/conversion-info/cashin-rate", { operationId = "getClassCashinRate" description = "Calculate cashin conversion rate for a rate class" tags = listOf("Conversion") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("CLASS_ID") { description = "Conversion rate class ID" } queryParameter("amount_debit") { description = "Amount to convert from fiat currency (mutually exclusive with amount_credit)" required = false } queryParameter("amount_credit") { description = "Amount to convert to regional currency (mutually exclusive with amount_debit)" required = false } } response { code(HttpStatusCode.OK) { description = "Class cashin conversion result"; body() } } }) { val id = call.longPath("CLASS_ID") val params = RateParams.extract(call.request.queryParameters) params.debit?.let { cfg.checkFiatCurrency(it) } params.credit?.let { cfg.checkRegionalCurrency(it) } if (params.debit != null) { call.convert(params.debit, { classToCashin(id, it) }) { ConversionResponse(params.debit, it) } } else { call.convert(params.credit!!, { classFromCashin(id, it) }) { ConversionResponse(it, params.credit) } } } } get("/accounts/{USERNAME}/conversion-info/cashin-rate", { operationId = "getAccountCashinRate" description = "Calculate cashin conversion rate for an account" tags = listOf("Conversion") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("amount_debit") { description = "Amount to convert from fiat currency (mutually exclusive with amount_credit)" required = false } queryParameter("amount_credit") { description = "Amount to convert to regional currency (mutually exclusive with amount_debit)" required = false } } response { code(HttpStatusCode.OK) { description = "Account cashin conversion result"; body() } } }) { val params = RateParams.extract(call.request.queryParameters) params.debit?.let { cfg.checkFiatCurrency(it) } params.credit?.let { cfg.checkRegionalCurrency(it) } if (params.debit != null) { call.convert(params.debit, { userToCashin(call.pathUsername, it) }) { ConversionResponse(params.debit, it) } } else { call.convert(params.credit!!, { userFromCashin(call.pathUsername, it) }) { ConversionResponse(it, params.credit) } } } optAuth(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat, allowAdmin = true) { get("/accounts/{USERNAME}/conversion-info/rate", { operationId = "getAccountConversionRate" description = "Get conversion rate for an account" tags = listOf("Conversion") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } } response { code(HttpStatusCode.OK) { description = "Account conversion rate"; body() } } }) { val (isExchange, rate) = db.conversion.getUserRate(call.pathUsername) if (!isExchange && !call.isAuthenticated) { throw forbidden("Non exchange account rates are private") } call.respond(rate) } } auth(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat, allowAdmin = true) { get("/accounts/{USERNAME}/conversion-info/cashout-rate", { operationId = "getAccountCashoutRate" description = "Calculate cashout conversion rate for an account" tags = listOf("Conversion") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("amount_debit") { description = "Amount to convert from regional currency (mutually exclusive with amount_credit)" required = false } queryParameter("amount_credit") { description = "Amount to convert to fiat currency (mutually exclusive with amount_debit)" required = false } } response { code(HttpStatusCode.OK) { description = "Account cashout conversion result"; body() } } }) { val params = RateParams.extract(call.request.queryParameters) params.debit?.let { cfg.checkRegionalCurrency(it) } params.credit?.let { cfg.checkFiatCurrency(it) } if (params.debit != null) { call.convert(params.debit, { userToCashout(call.pathUsername, it) }) { ConversionResponse(params.debit, it) } } else { call.convert(params.credit!!, { userFromCashout(call.pathUsername, it) }) { ConversionResponse(it, params.credit) } } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/api/CoreBankApi.kt0000664000175000017500000017427215204341712030162 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.future.await import kotlinx.coroutines.withContext import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.bank.* import tech.libeufin.bank.auth.* import tech.libeufin.bank.db.* import tech.libeufin.bank.db.AccountDAO.* import tech.libeufin.bank.db.CashoutDAO.CashoutCreationResult import tech.libeufin.bank.db.TanDAO.* import tech.libeufin.bank.db.TokenDAO.TokenCreationResult import tech.libeufin.bank.db.TransactionDAO.BankTransactionResult import tech.libeufin.bank.db.WithdrawalDAO.* import tech.libeufin.bank.db.ConversionDAO.* import tech.libeufin.common.* import tech.libeufin.common.crypto.* import java.time.Duration import java.time.Instant import java.time.temporal.ChronoUnit import java.util.* private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-api") fun Routing.coreBankApi(db: Database, cfg: BankConfig) { get("/config", { operationId = "getConfig" description = "Get bank configuration" tags = listOf("Core Bank") response { code(HttpStatusCode.OK) { description = "Bank configuration"; body() } } }) { call.respond( Config( bank_name = cfg.name, base_url = cfg.baseUrl, currency = cfg.regionalCurrency, currency_specification = cfg.regionalCurrencySpec, allow_conversion = cfg.allowConversion, allow_registrations = cfg.allowRegistration, allow_deletions = cfg.allowAccountDeletion, default_debit_threshold = cfg.defaultDebtLimit, supported_tan_channels = cfg.tanChannels.keys, allow_edit_name = cfg.allowEditName, allow_edit_cashout_payto_uri = cfg.allowEditCashout, wire_type = cfg.wireMethod, wire_transfer_fees = cfg.wireTransferFees, min_wire_transfer_amount = cfg.minAmount, max_wire_transfer_amount = cfg.maxAmount ) ) } authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat) { get("/monitor", { operationId = "getMonitor" description = "Get bank monitoring data (admin only)" tags = listOf("Core Bank") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { queryParameter("timeframe") { description = "Timeframe for monitoring data (hour, day, month, year). Default: hour" required = false } queryParameter("which") { description = "Deprecated. Which period to query within the timeframe" required = false deprecated = true } queryParameter("date_s") { description = "Timestamp in seconds to specify the period" required = false } } response { code(HttpStatusCode.OK) { description = "Monitoring data"; body() } } }) { val params = MonitorParams.extract(call.request.queryParameters) call.respond(db.monitor(params)) } } coreBankTokenApi(db, cfg) coreBankAccountsApi(db, cfg) coreBankTransactionsApi(db, cfg) coreBankWithdrawalApi(db, cfg) coreBankCashoutApi(db, cfg) coreBankTanApi(db, cfg) coreBankConversionApi(db, cfg) } private fun Routing.coreBankTokenApi(db: Database, cfg: BankConfig) { val TOKEN_DEFAULT_DURATION: Duration = Duration.ofDays(1L) auth(db, cfg.pwCrypto, TokenLogicalScope.refreshable, cfg.basicAuthCompat, allowPw = true) { post("/accounts/{USERNAME}/token", { operationId = "createToken" description = "Create or refresh an authentication token" tags = listOf("Core Bank - Tokens") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.OK) { description = "Token created"; body() } } }) { val (req, challenge) = call.receiveChallenge(db, Operation.create_token) val existingToken = call.authToken if (existingToken != null) { // This block checks permissions ONLY IF the call was authenticated with a token val refreshingToken = db.token.access(existingToken, Instant.now()) ?: throw internalServerError( "Token used to auth not found in the database!" ) if (!validScope(req.scope.logical(), refreshingToken.scope)) throw forbidden( "Impossible to refresh a token with a larger scope", TalerErrorCode.GENERIC_TOKEN_PERMISSION_INSUFFICIENT ) } val token = Base32Crockford32B.secureRand() val tokenDuration: Duration = req.duration?.duration ?: TOKEN_DEFAULT_DURATION val creationTime = Instant.now() val expirationTimestamp = if (tokenDuration == ChronoUnit.FOREVER.duration) { Instant.MAX } else { try { creationTime.plus(tokenDuration) } catch (e: Exception) { throw badRequest("Bad token duration: ${e.message}") } } when (db.token.create( username = call.pathUsername, content = token.raw, creationTime = creationTime, expirationTime = expirationTimestamp, scope = req.scope, isRefreshable = req.refreshable, description = req.description, is2fa = existingToken != null || challenge != null )) { TokenCreationResult.TanRequired -> call.respondMfa(db, Operation.create_token) TokenCreationResult.Success -> call.respond( TokenSuccessResponse( access_token = "$TOKEN_PREFIX$token", expiration = TalerTimestamp(expirationTimestamp) ) ) } } } auth(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat, allowAdmin = true) { delete("/accounts/{USERNAME}/tokens/{TOKEN_ID}", { operationId = "deleteTokenById" description = "Delete a specific authentication token by ID" tags = listOf("Core Bank - Tokens") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } pathParameter("TOKEN_ID") { description = "Token identifier" } } response { code(HttpStatusCode.NoContent) { description = "Token deleted" } code(HttpStatusCode.NotFound) { description = "Token not found" } } }) { val id = call.longPath("TOKEN_ID") if (db.token.deleteById(id)) { call.respond(HttpStatusCode.NoContent) } else { throw notFound( "Token '$id' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) } } } auth(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat) { delete("/accounts/{USERNAME}/token", { operationId = "deleteToken" description = "Delete the current authentication token" tags = listOf("Core Bank - Tokens") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } } response { code(HttpStatusCode.NoContent) { description = "Token deleted" } } }) { val token = call.authToken ?: throw badRequest("Basic auth not supported here.") db.token.delete(token) call.respond(HttpStatusCode.NoContent) } } auth(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat, allowAdmin = true) { get("/accounts/{USERNAME}/tokens", { operationId = "listTokens" description = "List authentication tokens for an account" tags = listOf("Core Bank - Tokens") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } } response { code(HttpStatusCode.OK) { description = "List of tokens"; body() } code(HttpStatusCode.NoContent) { description = "No tokens found" } } }) { val params = PageParams.extract(call.request.queryParameters) val tokens = db.token.page(params, call.pathUsername, Instant.now()) if (tokens.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(TokenInfos(tokens)) } } } } suspend fun createAccount( db: Database, cfg: BankConfig, req: RegisterAccountRequest, isAdmin: Boolean ): AccountCreationResult { // Prohibit reserved usernames: if (RESERVED_ACCOUNTS.contains(req.username)) throw conflict( "Username '${req.username}' is reserved", TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT ) // Check tan channels has the corresponding info val channels = req.channels if (!isAdmin) { if (req.debit_threshold != null) throw conflict( "only admin account can choose the debit limit", TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT ) if (req.conversion_rate_class_id != null) throw conflict( "only admin account can choose the conversion rate class", TalerErrorCode.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS ) if (channels.isNotEmpty()) throw conflict( "only admin account can enable 2fa on creation", TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL ) } for (channel in channels) { if (cfg.tanChannels[channel] == null) { throw unsupportedTanChannel(channel) } val info = when (channel) { TanChannel.sms -> req.contact_data?.phone?.get() TanChannel.email -> req.contact_data?.email?.get() } if (info == null) { throw conflict( "missing info for tan channel $channel", TalerErrorCode.BANK_MISSING_TAN_INFO ) } } if (req.username == "exchange" && !req.is_taler_exchange) throw conflict( "'exchange' account must be a taler exchange account", TalerErrorCode.END ) val password = req.password.checkPw(cfg.pwdCheckQuality) suspend fun doDb(internalPayto: Payto) = db.account.create( username = req.username, name = req.name, email = req.contact_data?.email?.get(), phone = req.contact_data?.phone?.get(), cashoutPayto = req.cashout_payto_uri, password = password.pw, internalPayto = internalPayto, isPublic = req.is_public, isTalerExchange = req.is_taler_exchange, maxDebt = req.debit_threshold ?: cfg.defaultDebtLimit, bonus = if (!req.is_taler_exchange) cfg.registrationBonus else TalerAmount(0, 0, cfg.regionalCurrency), tanChannels = req.channels, checkPaytoIdempotent = req.payto_uri != null, pwCrypto = cfg.pwCrypto, conversionRateClassId = req.conversion_rate_class_id ) when (cfg.wireMethod) { WireMethod.IBAN -> { req.payto_uri?.expectIban() var retry = if (req.payto_uri == null) IBAN_ALLOCATION_RETRY_COUNTER else 0 while (true) { val internalPayto = req.payto_uri ?: IbanPayto.rand() as Payto val res = doDb(internalPayto) // Retry with new IBAN if (res == AccountCreationResult.PayToReuse && retry > 0) { retry-- continue } return res } } WireMethod.X_TALER_BANK -> { if (req.payto_uri != null) { val payto = req.payto_uri.expectXTalerBank() if (payto.username != req.username) throw badRequest("Expected a payto uri for '${req.username}' got one for '${payto.username}'") } val internalPayto = XTalerBankPayto.forUsername(req.username) return doDb(internalPayto) } } } suspend fun patchAccount( db: Database, cfg: BankConfig, req: AccountReconfiguration, username: String, isAdmin: Boolean, is2fa: Boolean ): AccountPatchResult { req.debit_threshold?.run { cfg.checkRegionalCurrency(this) } if (username == "admin" && req.is_public == true) throw conflict( "'admin' account cannot be public", TalerErrorCode.END ) if (username == "exchange" && req.is_taler_exchange == false) throw conflict( "'exchange' account must be a taler exchange account", TalerErrorCode.END ) val channels = req.channels.get() if (channels != null) { for (channel in channels) { if (cfg.tanChannels[channel] == null) { throw unsupportedTanChannel(channel) } } } return db.account.reconfig( username = username, req = req, isAdmin = isAdmin, is2fa = is2fa, allowEditName = cfg.allowEditName, allowEditCashout = cfg.allowEditCashout ) } private fun Routing.coreBankAccountsApi(db: Database, cfg: BankConfig) { authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat, !cfg.allowRegistration) { post("/accounts", { operationId = "createAccount" description = "Create a new bank account" tags = listOf("Core Bank - Accounts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { body() } response { code(HttpStatusCode.OK) { description = "Account created"; body() } code(HttpStatusCode.Conflict) { description = "Account creation conflict" } } }) { val req = call.receive() when (val result = createAccount(db, cfg, req, call.isAdmin)) { AccountCreationResult.BonusBalanceInsufficient -> throw conflict( "Insufficient admin funds to grant bonus", TalerErrorCode.BANK_UNALLOWED_DEBIT ) AccountCreationResult.UsernameReuse -> throw conflict( "Account username reuse '${req.username}'", TalerErrorCode.BANK_REGISTER_USERNAME_REUSE ) AccountCreationResult.PayToReuse -> throw conflict( "Bank internalPayToUri reuse", TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE ) AccountCreationResult.UnknownConversionClass -> throw unknownConversionClass(req.conversion_rate_class_id) is AccountCreationResult.Success -> call.respond(RegisterAccountResponse(result.payto)) } } } auth( db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat, allowAdmin = true, requireAdmin = !cfg.allowAccountDeletion ) { delete("/accounts/{USERNAME}", { operationId = "deleteAccount" description = "Delete a bank account" tags = listOf("Core Bank - Accounts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } } response { code(HttpStatusCode.NoContent) { description = "Account deleted" } code(HttpStatusCode.NotFound) { description = "Account not found" } code(HttpStatusCode.Conflict) { description = "Account balance not zero or reserved" } } }) { val (_, challenge) = call.receiveChallenge(db, Operation.account_delete, Unit) // Not deleting reserved names. if (RESERVED_ACCOUNTS.contains(call.pathUsername)) throw conflict( "Cannot delete reserved accounts", TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT ) if (call.pathUsername == "exchange" && cfg.allowConversion) throw conflict( "Cannot delete 'exchange' accounts when conversion is enabled", TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT ) when (db.account.delete(call.pathUsername, call.isAdmin || challenge != null)) { AccountDeletionResult.UnknownAccount -> throw unknownAccount(call.pathUsername) AccountDeletionResult.BalanceNotZero -> throw conflict( "Account balance is not zero.", TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO ) AccountDeletionResult.TanRequired -> call.respondMfa(db, Operation.account_delete) AccountDeletionResult.Success -> call.respond(HttpStatusCode.NoContent) } } } auth(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat, allowAdmin = true) { patch("/accounts/{USERNAME}", { operationId = "reconfigureAccount" description = "Reconfigure a bank account" tags = listOf("Core Bank - Accounts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.NoContent) { description = "Account reconfigured" } code(HttpStatusCode.NotFound) { description = "Account not found" } code(HttpStatusCode.Conflict) { description = "Reconfiguration conflict" } } }) { val (req, pendingValidation) = call.receiveChallenge(db, Operation.account_reconfig) if (pendingValidation != null && pendingValidation.isNotEmpty()) { return@patch call.respondValidation(db, Operation.account_reconfig, pendingValidation) } val res = patchAccount(db, cfg, req, call.pathUsername, call.isAdmin, pendingValidation != null) when (res) { AccountPatchResult.Success -> call.respond(HttpStatusCode.NoContent) is AccountPatchResult.Challenges -> { if (res.validations.isNotEmpty()) { call.respondValidation(db, Operation.account_reconfig, res.validations) } else { call.respondMfa(db, Operation.account_reconfig) } } AccountPatchResult.UnknownAccount -> throw unknownAccount(call.pathUsername) AccountPatchResult.NonAdminName -> throw conflict( "non-admin user cannot change their legal name", TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME ) AccountPatchResult.NonAdminCashout -> throw conflict( "non-admin user cannot change their cashout account", TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT ) AccountPatchResult.NonAdminDebtLimit -> throw conflict( "non-admin user cannot change their debt limit", TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT ) AccountPatchResult.NonAdminConversionRateClass -> throw conflict( "non-admin user cannot change their conversion rate class", TalerErrorCode.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS ) AccountPatchResult.UnknownConversionClass -> throw unknownConversionClass(req.conversion_rate_class_id.get()) AccountPatchResult.MissingTanInfo -> throw conflict( "missing info for tan channel ${req.tan_channel.get()}", TalerErrorCode.BANK_MISSING_TAN_INFO ) } } patch("/accounts/{USERNAME}/auth", { operationId = "changePassword" description = "Change account password" tags = listOf("Core Bank - Accounts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.NoContent) { description = "Password changed" } code(HttpStatusCode.NotFound) { description = "Account not found" } code(HttpStatusCode.Conflict) { description = "Old password mismatch" } } }) { val (req, challenge) = call.receiveChallenge(db, Operation.account_auth_reconfig) if (!call.isAdmin && req.old_password == null) { throw conflict( "non-admin user cannot change password without providing old password", TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD ) } val newPassword = req.new_password.checkPw(cfg.pwdCheckQuality) when (db.account.reconfigPassword(call.pathUsername, newPassword, req.old_password, call.isAdmin || challenge != null, cfg.pwCrypto)) { AccountPatchAuthResult.Success -> call.respond(HttpStatusCode.NoContent) AccountPatchAuthResult.TanRequired -> call.respondMfa(db, Operation.account_auth_reconfig) AccountPatchAuthResult.UnknownAccount -> throw unknownAccount(call.pathUsername) AccountPatchAuthResult.OldPasswordMismatch -> throw conflict( "old password does not match", TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD ) } } } get("/public-accounts", { operationId = "listPublicAccounts" description = "List public bank accounts" tags = listOf("Core Bank - Accounts") request { queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } queryParameter("filter_name") { description = "Filter accounts by username substring" required = false } queryParameter("conversion_rate_class_id") { description = "Filter accounts by conversion rate class ID" required = false } } response { code(HttpStatusCode.OK) { description = "List of public accounts"; body() } code(HttpStatusCode.NoContent) { description = "No public accounts found" } } }) { val params = AccountParams.extract(call.request.queryParameters) val publicAccounts = db.account.pagePublic(params) if (publicAccounts.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(PublicAccountsResponse(publicAccounts)) } } authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat) { get("/accounts", { operationId = "listAccounts" description = "List all bank accounts (admin only)" tags = listOf("Core Bank - Accounts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } queryParameter("filter_name") { description = "Filter accounts by username substring" required = false } queryParameter("conversion_rate_class_id") { description = "Filter accounts by conversion rate class ID" required = false } } response { code(HttpStatusCode.OK) { description = "List of accounts"; body() } code(HttpStatusCode.NoContent) { description = "No accounts found" } } }) { val params = AccountParams.extract(call.request.queryParameters) val accounts = db.account.pageAdmin(params) if (accounts.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(ListBankAccountsResponse(accounts)) } } } auth(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat, allowAdmin = true) { get("/accounts/{USERNAME}", { operationId = "getAccount" description = "Get account details" tags = listOf("Core Bank - Accounts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } } response { code(HttpStatusCode.OK) { description = "Account details"; body() } code(HttpStatusCode.NotFound) { description = "Account not found" } } }) { val account = db.account.get(call.pathUsername) ?: throw unknownAccount(call.pathUsername) call.respond(account) } } } private fun Routing.coreBankTransactionsApi(db: Database, cfg: BankConfig) { auth(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat, allowAdmin = true) { get("/accounts/{USERNAME}/transactions", { operationId = "getTransactions" description = "Get transaction history for an account" tags = listOf("Core Bank - Transactions") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } queryParameter("timeout_ms") { description = "Timeout for long polling in milliseconds (default: 0, no long polling)" required = false } } response { code(HttpStatusCode.OK) { description = "Transaction history"; body() } code(HttpStatusCode.NoContent) { description = "No transactions found" } } }) { val params = HistoryParams.extract(call.request.queryParameters) val bankAccount = call.bankInfo(db) val history: List = db.transaction.pollHistory(params, bankAccount.bankAccountId) if (history.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(BankAccountTransactionsResponse(history)) } } get("/accounts/{USERNAME}/transactions/{T_ID}", { operationId = "getTransaction" description = "Get a specific transaction by ID" tags = listOf("Core Bank - Transactions") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } pathParameter("T_ID") { description = "Transaction identifier" } } response { code(HttpStatusCode.OK) { description = "Transaction details"; body() } code(HttpStatusCode.NotFound) { description = "Transaction not found" } } }) { val tId = call.longPath("T_ID") val tx = db.transaction.get(tId, call.pathUsername) ?: throw notFound( "Bank transaction '$tId' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) call.respond(tx) } } auth(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat) { post("/accounts/{USERNAME}/transactions", { operationId = "createTransaction" description = "Create a new bank transaction" tags = listOf("Core Bank - Transactions") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.OK) { description = "Transaction created"; body() } code(HttpStatusCode.Conflict) { description = "Transaction conflict" } } }) { val (req, challenge) = call.receiveChallenge(db, Operation.bank_transaction) val subject = req.payto_uri.message ?: throw badRequest("Wire transfer lacks subject") val amount = req.payto_uri.amount ?: req.amount ?: throw badRequest("Wire transfer lacks amount") cfg.checkRegionalCurrency(amount) val res = db.transaction.create( creditAccountPayto = req.payto_uri, debitAccountUsername = call.pathUsername, subject = subject, amount = amount, timestamp = Instant.now(), requestUid = req.request_uid, is2fa = challenge != null, wireTransferFees = cfg.wireTransferFees, minAmount = cfg.minAmount, maxAmount = cfg.maxAmount ) when (res) { BankTransactionResult.UnknownDebtor -> throw unknownAccount(call.pathUsername) BankTransactionResult.TanRequired -> { call.respondMfa(db, Operation.bank_transaction) } BankTransactionResult.BothPartySame -> throw conflict( "Wire transfer attempted with credit and debit party being the same bank account", TalerErrorCode.BANK_SAME_ACCOUNT ) BankTransactionResult.UnknownCreditor -> throw unknownCreditorAccount(req.payto_uri.canonical) BankTransactionResult.AdminCreditor -> throw conflict( "Cannot transfer money to admin account", TalerErrorCode.BANK_ADMIN_CREDITOR ) BankTransactionResult.BalanceInsufficient -> throw conflict( "Insufficient funds", TalerErrorCode.BANK_UNALLOWED_DEBIT ) BankTransactionResult.BadAmount -> throw conflict( "Amount either to high or too low", TalerErrorCode.BANK_UNALLOWED_DEBIT ) BankTransactionResult.RequestUidReuse -> throw conflict( "request_uid used already", TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED ) is BankTransactionResult.Success -> call.respond(TransactionCreateResponse(res.id)) } } } } private fun Routing.coreBankWithdrawalApi(db: Database, cfg: BankConfig) { auth(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat) { post("/accounts/{USERNAME}/withdrawals", { operationId = "createWithdrawal" description = "Create a new withdrawal operation" tags = listOf("Core Bank - Withdrawals") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.OK) { description = "Withdrawal created"; body() } code(HttpStatusCode.Conflict) { description = "Withdrawal conflict" } } }) { val req = call.receive() req.amount?.run(cfg::checkRegionalCurrency) req.suggested_amount?.run(cfg::checkRegionalCurrency) val opId = UUID.randomUUID() when (db.withdrawal.create( call.pathUsername, opId, req.amount, req.suggested_amount, req.no_amount_to_wallet, Instant.now(), cfg.wireTransferFees, cfg.minAmount, cfg.maxAmount )) { WithdrawalCreationResult.UnknownAccount -> throw unknownAccount(call.pathUsername) WithdrawalCreationResult.AccountIsExchange -> throw conflict( "Exchange account cannot perform withdrawal operation", TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE ) WithdrawalCreationResult.BalanceInsufficient -> throw conflict( "Insufficient funds to withdraw with Taler", TalerErrorCode.BANK_UNALLOWED_DEBIT ) WithdrawalCreationResult.BadAmount -> throw conflict( "Amount either to high or too low", TalerErrorCode.BANK_UNALLOWED_DEBIT ) WithdrawalCreationResult.Success -> { call.respond( BankAccountCreateWithdrawalResponse( withdrawal_id = opId.toString(), taler_withdraw_uri = cfg.talerWithdrawUri(opId) ) ) } } } post("/accounts/{USERNAME}/withdrawals/{withdrawal_id}/confirm", { operationId = "confirmWithdrawal" description = "Confirm a withdrawal operation" tags = listOf("Core Bank - Withdrawals") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } pathParameter("withdrawal_id") { description = "Withdrawal operation ID" } body() } response { code(HttpStatusCode.NoContent) { description = "Withdrawal confirmed" } code(HttpStatusCode.NotFound) { description = "Withdrawal operation not found" } code(HttpStatusCode.Conflict) { description = "Confirmation conflict" } } }) { val id = call.uuidPath("withdrawal_id") val (req, challenge) = call.receiveChallenge(db, Operation.withdrawal, BankAccountConfirmWithdrawalRequest()) req.amount?.run(cfg::checkRegionalCurrency) when (db.withdrawal.confirm( call.pathUsername, id, Instant.now(), req.amount, challenge != null, cfg.wireTransferFees, cfg.minAmount, cfg.maxAmount )) { WithdrawalConfirmationResult.UnknownOperation -> throw notFound( "Withdrawal operation $id not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) WithdrawalConfirmationResult.AlreadyAborted -> throw conflict( "Cannot confirm an aborted withdrawal", TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT ) WithdrawalConfirmationResult.ReservePubReuse -> throw conflict( "Reserve pub already used", TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT ) WithdrawalConfirmationResult.NotSelected -> throw conflict( "Cannot confirm an unselected withdrawal", TalerErrorCode.BANK_CONFIRM_INCOMPLETE ) WithdrawalConfirmationResult.BalanceInsufficient -> throw conflict( "Insufficient funds", TalerErrorCode.BANK_UNALLOWED_DEBIT ) WithdrawalConfirmationResult.MissingAmount -> throw conflict( "An amount is required", TalerErrorCode.BANK_AMOUNT_REQUIRED ) WithdrawalConfirmationResult.AmountDiffers -> throw conflict( "Given amount is different from the current", TalerErrorCode.BANK_AMOUNT_DIFFERS ) WithdrawalConfirmationResult.BadAmount -> throw conflict( "Amount either to high or too low", TalerErrorCode.BANK_UNALLOWED_DEBIT ) WithdrawalConfirmationResult.TanRequired -> { call.respondMfa(db, Operation.withdrawal) } WithdrawalConfirmationResult.Success -> call.respond(HttpStatusCode.NoContent) } } post("/accounts/{USERNAME}/withdrawals/{withdrawal_id}/abort", { operationId = "abortWithdrawal" description = "Abort a withdrawal operation" tags = listOf("Core Bank - Withdrawals") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } pathParameter("withdrawal_id") { description = "Withdrawal operation ID" } } response { code(HttpStatusCode.NoContent) { description = "Withdrawal aborted" } code(HttpStatusCode.NotFound) { description = "Withdrawal operation not found" } code(HttpStatusCode.Conflict) { description = "Cannot abort confirmed withdrawal" } } }) { val opId = call.uuidPath("withdrawal_id") when (db.withdrawal.abort(opId)) { AbortResult.UnknownOperation -> throw notFound( "Withdrawal operation $opId not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) AbortResult.AlreadyConfirmed -> throw conflict( "Cannot abort confirmed withdrawal", TalerErrorCode.BANK_ABORT_CONFIRM_CONFLICT ) AbortResult.Success -> call.respond(HttpStatusCode.NoContent) } } } get("/withdrawals/{withdrawal_id}", { operationId = "getWithdrawalStatus" description = "Get withdrawal operation status" tags = listOf("Core Bank - Withdrawals") request { pathParameter("withdrawal_id") { description = "Withdrawal operation ID" } queryParameter("timeout_ms") { description = "Timeout for long polling in milliseconds (default: 0, no long polling)" required = false } queryParameter("old_state") { description = "Previous state for long polling (pending, aborted, selected, confirmed). Default: pending" required = false } } response { code(HttpStatusCode.OK) { description = "Withdrawal status"; body() } code(HttpStatusCode.NotFound) { description = "Withdrawal operation not found" } } }) { val uuid = call.uuidPath("withdrawal_id") val params = StatusParams.extract(call.request.queryParameters) val op = db.withdrawal.pollInfo(uuid, params) ?: throw notFound( "Withdrawal operation '$uuid' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) call.respond(op) } } private fun Routing.coreBankCashoutApi(db: Database, cfg: BankConfig) = conditional(cfg.allowConversion) { auth(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat) { post("/accounts/{USERNAME}/cashouts", { operationId = "createCashout" description = "Create a new cashout operation" tags = listOf("Core Bank - Cashouts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.OK) { description = "Cashout created"; body() } code(HttpStatusCode.Conflict) { description = "Cashout conflict" } } }) { val (req, challenge) = call.receiveChallenge(db, Operation.cashout) cfg.checkRegionalCurrency(req.amount_debit) cfg.checkFiatCurrency(req.amount_credit) val res = db.cashout.create( username = call.pathUsername, requestUid = req.request_uid, amountDebit = req.amount_debit, amountCredit = req.amount_credit, subject = req.subject ?: "", // TODO default subject timestamp = Instant.now(), is2fa = challenge != null ) when (res) { CashoutCreationResult.AccountNotFound -> throw unknownAccount(call.pathUsername) CashoutCreationResult.BadConversion -> throw conflict( "Wrong currency conversion", TalerErrorCode.BANK_BAD_CONVERSION ) CashoutCreationResult.UnderMin -> throw conflict( "Amount of currency conversion it less than the minimum allowed", TalerErrorCode.BANK_CONVERSION_AMOUNT_TO_SMALL ) CashoutCreationResult.AccountIsExchange -> throw conflict( "Exchange account cannot perform cashout operation", TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE ) CashoutCreationResult.BalanceInsufficient -> throw conflict( "Insufficient funds to withdraw with Taler", TalerErrorCode.BANK_UNALLOWED_DEBIT ) CashoutCreationResult.RequestUidReuse -> throw conflict( "request_uid used already", TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED ) CashoutCreationResult.NoCashoutPayto -> throw conflict( "Missing cashout payto uri", TalerErrorCode.BANK_CONFIRM_INCOMPLETE ) CashoutCreationResult.TanRequired -> { call.respondMfa(db, Operation.cashout) } is CashoutCreationResult.Success -> call.respond(CashoutResponse(res.id)) } } } auth(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat, allowAdmin = true) { get("/accounts/{USERNAME}/cashouts/{CASHOUT_ID}", { operationId = "getCashout" description = "Get a specific cashout operation" tags = listOf("Core Bank - Cashouts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } pathParameter("CASHOUT_ID") { description = "Cashout operation identifier" } } response { code(HttpStatusCode.OK) { description = "Cashout details"; body() } code(HttpStatusCode.NotFound) { description = "Cashout operation not found" } } }) { val id = call.longPath("CASHOUT_ID") val cashout = db.cashout.get(id, call.pathUsername) ?: throw notFound( "Cashout operation $id not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) call.respond(cashout) } get("/accounts/{USERNAME}/cashouts", { operationId = "listAccountCashouts" description = "List cashout operations for an account" tags = listOf("Core Bank - Cashouts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } } response { code(HttpStatusCode.OK) { description = "List of cashouts for account"; body() } code(HttpStatusCode.NoContent) { description = "No cashout operations found" } } }) { val params = PageParams.extract(call.request.queryParameters) val cashouts = db.cashout.pageForUser(params, call.pathUsername) if (cashouts.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(Cashouts(cashouts)) } } } authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat) { get("/cashouts", { operationId = "listAllCashouts" description = "List all cashout operations (admin only)" tags = listOf("Core Bank - Cashouts") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } } response { code(HttpStatusCode.OK) { description = "List of all cashouts"; body() } code(HttpStatusCode.NoContent) { description = "No cashout operations found" } } }) { val params = PageParams.extract(call.request.queryParameters) val cashouts = db.cashout.pageAll(params) if (cashouts.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(GlobalCashouts(cashouts)) } } } } private fun Routing.coreBankTanApi(db: Database, cfg: BankConfig) { post("/accounts/{USERNAME}/challenge/{CHALLENGE_ID}", { operationId = "sendTanChallenge" description = "Send a TAN challenge" tags = listOf("Core Bank - TAN") request { pathParameter("USERNAME") { description = "Account username" } pathParameter("CHALLENGE_ID") { description = "Challenge identifier" } } response { code(HttpStatusCode.OK) { description = "Challenge response"; body() } code(HttpStatusCode.NotFound) { description = "Challenge not found or expired" } code(HttpStatusCode.Gone) { description = "Challenge already solved" } } }) { val uuid = call.uuidPath("CHALLENGE_ID") val res = db.tan.send( uuid = uuid, timestamp = Instant.now(), maxActive = MAX_ACTIVE_CHALLENGES ) when (res) { TanSendResult.NotFound -> throw notFound( "Challenge $uuid not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) TanSendResult.Expired -> throw notFound( "Challenge $uuid expired", TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED ) TanSendResult.TooMany -> throw tooManyRequests( "Too many active challenges", TalerErrorCode.BANK_TAN_RATE_LIMITED ) TanSendResult.Solved -> call.respond(HttpStatusCode.Gone) is TanSendResult.Send -> { val (tanScript, tanEnv) = cfg.tanChannels[res.tanChannel] ?: throw unsupportedTanChannel(res.tanChannel) val msg = "T-${res.tanCode} is your ${cfg.name} verification code" val exitValue = withContext(Dispatchers.IO) { val builder = ProcessBuilder(tanScript.toString(), res.tanInfo) builder.redirectErrorStream(true) for ((name, value) in tanEnv) { builder.environment()[name] = value } val process = builder.start() try { process.outputWriter().use { it.write(msg) } process.onExit().await() } catch (e: Exception) { process.destroy() } val exitValue = process.exitValue() if (exitValue != 0) { val out = runCatching { process.inputStream.use { res.tanCode.reader().readText() } }.getOrDefault("") if (out.isNotEmpty()) { logger.error("TAN ${res.tanChannel} - ${tanScript}: $out") } } exitValue } if (exitValue != 0) { throw apiError( HttpStatusCode.BadGateway, "Tan channel script failure with exit value $exitValue", TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED ) } val retransmission = Instant.now() + TAN_RETRANSMISSION_PERIOD db.tan.markSent(uuid, retransmission) call.respond(ChallengeRequestResponse( solve_expiration = res.expiration, earliest_retransmission = TalerTimestamp(retransmission) )) } is TanSendResult.Success -> { call.respond(ChallengeRequestResponse( solve_expiration = res.expiration, earliest_retransmission = res.retransmission )) } } } post("/accounts/{USERNAME}/challenge/{CHALLENGE_ID}/confirm", { operationId = "confirmTanChallenge" description = "Confirm a TAN challenge" tags = listOf("Core Bank - TAN") request { pathParameter("USERNAME") { description = "Account username" } pathParameter("CHALLENGE_ID") { description = "Challenge identifier" } body() } response { code(HttpStatusCode.NoContent) { description = "Challenge confirmed successfully" } code(HttpStatusCode.NotFound) { description = "Challenge not found or expired" } code(HttpStatusCode.Conflict) { description = "Incorrect TAN code" } } }) { val uuid = call.uuidPath("CHALLENGE_ID") val req = call.receive() val code = req.tan.removePrefix("T-") val res = db.tan.solve( uuid = uuid, code = code, timestamp = Instant.now() ) when (res) { TanSolveResult.NotFound -> throw notFound( "Challenge $uuid not found", TalerErrorCode.BANK_CHALLENGE_NOT_FOUND ) TanSolveResult.BadCode -> throw conflict( "Incorrect TAN code", TalerErrorCode.BANK_TAN_CHALLENGE_FAILED ) TanSolveResult.NoRetry -> throw tooManyRequests( "Too many failed confirmation attempt", TalerErrorCode.BANK_TAN_RATE_LIMITED ) TanSolveResult.Expired -> throw notFound( "Challenge $uuid expired", TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED ) is TanSolveResult.Success -> call.respond(HttpStatusCode.NoContent) } } } private fun Routing.coreBankConversionApi(db: Database, cfg: BankConfig) = conditional(cfg.allowConversion) { authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat) { post("/conversion-rate-classes", { operationId = "createConversionRateClass" description = "Create a conversion rate class" tags = listOf("Core Bank - Conversion Rate Classes") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { body() } response { code(HttpStatusCode.OK) { description = "Rate class created"; body() } code(HttpStatusCode.Conflict) { description = "Name already in use" } } }) { val req = call.receive() cfg.checkCurrency(req) when (val res = db.conversion.createClass(req)) { is ClassCreateResult.Success -> call.respond(ConversionRateClassResponse(res.id)) ClassCreateResult.NameReuse -> throw conflict( "Conversion rate class name '${req.name}' already use", TalerErrorCode.BANK_NAME_REUSE ) } } patch("/conversion-rate-classes/{CLASS_ID}", { operationId = "updateConversionRateClass" description = "Update a conversion rate class" tags = listOf("Core Bank - Conversion Rate Classes") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("CLASS_ID") { description = "Conversion rate class ID" } body() } response { code(HttpStatusCode.NoContent) { description = "Rate class updated" } code(HttpStatusCode.NotFound) { description = "Rate class not found" } code(HttpStatusCode.Conflict) { description = "Name already in use" } } }) { val id = call.longPath("CLASS_ID") val req = call.receive() cfg.checkCurrency(req) when (val res = db.conversion.patchClass(id, req)) { ClassPatchResult.Success -> call.respond(HttpStatusCode.NoContent) ClassPatchResult.Unknown -> throw notFound( "Conversion rate class '$id' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) ClassPatchResult.NameReuse -> throw conflict( "Conversion rate class name '${req.name}' already use", TalerErrorCode.BANK_NAME_REUSE ) } } delete("/conversion-rate-classes/{CLASS_ID}", { operationId = "deleteConversionRateClass" description = "Delete a conversion rate class" tags = listOf("Core Bank - Conversion Rate Classes") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("CLASS_ID") { description = "Conversion rate class ID" } } response { code(HttpStatusCode.NoContent) { description = "Rate class deleted" } code(HttpStatusCode.NotFound) { description = "Rate class not found" } } }) { val id = call.longPath("CLASS_ID") if (db.conversion.deleteClass(id)) { call.respond(HttpStatusCode.NoContent) } else { throw notFound( "Conversion rate class '$id' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) } } } authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readonly, cfg.basicAuthCompat) { get("/conversion-rate-classes/{CLASS_ID}", { operationId = "getConversionRateClass" description = "Get a conversion rate class" tags = listOf("Core Bank - Conversion Rate Classes") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("CLASS_ID") { description = "Conversion rate class ID" } } response { code(HttpStatusCode.OK) { description = "Rate class details"; body() } code(HttpStatusCode.NotFound) { description = "Rate class not found" } } }) { val id = call.longPath("CLASS_ID") val cashout = db.conversion.getClass(id) ?: throw notFound( "Conversion rate class $id not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) call.respond(cashout) } get("/conversion-rate-classes", { operationId = "listConversionRateClasses" description = "List all conversion rate classes" tags = listOf("Core Bank - Conversion Rate Classes") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } queryParameter("filter_name") { description = "Filter rate classes by name substring" required = false } } response { code(HttpStatusCode.OK) { description = "List of rate classes"; body() } code(HttpStatusCode.NoContent) { description = "No rate classes found" } } }) { val params = ClassParams.extract(call.request.queryParameters) val page = db.conversion.pageClass(params) if (page.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(ConversionRateClasses(page)) } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/api/WireGatewayApi.kt0000664000175000017500000004412315204341712030715 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ // This file contains the Taler Wire Gateway API handlers. package tech.libeufin.bank.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import tech.libeufin.bank.* import tech.libeufin.bank.auth.auth import tech.libeufin.bank.auth.authAdmin import tech.libeufin.bank.auth.pathUsername import tech.libeufin.bank.db.Database import tech.libeufin.bank.db.ExchangeDAO import tech.libeufin.bank.db.ExchangeDAO.AddIncomingResult import tech.libeufin.bank.db.ExchangeDAO.TransferResult import tech.libeufin.common.* import java.time.Instant fun Routing.wireGatewayApi(db: Database, cfg: BankConfig) { get("/accounts/{USERNAME}/taler-wire-gateway/config", { operationId = "getWireGatewayConfig" description = "Get wire gateway configuration" tags = listOf("Wire Gateway") request { pathParameter("USERNAME") { description = "Account username" } } response { code(HttpStatusCode.OK) { description = "Wire gateway configuration"; body() } } }) { call.respond( WireGatewayConfig( currency = cfg.regionalCurrency, support_account_check = false, ) ) } auth(db, cfg.pwCrypto, TokenLogicalScope.readwrite_wiregateway, cfg.basicAuthCompat) { post("/accounts/{USERNAME}/taler-wire-gateway/transfer", { operationId = "createWireGatewayTransfer" description = "Initiate a wire transfer from an exchange account" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.OK) { description = "Transfer initiated"; body() } code(HttpStatusCode.Conflict) { description = "Transfer conflict" } } }) { val req = call.receive() cfg.checkRegionalCurrency(req.amount) val res = db.exchange.transfer( req = req, username = call.pathUsername, timestamp = Instant.now(), conversion = cfg.allowConversion ) when (res) { TransferResult.UnknownExchange -> throw unknownAccount(call.pathUsername) TransferResult.NotAnExchange -> throw notExchange(call.pathUsername) TransferResult.BothPartyAreExchange -> throw conflict( "Wire transfer attempted with credit and debit party being both exchange account", TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE ) TransferResult.ReserveUidReuse -> throw conflict( "request_uid used already", TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED ) TransferResult.WtidReuse -> throw conflict( "wtid used already", TalerErrorCode.BANK_TRANSFER_WTID_REUSED ) TransferResult.BalanceInsufficient -> throw conflict( "Insufficient balance for exchange", TalerErrorCode.BANK_UNALLOWED_DEBIT ) TransferResult.AdminCreditor -> throw conflict( "Cannot transfer money to admin account when conversion is disabled", TalerErrorCode.BANK_ADMIN_CREDITOR ) is TransferResult.Success -> call.respond( TransferResponse( timestamp = res.timestamp, row_id = res.id ) ) } } } auth(db, cfg.pwCrypto, TokenLogicalScope.readonly_wiregateway, cfg.basicAuthCompat) { suspend fun ApplicationCall.historyEndpoint( reduce: (List, String) -> Any, dbLambda: suspend ExchangeDAO.(HistoryParams, Long) -> List ) { val params = HistoryParams.extract(this.request.queryParameters) val bankAccount = this.bankInfo(db) if (!bankAccount.isTalerExchange) throw notExchange(pathUsername) val items = db.exchange.dbLambda(params, bankAccount.bankAccountId) if (items.isEmpty()) { this.respond(HttpStatusCode.NoContent) } else { this.respond(reduce(items, bankAccount.payto)) } } get("/accounts/{USERNAME}/taler-wire-gateway/history/incoming", { operationId = "getIncomingHistory" description = "Get incoming wire transfer history" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } queryParameter("timeout_ms") { description = "Timeout for long polling in milliseconds (default: 0, no long polling)" required = false } } response { code(HttpStatusCode.OK) { description = "Incoming transfer history"; body() } code(HttpStatusCode.NoContent) { description = "No incoming transfers found" } } }) { call.historyEndpoint(::IncomingHistory, ExchangeDAO::incomingHistory) } get("/accounts/{USERNAME}/taler-wire-gateway/history/outgoing", { operationId = "getOutgoingHistory" description = "Get outgoing wire transfer history" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } queryParameter("timeout_ms") { description = "Timeout for long polling in milliseconds (default: 0, no long polling)" required = false } } response { code(HttpStatusCode.OK) { description = "Outgoing transfer history"; body() } code(HttpStatusCode.NoContent) { description = "No outgoing transfers found" } } }) { call.historyEndpoint(::OutgoingHistory, ExchangeDAO::outgoingHistory) } get("/accounts/{USERNAME}/taler-wire-gateway/transfers", { operationId = "listWireGatewayTransfers" description = "List wire gateway transfers" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } queryParameter("status") { description = "Filter by transfer status (pending, transient_failure, permanent_failure, success)" required = false } } response { code(HttpStatusCode.OK) { description = "List of transfers"; body() } code(HttpStatusCode.NoContent) { description = "No transfers found" } } }) { val params = TransferParams.extract(call.request.queryParameters) val bankAccount = call.bankInfo(db) if (!bankAccount.isTalerExchange) throw notExchange(call.pathUsername) if (params.status != null && params.status != TransferStatusState.success && params.status != TransferStatusState.permanent_failure) { call.respond(HttpStatusCode.NoContent) } else { val items = db.exchange.pageTransfer(params.page, bankAccount.bankAccountId, params.status) if (items.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(TransferList(items, bankAccount.payto)) } } } get("/accounts/{USERNAME}/taler-wire-gateway/transfers/{ROW_ID}", { operationId = "getWireGatewayTransfer" description = "Get a specific wire gateway transfer" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } pathParameter("ROW_ID") { description = "Transfer row ID" } } response { code(HttpStatusCode.OK) { description = "Transfer details"; body() } code(HttpStatusCode.NotFound) { description = "Transfer not found" } } }) { val bankAccount = call.bankInfo(db) if (!bankAccount.isTalerExchange) throw notExchange(call.pathUsername) val txId = call.longPath("ROW_ID") val transfer = db.exchange.getTransfer(bankAccount.bankAccountId, txId) ?: throw notFound( "Transfer '$txId' not found", TalerErrorCode.BANK_TRANSACTION_NOT_FOUND ) call.respond(transfer) } get("/accounts/{USERNAME}/taler-wire-gateway/account/check", { operationId = "checkAccount" description = "Check if an account exists" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("account") { description = "Payto URI of the account to check (required)" required = true } } response { code(HttpStatusCode.OK) { description = "Account information"; body() } code(HttpStatusCode.NotFound) { description = "Account not found" } } }) { val bankAccount = call.bankInfo(db) if (!bankAccount.isTalerExchange) throw notExchange(call.pathUsername) val params = AccountCheckParams.extract(call.request.queryParameters) val account = params.account.expectIban() val info = db.account.checkInfo(account) ?: throw unknownAccount(account.canonical) call.respond(info) } } authAdmin(db, cfg.pwCrypto, TokenLogicalScope.readwrite, cfg.basicAuthCompat) { suspend fun ApplicationCall.addIncoming( amount: TalerAmount, debitAccount: Payto, subject: String, metadata: IncomingSubject ) { cfg.checkRegionalCurrency(amount) val timestamp = Instant.now() val res = db.exchange.addIncoming( amount = amount, debitAccount = debitAccount, subject = subject, username = pathUsername, timestamp = timestamp, metadata = metadata ) when (res) { AddIncomingResult.UnknownExchange -> throw unknownAccount(pathUsername) AddIncomingResult.NotAnExchange -> throw notExchange(pathUsername) AddIncomingResult.UnknownDebtor -> throw conflict( "Debtor account $debitAccount was not found", TalerErrorCode.BANK_UNKNOWN_DEBTOR ) AddIncomingResult.BothPartyAreExchange -> throw conflict( "Wire transfer attempted with credit and debit party being both exchange account", TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE ) AddIncomingResult.ReservePubReuse -> throw conflict( "reserve_pub used already", TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT ) AddIncomingResult.BalanceInsufficient -> throw conflict( "Insufficient balance for debitor", TalerErrorCode.BANK_UNALLOWED_DEBIT ) AddIncomingResult.MappingReuse -> throw conflict( "authorization_pub used already", TalerErrorCode.BANK_TRANSFER_MAPPING_REUSED ) AddIncomingResult.UnknownMapping -> throw conflict( "authorization_pub unknown", TalerErrorCode.BANK_TRANSFER_MAPPING_UNKNOWN ) is AddIncomingResult.Success -> this.respond( AddIncomingResponse( timestamp = TalerTimestamp(timestamp), row_id = res.id ) ) } } post("/accounts/{USERNAME}/taler-wire-gateway/admin/add-incoming", { operationId = "addIncoming" description = "Add an incoming wire transfer (admin)" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.OK) { description = "Incoming transfer added"; body() } code(HttpStatusCode.Conflict) { description = "Transfer conflict" } } }) { val req = call.receive() call.addIncoming( amount = req.amount, debitAccount = req.debit_account, subject = "Admin incoming ${req.reserve_pub}", metadata = IncomingSubject.Reserve(req.reserve_pub) ) } post("/accounts/{USERNAME}/taler-wire-gateway/admin/add-kycauth", { operationId = "addKycauth" description = "Add an incoming KYC auth wire transfer (admin)" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.OK) { description = "KYC auth transfer added"; body() } code(HttpStatusCode.Conflict) { description = "Transfer conflict" } } }) { val req = call.receive() call.addIncoming( amount = req.amount, debitAccount = req.debit_account, subject = "Admin incoming KYC:${req.account_pub}", metadata = IncomingSubject.Kyc(req.account_pub) ) } post("/accounts/{USERNAME}/taler-wire-gateway/admin/add-mapped", { operationId = "addMapped" description = "Add an incoming mapped wire transfer (admin)" tags = listOf("Wire Gateway") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } body() } response { code(HttpStatusCode.OK) { description = "Mapped transfer added"; body() } code(HttpStatusCode.Conflict) { description = "Transfer conflict" } } }) { val req = call.receive() call.addIncoming( amount = req.amount, debitAccount = req.debit_account, subject = "Manual incoming MAP:${req.authorization_pub}", metadata = IncomingSubject.Map(req.authorization_pub) ) } } } libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/api/ObservabilityApi.kt0000664000175000017500000000630415204341712031302 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import io.ktor.util.pipeline.* import io.prometheus.metrics.core.metrics.* import io.prometheus.metrics.model.registry.PrometheusRegistry import io.prometheus.metrics.model.snapshots.Unit import io.prometheus.metrics.instrumentation.jvm.JvmMetrics; import io.prometheus.metrics.expositionformats.ExpositionFormats import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.bank.* import tech.libeufin.bank.db.* import tech.libeufin.bank.auth.* import java.time.Instant import java.io.ByteArrayOutputStream object Metrics { @Volatile private var tanChannelCounter = Counter.builder() .name("libeufin_bank_tan_channel") .help("TAN script calls") .labelNames("channel", "exit") init { // Register JVM metrics JvmMetrics.builder().register() } // TODO add database table counter info ? } fun Routing.observabilityApi(db: Database, cfg: BankConfig) { get("/taler-observability/config", { operationId = "getObservabilityConfig" description = "Get observability configuration" tags = listOf("Observability") response { code(HttpStatusCode.OK) { description = "Observability configuration"; body() } } }) { call.respond(TalerObservabilityConfig()) } authAdmin(db, cfg.pwCrypto, TokenLogicalScope.observability, cfg.basicAuthCompat) { get("/taler-observability/metrics", { operationId = "getMetrics" description = "Get Prometheus metrics" tags = listOf("Observability") protected = true securitySchemeNames("bearerAuth", "basicAuth") response { code(HttpStatusCode.OK) { description = "Prometheus metrics in text format" } } }) { val snapshot = PrometheusRegistry.defaultRegistry.scrape() val outputStream = ByteArrayOutputStream() ExpositionFormats.init().getPrometheusTextFormatWriter().write(outputStream, snapshot) call.respondText(outputStream.toString(Charsets.UTF_8), ContentType.parse("text/plain; version=0.0.4; charset=utf-8")) } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/api/RevenueApi.kt0000664000175000017500000000706715204341712030104 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.api import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.github.smiley4.ktoropenapi.* import tech.libeufin.bank.BankConfig import tech.libeufin.bank.TokenLogicalScope import tech.libeufin.bank.auth.auth import tech.libeufin.bank.bankInfo import tech.libeufin.bank.db.Database import tech.libeufin.common.HistoryParams import tech.libeufin.common.RevenueConfig import tech.libeufin.common.RevenueIncomingHistory fun Routing.revenueApi(db: Database, cfg: BankConfig) { get("/accounts/{USERNAME}/taler-revenue/config", { operationId = "getRevenueConfig" description = "Get revenue API configuration" tags = listOf("Revenue") request { pathParameter("USERNAME") { description = "Account username" } } response { code(HttpStatusCode.OK) { description = "Revenue API configuration"; body() } } }) { call.respond(RevenueConfig( currency = cfg.regionalCurrency )) } auth(db, cfg.pwCrypto, TokenLogicalScope.revenue, cfg.basicAuthCompat) { get("/accounts/{USERNAME}/taler-revenue/history", { operationId = "getRevenueHistory" description = "Get revenue history for an account" tags = listOf("Revenue") protected = true securitySchemeNames("bearerAuth", "basicAuth") request { pathParameter("USERNAME") { description = "Account username" } queryParameter("limit") { description = "Maximum number of results to return (default: -20, negative means descending)" required = false } queryParameter("offset") { description = "Row ID offset for pagination" required = false } queryParameter("timeout_ms") { description = "Timeout for long polling in milliseconds (default: 0, no long polling)" required = false } } response { code(HttpStatusCode.OK) { description = "Revenue history"; body() } code(HttpStatusCode.NoContent) { description = "No revenue history found" } } }) { val params = HistoryParams.extract(call.request.queryParameters) val bankAccount = call.bankInfo(db) val items = db.transaction.revenueHistory(params, bankAccount.bankAccountId) if (items.isEmpty()) { call.respond(HttpStatusCode.NoContent) } else { call.respond(RevenueIncomingHistory(items, bankAccount.payto)) } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/0000775000175000017500000000000015236145704025313 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt0000664000175000017500000004030315156463305030306 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeoutOrNull import tech.libeufin.bank.* import tech.libeufin.common.EddsaPublicKey import tech.libeufin.common.Payto import tech.libeufin.common.TalerAmount import tech.libeufin.common.db.* import tech.libeufin.common.micros import java.time.Instant import java.util.* /** Data access logic for withdrawal operations */ class WithdrawalDAO(private val db: Database) { /** Result status of withdrawal operation creation */ enum class WithdrawalCreationResult { Success, UnknownAccount, AccountIsExchange, BalanceInsufficient, BadAmount } /** Create a new withdrawal operation */ suspend fun create( username: String, uuid: UUID, amount: TalerAmount?, suggested_amount: TalerAmount?, no_amount_to_wallet: Boolean, timestamp: Instant, wireTransferFees: TalerAmount, minAmount: TalerAmount, maxAmount: TalerAmount ): WithdrawalCreationResult = db.serializable( """ SELECT out_account_not_found, out_account_is_exchange, out_balance_insufficient, out_bad_amount FROM create_taler_withdrawal( ?,?, ${optAmount(amount)}, ${optAmount(suggested_amount)}, ?, ?, (?, ?)::taler_amount, (?, ?)::taler_amount, (?, ?)::taler_amount ); """ ) { bind(username) bind(uuid) bind(amount) bind(suggested_amount) bind(no_amount_to_wallet) bind(timestamp.micros()) bind(wireTransferFees) bind(minAmount) bind(maxAmount) one { when { it.getBoolean("out_account_not_found") -> WithdrawalCreationResult.UnknownAccount it.getBoolean("out_account_is_exchange") -> WithdrawalCreationResult.AccountIsExchange it.getBoolean("out_balance_insufficient") -> WithdrawalCreationResult.BalanceInsufficient it.getBoolean("out_bad_amount") -> WithdrawalCreationResult.BadAmount else -> WithdrawalCreationResult.Success } } } /** Abort withdrawal operation [uuid] */ suspend fun abort( uuid: UUID ): AbortResult = db.serializable( """ SELECT out_no_op, out_already_confirmed FROM abort_taler_withdrawal(?) """ ) { bind(uuid) one { when { it.getBoolean("out_no_op") -> AbortResult.UnknownOperation it.getBoolean("out_already_confirmed") -> AbortResult.AlreadyConfirmed else -> AbortResult.Success } } } /** Result withdrawal operation selection */ sealed interface WithdrawalSelectionResult { data class Success(val status: WithdrawalStatus): WithdrawalSelectionResult data object UnknownOperation: WithdrawalSelectionResult data object AlreadySelected: WithdrawalSelectionResult data object ReservePubReuse: WithdrawalSelectionResult data object UnknownAccount: WithdrawalSelectionResult data object AccountIsNotExchange: WithdrawalSelectionResult data object AmountDiffers: WithdrawalSelectionResult data object BalanceInsufficient: WithdrawalSelectionResult data object BadAmount: WithdrawalSelectionResult data object AlreadyAborted: WithdrawalSelectionResult } /** Set details ([exchangePayto] & [reservePub] & [amount]) for withdrawal operation [uuid] */ suspend fun setDetails( uuid: UUID, exchangePayto: Payto, reservePub: EddsaPublicKey, amount: TalerAmount?, wireTransferFees: TalerAmount, minAmount: TalerAmount, maxAmount: TalerAmount ): WithdrawalSelectionResult = db.serializable( """ SELECT out_no_op, out_already_selected, out_reserve_pub_reuse, out_account_not_found, out_account_is_not_exchange, out_status, out_amount_differs, out_balance_insufficient, out_bad_amount, out_aborted FROM select_taler_withdrawal( ?, ?, ?, ?, ${optAmount(amount)}, (?,?)::taler_amount, (?,?)::taler_amount, (?,?)::taler_amount ); """ ) { bind(uuid) bind(reservePub) bind("Taler withdrawal $reservePub") bind(exchangePayto.canonical) bind(amount) bind(wireTransferFees) bind(minAmount) bind(maxAmount) one { when { it.getBoolean("out_aborted") -> WithdrawalSelectionResult.AlreadyAborted it.getBoolean("out_balance_insufficient") -> WithdrawalSelectionResult.BalanceInsufficient it.getBoolean("out_bad_amount") -> WithdrawalSelectionResult.BadAmount it.getBoolean("out_no_op") -> WithdrawalSelectionResult.UnknownOperation it.getBoolean("out_already_selected") -> WithdrawalSelectionResult.AlreadySelected it.getBoolean("out_amount_differs") -> WithdrawalSelectionResult.AmountDiffers it.getBoolean("out_reserve_pub_reuse") -> WithdrawalSelectionResult.ReservePubReuse it.getBoolean("out_account_not_found") -> WithdrawalSelectionResult.UnknownAccount it.getBoolean("out_account_is_not_exchange") -> WithdrawalSelectionResult.AccountIsNotExchange else -> WithdrawalSelectionResult.Success(it.getEnum("out_status")) } } } /** Result status of withdrawal operation confirmation */ enum class WithdrawalConfirmationResult { Success, UnknownOperation, BalanceInsufficient, BadAmount, NotSelected, AlreadyAborted, TanRequired, MissingAmount, AmountDiffers, ReservePubReuse } /** Confirm withdrawal operation [uuid] */ suspend fun confirm( username: String, uuid: UUID, timestamp: Instant, amount: TalerAmount?, is2fa: Boolean, wireTransferFees: TalerAmount, minAmount: TalerAmount, maxAmount: TalerAmount ): WithdrawalConfirmationResult = db.serializable( """ SELECT out_no_op, out_balance_insufficient, out_bad_amount, out_not_selected, out_aborted, out_tan_required, out_missing_amount, out_amount_differs, out_reserve_pub_reuse FROM confirm_taler_withdrawal( ?,?,?,?,(?,?)::taler_amount,(?,?)::taler_amount,(?,?)::taler_amount, ${optAmount(amount)} ); """ ) { bind(username) bind(uuid) bind(timestamp) bind(is2fa) bind(wireTransferFees) bind(minAmount) bind(maxAmount) bind(amount) one { when { it.getBoolean("out_no_op") -> WithdrawalConfirmationResult.UnknownOperation it.getBoolean("out_balance_insufficient") -> WithdrawalConfirmationResult.BalanceInsufficient it.getBoolean("out_bad_amount") -> WithdrawalConfirmationResult.BadAmount it.getBoolean("out_not_selected") -> WithdrawalConfirmationResult.NotSelected it.getBoolean("out_aborted") -> WithdrawalConfirmationResult.AlreadyAborted it.getBoolean("out_tan_required") -> WithdrawalConfirmationResult.TanRequired it.getBoolean("out_missing_amount") -> WithdrawalConfirmationResult.MissingAmount it.getBoolean("out_amount_differs") -> WithdrawalConfirmationResult.AmountDiffers it.getBoolean("out_reserve_pub_reuse") -> WithdrawalConfirmationResult.ReservePubReuse else -> WithdrawalConfirmationResult.Success } } } /** Get withdrawal operation [uuid] linked account username */ suspend fun getUsername(uuid: UUID): String? = db.serializable( """ SELECT username FROM taler_withdrawal_operations JOIN bank_accounts ON wallet_bank_account=bank_account_id JOIN customers ON customer_id=owning_customer_id WHERE withdrawal_uuid=? """ ) { bind(uuid) oneOrNull { it.getString(1) } } private suspend fun poll( uuid: UUID, params: StatusParams, status: (T) -> WithdrawalStatus, load: suspend () -> T? ): T? { return if (params.polling.timeout_ms > 0) { db.listenWithdrawals(uuid) { flow -> coroutineScope { // Start buffering notification before loading transactions to not miss any val polling = launch { withTimeoutOrNull(params.polling.timeout_ms) { flow.first { it != params.old_state } } } // Initial loading val init = load() // Long polling if there is no operation or its not confirmed if (init?.run { status(this) == params.old_state } != false) { polling.join() load() } else { polling.cancel() init } } } } else { load() } } /** Pool public info of operation [uuid] */ suspend fun pollInfo(uuid: UUID, params: StatusParams): WithdrawalPublicInfo? = poll(uuid, params, status = { it.status }) { db.serializable( """ SELECT CASE WHEN confirmation_done THEN 'confirmed' WHEN aborted THEN 'aborted' WHEN selection_done THEN 'selected' ELSE 'pending' END as status ,(amount).val as amount_val ,(amount).frac as amount_frac ,(suggested_amount).val as suggested_amount_val ,(suggested_amount).frac as suggested_amount_frac ,selection_done ,aborted ,confirmation_done ,reserve_pub ,wallet_user.username ,no_amount_to_wallet ,exchange_account.internal_payto as exchange_payto ,exchange_user.name as exchange_name FROM taler_withdrawal_operations JOIN bank_accounts AS wallet_account ON wallet_bank_account=wallet_account.bank_account_id JOIN customers AS wallet_user ON wallet_user.customer_id=wallet_account.owning_customer_id LEFT JOIN bank_accounts AS exchange_account ON exchange_bank_account=exchange_account.bank_account_id LEFT JOIN customers AS exchange_user ON exchange_user.customer_id=exchange_account.owning_customer_id WHERE withdrawal_uuid=? """ ) { bind(uuid) oneOrNull { WithdrawalPublicInfo( status = it.getEnum("status"), amount = it.getOptAmount("amount", db.bankCurrency), suggested_amount = it.getOptAmount("suggested_amount", db.bankCurrency), username = it.getString("username"), selected_exchange_account = it.getOptBankPayto("exchange_payto", "exchange_name", db.ctx), selected_reserve_pub = it.getBytes("reserve_pub")?.run(::EddsaPublicKey), no_amount_to_wallet = it.getBoolean("no_amount_to_wallet") ) } } } /** Pool public status of operation [uuid] */ suspend fun pollStatus( uuid: UUID, params: StatusParams, wire: WireMethod, maxAmount: TalerAmount ): BankWithdrawalOperationStatus? = poll(uuid, params, status = { it.status }) { db.serializable( """ SELECT CASE WHEN confirmation_done THEN 'confirmed' WHEN aborted THEN 'aborted' WHEN selection_done THEN 'selected' ELSE 'pending' END as status ,(amount).val as amount_val ,(amount).frac as amount_frac ,(suggested_amount).val as suggested_amount_val ,(suggested_amount).frac as suggested_amount_frac ,selection_done ,aborted ,confirmation_done ,wallet_account.internal_payto ,wallet_user.name ,reserve_pub ,exchange_account.internal_payto as exchange_payto ,exchange_user.name as exchange_name ,(max_amount).val as max_amount_val ,(max_amount).frac as max_amount_frac ,no_amount_to_wallet FROM taler_withdrawal_operations JOIN bank_accounts AS wallet_account ON wallet_bank_account=wallet_account.bank_account_id JOIN customers AS wallet_user ON wallet_user.customer_id=wallet_account.owning_customer_id LEFT JOIN bank_accounts AS exchange_account ON exchange_bank_account=exchange_account.bank_account_id LEFT JOIN customers AS exchange_user ON exchange_user.customer_id=exchange_account.owning_customer_id ,account_max_amount(wallet_account.bank_account_id, (?, ?)::taler_amount) AS max_amount WHERE withdrawal_uuid=? """ ) { bind(maxAmount) bind(uuid) oneOrNull { BankWithdrawalOperationStatus( status = it.getEnum("status"), amount = it.getOptAmount("amount", db.bankCurrency), suggested_amount = it.getOptAmount("suggested_amount", db.bankCurrency), max_amount = it.getAmount("max_amount", db.bankCurrency), selection_done = it.getBoolean("selection_done"), transfer_done = it.getBoolean("confirmation_done"), aborted = it.getBoolean("aborted"), sender_wire = it.getBankPayto("internal_payto", "name", db.ctx), confirm_transfer_url = null, suggested_exchange = null, selected_exchange_account = it.getOptBankPayto("exchange_payto", "exchange_name", db.ctx), no_amount_to_wallet = it.getBoolean("no_amount_to_wallet"), selected_reserve_pub = it.getBytes("reserve_pub")?.run(::EddsaPublicKey), wire_types = listOf( when (wire) { WireMethod.IBAN -> "iban" WireMethod.X_TALER_BANK -> "x-taler-bank" } ), currency = db.bankCurrency ) } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt0000664000175000017500000001406415122266731027610 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import tech.libeufin.bank.* import tech.libeufin.common.* import tech.libeufin.common.db.* import java.time.Instant /** Data access logic for cashout operations */ class CashoutDAO(private val db: Database) { /** Result of cashout operation creation */ sealed interface CashoutCreationResult { data class Success(val id: Long): CashoutCreationResult data object UnderMin: CashoutCreationResult data object BadConversion: CashoutCreationResult data object AccountNotFound: CashoutCreationResult data object AccountIsExchange: CashoutCreationResult data object BalanceInsufficient: CashoutCreationResult data object RequestUidReuse: CashoutCreationResult data object NoCashoutPayto: CashoutCreationResult data object TanRequired: CashoutCreationResult } /** Create a new cashout operation */ suspend fun create( username: String, requestUid: ShortHashCode, amountDebit: TalerAmount, amountCredit: TalerAmount, subject: String, timestamp: Instant, is2fa: Boolean ): CashoutCreationResult = db.serializable( """ SELECT out_bad_conversion, out_account_not_found, out_account_is_exchange, out_balance_insufficient, out_request_uid_reuse, out_no_cashout_payto, out_tan_required, out_cashout_id, out_under_min FROM cashout_create(?,?,(?,?)::taler_amount,(?,?)::taler_amount,?,?,?) """ ) { bind(username) bind(requestUid) bind(amountDebit) bind(amountCredit) bind(subject) bind(timestamp) bind(is2fa) one { when { it.getBoolean("out_under_min") -> CashoutCreationResult.UnderMin it.getBoolean("out_bad_conversion") -> CashoutCreationResult.BadConversion it.getBoolean("out_account_not_found") -> CashoutCreationResult.AccountNotFound it.getBoolean("out_account_is_exchange") -> CashoutCreationResult.AccountIsExchange it.getBoolean("out_balance_insufficient") -> CashoutCreationResult.BalanceInsufficient it.getBoolean("out_request_uid_reuse") -> CashoutCreationResult.RequestUidReuse it.getBoolean("out_no_cashout_payto") -> CashoutCreationResult.NoCashoutPayto it.getBoolean("out_tan_required") -> CashoutCreationResult.TanRequired else -> CashoutCreationResult.Success(it.getLong("out_cashout_id")) } } } /** Get status of cashout operation [id] owned by [username] */ suspend fun get(id: Long, username: String): CashoutStatusResponse? = db.serializable( """ SELECT (amount_debit).val as amount_debit_val ,(amount_debit).frac as amount_debit_frac ,(amount_credit).val as amount_credit_val ,(amount_credit).frac as amount_credit_frac ,cashout_operations.subject ,creation_time ,transaction_date as confirmation_date FROM cashout_operations JOIN bank_accounts ON bank_account=bank_account_id JOIN customers ON owning_customer_id=customer_id LEFT JOIN bank_account_transactions ON local_transaction=bank_transaction_id WHERE cashout_id=? AND username=? """ ) { bind(id) bind(username) oneOrNull { CashoutStatusResponse( amount_debit = it.getAmount("amount_debit", db.bankCurrency), amount_credit = it.getAmount("amount_credit", db.fiatCurrency!!), subject = it.getString("subject"), creation_time = it.getTalerTimestamp("creation_time"), confirmation_time = when (val timestamp = it.getLong("confirmation_date")) { 0L -> null else -> TalerTimestamp(timestamp.asInstant()) }, ) } } /** Get a page of all cashout operations */ suspend fun pageAll(params: PageParams): List = db.page(params, "cashout_id", """ SELECT cashout_id, username FROM cashout_operations JOIN bank_accounts ON bank_account=bank_account_id JOIN customers ON owning_customer_id=customer_id WHERE """) { GlobalCashoutInfo( cashout_id = it.getLong("cashout_id"), username = it.getString("username"), status = CashoutStatus.confirmed ) } /** Get a page of all cashout operations owned by [username] */ suspend fun pageForUser(params: PageParams, username: String): List = db.page(params, "cashout_id", """ SELECT cashout_id FROM cashout_operations WHERE bank_account=( SELECT bank_account_id FROM bank_accounts JOIN customers ON owning_customer_id=customer_id WHERE deleted_at IS NULL AND username = ? ) AND """, args = { bind(username) } ) { CashoutInfo( cashout_id = it.getLong("cashout_id"), status = CashoutStatus.confirmed ) } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt0000664000175000017500000001437215122266731027264 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import tech.libeufin.bank.* import tech.libeufin.common.PageParams import tech.libeufin.common.asInstant import tech.libeufin.common.db.* import tech.libeufin.common.micros import java.time.Instant /** Data access logic for auth tokens */ class TokenDAO(private val db: Database) { /** Result status of token creation */ sealed interface TokenCreationResult { data object Success: TokenCreationResult data object TanRequired: TokenCreationResult } /** Create new token for [username] */ suspend fun create( username: String, content: ByteArray, creationTime: Instant, expirationTime: Instant, scope: TokenScope, isRefreshable: Boolean, description: String?, is2fa: Boolean ): TokenCreationResult = db.serializable( """ SELECT out_tan_required FROM create_token( ?,?,?,?,?::token_scope_enum,?,?,? ) """ ) { bind(username) bind(content) bind(creationTime) bind(expirationTime) bind(scope) bind(isRefreshable) bind(description) bind(is2fa) one { when { it.getBoolean("out_tan_required") -> TokenCreationResult.TanRequired else -> TokenCreationResult.Success } } } /** Get info for [token] */ suspend fun access(token: ByteArray, accessTime: Instant): BearerToken? = db.serializable( """ UPDATE bearer_tokens SET last_access=? FROM customers WHERE bank_customer=customer_id AND content=? AND deleted_at IS NULL RETURNING creation_time, expiration_time, scope, is_refreshable """ ) { bind(accessTime) bind(token) oneOrNull { BearerToken( creationTime = it.getLong("creation_time").asInstant(), expirationTime = it.getLong("expiration_time").asInstant(), scope = it.getEnum("scope"), isRefreshable = it.getBoolean("is_refreshable") ) } } /** Get info for [token] and its associated bank account*/ suspend fun accessInfo(token: ByteArray, accessTime: Instant): Pair? = db.serializable( """ UPDATE bearer_tokens SET last_access=? FROM customers JOIN bank_accounts ON customer_id=owning_customer_id WHERE bank_customer=customer_id AND content=? AND deleted_at IS NULL RETURNING creation_time, expiration_time, scope, is_refreshable, username, is_taler_exchange, bank_account_id, internal_payto, name, tan_channels, email, phone """ ) { bind(accessTime) bind(token) oneOrNull { Pair( BearerToken( creationTime = it.getLong("creation_time").asInstant(), expirationTime = it.getLong("expiration_time").asInstant(), scope = it.getEnum("scope"), isRefreshable = it.getBoolean("is_refreshable") ), BankInfo( username = it.getString("username"), payto = it.getBankPayto("internal_payto", "name", db.ctx), bankAccountId = it.getLong("bank_account_id"), isTalerExchange = it.getBoolean("is_taler_exchange"), channels = it.getEnumSet("tan_channels"), phone = it.getString("phone"), email = it.getString("email") ) ) } } /** Delete token [token] */ suspend fun delete(token: ByteArray) = db.serializable( "DELETE FROM bearer_tokens WHERE content = ?" ) { bind(token) executeUpdate() } /** Delete token [id] */ suspend fun deleteById(id: Long) = db.serializable( "DELETE FROM bearer_tokens WHERE bearer_token_id = ?" ) { bind(id) executeUpdateCheck() } /** Get a page of all tokens of [username] accounts */ suspend fun page(params: PageParams, username: String, timestamp: Instant): List = db.page( params, "bearer_token_id", """ SELECT creation_time, expiration_time, scope, is_refreshable, description, last_access, bearer_token_id FROM bearer_tokens WHERE expiration_time > ? AND bank_customer=(SELECT customer_id FROM customers WHERE deleted_at IS NULL AND username = ?) AND """, { bind(timestamp.micros()) bind(username) } ) { TokenInfo( creation_time = it.getTalerTimestamp("creation_time"), expiration = it.getTalerTimestamp("expiration_time"), scope = it.getEnum("scope"), isRefreshable = it.getBoolean("is_refreshable"), description = it.getString("description"), last_access = it.getTalerTimestamp("last_access"), row_id = it.getLong("bearer_token_id"), token_id = it.getLong("bearer_token_id") ) } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt0000664000175000017500000005372215122266731030333 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import tech.libeufin.bank.* import tech.libeufin.common.* import tech.libeufin.common.db.* import java.sql.* import org.postgresql.util.PSQLState /** Data access logic for conversion */ class ConversionDAO(private val db: Database) { companion object { fun userRate(db: Database, it: ResultSet, username: String, isTalerExchange: Boolean): ConversionRate? { return if (db.fiatCurrency == null) { null } else if (username == "admin") { ConversionRate( cashin_ratio = DecimalNumber.ZERO, cashin_fee = TalerAmount.zero(db.bankCurrency), cashin_tiny_amount = TalerAmount.zero(db.bankCurrency), cashin_rounding_mode = RoundingMode.zero, cashin_min_amount = TalerAmount.zero(db.fiatCurrency), cashout_ratio = DecimalNumber.ZERO, cashout_fee = TalerAmount.zero(db.fiatCurrency), cashout_tiny_amount = TalerAmount.zero(db.fiatCurrency), cashout_rounding_mode = RoundingMode.zero, cashout_min_amount = TalerAmount.zero(db.bankCurrency), ) } else if (isTalerExchange) { ConversionRate( cashin_ratio = it.getDecimal("cashin_ratio"), cashin_fee = it.getAmount("cashin_fee", db.bankCurrency), cashin_tiny_amount = it.getAmount("cashin_tiny_amount", db.bankCurrency), cashin_rounding_mode = it.getEnum("cashin_rounding_mode"), cashin_min_amount = it.getAmount("cashin_min_amount", db.fiatCurrency), cashout_ratio = DecimalNumber.ZERO, cashout_fee = TalerAmount.zero(db.fiatCurrency), cashout_tiny_amount = TalerAmount.zero(db.fiatCurrency), cashout_rounding_mode = RoundingMode.zero, cashout_min_amount = TalerAmount.zero(db.bankCurrency), ) } else { ConversionRate( cashin_ratio = DecimalNumber.ZERO, cashin_fee = TalerAmount.zero(db.bankCurrency), cashin_tiny_amount = TalerAmount.zero(db.bankCurrency), cashin_rounding_mode = RoundingMode.zero, cashin_min_amount = TalerAmount.zero(db.fiatCurrency), cashout_ratio = it.getDecimal("cashout_ratio"), cashout_fee = it.getAmount("cashout_fee", db.fiatCurrency), cashout_tiny_amount = it.getAmount("cashout_tiny_amount", db.fiatCurrency), cashout_rounding_mode = it.getEnum("cashout_rounding_mode"), cashout_min_amount = it.getAmount("cashout_min_amount", db.bankCurrency), ) } } } /** Update in-db conversion config */ suspend fun updateConfig(cfg: ConversionRate) = db.serializable(""" CALL config_set_conversion_rate( (?, ?)::taler_amount, (?, ?)::taler_amount, (?, ?)::taler_amount, (?, ?)::taler_amount, ?::rounding_mode, (?, ?)::taler_amount, (?, ?)::taler_amount, (?, ?)::taler_amount, (?, ?)::taler_amount, ?::rounding_mode ) """) { bind(cfg.cashin_ratio) bind(cfg.cashin_fee) bind(cfg.cashin_tiny_amount) bind(cfg.cashin_min_amount) bind(cfg.cashin_rounding_mode) bind(cfg.cashout_ratio) bind(cfg.cashout_fee) bind(cfg.cashout_tiny_amount) bind(cfg.cashout_min_amount) bind(cfg.cashout_rounding_mode) executeUpdate() } /** Get default conversion rate */ suspend fun getDefaultRate(): ConversionRate = db.serializable(""" SELECT (cashin_ratio).val as cashin_ratio_val, (cashin_ratio).frac as cashin_ratio_frac, (cashin_fee).val as cashin_fee_val, (cashin_fee).frac as cashin_fee_frac, (cashin_tiny_amount).val as cashin_tiny_amount_val, (cashin_tiny_amount).frac as cashin_tiny_amount_frac, (cashin_min_amount).val as cashin_min_amount_val, (cashin_min_amount).frac as cashin_min_amount_frac, cashin_rounding_mode, (cashout_ratio).val as cashout_ratio_val, (cashout_ratio).frac as cashout_ratio_frac, (cashout_fee).val as cashout_fee_val, (cashout_fee).frac as cashout_fee_frac, (cashout_tiny_amount).val as cashout_tiny_amount_val, (cashout_tiny_amount).frac as cashout_tiny_amount_frac, (cashout_min_amount).val as cashout_min_amount_val, (cashout_min_amount).frac as cashout_min_amount_frac, cashout_rounding_mode FROM config_get_conversion_rate() """) { one { ConversionRate( cashin_ratio = it.getDecimal("cashin_ratio"), cashin_fee = it.getAmount("cashin_fee", db.bankCurrency), cashin_tiny_amount = it.getAmount("cashin_tiny_amount", db.bankCurrency), cashin_rounding_mode = it.getEnum("cashin_rounding_mode"), cashin_min_amount = it.getAmount("cashin_min_amount", db.fiatCurrency!!), cashout_ratio = it.getDecimal("cashout_ratio"), cashout_fee = it.getAmount("cashout_fee", db.fiatCurrency), cashout_tiny_amount = it.getAmount("cashout_tiny_amount", db.fiatCurrency), cashout_rounding_mode = it.getEnum("cashout_rounding_mode"), cashout_min_amount = it.getAmount("cashout_min_amount", db.bankCurrency), ) } } /** Get conversion class rate */ suspend fun getClassRate(conversionRateClassId: Long): ConversionRate = db.serializable(""" SELECT (cashin_ratio).val as cashin_ratio_val, (cashin_ratio).frac as cashin_ratio_frac, (cashin_fee).val as cashin_fee_val, (cashin_fee).frac as cashin_fee_frac, (cashin_tiny_amount).val as cashin_tiny_amount_val, (cashin_tiny_amount).frac as cashin_tiny_amount_frac, (cashin_min_amount).val as cashin_min_amount_val, (cashin_min_amount).frac as cashin_min_amount_frac, cashin_rounding_mode, (cashout_ratio).val as cashout_ratio_val, (cashout_ratio).frac as cashout_ratio_frac, (cashout_fee).val as cashout_fee_val, (cashout_fee).frac as cashout_fee_frac, (cashout_tiny_amount).val as cashout_tiny_amount_val, (cashout_tiny_amount).frac as cashout_tiny_amount_frac, (cashout_min_amount).val as cashout_min_amount_val, (cashout_min_amount).frac as cashout_min_amount_frac, cashout_rounding_mode FROM get_conversion_class_rate(?) """) { bind(conversionRateClassId) one { ConversionRate( cashin_ratio = it.getDecimal("cashin_ratio"), cashin_fee = it.getAmount("cashin_fee", db.bankCurrency), cashin_tiny_amount = it.getAmount("cashin_tiny_amount", db.bankCurrency), cashin_rounding_mode = it.getEnum("cashin_rounding_mode"), cashin_min_amount = it.getAmount("cashin_min_amount", db.fiatCurrency!!), cashout_ratio = it.getDecimal("cashout_ratio"), cashout_fee = it.getAmount("cashout_fee", db.fiatCurrency), cashout_tiny_amount = it.getAmount("cashout_tiny_amount", db.fiatCurrency), cashout_rounding_mode = it.getEnum("cashout_rounding_mode"), cashout_min_amount = it.getAmount("cashout_min_amount", db.bankCurrency), ) } } /** Get user rate */ suspend fun getUserRate(username: String): Pair = db.serializable(""" SELECT (cashin_ratio).val as cashin_ratio_val, (cashin_ratio).frac as cashin_ratio_frac, (cashin_fee).val as cashin_fee_val, (cashin_fee).frac as cashin_fee_frac, (cashin_tiny_amount).val as cashin_tiny_amount_val, (cashin_tiny_amount).frac as cashin_tiny_amount_frac, (cashin_min_amount).val as cashin_min_amount_val, (cashin_min_amount).frac as cashin_min_amount_frac, cashin_rounding_mode, (cashout_ratio).val as cashout_ratio_val, (cashout_ratio).frac as cashout_ratio_frac, (cashout_fee).val as cashout_fee_val, (cashout_fee).frac as cashout_fee_frac, (cashout_tiny_amount).val as cashout_tiny_amount_val, (cashout_tiny_amount).frac as cashout_tiny_amount_frac, (cashout_min_amount).val as cashout_min_amount_val, (cashout_min_amount).frac as cashout_min_amount_frac, cashout_rounding_mode, is_taler_exchange FROM bank_accounts JOIN customers ON customer_id=owning_customer_id CROSS JOIN LATERAL get_conversion_class_rate(conversion_rate_class_id) WHERE username=? """) { bind(username) one { val isTalerExchange = it.getBoolean("is_taler_exchange") val rate = ConversionDAO.userRate(db, it, username,isTalerExchange)!! Pair(isTalerExchange, rate) } } /** Clear in-db conversion config */ suspend fun clearConfig() = db.serializable( "DELETE FROM config WHERE key LIKE 'cashin%' OR key like 'cashout%'" ) { executeUpdate() } /** Result of conversions operations */ sealed interface ConversionResult { data class Success(val converted: TalerAmount): ConversionResult data object ToSmall: ConversionResult data object IsExchange: ConversionResult data object NotExchange: ConversionResult } /** Perform [direction] conversion of [amount] using in-db [function] */ private suspend fun conversion(amount: TalerAmount, function: String, direction: String, conversionRateClassId: Long?): ConversionResult = db.serializable( "SELECT too_small, (converted).val AS amount_val, (converted).frac AS amount_frac FROM conversion_$function((?, ?)::taler_amount, ?, ?)" ) { bind(amount) bind(direction) bind(conversionRateClassId) one { when { it.getBoolean("too_small") -> ConversionResult.ToSmall else -> ConversionResult.Success( it.getAmount("amount", if (amount.currency == db.bankCurrency) db.fiatCurrency!! else db.bankCurrency) ) } } } private suspend fun userConversion(amount: TalerAmount, function: String, direction: String, username: String): ConversionResult = db.serializable( """ SELECT is_taler_exchange, too_small, (converted).val AS amount_val, (converted).frac AS amount_frac FROM bank_accounts JOIN customers ON customer_id=owning_customer_id, LATERAL conversion_$function((?, ?)::taler_amount, ?, conversion_rate_class_id) WHERE username=? """ ) { bind(amount) bind(direction) bind(username) one { val isExchange = it.getBoolean("is_taler_exchange") when { direction == "cashout" && isExchange -> ConversionResult.IsExchange direction == "cashin" && !isExchange -> ConversionResult.NotExchange it.getBoolean("too_small") -> ConversionResult.ToSmall else -> ConversionResult.Success( it.getAmount("amount", if (amount.currency == db.bankCurrency) db.fiatCurrency!! else db.bankCurrency) ) } } } /** Convert [regional] amount to fiat using cashout rate */ suspend fun defaultToCashout(regional: TalerAmount): ConversionResult = conversion(regional, "to", "cashout", null) suspend fun classToCashout(id: Long, regional: TalerAmount): ConversionResult = conversion(regional, "to", "cashout", id) suspend fun userToCashout(username: String, regional: TalerAmount): ConversionResult = userConversion(regional, "to", "cashout", username) /** Convert [fiat] amount to regional using cashin rate */ suspend fun defaultToCashin(fiat: TalerAmount): ConversionResult = conversion(fiat, "to", "cashin", null) suspend fun classToCashin(id: Long, fiat: TalerAmount): ConversionResult = conversion(fiat, "to", "cashin", id) suspend fun userToCashin(username: String, fiat: TalerAmount): ConversionResult = userConversion(fiat, "to", "cashin", username) /** Convert [fiat] amount to regional using inverse cashout rate */ suspend fun defaultFromCashout(fiat: TalerAmount): ConversionResult = conversion(fiat, "from", "cashout", null) suspend fun classFromCashout(id: Long, fiat: TalerAmount): ConversionResult = conversion(fiat, "from", "cashout", id) suspend fun userFromCashout(username: String, fiat: TalerAmount): ConversionResult = userConversion(fiat, "from", "cashout", username) /** Convert [regional] amount to fiat using inverse cashin rate */ suspend fun defaultFromCashin(regional: TalerAmount): ConversionResult = conversion(regional, "from", "cashin", null) suspend fun classFromCashin(id: Long, regional: TalerAmount): ConversionResult = conversion(regional, "from", "cashin", id) suspend fun userFromCashin(username: String, regional: TalerAmount): ConversionResult = userConversion(regional, "from", "cashin", username) /** Result status of conversion rate class creation */ sealed interface ClassCreateResult { data class Success(val id: Long): ClassCreateResult data object NameReuse: ClassCreateResult } /** Create a new conversion rate class */ suspend fun createClass( input: ConversionRateClassInput ): ClassCreateResult = db.serializable( """ INSERT INTO conversion_rate_classes ( name ,description ,cashin_ratio ,cashin_fee ,cashin_min_amount ,cashin_rounding_mode ,cashout_ratio ,cashout_fee ,cashout_min_amount ,cashout_rounding_mode ) VALUES ( ?, ?, ${optDecimal(input.cashin_ratio)}, ${optAmount(input.cashin_fee)}, ${optAmount(input.cashin_min_amount)}, ?::rounding_mode, ${optDecimal(input.cashout_ratio)}, ${optAmount(input.cashout_fee)}, ${optAmount(input.cashout_min_amount)}, ?::rounding_mode ) RETURNING conversion_rate_class_id """ ) { bind(input.name) bind(input.description) bind(input.cashin_ratio) bind(input.cashin_fee) bind(input.cashin_min_amount) bind(input.cashin_rounding_mode) bind(input.cashout_ratio) bind(input.cashout_fee) bind(input.cashout_min_amount) bind(input.cashout_rounding_mode) try { one { ClassCreateResult.Success(it.getLong("conversion_rate_class_id")) } } catch (e: SQLException) { if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) ClassCreateResult.NameReuse else throw e } } /** Result status of conversion rate class patching */ enum class ClassPatchResult { Success, Unknown, NameReuse } /** Patch a conversion rate class */ suspend fun patchClass( id: Long, input: ConversionRateClassInput ): ClassPatchResult = db.serializable( """ UPDATE conversion_rate_classes SET name=? ,description=? ,cashin_ratio=${optDecimal(input.cashin_ratio)} ,cashin_fee=${optAmount(input.cashin_fee)} ,cashin_min_amount=${optAmount(input.cashin_min_amount)} ,cashin_rounding_mode=?::rounding_mode ,cashout_ratio=${optDecimal(input.cashout_ratio)} ,cashout_fee=${optAmount(input.cashout_fee)} ,cashout_min_amount=${optAmount(input.cashout_min_amount)} ,cashout_rounding_mode=?::rounding_mode WHERE conversion_rate_class_id=? """ ) { bind(input.name) bind(input.description) bind(input.cashin_ratio) bind(input.cashin_fee) bind(input.cashin_min_amount) bind(input.cashin_rounding_mode) bind(input.cashout_ratio) bind(input.cashout_fee) bind(input.cashout_min_amount) bind(input.cashout_rounding_mode) bind(id) try { if (executeUpdateCheck()) { ClassPatchResult.Success } else { ClassPatchResult.Unknown } } catch (e: SQLException) { if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) ClassPatchResult.NameReuse else throw e } } /** Delete a conversion rate class */ suspend fun deleteClass( id: Long ): Boolean = db.serializable( "DELETE FROM conversion_rate_classes WHERE conversion_rate_class_id=?" ) { bind(id) executeUpdateCheck() } /** Get conversion rate class [id] */ suspend fun getClass(id: Long): ConversionRateClass? = db.serializable( """ SELECT name ,description ,(cashin_ratio).val as cashin_ratio_val, (cashin_ratio).frac as cashin_ratio_frac ,(cashin_fee).val as cashin_fee_val, (cashin_fee).frac as cashin_fee_frac ,(cashin_min_amount).val as cashin_min_amount_val, (cashin_min_amount).frac as cashin_min_amount_frac ,cashin_rounding_mode ,(cashout_ratio).val as cashout_ratio_val, (cashout_ratio).frac as cashout_ratio_frac ,(cashout_fee).val as cashout_fee_val, (cashout_fee).frac as cashout_fee_frac ,(cashout_min_amount).val as cashout_min_amount_val, (cashout_min_amount).frac as cashout_min_amount_frac ,cashout_rounding_mode ,(SELECT count(*) FROM bank_accounts WHERE bank_accounts.conversion_rate_class_id=conversion_rate_classes.conversion_rate_class_id) as num_users FROM conversion_rate_classes WHERE conversion_rate_class_id=? """ ) { bind(id) oneOrNull { ConversionRateClass( name = it.getString("name"), description = it.getString("description"), conversion_rate_class_id = id, num_users = it.getInt("num_users"), cashin_ratio = it.getOptDecimal("cashin_ratio"), cashin_fee = it.getOptAmount("cashin_fee", db.bankCurrency), cashin_rounding_mode = it.getOptEnum("cashin_rounding_mode"), cashin_min_amount = it.getOptAmount("cashin_min_amount", db.fiatCurrency!!), cashout_ratio = it.getOptDecimal("cashout_ratio"), cashout_fee = it.getOptAmount("cashout_fee", db.fiatCurrency), cashout_rounding_mode = it.getOptEnum("cashout_rounding_mode"), cashout_min_amount = it.getOptAmount("cashout_min_amount", db.bankCurrency), ) } } /** Get a page of conversion rate classes */ suspend fun pageClass(params: ClassParams): List = db.page( params.page, "conversion_rate_class_id", """ SELECT name ,description ,(cashin_ratio).val as cashin_ratio_val, (cashin_ratio).frac as cashin_ratio_frac ,(cashin_fee).val as cashin_fee_val, (cashin_fee).frac as cashin_fee_frac ,(cashin_min_amount).val as cashin_min_amount_val, (cashin_min_amount).frac as cashin_min_amount_frac ,cashin_rounding_mode ,(cashout_ratio).val as cashout_ratio_val, (cashout_ratio).frac as cashout_ratio_frac ,(cashout_fee).val as cashout_fee_val, (cashout_fee).frac as cashout_fee_frac ,(cashout_min_amount).val as cashout_min_amount_val, (cashout_min_amount).frac as cashout_min_amount_frac ,cashout_rounding_mode ,(SELECT count(*) FROM bank_accounts WHERE bank_accounts.conversion_rate_class_id=conversion_rate_classes.conversion_rate_class_id) as num_users ,conversion_rate_class_id FROM conversion_rate_classes WHERE ${if (params.nameFilter != null) "name ILIKE ? AND" else ""} """, { if (params.nameFilter != null) { bind(params.nameFilter) } } ) { ConversionRateClass( name = it.getString("name"), description = it.getString("description"), conversion_rate_class_id = it.getLong("conversion_rate_class_id"), num_users = it.getInt("num_users"), cashin_ratio = it.getOptDecimal("cashin_ratio"), cashin_fee = it.getOptAmount("cashin_fee", db.bankCurrency), cashin_rounding_mode = it.getOptEnum("cashin_rounding_mode"), cashin_min_amount = it.getOptAmount("cashin_min_amount", db.fiatCurrency!!), cashout_ratio = it.getOptDecimal("cashout_ratio"), cashout_fee = it.getOptAmount("cashout_fee", db.fiatCurrency), cashout_rounding_mode = it.getOptEnum("cashout_rounding_mode"), cashout_min_amount = it.getOptAmount("cashout_min_amount", db.bankCurrency), ) } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt0000664000175000017500000001625115156463305027365 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import kotlinx.coroutines.flow.Flow import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.bank.* import tech.libeufin.common.db.* import tech.libeufin.common.* import java.util.* import java.util.concurrent.ConcurrentHashMap private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-db") class Database( dbConfig: DatabaseConfig, internal val bankCurrency: String, internal val fiatCurrency: String?, internal val ctx: BankPaytoCtx ): DbPool(dbConfig, "libeufin-bank") { // DAOs val cashout = CashoutDAO(this) val withdrawal = WithdrawalDAO(this) val exchange = ExchangeDAO(this) val conversion = ConversionDAO(this) val account = AccountDAO(this) val transaction = TransactionDAO(this) val token = TokenDAO(this) val tan = TanDAO(this) val gc = GcDAO(this) val transfer = TransferDAO(this) // Transaction flows, the keys are the bank account id private val bankTxFlows = ConcurrentHashMap>() private val outgoingTxFlows = ConcurrentHashMap>() private val incomingTxFlows = ConcurrentHashMap>() private val revenueTxFlows = ConcurrentHashMap>() // Withdrawal confirmation flow, the key is the public withdrawal UUID private val withdrawalFlow = ConcurrentHashMap>() init { watchNotifications(pgSource, "libeufin_bank", LoggerFactory.getLogger("libeufin-bank-db-watcher"), mapOf( "bank_tx" to { val (debtor, creditor, debitRow, creditRow) = it.split(' ', limit = 4).map { it.toLong() } bankTxFlows[debtor]?.run { flow.emit(debitRow) } bankTxFlows[creditor]?.run { flow.emit(creditRow) } revenueTxFlows[creditor]?.run { flow.emit(creditRow) } }, "bank_outgoing_tx" to { val (account, merchant, debitRow, creditRow) = it.split(' ', limit = 4).map { it.toLong() } outgoingTxFlows[account]?.run { flow.emit(debitRow) } }, "bank_incoming_tx" to { val (account, row) = it.split(' ', limit = 2).map { it.toLong() } incomingTxFlows[account]?.run { flow.emit(row) } }, "bank_withdrawal_status" to { val raw = it.split(' ', limit = 2) val uuid = UUID.fromString(raw[0]) val status = WithdrawalStatus.valueOf(raw[1]) withdrawalFlow[uuid]?.run { flow.emit(status) } } )) } /** Listen for new bank transactions for [account] */ suspend fun listenBank(account: Long, lambda: suspend (Flow) -> R): R = listen(bankTxFlows, account, lambda) /** Listen for new taler outgoing transactions from [exchange] */ suspend fun listenOutgoing(exchange: Long, lambda: suspend (Flow) -> R): R = listen(outgoingTxFlows, exchange, lambda) /** Listen for new taler incoming transactions to [exchange] */ suspend fun listenIncoming(exchange: Long, lambda: suspend (Flow) -> R): R = listen(incomingTxFlows, exchange, lambda) /** Listen for new incoming transactions to [merchant] */ suspend fun listenRevenue(merchant: Long, lambda: suspend (Flow) -> R): R = listen(revenueTxFlows, merchant, lambda) /** Listen for new withdrawal confirmations */ suspend fun listenWithdrawals(withdrawal: UUID, lambda: suspend (Flow) -> R): R = listen(withdrawalFlow, withdrawal, lambda) suspend fun monitor( params: MonitorParams ): MonitorResponse = serializable( """ SELECT cashin_count ,(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_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 ,taler_out_count ,(taler_out_volume).val as taler_out_volume_val ,(taler_out_volume).frac as taler_out_volume_frac FROM stats_get_frame(?::timestamp, ?::stat_timeframe_enum) """ ) { bind(params.date) bind(params.timeframe) oneOrNull { fiatCurrency?.run { MonitorWithConversion( cashinCount = it.getLong("cashin_count"), cashinRegionalVolume = it.getAmount("cashin_regional_volume", bankCurrency), cashinFiatVolume = it.getAmount("cashin_fiat_volume", this), cashoutCount = it.getLong("cashout_count"), cashoutRegionalVolume = it.getAmount("cashout_regional_volume", bankCurrency), cashoutFiatVolume = it.getAmount("cashout_fiat_volume", this), talerInCount = it.getLong("taler_in_count"), talerInVolume = it.getAmount("taler_in_volume", bankCurrency), talerOutCount = it.getLong("taler_out_count"), talerOutVolume = it.getAmount("taler_out_volume", bankCurrency), ) } ?: MonitorNoConversion( talerInCount = it.getLong("taler_in_count"), talerInVolume = it.getAmount("taler_in_volume", bankCurrency), talerOutCount = it.getLong("taler_out_count"), talerOutVolume = it.getAmount("taler_out_volume", bankCurrency), ) } ?: throw internalServerError("No result from DB procedure stats_get_frame") } } /** Result status of withdrawal or cashout operation abortion */ enum class AbortResult { Success, UnknownOperation, AlreadyConfirmed }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt0000664000175000017500000007404715156463305027610 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2025, 2024, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import tech.libeufin.bank.* import tech.libeufin.common.* import tech.libeufin.common.crypto.* import tech.libeufin.common.db.* import java.time.Instant import java.sql.SQLException import org.postgresql.util.PSQLState /** Data access logic for accounts */ class AccountDAO(private val db: Database) { /** Result status of account creation */ sealed interface AccountCreationResult { data class Success(val payto: String): AccountCreationResult data object UsernameReuse: AccountCreationResult data object PayToReuse: AccountCreationResult data object UnknownConversionClass: AccountCreationResult data object BonusBalanceInsufficient: AccountCreationResult } /** Create new account */ suspend fun create( username: String, password: String, name: String, email: String?, phone: String?, cashoutPayto: IbanPayto?, internalPayto: Payto, isPublic: Boolean, isTalerExchange: Boolean, maxDebt: TalerAmount, bonus: TalerAmount, tanChannels: Set, // Whether to check [internalPaytoUri] for idempotency checkPaytoIdempotent: Boolean, pwCrypto: PwCrypto, conversionRateClassId: Long? ): AccountCreationResult = db.serializableTransaction { conn -> val timestamp = Instant.now() val idempotent = conn.withStatement(""" SELECT password_hash, name=? AND email IS NOT DISTINCT FROM ? AND phone IS NOT DISTINCT FROM ? AND cashout_payto IS NOT DISTINCT FROM ? AND tan_channels = sort_uniq(?::tan_enum[]) AND (NOT ? OR internal_payto=?) AND is_public=? AND is_taler_exchange=? AND max_debt=(?,?)::taler_amount AND conversion_rate_class_id IS NOT DISTINCT FROM ? ,internal_payto, name FROM customers JOIN bank_accounts ON customer_id=owning_customer_id WHERE username=? """) { bind(name) bind(email) bind(phone) bind(cashoutPayto?.simple()) bind(tanChannels.toTypedArray()) bind(checkPaytoIdempotent) bind(internalPayto.canonical) bind(isPublic) bind(isTalerExchange) bind(maxDebt) bind(conversionRateClassId) bind(username) oneOrNull { Pair( pwCrypto.checkpw(password, it.getString(1)).match && it.getBoolean(2), it.getBankPayto("internal_payto", "name", db.ctx) ) } } if (idempotent != null) { if (idempotent.first) { AccountCreationResult.Success(idempotent.second) } else { AccountCreationResult.UsernameReuse } } else { if (internalPayto is IbanPayto) conn.withStatement (""" INSERT INTO iban_history( iban ,creation_time ) VALUES (?, ?) """) { bind(internalPayto.iban.value) bind(timestamp) if (!executeUpdateViolation()) { conn.rollback() return@serializableTransaction AccountCreationResult.PayToReuse } } val customerId = conn.withStatement(""" INSERT INTO customers ( username ,password_hash ,name ,email ,phone ,cashout_payto ,tan_channels ) VALUES (?, ?, ?, ?, ?, ?, sort_uniq(?::tan_enum[])) RETURNING customer_id """ ) { bind(username) bind(pwCrypto.hashpw(password)) bind(name) bind(email) bind(phone) bind(cashoutPayto?.simple()) bind(tanChannels.toTypedArray()) one { it.getLong("customer_id") } } conn.withStatement(""" INSERT INTO bank_accounts( internal_payto ,owning_customer_id ,is_public ,is_taler_exchange ,max_debt ,conversion_rate_class_id ) VALUES (?, ?, ?, ?, (?, ?)::taler_amount, ?) """) { bind(internalPayto.canonical) bind(customerId) bind(isPublic) bind(isTalerExchange) bind(maxDebt) bind(conversionRateClassId) try { executeUpdate() } catch (e: SQLException) { logger.debug(e.message) if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) { conn.rollback() return@serializableTransaction AccountCreationResult.PayToReuse } else if (e.sqlState == PSQLState.FOREIGN_KEY_VIOLATION.state) { conn.rollback() return@serializableTransaction AccountCreationResult.UnknownConversionClass } throw e } } if (bonus.value != 0L || bonus.frac != 0) { conn.withStatement(""" SELECT out_balance_insufficient FROM bank_transaction(?,'admin','bonus',(?,?)::taler_amount,?,true,NULL,NULL,NULL,NULL, NULL, NULL, NULL) """) { bind(internalPayto.canonical) bind(bonus) bind(timestamp) one { when { it.getBoolean("out_balance_insufficient") -> { conn.rollback() AccountCreationResult.BonusBalanceInsufficient } else -> AccountCreationResult.Success(internalPayto.bank(name, db.ctx)) } } } } else { AccountCreationResult.Success(internalPayto.bank(name, db.ctx)) } } } /** Result status of account deletion */ enum class AccountDeletionResult { Success, UnknownAccount, BalanceNotZero, TanRequired } /** Delete account [username] */ suspend fun delete( username: String, is2fa: Boolean ): AccountDeletionResult = db.serializable( """ SELECT out_not_found, out_balance_not_zero, out_tan_required FROM account_delete(?,?,?) """ ) { bind(username) bind(Instant.now()) bind(is2fa) one { when { it.getBoolean("out_not_found") -> AccountDeletionResult.UnknownAccount it.getBoolean("out_balance_not_zero") -> AccountDeletionResult.BalanceNotZero it.getBoolean("out_tan_required") -> AccountDeletionResult.TanRequired else -> AccountDeletionResult.Success } } } /** Result status of customer account patch */ sealed interface AccountPatchResult { data object UnknownAccount: AccountPatchResult data object NonAdminName: AccountPatchResult data object NonAdminCashout: AccountPatchResult data object NonAdminDebtLimit: AccountPatchResult data object NonAdminConversionRateClass: AccountPatchResult data object UnknownConversionClass: AccountPatchResult data object MissingTanInfo: AccountPatchResult data class Challenges(val validations: Tans): AccountPatchResult data object Success: AccountPatchResult } /** Change account [username] information */ suspend fun reconfig( username: String, req: AccountReconfiguration, isAdmin: Boolean, is2fa: Boolean, allowEditName: Boolean, allowEditCashout: Boolean ): AccountPatchResult = db.serializableTransaction { conn -> val name = req.name val cashoutPayto = req.cashout_payto_uri val email = req.contact_data?.email ?: Option.None val phone = req.contact_data?.phone ?: Option.None val tan_channels = req.channels val isPublic = req.is_public val debtLimit = req.debit_threshold val conversionRateClassId = req.conversion_rate_class_id val channels = req.channels.get() val checkName = !isAdmin && !allowEditName && name != null val checkCashout = !isAdmin && !allowEditCashout && cashoutPayto.isSome() val checkDebtLimit = !isAdmin && debtLimit != null val checkConversionRateClass = !isAdmin && conversionRateClassId.isSome() data class CurrentAccount( val id: Long, override val channels: Set, override val email: String?, override val phone: String?, val name: String, val cashoutPayTo: String?, val debtLimit: TalerAmount, val conversionRateClassId: Long? ): TanInfo // Get user ID and current data val curr = conn.withStatement(""" SELECT customer_id, tan_channels, phone, email, name, cashout_payto ,(max_debt).val AS max_debt_val ,(max_debt).frac AS max_debt_frac ,conversion_rate_class_id FROM customers JOIN bank_accounts ON customer_id=owning_customer_id WHERE username=? AND deleted_at IS NULL """) { bind(username) oneOrNull { CurrentAccount( id = it.getLong("customer_id"), channels = it.getEnumSet("tan_channels"), phone = it.getString("phone"), email = it.getString("email"), name = it.getString("name"), cashoutPayTo = it.getOptIbanPayto("cashout_payto")?.simple(), debtLimit = it.getAmount("max_debt", db.bankCurrency), conversionRateClassId = it.getOptLong("conversion_rate_class_id"), ) } ?: return@serializableTransaction AccountPatchResult.UnknownAccount } // Check tan info val validations = req.requiredValidation(curr) // Check performed 2fa check if (!isAdmin && !is2fa) { // Check if mfa is required if (curr.channels.isNotEmpty()) { val tans = curr.mfa; if (tans.size == 1) { // Perform mfa and validation at the same time return@serializableTransaction AccountPatchResult.Challenges(validations + tans) } else { return@serializableTransaction AccountPatchResult.Challenges(emptyList()) } } // Check if validation is required if (validations.isNotEmpty()) { return@serializableTransaction AccountPatchResult.Challenges(validations) } } // Cashout payto without a receiver-name val simpleCashoutPayto = cashoutPayto.get()?.simple() // Check reconfig rights if (checkName && name != curr.name) return@serializableTransaction AccountPatchResult.NonAdminName if (checkCashout && simpleCashoutPayto != curr.cashoutPayTo) return@serializableTransaction AccountPatchResult.NonAdminCashout if (checkDebtLimit && debtLimit != curr.debtLimit) return@serializableTransaction AccountPatchResult.NonAdminDebtLimit if (checkConversionRateClass && conversionRateClassId.get() != curr.conversionRateClassId) return@serializableTransaction AccountPatchResult.NonAdminConversionRateClass try { // Update bank info conn.dynamicUpdate( "bank_accounts", sequence { if (isPublic != null) yield("is_public=?") if (debtLimit != null) yield("max_debt=(?, ?)::taler_amount") conversionRateClassId.some { yield("conversion_rate_class_id=?") } }, "WHERE owning_customer_id = ?" ) { isPublic?.let { bind(it) } debtLimit?.let { bind(it) } conversionRateClassId?.some { bind(it) } bind(curr.id) } } catch (e: SQLException) { logger.debug(e.message) if (e.sqlState == PSQLState.FOREIGN_KEY_VIOLATION.state) { conn.rollback() return@serializableTransaction AccountPatchResult.UnknownConversionClass } throw e } // Update customer info conn.dynamicUpdate( "customers", sequence { cashoutPayto.some { yield("cashout_payto=?") } phone.some { yield("phone=?") } email.some { yield("email=?") } tan_channels.some { yield("tan_channels=sort_uniq(?::tan_enum[])") } name?.let { yield("name=?") } }, "WHERE customer_id = ?" ) { cashoutPayto.some { bind(simpleCashoutPayto) } phone.some { bind(it) } email.some { bind(it) } tan_channels.some { bind(it.toTypedArray()) } name?.let { bind(it) } bind(curr.id) } // Invalidate current challenges if (validations.isNotEmpty()) { conn.withStatement("UPDATE tan_challenges SET expiration_date=0 WHERE customer=?") { bind(curr.id) executeUpdate() } } AccountPatchResult.Success } /** Result status of customer account auth patch */ enum class AccountPatchAuthResult { UnknownAccount, OldPasswordMismatch, TanRequired, Success } /** Change account [username] password to [newPw] if current match [oldPw] */ suspend fun reconfigPassword( username: String, newPw: Password, oldPw: String?, is2fa: Boolean, pwCrypto: PwCrypto ): AccountPatchAuthResult = db.serializableTransaction { conn -> val (customerId, currentPwh, tanRequired) = conn.withStatement(""" SELECT customer_id, password_hash, NOT ? AND cardinality(tan_channels) > 0 FROM customers WHERE username=? AND deleted_at IS NULL """) { bind(is2fa) bind(username) oneOrNull { Triple(it.getLong(1), it.getString(2), it.getBoolean(3)) } ?: return@serializableTransaction AccountPatchAuthResult.UnknownAccount } if (oldPw != null && !pwCrypto.checkpw(oldPw, currentPwh).match) { AccountPatchAuthResult.OldPasswordMismatch } else if (tanRequired) { AccountPatchAuthResult.TanRequired } else { val newPwh = pwCrypto.hashpw(newPw.pw) conn.withStatement("UPDATE customers SET password_hash=?, token_creation_counter=0 WHERE customer_id=?") { bind(newPwh) bind(customerId) executeUpdate() } AccountPatchAuthResult.Success } } /** Result status of customer account password check */ sealed interface CheckPasswordResult { data object UnknownAccount: CheckPasswordResult data object PasswordMismatch: CheckPasswordResult data object Locked: CheckPasswordResult data class Success(val info: BankInfo): CheckPasswordResult } /** Check password of account [username] against [pw], rehashing it if outdated and returning info */ suspend fun checkPassword(username: String, pw: String, pwCrypto: PwCrypto): CheckPasswordResult { // Get user current password hash val res = db.serializable( """ SELECT username, password_hash, token_creation_counter, bank_account_id, internal_payto, is_taler_exchange, name, tan_channels, email, phone FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username=? AND deleted_at IS NULL """ ) { bind(username) oneOrNull { val info = BankInfo( username = it.getString("username"), payto = it.getBankPayto("internal_payto", "name", db.ctx), bankAccountId = it.getLong("bank_account_id"), isTalerExchange = it.getBoolean("is_taler_exchange"), channels = it.getEnumSet("tan_channels"), phone = it.getString("phone"), email = it.getString("email") ) Triple(info, it.getString("password_hash"), it.getInt("token_creation_counter")) } } if (res == null) return CheckPasswordResult.UnknownAccount val (info, currentPwh, tokenCreationCounter) = res // Check locked if (tokenCreationCounter >= MAX_TOKEN_CREATION_ATTEMPTS) return CheckPasswordResult.Locked // Check password val check = pwCrypto.checkpw(pw, currentPwh) if (!check.match) return CheckPasswordResult.PasswordMismatch // Reshah if outdated if (check.outdated) { val newPwh = pwCrypto.hashpw(pw) db.serializable( "UPDATE customers SET password_hash=? where username=? AND password_hash=?" ) { bind(newPwh) bind(username) bind(currentPwh) executeUpdate() } } return CheckPasswordResult.Success(info) } /** Get bank info of account [username] */ suspend fun bankInfo(username: String): BankInfo? = db.serializable( """ SELECT bank_account_id, internal_payto, name, is_taler_exchange, tan_channels, email, phone FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username=? """ ) { bind(username) oneOrNull { BankInfo( username = username, payto = it.getBankPayto("internal_payto", "name", db.ctx), bankAccountId = it.getLong("bank_account_id"), isTalerExchange = it.getBoolean("is_taler_exchange"), channels = it.getEnumSet("tan_channels"), phone = it.getString("phone"), email = it.getString("email") ) } } /** Check bank info of account [payto] */ suspend fun checkInfo(payto: IbanPayto): AccountInfo? = db.serializable( """ SELECT FROM bank_accounts WHERE internal_payto=? """ ) { bind(payto.canonical) oneOrNull { AccountInfo() } } /** Get data of account [username] */ suspend fun get(username: String): AccountData? = db.serializable( """ SELECT customers.name ,email ,phone ,tan_channels ,cashout_payto ,internal_payto ,(balance).val AS balance_val ,(balance).frac AS balance_frac ,has_debt ,(max_debt).val AS max_debt_val ,(max_debt).frac AS max_debt_frac ,is_public ,is_taler_exchange ,CASE WHEN deleted_at IS NOT NULL THEN 'deleted' WHEN token_creation_counter > ? THEN 'locked' ELSE 'active' END as status, conversion_rate_class_id, (cashin_ratio).val as cashin_ratio_val, (cashin_ratio).frac as cashin_ratio_frac, (cashin_fee).val as cashin_fee_val, (cashin_fee).frac as cashin_fee_frac, (cashin_tiny_amount).val as cashin_tiny_amount_val, (cashin_tiny_amount).frac as cashin_tiny_amount_frac, (cashin_min_amount).val as cashin_min_amount_val, (cashin_min_amount).frac as cashin_min_amount_frac, cashin_rounding_mode, (cashout_ratio).val as cashout_ratio_val, (cashout_ratio).frac as cashout_ratio_frac, (cashout_fee).val as cashout_fee_val, (cashout_fee).frac as cashout_fee_frac, (cashout_tiny_amount).val as cashout_tiny_amount_val, (cashout_tiny_amount).frac as cashout_tiny_amount_frac, (cashout_min_amount).val as cashout_min_amount_val, (cashout_min_amount).frac as cashout_min_amount_frac, cashout_rounding_mode FROM customers JOIN bank_accounts ON customer_id=owning_customer_id CROSS JOIN LATERAL get_conversion_class_rate(conversion_rate_class_id) WHERE username=? """ ) { bind(MAX_TOKEN_CREATION_ATTEMPTS) bind(username) oneOrNull { val name = it.getString("name") val status: AccountStatus = it.getEnum("status") val isTalerExchange = it.getBoolean("is_taler_exchange") val channels: Set = it.getEnumSet("tan_channels") AccountData( name = name, contact_data = ChallengeContactData( email = Option.Some(it.getString("email")), phone = Option.Some(it.getString("phone")) ), tan_channel = channels.firstOrNull(), tan_channels = channels, cashout_payto_uri = it.getOptIbanPayto("cashout_payto")?.full(name), payto_uri = it.getBankPayto("internal_payto", "name", db.ctx), balance = Balance( amount = it.getAmount("balance", db.bankCurrency), credit_debit_indicator = if (it.getBoolean("has_debt")) { CreditDebitInfo.debit } else { CreditDebitInfo.credit } ), debit_threshold = it.getAmount("max_debt", db.bankCurrency), is_public = it.getBoolean("is_public"), is_taler_exchange = isTalerExchange, status = status, is_locked = status == AccountStatus.locked, conversion_rate = ConversionDAO.userRate(db, it, username,isTalerExchange), conversion_rate_class_id = it.getOptLong("conversion_rate_class_id") ) } } /** Get a page of all public accounts */ suspend fun pagePublic(params: AccountParams): List = db.page( params.page, "bank_account_id", """ SELECT (balance).val AS balance_val, (balance).frac AS balance_frac, has_debt, internal_payto, username, is_taler_exchange, name, bank_account_id FROM bank_accounts JOIN customers ON owning_customer_id = customer_id WHERE is_public=true AND ${if (params.usernameFilter != null) "name ILIKE ? AND" else ""} deleted_at IS NULL AND """, { if (params.usernameFilter != null) { bind(params.usernameFilter) } } ) { PublicAccount( username = it.getString("username"), row_id = it.getLong("bank_account_id"), payto_uri = it.getBankPayto("internal_payto", "name", db.ctx), balance = Balance( amount = it.getAmount("balance", db.bankCurrency), credit_debit_indicator = if (it.getBoolean("has_debt")) { CreditDebitInfo.debit } else { CreditDebitInfo.credit } ), is_taler_exchange = it.getBoolean("is_taler_exchange") ) } /** Get a page of accounts */ suspend fun pageAdmin(params: AccountParams): List = db.page( params.page, "bank_account_id", """ SELECT username ,name ,(balance).val AS balance_val ,(balance).frac AS balance_frac ,has_debt AS balance_has_debt ,(max_debt).val as max_debt_val ,(max_debt).frac as max_debt_frac ,is_public ,is_taler_exchange ,internal_payto ,bank_account_id ,CASE WHEN deleted_at IS NOT NULL THEN 'deleted' WHEN token_creation_counter > ? THEN 'locked' ELSE 'active' END as status, conversion_rate_class_id, (cashin_ratio).val as cashin_ratio_val, (cashin_ratio).frac as cashin_ratio_frac, (cashin_fee).val as cashin_fee_val, (cashin_fee).frac as cashin_fee_frac, (cashin_tiny_amount).val as cashin_tiny_amount_val, (cashin_tiny_amount).frac as cashin_tiny_amount_frac, (cashin_min_amount).val as cashin_min_amount_val, (cashin_min_amount).frac as cashin_min_amount_frac, cashin_rounding_mode, (cashout_ratio).val as cashout_ratio_val, (cashout_ratio).frac as cashout_ratio_frac, (cashout_fee).val as cashout_fee_val, (cashout_fee).frac as cashout_fee_frac, (cashout_tiny_amount).val as cashout_tiny_amount_val, (cashout_tiny_amount).frac as cashout_tiny_amount_frac, (cashout_min_amount).val as cashout_min_amount_val, (cashout_min_amount).frac as cashout_min_amount_frac, cashout_rounding_mode FROM bank_accounts JOIN customers ON owning_customer_id = customer_id CROSS JOIN LATERAL get_conversion_class_rate(conversion_rate_class_id) WHERE ${if (params.usernameFilter != null) "name ILIKE ? AND" else ""} ${when (params.conversionRateClassId) { null -> "" 0L -> "conversion_rate_class_id IS NULL AND" else -> "conversion_rate_class_id=? AND" }} """, { bind(MAX_TOKEN_CREATION_ATTEMPTS) if (params.usernameFilter != null) { bind(params.usernameFilter) } if (params.conversionRateClassId != null && params.conversionRateClassId != 0L) { bind(params.conversionRateClassId) } } ) { val status: AccountStatus = it.getEnum("status") val isTalerExchange = it.getBoolean("is_taler_exchange") val username = it.getString("username") AccountMinimalData( username = username, row_id = it.getLong("bank_account_id"), name = it.getString("name"), balance = Balance( amount = it.getAmount("balance", db.bankCurrency), credit_debit_indicator = if (it.getBoolean("balance_has_debt")) { CreditDebitInfo.debit } else { CreditDebitInfo.credit } ), debit_threshold = it.getAmount("max_debt", db.bankCurrency), is_public = it.getBoolean("is_public"), is_taler_exchange = isTalerExchange, payto_uri = it.getBankPayto("internal_payto", "name", db.ctx), status = status, is_locked = status == AccountStatus.locked, conversion_rate = ConversionDAO.userRate(db, it, username, isTalerExchange), conversion_rate_class_id = it.getOptLong("conversion_rate_class_id") ) } } /** List all new tan channels that need to be validated */ fun AccountReconfiguration.requiredValidation(current: TanInfo): Tans { // Tan channels are either the new ones or the current one val channels = this.channels.get() ?: current.channels val validated = current.mfa return channels.mapNotNull { channel -> // Info are either the new one or the current ones val info = when (channel) { TanChannel.sms -> this.contact_data?.phone?.get() ?: current.phone TanChannel.email -> this.contact_data?.email?.get() ?: current.email } if (info == null) { throw conflict( "missing info for tan channel $channel", TalerErrorCode.BANK_MISSING_TAN_INFO ) } val tan = Pair(channel, info) // Check if tan is already used and therefore already validated if (validated.contains(tan)) null else tan } } libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/GcDAO.kt0000664000175000017500000000617015173736052026536 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import tech.libeufin.common.db.withStatement import tech.libeufin.common.micros import java.time.Duration import java.time.Instant /** Data access logic for garbage collection */ class GcDAO(private val db: Database) { /** Run garbage collection */ suspend fun collect( timestamp: Instant, abortAfter: Duration, cleanAfter: Duration, deleteAfter: Duration ) = db.conn { conn -> val abortAfterMicro = timestamp.minus(abortAfter).micros() val cleanAfterMicro = timestamp.minus(cleanAfter).micros() val deleteAfterMicro = timestamp.minus(deleteAfter).micros() // Abort pending operations conn.withStatement( """ UPDATE taler_withdrawal_operations SET aborted = true WHERE creation_date < ? AND NOT EXISTS( SELECT FROM prepared_transfers JOIN taler_withdrawal_operations USING (withdrawal_id) ) """ ) { bind(abortAfterMicro) executeUpdate() } // Clean aborted operations, expired challenges and expired tokens for (smt in listOf( """DELETE FROM taler_withdrawal_operations WHERE aborted = true AND creation_date < ? AND NOT EXISTS( SELECT FROM prepared_transfers JOIN taler_withdrawal_operations USING (withdrawal_id) )""", "DELETE FROM tan_challenges WHERE expiration_date < ?", "DELETE FROM bearer_tokens WHERE expiration_time < ?" )) { conn.withStatement(smt) { bind(cleanAfterMicro) executeUpdate() } } // Delete old bank transactions, linked operations are deleted by CASCADE conn.withStatement( "DELETE FROM bank_account_transactions WHERE transaction_date < ?" ) { bind(deleteAfterMicro) executeUpdate() } // Hard delete soft deleted customer without bank transactions, bank account are deleted by CASCADE conn.withStatement(""" DELETE FROM customers WHERE deleted_at IS NOT NULL AND NOT EXISTS( SELECT FROM bank_account_transactions NATURAL JOIN bank_accounts WHERE owning_customer_id=customer_id ) """) { executeUpdate() } // TODO clean stats } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt0000664000175000017500000002066615156463305030477 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.bank.BankAccountTransactionInfo import tech.libeufin.common.* import tech.libeufin.common.db.* import java.sql.Types import java.time.Instant private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-tx-dao") /** Data access logic for transactions */ class TransactionDAO(private val db: Database) { /** Result status of bank transaction creation */ sealed interface BankTransactionResult { data class Success(val id: Long): BankTransactionResult data object UnknownCreditor: BankTransactionResult data object AdminCreditor: BankTransactionResult data object UnknownDebtor: BankTransactionResult data object BothPartySame: BankTransactionResult data object BalanceInsufficient: BankTransactionResult data object BadAmount: BankTransactionResult data object TanRequired: BankTransactionResult data object RequestUidReuse: BankTransactionResult } /** Create a new transaction */ suspend fun create( creditAccountPayto: Payto, debitAccountUsername: String, subject: String, amount: TalerAmount, timestamp: Instant, is2fa: Boolean, requestUid: ShortHashCode?, wireTransferFees: TalerAmount, minAmount: TalerAmount, maxAmount: TalerAmount ): BankTransactionResult { val (type: IncomingType?, metadata: EddsaPublicKey?, bounceCause: String?) = runCatching { parseIncomingSubject(subject) }.fold( onSuccess = { metadata -> if (metadata is IncomingSubject.AdminBalanceAdjust) { Triple(null, null, "unsupported admin balance adjust") } else { Triple(metadata.type, metadata.key, null) } }, onFailure = { e -> Triple(null, null, "malformed metadata - ${e.message}") } ) return db.serializable(""" SELECT out_creditor_not_found ,out_debtor_not_found ,out_same_account ,out_balance_insufficient ,out_bad_amount ,out_request_uid_reuse ,out_tan_required ,out_credit_bank_account_id ,out_debit_bank_account_id ,out_credit_row_id ,out_debit_row_id ,out_creditor_is_exchange ,out_debtor_is_exchange ,out_creditor_admin ,out_idempotent FROM bank_transaction(?,?,?,(?,?)::taler_amount,?,?,?,(?,?)::taler_amount,(?,?)::taler_amount,(?,?)::taler_amount,?::taler_incoming_type,?,?) """ ) { bind(creditAccountPayto.canonical) bind(debitAccountUsername) bind(subject) bind(amount) bind(timestamp) bind(is2fa) bind(requestUid) bind(wireTransferFees) bind(minAmount) bind(maxAmount) bind(type) bind(metadata) bind(bounceCause) one { when { it.getBoolean("out_creditor_not_found") -> BankTransactionResult.UnknownCreditor it.getBoolean("out_debtor_not_found") -> BankTransactionResult.UnknownDebtor it.getBoolean("out_same_account") -> BankTransactionResult.BothPartySame it.getBoolean("out_balance_insufficient") -> BankTransactionResult.BalanceInsufficient it.getBoolean("out_bad_amount") -> BankTransactionResult.BadAmount it.getBoolean("out_creditor_admin") -> BankTransactionResult.AdminCreditor it.getBoolean("out_request_uid_reuse") -> BankTransactionResult.RequestUidReuse it.getBoolean("out_idempotent") -> BankTransactionResult.Success(it.getLong("out_debit_row_id")) it.getBoolean("out_tan_required") -> BankTransactionResult.TanRequired else -> BankTransactionResult.Success(it.getLong("out_debit_row_id")) } } } } /** Get transaction [rowId] owned by [username] */ suspend fun get(rowId: Long, username: String): BankAccountTransactionInfo? = db.serializable( """ SELECT creditor_payto ,creditor_name ,debtor_payto ,debtor_name ,subject ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,transaction_date ,direction ,bank_transaction_id FROM bank_account_transactions JOIN bank_accounts ON bank_account_transactions.bank_account_id=bank_accounts.bank_account_id JOIN customers ON customer_id=owning_customer_id WHERE bank_transaction_id=? AND username=? """ ) { bind(rowId) bind(username) oneOrNull { BankAccountTransactionInfo( creditor_payto_uri = it.getBankPayto("creditor_payto", "creditor_name", db.ctx), debtor_payto_uri = it.getBankPayto("debtor_payto", "debtor_name", db.ctx), amount = it.getAmount("amount", db.bankCurrency), direction = it.getEnum("direction"), subject = it.getString("subject"), date = it.getTalerTimestamp("transaction_date"), row_id = it.getLong("bank_transaction_id") ) } } /** Pool [accountId] transactions history */ suspend fun pollHistory( params: HistoryParams, accountId: Long ): List { return db.poolHistory(params, accountId, db::listenBank, """ SELECT bank_transaction_id ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,debtor_payto ,debtor_name ,creditor_payto ,creditor_name ,subject ,direction FROM bank_account_transactions WHERE """) { BankAccountTransactionInfo( row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), creditor_payto_uri = it.getBankPayto("creditor_payto", "creditor_name", db.ctx), debtor_payto_uri = it.getBankPayto("debtor_payto", "debtor_name", db.ctx), amount = it.getAmount("amount", db.bankCurrency), subject = it.getString("subject"), direction = it.getEnum("direction") ) } } /** Query [accountId] history of incoming transactions to its account */ suspend fun revenueHistory( params: HistoryParams, accountId: Long ): List = db.poolHistory(params, accountId, db::listenRevenue, """ SELECT bank_transaction_id ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,debtor_payto ,debtor_name ,subject FROM bank_account_transactions WHERE direction='credit' AND """) { RevenueIncomingBankTransaction( row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), amount = it.getAmount("amount", db.bankCurrency), debit_account = it.getBankPayto("debtor_payto", "debtor_name", db.ctx), subject = it.getString("subject") ) } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt0000664000175000017500000003026315156463305027726 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import tech.libeufin.common.* import tech.libeufin.common.db.* import java.time.Instant /** Data access logic for exchange specific logic */ class ExchangeDAO(private val db: Database) { /** Query [exchangeId] history of taler incoming transactions */ suspend fun incomingHistory( params: HistoryParams, exchangeId: Long ): List = db.poolHistory(params, exchangeId, db::listenIncoming, """ SELECT bank_transaction_id ,transaction_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,debtor_payto ,debtor_name ,type ,metadata ,authorization_pub ,authorization_sig FROM taler_exchange_incoming AS tfr JOIN bank_account_transactions AS txs ON bank_transaction=txs.bank_transaction_id WHERE """) { val type = it.getEnum("type") when (type) { IncomingType.reserve -> IncomingReserveTransaction( row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), amount = it.getAmount("amount", db.bankCurrency), debit_account = it.getBankPayto("debtor_payto", "debtor_name", db.ctx), reserve_pub = EddsaPublicKey(it.getBytes("metadata")), authorization_pub = it.getOptKey("authorization_pub"), authorization_sig = it.getOptSig("authorization_sig") ) IncomingType.kyc -> IncomingKycAuthTransaction( row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), amount = it.getAmount("amount", db.bankCurrency), debit_account = it.getBankPayto("debtor_payto", "debtor_name", db.ctx), account_pub = EddsaPublicKey(it.getBytes("metadata")), authorization_pub = it.getOptKey("authorization_pub"), authorization_sig = it.getOptSig("authorization_sig") ) IncomingType.map -> throw UnsupportedOperationException() } } /** Query [exchangeId] history of taler outgoing transactions */ suspend fun outgoingHistory( params: HistoryParams, exchangeId: Long ): List = db.poolHistory(params, exchangeId, db::listenOutgoing, """ SELECT bank_transaction_id ,transaction_date ,(txs.amount).val AS amount_val ,(txs.amount).frac AS amount_frac ,txs.creditor_payto ,txs.creditor_name ,wtid ,exchange_base_url ,transfer_operations.metadata FROM taler_exchange_outgoing AS tfr JOIN transfer_operations USING (exchange_outgoing_id) JOIN bank_account_transactions AS txs ON bank_transaction=txs.bank_transaction_id WHERE """) { OutgoingTransaction( row_id = it.getLong("bank_transaction_id"), date = it.getTalerTimestamp("transaction_date"), amount = it.getAmount("amount", db.bankCurrency), credit_account = it.getBankPayto("creditor_payto", "creditor_name", db.ctx), wtid = ShortHashCode(it.getBytes("wtid")), exchange_base_url = it.getString("exchange_base_url"), metadata = it.getString("metadata"), debit_fee = null ) } /** Result of taler transfer transaction creation */ sealed interface TransferResult { /** Transaction [id] and wire transfer [timestamp] */ data class Success(val id: Long, val timestamp: TalerTimestamp): TransferResult data object NotAnExchange: TransferResult data object UnknownExchange: TransferResult data object BothPartyAreExchange: TransferResult data object BalanceInsufficient: TransferResult data object ReserveUidReuse: TransferResult data object WtidReuse: TransferResult data object AdminCreditor: TransferResult } /** Perform a Taler transfer */ suspend fun transfer( req: TransferRequest, username: String, timestamp: Instant, conversion: Boolean ): TransferResult = db.serializable( """ SELECT out_debtor_not_found ,out_debtor_not_exchange ,out_both_exchanges ,out_request_uid_reuse ,out_wtid_reuse ,out_exchange_balance_insufficient ,out_creditor_admin ,out_tx_row_id ,out_timestamp FROM taler_transfer ( ?, ?, ?, (?,?)::taler_amount, ?, ?, ?, ?, ?, ? ); """ ) { val subject = fmtOutgoingSubject(req.wtid, req.exchange_base_url, req.metadata) bind(req.request_uid) bind(req.wtid) bind(subject) bind(req.amount) bind(req.exchange_base_url.url.toString()) bind(req.metadata) bind(req.credit_account.canonical) bind(username) bind(timestamp) bind(conversion) one { when { it.getBoolean("out_debtor_not_found") -> TransferResult.UnknownExchange it.getBoolean("out_debtor_not_exchange") -> TransferResult.NotAnExchange it.getBoolean("out_both_exchanges") -> TransferResult.BothPartyAreExchange it.getBoolean("out_exchange_balance_insufficient") -> TransferResult.BalanceInsufficient it.getBoolean("out_request_uid_reuse") -> TransferResult.ReserveUidReuse it.getBoolean("out_wtid_reuse") -> TransferResult.WtidReuse it.getBoolean("out_creditor_admin") -> TransferResult.AdminCreditor else -> TransferResult.Success( id = it.getLong("out_tx_row_id"), timestamp = it.getTalerTimestamp("out_timestamp") ) } } } /** Get status of transfer [txId] of account [exchangeId] */ suspend fun getTransfer( exchangeId: Long, txId: Long ): TransferStatus? = db.serializable( """ SELECT wtid ,exchange_base_url ,metadata ,transfer_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,creditor_payto ,status ,status_msg FROM transfer_operations WHERE transfer_operation_id=? AND exchange_id=? """ ) { bind(txId) bind(exchangeId) oneOrNull { TransferStatus( status = it.getEnum("status"), status_msg = it.getString("status_msg"), amount = it.getAmount("amount", db.bankCurrency), origin_exchange_url = it.getString("exchange_base_url"), metadata = it.getString("metadata"), wtid = ShortHashCode(it.getBytes("wtid")), credit_account = it.getBankPayto("creditor_payto", null, db.ctx), timestamp = it.getTalerTimestamp("transfer_date"), ) } } /** Get a page of transfers status of account [exchangeId] */ suspend fun pageTransfer( params: PageParams, exchangeId: Long, status: TransferStatusState? ): List = db.page( params, "transfer_operation_id", """ SELECT transfer_operation_id ,transfer_date ,(amount).val AS amount_val ,(amount).frac AS amount_frac ,creditor_payto ,status FROM transfer_operations WHERE exchange_id=? AND ${ when (status) { null -> "" else -> "status=?::transfer_status AND" } } """, { bind(exchangeId) if (status != null) { bind(status) } } ) { TransferListStatus( row_id = it.getLong("transfer_operation_id"), status = it.getEnum("status"), amount = it.getAmount("amount", db.bankCurrency), credit_account = it.getBankPayto("creditor_payto", null, db.ctx), timestamp = it.getTalerTimestamp("transfer_date"), ) } /** Result of taler add incoming transaction creation */ sealed interface AddIncomingResult { /** Transaction [id] and wire transfer [timestamp] */ data class Success(val id: Long, val timestamp: TalerTimestamp, val pending: Boolean): AddIncomingResult data object NotAnExchange: AddIncomingResult data object UnknownExchange: AddIncomingResult data object UnknownDebtor: AddIncomingResult data object BothPartyAreExchange: AddIncomingResult data object ReservePubReuse: AddIncomingResult data object UnknownMapping: AddIncomingResult data object MappingReuse: AddIncomingResult data object BalanceInsufficient: AddIncomingResult } /** Add a new taler incoming transaction */ suspend fun addIncoming( amount: TalerAmount, debitAccount: Payto, subject: String, username: String, timestamp: Instant, metadata: IncomingSubject ): AddIncomingResult = db.serializable( """ SELECT out_creditor_not_found ,out_creditor_not_exchange ,out_debtor_not_found ,out_both_exchanges ,out_reserve_pub_reuse ,out_mapping_reuse ,out_unknown_mapping ,out_debitor_balance_insufficient ,out_tx_row_id ,out_pending FROM taler_add_incoming ( ?, ?, (?,?)::taler_amount, ?, ?, ?, ?::taler_incoming_type ); """ ) { bind(metadata.key) bind(subject) bind(amount) bind(debitAccount.canonical) bind(username) bind(timestamp) bind(metadata.type) one { when { it.getBoolean("out_creditor_not_found") -> AddIncomingResult.UnknownExchange it.getBoolean("out_creditor_not_exchange") -> AddIncomingResult.NotAnExchange it.getBoolean("out_debtor_not_found") -> AddIncomingResult.UnknownDebtor it.getBoolean("out_both_exchanges") -> AddIncomingResult.BothPartyAreExchange it.getBoolean("out_debitor_balance_insufficient") -> AddIncomingResult.BalanceInsufficient it.getBoolean("out_reserve_pub_reuse") -> AddIncomingResult.ReservePubReuse it.getBoolean("out_mapping_reuse") -> AddIncomingResult.MappingReuse it.getBoolean("out_unknown_mapping") -> AddIncomingResult.UnknownMapping else -> AddIncomingResult.Success( id = it.getLong("out_tx_row_id"), timestamp = TalerTimestamp(timestamp), pending = it.getBoolean("out_pending") ) } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt0000664000175000017500000001731115122266731026722 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import tech.libeufin.bank.Operation import tech.libeufin.bank.TanChannel import tech.libeufin.common.db.* import tech.libeufin.common.* import tech.libeufin.bank.* import tech.libeufin.bank.auth.* import java.time.Duration import java.time.Instant import java.util.UUID import java.util.concurrent.TimeUnit /** Data access logic for tan challenged */ class TanDAO(private val db: Database) { /** Create a new challenge */ suspend fun new( username: String, op: Operation, hbody: Base32Crockford64B, salt: Base32Crockford16B, code: String, timestamp: Instant, retryCounter: Int, validityPeriod: Duration, tanChannel: TanChannel, tanInfo: String ): UUID = db.serializable( """ INSERT INTO tan_challenges ( hbody, salt, op, code, creation_date, expiration_date, retry_counter, customer, tan_channel, tan_info, uuid ) VALUES ( ?, ?, ?::op_enum, ?, ?, ?, ?, (SELECT customer_id FROM customers WHERE username = ? AND deleted_at IS NULL), ?::tan_enum, ?, gen_random_uuid() ) RETURNING uuid """ ) { bind(hbody) bind(salt) bind(op) bind(code) bind(timestamp) bind(timestamp.micros() + TimeUnit.MICROSECONDS.convert(validityPeriod)) bind(retryCounter) bind(username) bind(tanChannel) bind(tanInfo) one { it.getObject(1) as UUID } } /** Result of TAN challenge transmission */ sealed interface TanSendResult { data class Send( val tanInfo: String, val tanChannel: TanChannel, val tanCode: String, val expiration: TalerTimestamp ) data class Success( val expiration: TalerTimestamp, val retransmission: TalerTimestamp ): TanSendResult data object Expired: TanSendResult data object Solved: TanSendResult data object NotFound: TanSendResult data object TooMany: TanSendResult } /** Request TAN challenge transmission */ suspend fun send( uuid: UUID, timestamp: Instant, maxActive: Int ) = db.serializable( """ SELECT (confirmation_date IS NOT NULL) as solved ,retransmission_date ,expiration_date ,code ,tan_channel ,tan_info -- If this is the first time we submit this challenge check there is not too many active challenges ,(retransmission_date = 0 AND ( SELECT count(*) >= ? FROM tan_challenges as o WHERE c.customer = o.customer AND retransmission_date != 0 AND confirmation_date IS NULL AND expiration_date >= ? )) AS too_many FROM tan_challenges as c WHERE uuid = ? """ ) { bind(maxActive) bind(timestamp) bind(uuid) oneOrNull { when { it.getBoolean("solved") -> TanSendResult.Solved it.getBoolean("too_many") -> TanSendResult.TooMany else -> { val retransmission = it.getTalerTimestamp("retransmission_date") val expiration = it.getTalerTimestamp("expiration_date") if (expiration.instant.isBefore(timestamp)) { TanSendResult.Expired } else if (retransmission.instant.isBefore(timestamp)) { TanSendResult.Send( tanInfo = it.getString("tan_info"), tanChannel = it.getEnum("tan_channel"), tanCode = it.getString("code"), expiration = expiration ) } else { TanSendResult.Success( expiration = expiration, retransmission = retransmission ) } } } } ?: TanSendResult.NotFound } /** Mark TAN challenge transmission */ suspend fun markSent( uuid: UUID, retransmission: Instant ) = db.serializable( "UPDATE tan_challenges SET retransmission_date = ? WHERE uuid = ?" ) { bind(retransmission) bind(uuid) executeUpdate() } /** Result of TAN challenge solution */ sealed interface TanSolveResult { data class Success(val op: Operation, val channel: TanChannel?, val info: String?): TanSolveResult data object NotFound: TanSolveResult data object NoRetry: TanSolveResult data object Expired: TanSolveResult data object BadCode: TanSolveResult } /** Solve TAN challenge */ suspend fun solve( uuid: UUID, code: String, timestamp: Instant ) = db.serializable( """ SELECT out_ok, out_no_op, out_no_retry, out_expired, out_op, out_channel, out_info FROM tan_challenge_try(?,?,?) """ ) { bind(uuid) bind(code) bind(timestamp.micros()) one { when { it.getBoolean("out_ok") -> TanSolveResult.Success( op = it.getEnum("out_op"), channel = it.getOptEnum("out_channel"), info = it.getString("out_info") ) it.getBoolean("out_no_op") -> TanSolveResult.NotFound it.getBoolean("out_no_retry") -> TanSolveResult.NoRetry it.getBoolean("out_expired") -> TanSolveResult.Expired else -> TanSolveResult.BadCode } } } data class SolvedChallenge( val salt: Base32Crockford16B, val hbody: Base32Crockford64B, val channel: TanChannel, val info: String, val confirmed: Boolean, val op: Operation ) /** Get a TAN challenge [uuid] */ suspend fun challenge(uuids: List): List = db.serializable( """ SELECT salt, hbody, tan_channel, tan_info, op, (confirmation_date IS NOT NULL) as confirmed FROM tan_challenges WHERE uuid = ANY(?::uuid[]) """ ) { bind(uuids.toTypedArray()) all { SolvedChallenge( salt = Base32Crockford16B(it.getBytes("salt")), hbody = Base32Crockford64B(it.getBytes("hbody")), op = it.getEnum("op"), channel = it.getEnum("tan_channel"), info = it.getString("tan_info"), confirmed = it.getBoolean("confirmed") ) } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/db/TransferDAO.kt0000664000175000017500000000562415221677432027774 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.db import tech.libeufin.common.* import tech.libeufin.common.db.* import java.time.Instant import java.util.UUID /** Data access logic for transfer specific logic */ class TransferDAO(private val db: Database) { /** Result of prepared transfer registration */ sealed interface RegistrationResult { data class Success(val uuid: UUID?): RegistrationResult data object NotExchange: RegistrationResult data object ReservePubReuse: RegistrationResult data object UnknownCreditor: RegistrationResult } /** Register a prepared transfer */ suspend fun register( account: Payto, type: TransferType, accountPub: EddsaPublicKey, authPub: EddsaPublicKey, authSig: EddsaSignature, recurrent: Boolean, amount: TalerAmount, timestamp: Instant ): RegistrationResult = db.serializable( """ SELECT out_unknown_creditor, out_not_exchange, out_reserve_pub_reuse, out_withdrawal_uuid FROM register_prepared_transfers ( ?, ?::taler_incoming_type, ?, ?, ?, ?, (?, ?)::taler_amount, ?, ? ) """ ) { bind(account.canonical) bind(type) bind(accountPub) bind(authPub) bind(authSig) bind(recurrent) bind(amount) bind(timestamp) bind("Taler prepared MAP:$authPub") one { when { it.getBoolean("out_unknown_creditor") -> RegistrationResult.UnknownCreditor it.getBoolean("out_not_exchange") -> RegistrationResult.NotExchange it.getBoolean("out_reserve_pub_reuse") -> RegistrationResult.ReservePubReuse else -> RegistrationResult.Success(it.getOptObject("out_withdrawal_uuid")) } } } /** Unregister a prepared transfer */ suspend fun unregister( authorizationPub: EddsaPublicKey, timestamp: Instant ) = db.serializable( "SELECT out_found FROM delete_prepared_transfers(?,?)", { bind(authorizationPub) bind(timestamp) one { it.getBoolean(1) } } ) }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/Constants.kt0000664000175000017500000000300715156463305027243 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank import tech.libeufin.common.ConfigSource import java.time.Duration // Config val BANK_CONFIG_SOURCE = ConfigSource("libeufin", "libeufin-bank", "libeufin-bank") // TAN const val TAN_RETRY_COUNTER: Int = 3 val TAN_VALIDITY_PERIOD: Duration = Duration.ofMinutes(30) val TAN_RETRANSMISSION_PERIOD: Duration = Duration.ofMinutes(3) // Token val TOKEN_DEFAULT_DURATION: Duration = Duration.ofHours(3) // Account val RESERVED_ACCOUNTS = setOf("admin", "bank") const val IBAN_ALLOCATION_RETRY_COUNTER: Int = 5 const val MAX_TOKEN_CREATION_ATTEMPTS: Int = 5 const val MAX_ACTIVE_CHALLENGES: Int = 5 // API version const val COREBANK_API_VERSION: String = "12:0:0" const val CONVERSION_API_VERSION: String = "2:0:1" const val INTEGRATION_API_VERSION: String = "5:0:5" libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/Config.kt0000664000175000017500000002223415204341712026466 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank import kotlinx.serialization.Serializable import io.github.smiley4.schemakenerator.core.annotations.Description import tech.libeufin.bank.db.Database import tech.libeufin.common.* import tech.libeufin.common.crypto.PwCrypto import tech.libeufin.common.db.DatabaseConfig import java.nio.file.Path import java.time.Duration /** Configuration for libeufin-bank */ data class BankConfig( private val cfg: TalerConfig, val name: String, val baseUrl: BaseURL, val regionalCurrency: String, val regionalCurrencySpec: CurrencySpecification, val wireTransferFees: TalerAmount, val minAmount: TalerAmount, val maxAmount: TalerAmount, val allowRegistration: Boolean, val allowAccountDeletion: Boolean, val allowEditName: Boolean, val allowEditCashout: Boolean, val defaultDebtLimit: TalerAmount, val registrationBonus: TalerAmount, val suggestedWithdrawalExchange: String?, val allowConversion: Boolean, val fiatCurrency: String?, val fiatCurrencySpec: CurrencySpecification?, val spaPath: Path?, val tanChannels: Map>>, val payto: BankPaytoCtx, val wireMethod: WireMethod, val pwCrypto: PwCrypto, val gcAbortAfter: Duration, val gcCleanAfter: Duration, val gcDeleteAfter: Duration, val pwdCheckQuality: Boolean, val basicAuthCompat: Boolean ) { val dbCfg: DatabaseConfig by lazy { val sect = cfg.section("libeufin-bankdb-postgres") DatabaseConfig( dbConnStr = sect.stringsub("config").require(), sqlDir = sect.path("sql_dir").require() ) } val serverCfg: ServerConfig by lazy { cfg.loadServerConfig("libeufin-bank") } } @Description("Currency conversion rate configuration") @Serializable data class ConversionRate ( @Description("Ratio for converting fiat to regional currency") val cashin_ratio: DecimalNumber, @Description("Fee charged on cash-in conversions") val cashin_fee: TalerAmount, @Description("Smallest possible cash-in amount") val cashin_tiny_amount: TalerAmount, @Description("Rounding mode for cash-in conversions") val cashin_rounding_mode: RoundingMode, @Description("Minimum amount for cash-in conversions") val cashin_min_amount: TalerAmount, @Description("Ratio for converting regional currency to fiat") val cashout_ratio: DecimalNumber, @Description("Fee charged on cash-out conversions") val cashout_fee: TalerAmount, @Description("Smallest possible cash-out amount") val cashout_tiny_amount: TalerAmount, @Description("Rounding mode for cash-out conversions") val cashout_rounding_mode: RoundingMode, @Description("Minimum amount for cash-out conversions") val cashout_min_amount: TalerAmount, ) { fun check(cfg: BankConfig) { for (regionalAmount in sequenceOf(cashin_fee, cashin_tiny_amount, cashout_min_amount)) { cfg.checkRegionalCurrency(regionalAmount) } for (fiatAmount in sequenceOf(cashout_fee, cashout_tiny_amount, cashin_min_amount)) { cfg.checkFiatCurrency(fiatAmount) } if (cashout_tiny_amount.isZero()) { throw badRequest("cashout_tiny_amount must be > 0") } else if (cashin_tiny_amount.isZero()) { throw badRequest("cashin_tiny_amount must be > 0") } else if (cashout_tiny_amount.isSubCent()) { throw badRequest("Sub-cent amounts no supported by cashout, cashout_tiny_amount must be >= 0.01") } } } /** Load bank config at [configPath] */ fun bankConfig(configPath: Path?): BankConfig = BANK_CONFIG_SOURCE.fromFile(configPath).loadBankConfig() /** Run [lambda] with access to a database conn pool */ suspend fun BankConfig.withDb(lambda: suspend (Database, BankConfig) -> Unit) { Database(dbCfg, regionalCurrency, fiatCurrency, payto).use { lambda(it, this) } } private fun TalerConfig.loadBankConfig(): BankConfig = section("libeufin-bank").run { val regionalCurrency = string("currency").require() var fiatCurrency: String? = null var fiatCurrencySpec: CurrencySpecification? = null val allowConversion = boolean("allow_conversion").default(false) if (allowConversion) { fiatCurrency = string("fiat_currency").require() fiatCurrencySpec = currencySpecificationFor(fiatCurrency) } val tanChannels = buildMap { for (channel in TanChannel.entries) { path("tan_$channel").orNull()?.let { put(channel, Pair(it, jsonMap("tan_${channel}_env").orNull() ?: mapOf())) } } } val baseUrl = baseURL("base_url").require() val hostname = baseUrl.url.host val method = map("wire_type", "payment target type", mapOf( "iban" to WireMethod.IBAN, "x-taler-bank" to WireMethod.X_TALER_BANK, )).default(WireMethod.IBAN, logger, " defaulting to 'iban' but will fail in a future update") if (method == WireMethod.X_TALER_BANK) { val xhostname = string("x_taler_bank_payto_hostname").orNull() if (xhostname != null && xhostname != hostname) { logger.warn("deprecated x_taler_bank_payto_hostname '${xhostname}' does not match base_url hostname '$hostname'") } } val payto = BankPaytoCtx( bic = string("iban_payto_bic").orNull(), hostname = hostname ) val pwCrypto = map("pwd_hash_algorithm", "password hash algorithm", mapOf( "bcrypt" to json("pwd_hash_config", "bcrypt JSON config").require() )).require() val ZERO = TalerAmount.zero(regionalCurrency) val MAX = TalerAmount.max(regionalCurrency) BankConfig( cfg = this@loadBankConfig, name = string("name").default("Taler Bank"), regionalCurrency = regionalCurrency, regionalCurrencySpec = currencySpecificationFor(regionalCurrency), allowRegistration = boolean("allow_registration").default(false), allowAccountDeletion = boolean("allow_account_deletion").default(false), allowEditName = boolean("allow_edit_name").default(false), allowEditCashout = boolean("allow_edit_cashout_payto_uri").default(false), allowConversion = allowConversion, defaultDebtLimit = amount("default_debt_limit", regionalCurrency).default(ZERO), registrationBonus = amount("registration_bonus", regionalCurrency).default(ZERO), wireTransferFees = amount("wire_transfer_fees", regionalCurrency).default(ZERO), minAmount = amount("min_wire_transfer_amount", regionalCurrency).default(ZERO), maxAmount = amount("max_wire_transfer_amount", regionalCurrency).default(MAX), suggestedWithdrawalExchange = string("suggested_withdrawal_exchange").orNull(), spaPath = path("spa").orNull(), baseUrl = baseUrl, fiatCurrency = fiatCurrency, fiatCurrencySpec = fiatCurrencySpec, tanChannels = tanChannels, payto = payto, wireMethod = method, pwCrypto = pwCrypto, gcAbortAfter = duration("gc_abort_after").require(), gcCleanAfter = duration("gc_clean_after").require(), gcDeleteAfter = duration("gc_delete_after").require(), pwdCheckQuality = boolean("pwd_check").require(), basicAuthCompat = boolean("pwd_auth_compat").require() ) } private fun TalerConfig.currencySpecificationFor(currency: String): CurrencySpecification = sections.find { val section = section(it) it.startsWith("CURRENCY-") && section.boolean("enabled").require() && section.string("code").require() == currency }?.let { section(it).loadCurrencySpecification() } ?: run { logger.warn("Missing currency specification for $currency, using sane defaults") CurrencySpecification( name = currency, num_fractional_input_digits = 2, num_fractional_normal_digits = 2, num_fractional_trailing_zero_digits = 2, alt_unit_names = mapOf("0" to currency) ) } private fun TalerConfigSection.loadCurrencySpecification(): CurrencySpecification { return CurrencySpecification( name = string("name").require(), num_fractional_input_digits = number("fractional_input_digits").require(), num_fractional_normal_digits = number("fractional_normal_digits").require(), num_fractional_trailing_zero_digits = number("fractional_trailing_zero_digits").require(), alt_unit_names = jsonMap("alt_unit_names").require() ) } libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/0000775000175000017500000000000015236145704025475 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/LibeufinBank.kt0000664000175000017500000000245515122266731030372 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.options.versionOption import tech.libeufin.bank.BANK_CONFIG_SOURCE import tech.libeufin.common.CliConfigCmd import tech.libeufin.common.VERSION class LibeufinBank : CliktCommand() { init { versionOption(VERSION) subcommands(DbInit(), ChangePw(), CreateToken(), Serve(), CreateAccount(), EditAccount(), GC(), BenchPwh(), CliConfigCmd(BANK_CONFIG_SOURCE)) } override fun run() = Unit }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/Gc.kt0000664000175000017500000000273415122266731026372 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import tech.libeufin.bank.bankConfig import tech.libeufin.bank.logger import tech.libeufin.bank.withDb import tech.libeufin.common.TalerCmd import java.time.Instant class GC : TalerCmd("gc") { override fun help(context: Context) = "Run garbage collection: abort expired operations and clean expired data" override fun run() = cliCmd(logger) { bankConfig(config).withDb { db, cfg -> logger.info("Run garbage collection") db.gc.collect(Instant.now(), cfg.gcAbortAfter, cfg.gcCleanAfter, cfg.gcDeleteAfter) } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/Serve.kt0000664000175000017500000000560415122266731027124 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import tech.libeufin.bank.bankConfig import tech.libeufin.bank.corebankWebApp import tech.libeufin.bank.logger import tech.libeufin.bank.withDb import tech.libeufin.common.TalerCmd import tech.libeufin.common.api.serve import kotlin.io.path.Path import kotlin.io.path.exists import kotlin.io.path.readText class Serve: TalerCmd("serve") { override fun help(context: Context) = "Run libeufin-bank HTTP server" override fun run() = cliCmd(logger) { bankConfig(config).withDb { db, cfg -> if (cfg.allowConversion) { logger.info("Ensure exchange account exists") val info = db.account.bankInfo("exchange") if (info == null) { throw Exception("Exchange account missing: an exchange account named 'exchange' is required for conversion to be enabled") } else if (!info.isTalerExchange) { throw Exception("Account is not an exchange: an exchange account named 'exchange' is required for conversion to be enabled") } logger.info("Ensure conversion is enabled") val sqlProcedures = Path("${cfg.dbCfg.sqlDir}/libeufin-conversion-setup.sql") if (!sqlProcedures.exists()) { throw Exception("Missing libeufin-conversion-setup.sql file") } db.conn { it.execSQLUpdate(sqlProcedures.readText()) } } else { logger.info("Ensure conversion is disabled") val sqlProcedures = Path("${cfg.dbCfg.sqlDir}/libeufin-conversion-drop.sql") if (!sqlProcedures.exists()) { throw Exception("Missing libeufin-conversion-drop.sql file") } db.conn { it.execSQLUpdate(sqlProcedures.readText()) } // Remove conversion info from the database ? } serve(cfg.serverCfg, logger) { corebankWebApp(db, cfg) } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/BenchPwh.kt0000664000175000017500000000435415122266731027537 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import tech.libeufin.bank.bankConfig import tech.libeufin.bank.logger import tech.libeufin.common.TalerCmd import tech.libeufin.common.crypto.PwCrypto class BenchPwh : TalerCmd("bench-pwh") { override fun help(context: Context) = "Benchmark password hashing algorithm and configuration" override fun run() = cliCmd(logger) { val pwCrypto = bankConfig(config).pwCrypto when (pwCrypto) { is PwCrypto.Bcrypt -> println("Benching bcrypt with cost=${pwCrypto.cost} for 10s") } val start = System.currentTimeMillis() val stop = start + 10000 // 10s var count = 0 while (true) { val now = System.currentTimeMillis() if (now < stop) { val password = (0..10).map { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#".random() }.joinToString("") pwCrypto.hashpw(password) count ++ } else { val elapsed = (now-start).toDouble() val perSec = count.toDouble() / (elapsed / 1000.0) val iterTime = elapsed / count.toDouble() println("hash password in ${String.format("%.0f", iterTime)}ms ${String.format("%.2f", perSec)} H/s") break } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/ChangePw.kt0000664000175000017500000000566115122266731027537 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.* import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.* import tech.libeufin.bank.bankConfig import tech.libeufin.bank.db.AccountDAO.AccountPatchAuthResult import tech.libeufin.bank.logger import tech.libeufin.bank.withDb import tech.libeufin.common.TalerCmd import tech.libeufin.common.crypto.checkPw import com.github.ajalt.mordant.terminal.* class ChangePw : TalerCmd("passwd") { override fun help(context: Context) = "Change account password" private val username by argument("username", help = "Account username") private val password by argument( "password", help = "Account password used for authentication" ).defaultLazy("prompt") { val terminal = Terminal() ConfirmationPrompt.create( "Password", "Repeat for confirmation", "Values do not match, try again", { object : Prompt( prompt = it, terminal = terminal, hideInput = true ) { override fun convert(input: String): ConversionResult { return ConversionResult.Valid(input) } } } ).ask()!! } override fun run() = cliCmd(logger) { bankConfig(config).withDb { db, cfg -> val password = password.checkPw(cfg.pwdCheckQuality) val res = db.account.reconfigPassword(username, password, null, true, cfg.pwCrypto) when (res) { AccountPatchAuthResult.UnknownAccount -> throw Exception("Password change for '$username' account failed: unknown account") AccountPatchAuthResult.OldPasswordMismatch, AccountPatchAuthResult.TanRequired -> { /* Can never happen */ } AccountPatchAuthResult.Success -> logger.info("Password change for '$username' account succeeded") } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/CreateAccount.kt0000664000175000017500000001157215122266731030561 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.convert import com.github.ajalt.clikt.parameters.arguments.optional import com.github.ajalt.clikt.parameters.groups.OptionGroup import com.github.ajalt.clikt.parameters.groups.cooccurring import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.* import kotlinx.serialization.json.Json import tech.libeufin.bank.* import tech.libeufin.bank.api.* import tech.libeufin.bank.db.AccountDAO.* import tech.libeufin.common.* class CreateAccountOption: OptionGroup() { val username: String by option( "-u", "--user", "--username", metavar = "", help = "Account unique username" ).required() val password: String by option( "--password", "-p", help = "Account password used for authentication" ).prompt(requireConfirmation = true, hideInput = true) val name: String by option( help = "Legal name of the account owner" ).required() val is_public: Boolean by option( "--public", help = "Make this account visible to anyone" ).flag() val exchange: Boolean by option( help = "Make this account a taler exchange" ).flag() val email: String? by option(help = "E-Mail address used for TAN transmission") val phone: String? by option(help = "Phone number used for TAN transmission") val cashout_payto_uri: IbanPayto? by option( help = "Payto URI of a fiant account who receive cashout amount" ).convert { Payto.parse(it).expectIban() } val payto_uri: Payto? by option( help = "Payto URI of this account" ).convert { Payto.parse(it) } val debit_threshold: TalerAmount? by option( help = "Max debit allowed for this account" ).convert { TalerAmount(it) } val tan_channel: TanChannel? by option( help = "Enables 2FA and set the TAN channel used for challenges" ).convert { TanChannel.valueOf(it) } } class CreateAccount : TalerCmd("create-account") { override fun help(context: Context) = "Create an account, returning the payto://-URI associated with it" private val json by argument().convert { Json.decodeFromString(it) }.optional() private val options by CreateAccountOption().cooccurring() override fun run() = cliCmd(logger) { bankConfig(config).withDb { db, cfg -> val req = json ?: options?.run { RegisterAccountRequest( username = username, password = password, name = name, is_public = is_public, is_taler_exchange = exchange, contact_data = ChallengeContactData( email = Option.Some(email), phone = Option.Some(phone), ), cashout_payto_uri = cashout_payto_uri, payto_uri = payto_uri, debit_threshold = debit_threshold, tan_channel = tan_channel ) } req?.let { when (val result = createAccount(db, cfg, req, true)) { AccountCreationResult.BonusBalanceInsufficient -> throw Exception("Insufficient admin funds to grant bonus") AccountCreationResult.UsernameReuse -> throw Exception("Account username reuse '${req.username}'") AccountCreationResult.PayToReuse -> throw Exception("Bank internalPayToUri reuse") AccountCreationResult.UnknownConversionClass -> throw Exception("Unknown conversion class ${req.conversion_rate_class_id}") is AccountCreationResult.Success -> { logger.info("Account '${req.username}' created") println(result.payto) } } } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/EditAccount.kt0000664000175000017500000001051015122266731030232 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.convert import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.boolean import tech.libeufin.bank.* import tech.libeufin.bank.api.patchAccount import tech.libeufin.bank.db.AccountDAO.AccountPatchResult import tech.libeufin.common.* class EditAccount : TalerCmd("edit-account") { override fun help(context: Context) = "Edit an existing account" private val username: String by argument( "username", help = "Account username" ) private val name: String? by option( help = "Legal name of the account owner" ) private val is_public: Boolean? by option( "--public", help = "Make this account visible to anyone" ).boolean() private val exchange: Boolean? by option( help = "Make this account a taler exchange" ).boolean() private val email: String? by option(help = "E-Mail address used for TAN transmission") private val phone: String? by option(help = "Phone number used for TAN transmission") private val cashout_payto_uri: IbanPayto? by option( help = "Payto URI of a fiant account who receive cashout amount" ).convert { Payto.parse(it).expectIban() } private val debit_threshold: TalerAmount? by option( help = "Max debit allowed for this account" ).convert { TalerAmount(it) } private val tan_channel: Option? by option( help = "Enables 2FA and set the TAN channel used for challenges" ).convert { if (it == "") { Option.None } else { Option.Some(TanChannel.valueOf(it)) } } override fun run() = cliCmd(logger) { bankConfig(config).withDb { db, cfg -> val req = AccountReconfiguration( name = name, is_taler_exchange = exchange, is_public = is_public, contact_data = ChallengeContactData( // PATCH semantic, if not given do not change, if empty remove email = if (email == null) Option.None else Option.Some(if (email != "") email else null), phone = if (phone == null) Option.None else Option.Some(if (phone != "") phone else null), ), cashout_payto_uri = Option.Some(cashout_payto_uri), debit_threshold = debit_threshold, tan_channel = Option.invert(tan_channel) ) when (val res = patchAccount(db, cfg, req, username, true, true)) { AccountPatchResult.Success -> logger.info("Account '$username' edited") AccountPatchResult.UnknownAccount -> throw Exception("Account '$username' not found") AccountPatchResult.MissingTanInfo -> throw Exception("missing info for tan channel ${req.tan_channel.get()}") AccountPatchResult.NonAdminName, AccountPatchResult.NonAdminCashout, AccountPatchResult.NonAdminDebtLimit, AccountPatchResult.NonAdminConversionRateClass, AccountPatchResult.UnknownConversionClass, is AccountPatchResult.Challenges -> throw IllegalStateException("Those error can never happen $res") } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/CreateToken.kt0000664000175000017500000000774115122266731030250 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.arguments.* import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.* import com.github.ajalt.clikt.parameters.types.* import tech.libeufin.bank.* import tech.libeufin.bank.auth.* import tech.libeufin.common.* import java.time.* import java.time.temporal.ChronoUnit import java.util.concurrent.TimeUnit class CreateToken : TalerCmd("create-token") { override fun help(context: Context) = "Create authentication token for a user" private val username by option( "-u", "--user", "--username", metavar = "", help = "Account username" ).required() private val scope by option("--scope", "-s", help = "Scope for the token").enum().required() private val duration by option("--duration", "-d", metavar = "", help = "Custom token validity duration").convert { if (it == "forever") { ChronoUnit.FOREVER.duration } else { val dUs = it.toLongOrNull() ?: throw Exception("Expected forever or a number in micros") when { dUs < 0 -> throw Exception("Negative duration specified") dUs > RelativeTime.MAX_SAFE_INTEGER -> throw Exception("Duration value exceed cap (2^53-1)") else -> Duration.of(dUs, ChronoUnit.MICROS) } } }.default(TOKEN_DEFAULT_DURATION) private val description by option("--description", help = "Optional token description") private val refreshable by option("--refreshable", help = "Make the token refreshable into a new token").flag() private val currentToken by option("--current-token", help = "Current token to reuse if still valid").convert { Base32Crockford.decode(it.removePrefix(TOKEN_PREFIX)) } override fun run() = cliCmd(logger) { bankConfig(config).withDb { db, cfg -> val now = Instant.now() val token = currentToken?.let { db.token.access(it, now) } if (token != null && token.expirationTime.isBefore(now) && validScope(scope.logical(), token.scope)) { println("$TOKEN_PREFIX$currentToken") } else { val expirationTimestamp = if (duration == ChronoUnit.FOREVER.duration) { Instant.MAX } else { try { now.plus(duration) } catch (e: Exception) { throw Exception("Bad token duration: ${e.message}") } } val token = Base32Crockford32B.secureRand() db.token.create( username = username, content = token.raw, creationTime = now, expirationTime = expirationTimestamp, scope = scope, isRefreshable = refreshable, description = description, is2fa = true ) println("$TOKEN_PREFIX$token") } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/cli/DbInit.kt0000664000175000017500000000472315122266731027212 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import tech.libeufin.bank.bankConfig import tech.libeufin.bank.createAdminAccount import tech.libeufin.bank.db.AccountDAO.AccountCreationResult import tech.libeufin.bank.logger import tech.libeufin.bank.withDb import tech.libeufin.common.TalerCmd import tech.libeufin.common.db.dbInit import tech.libeufin.common.db.pgDataSource class DbInit : TalerCmd("dbinit") { override fun help(context: Context) = "Initialize the libeufin-bank database" private val reset by option( "--reset", "-r", help = "Reset database (DANGEROUS: All existing data is lost)" ).flag() override fun run() = cliCmd(logger) { val cfg = bankConfig(config) val dbCfg = cfg.dbCfg pgDataSource(dbCfg.dbConnStr).dbInit(dbCfg, "libeufin-bank", reset) cfg.withDb { db, cfg -> // Create admin account if missing val res = createAdminAccount(db, cfg) when (res) { AccountCreationResult.UsernameReuse -> {} AccountCreationResult.BonusBalanceInsufficient, AccountCreationResult.UnknownConversionClass -> throw IllegalStateException("Those error can never happen $res") AccountCreationResult.PayToReuse -> throw Exception("Failed to create admin's account") is AccountCreationResult.Success -> logger.info("Admin's account created") } } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/Error.kt0000664000175000017500000000472015122266731026360 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank import tech.libeufin.common.* /* ----- Currency checks ----- */ fun BankConfig.checkRegionalCurrency(amount: TalerAmount) { if (amount.currency != regionalCurrency) throw badRequest( "Wrong currency: expected regional currency $regionalCurrency got ${amount.currency}", TalerErrorCode.GENERIC_CURRENCY_MISMATCH ) } fun BankConfig.checkFiatCurrency(amount: TalerAmount) { if (amount.currency != fiatCurrency) throw badRequest( "Wrong currency: expected fiat currency $fiatCurrency got ${amount.currency}", TalerErrorCode.GENERIC_CURRENCY_MISMATCH ) } fun BankConfig.checkCurrency(input: ConversionRateClassInput) { for (regionalAmount in sequenceOf(input.cashin_fee, input.cashout_min_amount).filterNotNull()) { this.checkRegionalCurrency(regionalAmount) } for (fiatAmount in sequenceOf(input.cashout_fee, input.cashin_min_amount).filterNotNull()) { this.checkFiatCurrency(fiatAmount) } } /* ----- Common errors ----- */ fun unknownAccount(id: String) = notFound( "Account '$id' not found", TalerErrorCode.BANK_UNKNOWN_ACCOUNT ) fun unknownCreditorAccount(id: String) = conflict( "Creditor account '$id' not found", TalerErrorCode.BANK_UNKNOWN_CREDITOR ) fun unsupportedTanChannel(channel: TanChannel) = conflict( "Unsupported tan channel $channel", TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED ) fun notExchange(username: String): ApiException = conflict( "Account '$username' is not an exchange account.", TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE ) fun unknownConversionClass(id: Long?): ApiException = conflict( "Unknown conversion rate class $id", TalerErrorCode.BANK_CONVERSION_RATE_CLASS_UNKNOWN )libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/params.kt0000664000175000017500000001362315122266731026554 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank import io.ktor.http.* import tech.libeufin.common.* import java.time.Instant import java.time.LocalDateTime import java.time.ZoneOffset import java.time.temporal.TemporalAdjusters data class MonitorParams( val timeframe: Timeframe, val date: LocalDateTime ) { constructor(timeframe: Timeframe, timestamp: LocalDateTime, which: Int) : this( timeframe, when (timeframe) { Timeframe.hour -> timestamp.withHour(which) Timeframe.day -> timestamp.withDayOfMonth(which) Timeframe.month -> timestamp.withMonth(which) Timeframe.year -> timestamp.withYear(which) } ) constructor(timeframe: Timeframe, secs: Long) : this( timeframe, LocalDateTime.ofInstant(Instant.ofEpochSecond(secs), ZoneOffset.UTC) ) companion object { val names = Timeframe.entries.map { it.name } val names_fmt = names.joinToString() fun extract(params: Parameters): MonitorParams { val raw = params["timeframe"] ?: "hour" if (!names.contains(raw)) { throw badRequest("Param 'timeframe' must be one of $names_fmt", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) } val timeframe = Timeframe.valueOf(raw) val now = LocalDateTime.now(ZoneOffset.UTC) val which = params.int("which") val dateS = params.long("date_s") if (which != null && dateS != null) { throw badRequest("Cannot use both 'date_s' and deprecated 'which'", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) } return if (which != null) { val lastDayOfMonth = now.with(TemporalAdjusters.lastDayOfMonth()).dayOfMonth when { timeframe == Timeframe.hour && (0 > which || which > 23) -> throw badRequest("For hour timestamp param 'which' must be between 00 to 23", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) timeframe == Timeframe.day && (1 > which || which > lastDayOfMonth) -> throw badRequest("For day timestamp param 'which' must be between 1 to $lastDayOfMonth", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) timeframe == Timeframe.month && (1 > which || which > 12) -> throw badRequest("For month timestamp param 'which' must be between 1 to 12", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) timeframe == Timeframe.year && (1 > which|| which > 9999) -> throw badRequest("For year timestamp param 'which' must be between 0001 to 9999", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) else -> {} } MonitorParams(timeframe, now, which) } else if (dateS != null) { MonitorParams(timeframe, dateS) } else { MonitorParams(timeframe, now) } } } } data class AccountParams( val page: PageParams, val usernameFilter: String?, val conversionRateClassId: Long? ) { companion object { fun extract(params: Parameters): AccountParams { val usernameFilter = params["filter_name"]?.run { "%$this%" } val conversionRateClassId = params.long("conversion_rate_class_id") return AccountParams(PageParams.extract(params), usernameFilter, conversionRateClassId) } } } data class ClassParams( val page: PageParams, val nameFilter: String? ) { companion object { fun extract(params: Parameters): ClassParams { val usernameFilter = params["filter_name"]?.run { "%$this%" } return ClassParams(PageParams.extract(params), usernameFilter) } } } data class RateParams( val debit: TalerAmount?, val credit: TalerAmount? ) { companion object { fun extract(params: Parameters): RateParams { val debit = params.amount("amount_debit") val credit = params.amount("amount_credit") if (debit == null && credit == null) { throw badRequest("Either param 'amount_debit' or 'amount_credit' is required", TalerErrorCode.GENERIC_PARAMETER_MISSING) } else if (debit != null && credit != null) { throw badRequest("Cannot have both 'amount_debit' and 'amount_credit' params", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) } return RateParams(debit, credit) } } } data class StatusParams( val polling: PollingParams, val old_state: WithdrawalStatus ) { companion object { private val names = WithdrawalStatus.entries.map { it.name } private val names_fmt = names.joinToString() fun extract(params: Parameters): StatusParams { val old_state = params["old_state"] ?: "pending" if (!names.contains(old_state)) { throw badRequest("Param 'old_state' must be one of $names_fmt", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) } return StatusParams( polling = PollingParams.extract(params), old_state = WithdrawalStatus.valueOf(old_state) ) } } }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/Main.kt0000664000175000017500000000555215204341712026151 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank import io.ktor.server.application.* import io.ktor.server.http.content.* import io.ktor.server.response.* import io.ktor.server.routing.* import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.bank.api.* import tech.libeufin.bank.cli.LibeufinBank import tech.libeufin.bank.db.Database import tech.libeufin.common.api.OpenApiInfo import tech.libeufin.common.api.talerApi import tech.libeufin.common.VERSION import com.github.ajalt.clikt.core.main val logger: Logger = LoggerFactory.getLogger("libeufin-bank") /** Set up web server handlers for the Taler corebank API */ fun Application.corebankWebApp(db: Database, cfg: BankConfig, serveSpec: Boolean = false) = talerApi( LoggerFactory.getLogger("libeufin-bank-api"), OpenApiInfo( title = "LibEuFin Bank API", version = VERSION, description = "Taler corebank, wire gateway, wire transfer gateway, integration, conversion, revenue, and observability APIs for LibEuFin Bank", securityConfig = { securityScheme("bearerAuth") { type = io.github.smiley4.ktoropenapi.config.AuthType.HTTP scheme = io.github.smiley4.ktoropenapi.config.AuthScheme.BEARER bearerFormat = "token" description = "Bearer tokens minted by libeufin-bank /accounts/{USERNAME}/token" } securityScheme("basicAuth") { type = io.github.smiley4.ktoropenapi.config.AuthType.HTTP scheme = io.github.smiley4.ktoropenapi.config.AuthScheme.BASIC description = "HTTP Basic authentication, supported only on compatibility-enabled endpoints" } } ), serveSpec = serveSpec ) { coreBankApi(db, cfg) conversionApi(db, cfg) bankIntegrationApi(db, cfg) wireGatewayApi(db, cfg) preparedTransferApi(db, cfg) revenueApi(db, cfg) observabilityApi(db, cfg) cfg.spaPath?.let { get("/") { call.respondRedirect("/webui/") } staticFiles("/webui/", it.toFile()) } } fun main(args: Array) { LibeufinBank().main(args) } libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/TalerMessage.kt0000664000175000017500000010325015204341712027633 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import io.github.smiley4.schemakenerator.core.annotations.Description import io.github.smiley4.schemakenerator.core.annotations.Name import tech.libeufin.common.* import java.time.Instant /** * Allowed lengths for fractional digits in amounts. */ enum class FracDigits { TWO, EIGHT } // Allowed values for bank transactions directions. @Description("Direction of a bank transaction") enum class TransactionDirection { credit, debit } @Description("Status of a cashout operation") enum class CashoutStatus { pending, aborted, confirmed } @Description("Status of a withdrawal operation") enum class WithdrawalStatus { pending, aborted, selected, confirmed } @Description("Status of a bank account") enum class AccountStatus { active, locked, deleted } @Description("Rounding mode for currency conversion") enum class RoundingMode { zero, up, nearest } enum class Timeframe { hour, day, month, year } enum class Operation { account_reconfig, account_delete, account_auth_reconfig, bank_transaction, cashout, withdrawal, create_token } @Description("Wire transfer method type") enum class WireMethod { IBAN, X_TALER_BANK } @Serializable(with = Option.Serializer::class) sealed class Option { data object None : Option() data class Some(val value: T) : Option() fun get(): T? { return when (this) { None -> null is Some -> this.value } } inline fun some(lambda: (T) -> Unit) { if (this is Some) { lambda(value) } } fun isSome(): Boolean = this is Some @OptIn(ExperimentalSerializationApi::class) internal class Serializer ( private val valueSerializer: KSerializer ) : KSerializer> { override val descriptor: SerialDescriptor = valueSerializer.descriptor override fun serialize(encoder: Encoder, value: Option) { when (value) { None -> encoder.encodeNull() is Some -> valueSerializer.serialize(encoder, value.value) } } override fun deserialize(decoder: Decoder): Option { return Some(valueSerializer.deserialize(decoder)) } } companion object { fun invert(optional: Option?): Option { return when (optional) { null -> Option.None is Option.None -> Option.Some(null) is Option.Some -> Option.Some(optional.value) } } } } @Serializable @Description("Response containing TAN challenges") data class ChallengeResponse( @Description("List of pending challenges") val challenges: List, @Description("Whether all challenges must be solved") val combi_and: Boolean ) @Serializable @Description("Single TAN challenge details") data class Challenge( @Description("Unique challenge identifier") val challenge_id: String, @Description("Channel used for TAN delivery") val tan_channel: TanChannel, @Description("Masked contact information for TAN") val tan_info: String ) @Serializable @Description("Response after requesting a TAN challenge") data class ChallengeRequestResponse( @Description("Expiration time for solving the challenge") val solve_expiration: TalerTimestamp, @Description("Earliest time to request retransmission") val earliest_retransmission: TalerTimestamp ) /** * HTTP response type of successful token refresh. * access_token is the Crockford encoding of the 32 byte * access token, whereas 'expiration' is the point in time * when this token expires. */ @Serializable @Description("Successful token creation or refresh response") data class TokenSuccessResponse( @Description("Crockford-encoded access token") val access_token: String, @Description("Token expiration timestamp") val expiration: TalerTimestamp ) /* Contains contact data to send TAN challges to the * users, to let them complete cashout operations. */ @Serializable @Description("Contact data for TAN challenge delivery") data class ChallengeContactData( @Description("Email address for TAN delivery") val email: Option = Option.None, @Description("Phone number for TAN delivery") val phone: Option = Option.None ) { init { if (email.get()?.let { !EMAIL_PATTERN.matches(it) } == true) throw badRequest("email contact data '$email' is malformed") if (phone.get()?.let { !PHONE_PATTERN.matches(it) } == true) throw badRequest("phone contact data '$phone' is malformed") } companion object { private val EMAIL_PATTERN = Regex("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}") private val PHONE_PATTERN = Regex("\\+?[0-9]+") } } // Type expected at POST /accounts @Serializable @Description("Request to register a new bank account") data class RegisterAccountRequest( @Description("Unique account username") val username: String, @Description("Account password") val password: String, @Description("Legal name of account holder") val name: String, @Description("Whether account is publicly visible") val is_public: Boolean = false, @Description("Whether account is a Taler exchange") val is_taler_exchange: Boolean = false, @Description("Contact data for TAN challenges") val contact_data: ChallengeContactData? = null, @Description("Cashout payto URI for fiat withdrawals") val cashout_payto_uri: IbanPayto? = null, @Description("Payto URI for the account") val payto_uri: Payto? = null, @Description("Maximum allowed debit balance") val debit_threshold: TalerAmount? = null, @Description("Preferred TAN channel (deprecated)") val tan_channel: TanChannel? = null, @Description("Set of enabled TAN channels") val tan_channels: Set? = null, @Description("Conversion rate class identifier") val conversion_rate_class_id: Long? = null ) { init { if (!USERNAME_REGEX.matches(username)) throw badRequest("username '$username' is malformed, must match [a-zA-Z0-9\\-\\._~]{1,126}") else if (tan_channel != null && tan_channels != null) throw badRequest("you must only use either tan_channel or tan_channels") } @Description("Computed set of enabled TAN channels") val channels: Set get() { if (tan_channels != null) { return tan_channels } else if (tan_channel != null) { return setOf(tan_channel) } else { return emptySet() } } companion object { private val USERNAME_REGEX = Regex("^[a-zA-Z0-9-._~]{1,126}$") } } @Serializable @Description("Response after successful account registration") data class RegisterAccountResponse( @Description("Internal payto URI of the new account") val internal_payto_uri: String ) /** * Request of PATCH /accounts/{USERNAME} */ @Serializable @Description("Request to reconfigure an existing account") data class AccountReconfiguration( @Description("Updated contact data for TAN challenges") val contact_data: ChallengeContactData? = null, @Description("Updated cashout payto URI") val cashout_payto_uri: Option = Option.None, @Description("Updated legal name of account holder") val name: String? = null, @Description("Whether account is publicly visible") val is_public: Boolean? = null, @Description("Updated maximum allowed debit balance") val debit_threshold: TalerAmount? = null, @Description("Updated preferred TAN channel (deprecated)") val tan_channel: Option = Option.None, @Description("Updated set of enabled TAN channels") val tan_channels: Option> = Option.None, @Description("Whether account is a Taler exchange") val is_taler_exchange: Boolean? = null, @Description("Updated conversion rate class identifier") val conversion_rate_class_id: Option = Option.None ) { init { if (tan_channel.isSome() && tan_channels.isSome()) throw badRequest("you must only use either tan_channel or tan_channels") } @Description("Computed set of enabled TAN channels") val channels: Option> get() { if (tan_channels.isSome()) { return tan_channels } else if (tan_channel is Option.Some) { if (tan_channel.value == null) { return Option.Some(emptySet()) } else { return Option.Some(setOf(tan_channel.value)) } } else { return Option.None } } } /** * Type expected at POST /accounts/{USERNAME}/token * It complies with Taler's design document #49 */ @Serializable @Description("Request to create an authentication token") data class TokenRequest( @Description("Permission scope for the token") val scope: TokenScope, @Description("Token validity duration") val duration: RelativeTime? = null, @Description("Human-readable token description") val description: String? = null, @Description("Whether the token can be refreshed") val refreshable: Boolean = false ) @Serializable @Description("Monitor statistics response") sealed interface MonitorResponse { val talerInCount: Long val talerInVolume: TalerAmount val talerOutCount: Long val talerOutVolume: TalerAmount } @Serializable @SerialName("no-conversions") @Name("MonitorNoConversion", qualifiedName = "no-conversions") @Description("Monitor stats without currency conversion") data class MonitorNoConversion( @Description("Number of incoming Taler transactions") override val talerInCount: Long, @Description("Total volume of incoming Taler transactions") override val talerInVolume: TalerAmount, @Description("Number of outgoing Taler transactions") override val talerOutCount: Long, @Description("Total volume of outgoing Taler transactions") override val talerOutVolume: TalerAmount ) : MonitorResponse @Serializable @SerialName("with-conversions") @Name("MonitorWithConversion", qualifiedName = "with-conversions") @Description("Monitor stats with currency conversion") data class MonitorWithConversion( @Description("Number of cash-in operations") val cashinCount: Long, @Description("Total regional currency cash-in volume") val cashinRegionalVolume: TalerAmount, @Description("Total fiat currency cash-in volume") val cashinFiatVolume: TalerAmount, @Description("Number of cashout operations") val cashoutCount: Long, @Description("Total regional currency cashout volume") val cashoutRegionalVolume: TalerAmount, @Description("Total fiat currency cashout volume") val cashoutFiatVolume: TalerAmount, @Description("Number of incoming Taler transactions") override val talerInCount: Long, @Description("Total volume of incoming Taler transactions") override val talerInVolume: TalerAmount, @Description("Number of outgoing Taler transactions") override val talerOutCount: Long, @Description("Total volume of outgoing Taler transactions") override val talerOutVolume: TalerAmount ) : MonitorResponse typealias Tans = List> /** * Convenience type to get bank account information * from/to the database. */ data class BankInfo( val username: String, val payto: String, val bankAccountId: Long, val isTalerExchange: Boolean, override val phone: String?, override val email: String?, override val channels: Set ): TanInfo interface TanInfo { val phone: String? val email: String? val channels: Set val mfa: Tans get() = channels.map { channel -> val info = when (channel) { TanChannel.sms -> phone TanChannel.email -> email } Pair(channel, requireNotNull(info)) } } // Allowed values for cashout TAN channels. @Description("Channel for TAN delivery") enum class TanChannel { sms, email } // Scopes for authentication tokens. @Description("Scope for authentication tokens") enum class TokenScope { readonly, readwrite, revenue, wiregateway, observability; fun logical(): TokenLogicalScope = when (this) { readonly -> TokenLogicalScope.readonly readwrite -> TokenLogicalScope.readwrite revenue -> TokenLogicalScope.revenue wiregateway -> TokenLogicalScope.readwrite_wiregateway observability -> TokenLogicalScope.observability } } enum class TokenLogicalScope { readonly, readwrite, revenue, refreshable, readonly_wiregateway, readwrite_wiregateway, observability } data class BearerToken( val scope: TokenScope, val isRefreshable: Boolean, val creationTime: Instant, val expirationTime: Instant ) @Serializable @Description("Information about an authentication token") data class TokenInfo( @Description("Token creation timestamp") val creation_time: TalerTimestamp, @Description("Token expiration timestamp") val expiration: TalerTimestamp, @Description("Permission scope of the token") val scope: TokenScope, @Description("Whether the token can be refreshed") val isRefreshable: Boolean, @Description("Human-readable token description") val description: String? = null, @Description("Timestamp of last token usage") val last_access: TalerTimestamp, @Description("Row identifier of the token") val row_id: Long, @Description("Unique token identifier") val token_id: Long ) @Serializable @Description("List of authentication tokens") data class TokenInfos ( @Description("Array of token information entries") val tokens: List ) @Serializable @Description("Bank configuration response") data class Config( @Description("Regional currency code") val currency: String, @Description("Currency specification for display") val currency_specification: CurrencySpecification, @Description("Base URL of the bank") val base_url: BaseURL?, @Description("Human-readable bank name") val bank_name: String, @Description("Whether currency conversion is enabled") val allow_conversion: Boolean, @Description("Whether account registration is open") val allow_registrations: Boolean, @Description("Whether account deletion is allowed") val allow_deletions: Boolean, @Description("Whether users can edit their legal name") val allow_edit_name: Boolean, @Description("Whether users can edit their cashout payto URI") val allow_edit_cashout_payto_uri: Boolean, @Description("Default debit threshold for new accounts") val default_debit_threshold: TalerAmount, @Description("Supported TAN channels for two-factor authentication") val supported_tan_channels: Set, @Description("Wire transfer method (IBAN or X_TALER_BANK)") val wire_type: WireMethod, @Description("Fee charged per wire transfer") val wire_transfer_fees: TalerAmount, @Description("Minimum wire transfer amount") val min_wire_transfer_amount: TalerAmount, @Description("Maximum wire transfer amount") val max_wire_transfer_amount: TalerAmount ) { @Description("API name identifier") val name: String = "taler-corebank" @Description("API version string") val version: String = COREBANK_API_VERSION } @Serializable @Description("Currency conversion configuration") data class ConversionConfig( @Description("Regional currency code") val regional_currency: String, @Description("Regional currency display specification") val regional_currency_specification: CurrencySpecification, @Description("Fiat currency code") val fiat_currency: String, @Description("Fiat currency display specification") val fiat_currency_specification: CurrencySpecification, @Description("Applicable conversion rate") val conversion_rate: ConversionRate ) { @Description("API name identifier") val name: String = "taler-conversion-info" @Description("API version string") val version: String = CONVERSION_API_VERSION } @Serializable @Description("Taler integration API configuration response") data class TalerIntegrationConfigResponse( @Description("Currency used by this bank") val currency: String, @Description("Currency display specification") val currency_specification: CurrencySpecification ) { @Description("API name identifier") val name: String = "taler-bank-integration" @Description("API version string") val version: String = INTEGRATION_API_VERSION } @Description("Indicates whether a transaction is a credit or debit") enum class CreditDebitInfo { credit, debit } @Serializable @Description("Account balance information") data class Balance( @Description("Balance amount") val amount: TalerAmount, @Description("Whether balance is credit or debit") val credit_debit_indicator: CreditDebitInfo, ) /** * GET /accounts response. */ @Serializable @Description("Minimal account data for account listings") data class AccountMinimalData( @Description("Account username") val username: String, @Description("Legal name of account holder") val name: String, @Description("Payto URI of the account") val payto_uri: String, @Description("Current account balance") val balance: Balance, @Description("Maximum allowed debit balance") val debit_threshold: TalerAmount, @Description("Whether account is publicly visible") val is_public: Boolean, @Description("Whether account is a Taler exchange") val is_taler_exchange: Boolean, @Description("Whether account is locked") val is_locked: Boolean, @Description("Row identifier of the account") val row_id: Long, @Description("Current account status") val status: AccountStatus, @Description("Conversion rate class identifier") val conversion_rate_class_id: Long? = null, @Description("Applicable conversion rate") val conversion_rate: ConversionRate? = null ) /** * Response type of GET /accounts. */ @Serializable @Description("Paginated list of bank accounts") data class ListBankAccountsResponse( @Description("Array of account summary entries") val accounts: List ) /** * GET /accounts/$USERNAME response. */ @Serializable @Description("Detailed account data for a single account") data class AccountData( @Description("Legal name of account holder") val name: String, @Description("Payto URI of the account") val payto_uri: String, @Description("Current account balance") val balance: Balance, @Description("Maximum allowed debit balance") val debit_threshold: TalerAmount, @Description("Contact data for TAN challenges") val contact_data: ChallengeContactData? = null, @Description("Cashout payto URI for fiat withdrawals") val cashout_payto_uri: String? = null, @Description("Preferred TAN channel (deprecated)") val tan_channel: TanChannel? = null, @Description("Set of enabled TAN channels") val tan_channels: Set = emptySet(), @Description("Whether account is publicly visible") val is_public: Boolean, @Description("Whether account is a Taler exchange") val is_taler_exchange: Boolean, @Description("Whether account is locked") val is_locked: Boolean, @Description("Current account status") val status: AccountStatus, @Description("Conversion rate class identifier") val conversion_rate_class_id: Long? = null, @Description("Applicable conversion rate") val conversion_rate: ConversionRate? = null ) @Serializable @Description("Request to create a bank transaction") data class TransactionCreateRequest( @Description("Recipient payto URI") val payto_uri: Payto, @Description("Transaction amount") val amount: TalerAmount?, @Description("Idempotency key for the request") val request_uid: ShortHashCode? ) @Serializable @Description("Response after creating a bank transaction") data class TransactionCreateResponse( @Description("Row identifier of the new transaction") val row_id: Long ) /* History element, either from GET /transactions/T_ID or from GET /transactions */ @Serializable @Description("Details of a single bank transaction") data class BankAccountTransactionInfo( @Description("Payto URI of the creditor") val creditor_payto_uri: String, @Description("Payto URI of the debtor") val debtor_payto_uri: String, @Description("Transaction amount") val amount: TalerAmount, @Description("Transaction direction (credit or debit)") val direction: TransactionDirection, @Description("Wire transfer subject line") val subject: String, @Description("Row identifier of the transaction") val row_id: Long, // is T_ID @Description("Transaction timestamp") val date: TalerTimestamp ) // Response type for histories, namely GET /transactions @Serializable @Description("Paginated list of bank transactions") data class BankAccountTransactionsResponse( @Description("Array of transaction entries") val transactions: List ) // Taler withdrawal request. @Serializable @Description("Request to create a Taler withdrawal") data class BankAccountCreateWithdrawalRequest( @Description("Exact withdrawal amount") val amount: TalerAmount? = null, @Description("Suggested withdrawal amount for wallet") val suggested_amount: TalerAmount? = null, @Description("Whether wallet should choose the amount") val no_amount_to_wallet: Boolean = false ) // Taler withdrawal response. @Serializable @Description("Response after creating a Taler withdrawal") data class BankAccountCreateWithdrawalResponse( @Description("Unique withdrawal operation identifier") val withdrawal_id: String, @Description("Taler URI for the wallet to process") val taler_withdraw_uri: String ) @Serializable @Description("Public information about a withdrawal operation") data class WithdrawalPublicInfo ( @Description("Current withdrawal status") val status: WithdrawalStatus, @Description("Withdrawal amount if fixed") val amount: TalerAmount? = null, @Description("Suggested withdrawal amount") val suggested_amount: TalerAmount? = null, @Description("Whether wallet should choose the amount") val no_amount_to_wallet: Boolean, @Description("Username of the withdrawing account") val username: String, @Description("Selected reserve public key") val selected_reserve_pub: EddsaPublicKey? = null, @Description("Selected exchange payto account") val selected_exchange_account: String? = null, ) @Serializable @Description("Currency display specification") data class CurrencySpecification( @Description("Human-readable currency name") val name: String, @Description("Fractional digits for input") val num_fractional_input_digits: Int, @Description("Fractional digits for normal display") val num_fractional_normal_digits: Int, @Description("Trailing zero digits to display") val num_fractional_trailing_zero_digits: Int, @Description("Alternative unit names by power of ten") val alt_unit_names: Map ) @Serializable @Description("Detailed withdrawal operation status") data class BankWithdrawalOperationStatus( @Description("Current withdrawal status") val status: WithdrawalStatus, @Description("Withdrawal amount if fixed") val amount: TalerAmount? = null, @Description("Suggested withdrawal amount") val suggested_amount: TalerAmount? = null, @Description("Minimum allowed withdrawal amount") val min_amount: TalerAmount? = null, @Description("Maximum allowed withdrawal amount") val max_amount: TalerAmount? = null, @Description("Card processing fees") val card_fees: TalerAmount? = null, @Description("Sender wire account details") val sender_wire: String? = null, @Description("Suggested exchange base URL") val suggested_exchange: String? = null, @Description("Required exchange base URL") val required_exchange: String? = null, @Description("URL to confirm the wire transfer") val confirm_transfer_url: String? = null, @Description("Supported wire transfer types") val wire_types: List, @Description("Selected reserve public key") val selected_reserve_pub: EddsaPublicKey? = null, @Description("Selected exchange payto account") val selected_exchange_account: String? = null, @Description("Whether wallet should choose the amount") val no_amount_to_wallet: Boolean = false, @Description("Currency of the withdrawal") val currency: String? = null, // TODO deprecated remove in the next breaking release @Description("Whether withdrawal was aborted (deprecated)") val aborted: Boolean, @Description("Whether exchange was selected (deprecated)") val selection_done: Boolean, @Description("Whether wire transfer completed (deprecated)") val transfer_done: Boolean, ) /** * Selection request on a Taler withdrawal. */ @Serializable @Description("Wallet request to select exchange for withdrawal") data class BankWithdrawalOperationPostRequest( @Description("Reserve public key from the wallet") val reserve_pub: EddsaPublicKey, @Description("Selected exchange payto URI") val selected_exchange: Payto, @Description("Withdrawal amount chosen by wallet") val amount: TalerAmount? = null ) /** * Response to the wallet after it selects the exchange * and the reserve pub. */ @Serializable @Description("Response after wallet selects exchange") data class BankWithdrawalOperationPostResponse( @Description("Current withdrawal status") val status: WithdrawalStatus, @Description("URL to confirm the wire transfer") val confirm_transfer_url: String? = null, // TODO deprecated remove in the next breaking release @Description("Whether wire transfer completed (deprecated)") val transfer_done: Boolean, ) @Serializable @Description("Request to initiate a cashout operation") data class CashoutRequest( @Description("Idempotency key for the request") val request_uid: ShortHashCode, @Description("Wire transfer subject line") val subject: String?, @Description("Amount debited in regional currency") val amount_debit: TalerAmount, @Description("Amount credited in fiat currency") val amount_credit: TalerAmount ) @Serializable @Description("Response after creating a cashout operation") data class CashoutResponse( @Description("Unique cashout operation identifier") val cashout_id: Long, ) @Serializable @Description("List of cashout operations for an account") data class Cashouts( @Description("Array of cashout summary entries") val cashouts: List, ) @Serializable @Description("Summary of a single cashout operation") data class CashoutInfo( @Description("Unique cashout operation identifier") val cashout_id: Long, @Description("Current cashout status") val status: CashoutStatus, ) @Serializable @Description("Global list of cashout operations") data class GlobalCashouts( @Description("Array of global cashout entries") val cashouts: List, ) @Serializable @Description("Global cashout entry with username") data class GlobalCashoutInfo( @Description("Unique cashout operation identifier") val cashout_id: Long, @Description("Account username of the cashout owner") val username: String, @Description("Current cashout status") val status: CashoutStatus, ) @Serializable @Description("Detailed status of a cashout operation") data class CashoutStatusResponse( @Description("Amount debited in regional currency") val amount_debit: TalerAmount, @Description("Amount credited in fiat currency") val amount_credit: TalerAmount, @Description("Wire transfer subject line") val subject: String, @Description("Cashout creation timestamp") val creation_time: TalerTimestamp, @Description("Cashout confirmation timestamp") val confirmation_time: TalerTimestamp? = null // TODO update doc ) @Serializable @Description("Request to solve a TAN challenge") data class ChallengeSolve( @Description("TAN code entered by the user") val tan: String ) @Serializable @Description("Currency conversion result") data class ConversionResponse( @Description("Amount debited from source currency") val amount_debit: TalerAmount, @Description("Amount credited in target currency") val amount_credit: TalerAmount, ) /** * Response to GET /public-accounts */ @Serializable @Description("List of publicly visible accounts") data class PublicAccountsResponse( @Description("Array of public account entries") val public_accounts: List ) /** * Single element of GET /public-accounts list. */ @Serializable @Description("Public account summary information") data class PublicAccount( @Description("Account username") val username: String, @Description("Payto URI of the account") val payto_uri: String, @Description("Current account balance") val balance: Balance, @Description("Whether account is a Taler exchange") val is_taler_exchange: Boolean, @Description("Row identifier of the account") val row_id: Long ) /** * Request of PATCH /accounts/{USERNAME}/auth */ @Serializable @Description("Request to change account password") data class AccountPasswordChange( @Description("New password for the account") val new_password: String, @Description("Current password for verification") val old_password: String? = null ) // Request POST /accounts/{USERNAME}/withdrawals/{WITHDRAWAL_ID}/confirm @Serializable @Description("Request to confirm a withdrawal operation") data class BankAccountConfirmWithdrawalRequest( @Description("Final withdrawal amount") val amount: TalerAmount? = null ) /** * Request POST /conversion-rate-classes * Request PATCH /conversion-rate-classes/{CLASS_ID} */ @Serializable @Description("Input for creating or updating a conversion rate class") data class ConversionRateClassInput( @Description("Human-readable class name") val name: String, @Description("Description of the rate class") val description: String? = null, @Description("Cash-in conversion ratio") val cashin_ratio: DecimalNumber? = null, @Description("Fee applied on cash-in operations") val cashin_fee: TalerAmount? = null, @Description("Rounding mode for cash-in amounts") val cashin_rounding_mode: RoundingMode? = null, @Description("Minimum amount for cash-in operations") val cashin_min_amount: TalerAmount? = null, @Description("Cashout conversion ratio") val cashout_ratio: DecimalNumber? = null, @Description("Fee applied on cashout operations") val cashout_fee: TalerAmount? = null, @Description("Rounding mode for cashout amounts") val cashout_rounding_mode: RoundingMode? = null, @Description("Minimum amount for cashout operations") val cashout_min_amount: TalerAmount? = null ) /** Response POST /conversion-rate-classes */ @Serializable @Description("Response after creating a conversion rate class") data class ConversionRateClassResponse( @Description("Identifier of the created rate class") val conversion_rate_class_id: Long, ) /** * Response GET /conversion-rate-classes/{CLASS_ID} */ @Serializable @Description("Detailed conversion rate class information") data class ConversionRateClass( @Description("Unique rate class identifier") val conversion_rate_class_id: Long, @Description("Human-readable class name") val name: String, @Description("Description of the rate class") val description: String? = null, @Description("Number of users in this class") val num_users: Int, @Description("Cash-in conversion ratio") val cashin_ratio: DecimalNumber? = null, @Description("Fee applied on cash-in operations") val cashin_fee: TalerAmount? = null, @Description("Rounding mode for cash-in amounts") val cashin_rounding_mode: RoundingMode? = null, @Description("Minimum amount for cash-in operations") val cashin_min_amount: TalerAmount? = null, @Description("Cashout conversion ratio") val cashout_ratio: DecimalNumber? = null, @Description("Fee applied on cashout operations") val cashout_fee: TalerAmount? = null, @Description("Rounding mode for cashout amounts") val cashout_rounding_mode: RoundingMode? = null, @Description("Minimum amount for cashout operations") val cashout_min_amount: TalerAmount? = null ) /** * Response GET /conversion-rate-classes */ @Serializable @Description("List of all conversion rate classes") data class ConversionRateClasses( @Description("Array of conversion rate class entries") val classes: List ) libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/auth/0000775000175000017500000000000015236145704025667 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/auth/auth.kt0000664000175000017500000002306715122266731027176 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.auth import org.slf4j.Logger import org.slf4j.LoggerFactory import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.util.* import io.ktor.util.pipeline.* import tech.libeufin.bank.* import tech.libeufin.bank.db.AccountDAO.CheckPasswordResult import tech.libeufin.bank.db.Database import tech.libeufin.common.* import tech.libeufin.common.api.intercept import tech.libeufin.common.crypto.PwCrypto import java.time.Instant private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-auth") /** Used to store if the current request is authenticated */ private val AUTH = AttributeKey("auth") /** Used to store if the currently authenticated user is admin */ private val AUTH_IS_ADMIN = AttributeKey("is_admin") /** Used to store used auth token */ private val AUTH_TOKEN = AttributeKey("auth_token") /** Used to store auth account info */ val AUTH_INFO = AttributeKey("auth_info") const val TOKEN_PREFIX = "secret-token:" /** Get username of the request account */ val ApplicationCall.pathUsername: String get() = parameters.expect("USERNAME") /** Check if current request is authenticated */ val ApplicationCall.isAuthenticated: Boolean get() = attributes.getOrNull(AUTH) == true /** Check if current auth account is admin */ val ApplicationCall.isAdmin: Boolean get() = attributes.getOrNull(AUTH_IS_ADMIN) == true /** Check auth token used for authentication */ val ApplicationCall.authToken: ByteArray? get() = attributes.getOrNull(AUTH_TOKEN) /** * Create an admin authenticated route for [scope]. * * If [enforce], only admin can access this route. * * You can check is the currently authenticated user is admin using [isAdmin]. **/ fun Route.authAdmin( db: Database, pwCrypto: PwCrypto, scope: TokenLogicalScope, compatPw: Boolean, enforce: Boolean = true, callback: Route.() -> Unit ): Route = intercept("AuthAdmin", callback) { if (enforce) { val info = this.authenticateBankRequest(db, pwCrypto, scope, false, compatPw) if (info.username != "admin") { throw forbidden("Only administrator allowed") } } else { try { this.authenticateBankRequest(db, pwCrypto, scope, false, compatPw) } catch (e: Exception) { null } } } /** * Create an authenticated route for [scope]. * * If [allowAdmin], admin is allowed to auth for any user. * If [requireAdmin], only admin can access this route. * * You can check is the currently authenticated user is admin using [isAdmin]. **/ fun Route.auth( db: Database, pwCrypto: PwCrypto, scope: TokenLogicalScope, compatPw: Boolean, allowAdmin: Boolean = false, requireAdmin: Boolean = false, allowPw: Boolean = false, callback: Route.() -> Unit ): Route = intercept("Auth", callback) { val info = this.authenticateBankRequest(db, pwCrypto, scope, allowPw, compatPw) if (requireAdmin && info.username != "admin") { throw forbidden("Only administrator allowed") } else { val hasRight = info.username == pathUsername || (allowAdmin && info.username == "admin") if (!hasRight) { throw forbidden("Customer ${info.username} have no right on $pathUsername account") } } } /** * Create an optionally authenticated route for [scope]. * * You can check is the currently authenticated user is admin using [isAdmin]. **/ fun Route.optAuth( db: Database, pwCrypto: PwCrypto, scope: TokenLogicalScope, compatPw: Boolean, allowAdmin: Boolean = false, callback: Route.() -> Unit ): Route = intercept("Auth", callback) { val header = request.headers[HttpHeaders.Authorization] if (header != null) { val info = this.authenticateBankRequest(db, pwCrypto, scope, false, compatPw) val hasRight = info.username == pathUsername || (allowAdmin && info.username == "admin") if (!hasRight) { throw forbidden("Customer ${info.username} have no right on $pathUsername account") } } } fun missingAuth(): ApiException = unauthorized( "Authorization header not found", TalerErrorCode.GENERIC_PARAMETER_MISSING ) /** * Authenticate an HTTP request for [requiredScope] according to the scheme that is mentioned * in the Authorization header. * The allowed schemes are either 'Basic' or 'Bearer'. * * Returns the authenticated customer username. */ private suspend fun ApplicationCall.authenticateBankRequest( db: Database, pwCrypto: PwCrypto, requiredScope: TokenLogicalScope, allowPw: Boolean, compatPw: Boolean ): BankInfo { val header = request.headers[HttpHeaders.Authorization] // Basic auth challenge if (header == null) { if (allowPw || compatPw) { response.header(HttpHeaders.WWWAuthenticate, "Basic realm=\"LibEuFin Bank\", charset=\"UTF-8\"") } throw missingAuth() } // Parse header val (scheme, content) = header.splitOnce(" ") ?: throw badRequest( "Authorization is invalid", TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED ) val info = when (scheme) { "Basic" -> doBasicAuth(db, content, pwCrypto, allowPw, compatPw) "Bearer" -> doTokenAuth(db, content, requiredScope) else -> throw unauthorized("Authorization method '$scheme' wrong or not supported") } this.attributes.put(AUTH, true) this.attributes.put(AUTH_IS_ADMIN, info.username == "admin") this.attributes.put(AUTH_INFO, info) return info } /** * Performs the HTTP Basic Authentication. * * Returns the authenticated customer username */ private suspend fun doBasicAuth( db: Database, encoded: String, pwCrypto: PwCrypto, allowPw: Boolean, compatPw: Boolean ): BankInfo { val decoded = String(encoded.decodeBase64(), Charsets.UTF_8) val (username, plainPassword) = decoded.splitOnce(":") ?: throw badRequest( "Malformed Basic auth credentials found in the Authorization header", TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED ) if (!allowPw) { logger.warn("User '$username' used deprecated password auth") if (!compatPw) { throw unauthorized("Authorization method 'Basic' not supported") } } when (val res = db.account.checkPassword(username, plainPassword, pwCrypto)) { CheckPasswordResult.UnknownAccount -> throw unauthorized("Unknown account") CheckPasswordResult.PasswordMismatch -> throw unauthorized("Bad password") CheckPasswordResult.Locked -> throw forbidden("Account is locked", TalerErrorCode.BANK_ACCOUNT_LOCKED) is CheckPasswordResult.Success -> return res.info } } fun validScope(required: TokenLogicalScope, scope: TokenScope): Boolean = when (required) { TokenLogicalScope.readonly -> scope in setOf(TokenScope.readonly, TokenScope.readwrite) TokenLogicalScope.readwrite -> scope in setOf(TokenScope.readwrite) TokenLogicalScope.revenue -> scope in setOf(TokenScope.readonly, TokenScope.readwrite, TokenScope.revenue) TokenLogicalScope.readonly_wiregateway -> scope in setOf(TokenScope.wiregateway, TokenScope.readonly, TokenScope.readwrite) TokenLogicalScope.readwrite_wiregateway -> scope in setOf(TokenScope.wiregateway, TokenScope.readwrite) TokenLogicalScope.observability -> scope in setOf(TokenScope.readonly, TokenScope.readwrite, TokenScope.observability) TokenLogicalScope.refreshable -> true } /** * Performs the secret-token HTTP Bearer Authentication. * * Returns the authenticated customer username */ private suspend fun ApplicationCall.doTokenAuth( db: Database, bearer: String, requiredScope: TokenLogicalScope, ): BankInfo { if (!bearer.startsWith(TOKEN_PREFIX)) throw badRequest( "Bearer token malformed", TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED ) val decoded = try { Base32Crockford.decode(bearer.slice(13.. throw unauthorized("Expired auth token", TalerErrorCode.GENERIC_TOKEN_EXPIRED) !validScope(requiredScope, token.scope) -> throw forbidden("Auth token has insufficient scope", TalerErrorCode.GENERIC_TOKEN_PERMISSION_INSUFFICIENT) !token.isRefreshable && requiredScope == TokenLogicalScope.refreshable -> throw forbidden("Unrefreshable token", TalerErrorCode.GENERIC_TOKEN_PERMISSION_INSUFFICIENT) } this.attributes.put(AUTH_TOKEN, decoded) this.attributes.put(AUTH_INFO, info) return info }libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/auth/mfa.kt0000664000175000017500000001272215122266731026774 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank.auth import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.plugins.* import kotlinx.serialization.json.Json import tech.libeufin.bank.* import tech.libeufin.bank.db.* import tech.libeufin.bank.db.TanDAO.* import tech.libeufin.common.* import tech.libeufin.common.crypto.* import tech.libeufin.common.api.* import java.text.DecimalFormat import java.time.Instant import java.util.UUID private suspend fun ApplicationCall.respondChallenges( db: Database, op: Operation, tans: Tans ): List { val (hbody, salt) = CryptoUtil.mfaBodyHashCreate(this.rawBody) val challenges = mutableListOf() for ((channel, info) in tans) { val code = Tan.genCode() val uuid = db.tan.new( hbody = hbody, salt = salt, username = pathUsername, op = op, code = code, timestamp = Instant.now(), retryCounter = TAN_RETRY_COUNTER, validityPeriod = TAN_VALIDITY_PERIOD, tanChannel = channel, tanInfo = info ) val privateInfo = if (op == Operation.create_token) { "REDACTED" } else { info } challenges.add(Challenge( challenge_id = uuid.toString(), tan_channel = channel, tan_info = privateInfo )) } return challenges } /** * Generate a TAN challenge for an [op] request with [body] and * respond to the HTTP request with a TAN challenge. * * If [channel] and [info] are present, they will be used * to send the TAN code, otherwise defaults will be used. */ suspend fun ApplicationCall.respondMfa( db: Database, op: Operation ) { val info = this.bankInfo(db) var challenges = respondChallenges(db, op, info.mfa) respond( status = HttpStatusCode.Accepted, message = ChallengeResponse( challenges = challenges, combi_and = false ) ) } suspend fun ApplicationCall.respondValidation( db: Database, op: Operation, tans: Tans ) { val challenges = respondChallenges(db, op, tans) respond( status = HttpStatusCode.Accepted, message = ChallengeResponse( challenges = challenges, combi_and = true ) ) } /** * Retrieve a confirmed challenge and its body for [op] from the database * if the challenge header is defined, otherwise extract the HTTP body. */ suspend inline fun ApplicationCall.receiveChallenge( db: Database, op: Operation, default: B? = null ): Pair { // Parse body val contentLenght = request.headers[HttpHeaders.ContentLength]?.toIntOrNull() val body: B = if (contentLenght == 0 && default != null) { default } else { this.receive() } // Check if challenges are used val ids = request.headers[TALER_CHALLENGE_IDS] if (ids == null) return Pair(body, null) // List validated challenges val uuids = ids.split(',').map { UUID.fromString(it.trim()) } val challenges = db.tan.challenge(uuids) val validated = challenges.mapNotNull { challenge -> if (challenge.op != op) { throw forbidden("Challenge is for a different operation body") } else if (!CryptoUtil.mfaBodyHashCheck(this.rawBody, challenge.hbody, challenge.salt)) { throw forbidden("Challenge is for a different request body") } else if (challenge.confirmed) { Pair(challenge.channel, challenge.info) } else { null } } if (validated.isEmpty()) return Pair(body, null) // CHeck if challenges are solved val bankInfo = this.bankInfo(db) // Account reconfig require mfa & new TAN validation if (op == Operation.account_reconfig) { val req = body as AccountReconfiguration val requiredValidation = req.requiredValidation(bankInfo) if (requiredValidation.all { validated.contains(it) }) { return Pair(body, emptyList()) } else if (bankInfo.mfa.any { validated.contains(it) }) { return Pair(body, requiredValidation) } else { return Pair(body, null) } } else { // Check mfa if (bankInfo.mfa.any { validated.contains(it) }) { return Pair(body, emptyList()) } else { return Pair(body, null) } } } object Tan { private val CODE_FORMAT = DecimalFormat("00000000") /** Generate a secure random TAN code */ fun genCode(): String { val rand = SECURE_RNG.get().nextInt(100000000) val code = CODE_FORMAT.format(rand) return code } } libeufin-1.6.8/libeufin-bank/src/main/kotlin/tech/libeufin/bank/helpers.kt0000664000175000017500000001101515157322161026722 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.bank import io.ktor.http.* import io.ktor.util.* import io.ktor.server.application.* import io.ktor.server.plugins.* import io.ktor.server.request.* import io.ktor.server.routing.* import io.ktor.server.util.* import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.descriptors.PrimitiveKind import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import tech.libeufin.bank.auth.pathUsername import tech.libeufin.bank.auth.AUTH_INFO import tech.libeufin.bank.db.AccountDAO.AccountCreationResult import tech.libeufin.bank.db.Database import tech.libeufin.bank.BankConfig import tech.libeufin.common.* import tech.libeufin.common.api.intercept import java.util.* private val BANK_INFO = AttributeKey("bank_info") /** Retrieve the bank account info for the selected username*/ suspend fun ApplicationCall.bankInfo(db: Database): BankInfo { val username = this.pathUsername // CHeck cached bank info val cachedInfo = this.attributes.getOrNull(BANK_INFO) if (cachedInfo != null) { require(cachedInfo.username == username) return cachedInfo } // Check cached auth info val authInfo = this.attributes.getOrNull(AUTH_INFO) if (authInfo != null && authInfo.username == username) { this.attributes.put(BANK_INFO, authInfo) return authInfo } // Else load from db val info = db.account.bankInfo(pathUsername) ?: throw unknownAccount(pathUsername) this.attributes.put(BANK_INFO, info) return info } /** * Builds the taler://withdraw-URI. Such URI will serve the requests * from wallets, when they need to manage the operation. For example, * a URI like taler://withdraw/$BANK_URL/taler-integration/$WO_ID needs * the bank to implement the Taler integratino API at the following base URL: * * https://$BANK_URL/taler-integration */ fun BankConfig.talerWithdrawUri(id: UUID): String { val base = this.baseUrl.url val protocol = if (base.protocol.name == "http") "taler+http" else "taler" val port = if (base.port != -1) ":${base.port}" else "" return "${protocol}://withdraw/${base.host}${port}${base.encodedPath}taler-integration/${id}" } fun BankConfig.withdrawConfirmUrl(id: UUID): String { val base = this.baseUrl.url return "${base}webui/#/operation/${id}" } /** * This function creates the admin account ONLY IF it was * NOT found in the database. It sets it to a random password that * is only meant to be overridden by a dedicated CLI tool. * * It returns false in case of problems, true otherwise. */ suspend fun createAdminAccount(db: Database, cfg: BankConfig, pw: String? = null): AccountCreationResult { var pwStr = pw ?: Base32Crockford32B.secureRand().toString() val payto = when (cfg.wireMethod) { WireMethod.IBAN -> IbanPayto.rand() WireMethod.X_TALER_BANK -> XTalerBankPayto.forUsername("admin") } return db.account.create( username = "admin", password = pwStr, name = "Bank administrator", internalPayto = payto, isPublic = false, isTalerExchange = false, maxDebt = cfg.defaultDebtLimit, bonus = TalerAmount(0, 0, cfg.regionalCurrency), checkPaytoIdempotent = false, email = null, phone = null, cashoutPayto = null, tanChannels = emptySet(), pwCrypto = cfg.pwCrypto, conversionRateClassId = null, ) } fun Route.conditional(implemented: Boolean, callback: Route.() -> Unit): Route = intercept("Conditional", callback) { if (!implemented) { throw notImplemented() } }libeufin-1.6.8/libeufin-bank/src/test/0000775000175000017500000000000015236145704020026 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/test/kotlin/0000775000175000017500000000000015236145704021326 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/src/test/kotlin/SecurityTest.kt0000664000175000017500000000635515122266731024344 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.http.* import io.ktor.http.content.* import kotlinx.serialization.json.Json import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.test.* inline fun HttpRequestBuilder.jsonDeflate(b: B) { val json = Json.encodeToString(kotlinx.serialization.serializer(), b) contentType(ContentType.Application.Json) headers[HttpHeaders.ContentEncoding] = "deflate" setBody(json.toByteArray().inputStream().deflate().readBytes()) } inline fun HttpRequestBuilder.jsonStreamDeflate(b: B) { val json = Json.encodeToString(kotlinx.serialization.serializer(), b) headers[HttpHeaders.ContentEncoding] = "deflate" setBody(OutputStreamContent({ write(json.toByteArray().inputStream().deflate().readBytes()) }, ContentType.Application.Json)) } inline fun HttpRequestBuilder.jsonStream(b: B) { val json = Json.encodeToString(kotlinx.serialization.serializer(), b) setBody(OutputStreamContent({ write(json.toByteArray()) }, ContentType.Application.Json)) } class SecurityTest { @Test fun bodySizeLimit() = bankSetup { val valid_req = obj { "payto_uri" to "$exchangePayto?message=payout" "amount" to "KUDOS:0.3" } val too_big = obj(valid_req) { "payto_uri" to "$exchangePayto?message=payout${"A".repeat(MAX_BODY_LENGTH+1)}" } client.postA("/accounts/merchant/transactions") { json(valid_req) }.assertOk() // Check body too big client.postA("/accounts/merchant/transactions") { json(too_big) }.assertPayloadTooLarge() // Check body too big even after compression client.postA("/accounts/merchant/transactions") { jsonDeflate(too_big) }.assertPayloadTooLarge() // Check streaming body too big client.postA("/accounts/merchant/transactions") { jsonStream(too_big) }.assertPayloadTooLarge() // Check streaming body too big even after compression client.postA("/accounts/merchant/transactions") { jsonStreamDeflate(too_big) }.assertPayloadTooLarge() // Check unknown encoding client.postA("/accounts/merchant/transactions") { headers[HttpHeaders.ContentEncoding] = "unknown" json(valid_req) }.assertStatus(HttpStatusCode.UnsupportedMediaType, TalerErrorCode.GENERIC_COMPRESSION_INVALID) } } libeufin-1.6.8/libeufin-bank/src/test/kotlin/bench.kt0000664000175000017500000004434415221677432022760 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.http.* import org.junit.Test import org.postgresql.jdbc.PgConnection import tech.libeufin.bank.* import tech.libeufin.common.* import tech.libeufin.common.crypto.PwCrypto import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.test.* import java.time.Instant import java.time.LocalDateTime import java.time.ZoneId import java.util.* import kotlin.math.max class Bench { /** Generate [amount] rows to fill the database */ fun genData(conn: PgConnection, amount: Int) { val amount = max(amount, 10) // Skip 4 accounts created by bankSetup val skipAccount = 4 // Customer account will be used in tests so we want to generate more data for him val customerAccount = 3 val exchangeAccount = 2 // In general half of the data is for generated account and half is for customer val mid = amount / 2 val password = PwCrypto.Bcrypt(cost = 4).hashpw("password") val token16 = ByteArray(16) val token32 = ByteArray(32) val token64 = ByteArray(64) val accountPubs = List(amount*2) { EddsaPublicKey.randEdsaKey() } conn.genData(amount, sequenceOf( "customers(username, name, password_hash, cashout_payto)" to { "account_$it\t$password\tMr n°$it\t$unknownPayto\n" }, "conversion_rate_classes(name)" to { "Class n0$it\n" }, "bank_accounts(internal_payto, owning_customer_id, is_public,conversion_rate_class_id)" to { val conversionId = when (it%5) { 0 -> "\\N" 1, 2 -> "1" 3 -> "2" else -> it%10 } "payto://x-taler-bank/localhost/account_$it\t${it+skipAccount}\t${it%3==0}\t$conversionId\n" }, "bearer_tokens(content, creation_time, expiration_time, scope, is_refreshable, bank_customer, description, last_access)" to { val account = if (it > mid) customerAccount else it+4 val hex = token32.rand().encodeHex() "\\\\x$hex\t0\t0\treadonly\tfalse\t$account\t\\N\t0\n" }, "bank_account_transactions(creditor_payto, creditor_name, debtor_payto, debtor_name, subject, amount, transaction_date, direction, bank_account_id)" to { val account = if (it > mid) customerAccount else it+4 "$unknownPayto\tcreditor_name\t$unknownPayto\tdebtor_name\tsubject\t(42,0)\t0\tcredit\t$exchangeAccount\n" + "$unknownPayto\tcreditor_name\t$unknownPayto\tdebtor_name\tsubject\t(42,0)\t0\tdebit\t$account\n" }, "bank_transaction_operations" to { val hex = token32.rand().encodeHex() "\\\\x$hex\t$it\n" }, "tan_challenges(uuid, hbody, salt, op, code, creation_date, expiration_date, retry_counter, customer, tan_channel, tan_info)" to { val account = if (it > mid) customerAccount else it+4 val uuid = UUID.randomUUID() val hex16 = token16.rand().encodeHex() val hex64 = token64.rand().encodeHex() "$uuid\t\\\\x$hex64\t\\\\x$hex16\taccount_reconfig\tcode\t0\t0\t0\t$account\tsms\tinfo\n" }, "taler_withdrawal_operations(withdrawal_uuid, wallet_bank_account, reserve_pub, creation_date)" to { val account = if (it > mid) customerAccount else it+4 val hex = token32.rand().encodeHex() val uuid = UUID.randomUUID() "$uuid\t$account\t\\\\x$hex\t0\n" }, "prepared_transfers(type, account_pub, authorization_pub, authorization_sig, recurrent, registered_at, bank_transaction_id)" to { val type = if (it % 2 == 0) "reserve" else "kyc" val recurrent = if (it % 3 == 0) "true" else "false" val incoming_transaction_id = if (it % 5 == 0) "\\N" else "${it*2}" val hex = accountPubs[it].raw.encodeHex() val hex64 = token64.rand().encodeHex() "$type\t\\\\x$hex\t\\\\x$hex\t\\\\x$hex64\t$recurrent\t0\t$incoming_transaction_id\n" }, "pending_recurrent_incoming_transactions(bank_transaction_id, debtor_account_id, authorization_pub)" to { val hex = accountPubs[it].raw.encodeHex() "${it*2}\t${it}\t\\\\x$hex\n" }, "taler_exchange_outgoing(bank_transaction)" to { "${it*2-1}\n" }, "transfer_operations(wtid, request_uid, amount, exchange_base_url, exchange_outgoing_id, exchange_id, transfer_date, creditor_payto, status, status_msg)" to { val hex32 = token32.rand().encodeHex() val hex64 = token64.rand().encodeHex() if (it % 2 == 0) { "\\\\x$hex32\t\\\\x$hex64\t(42, 0)\turl\t$it\t$it\t0\tpayto://x-taler-bank/localhost/10\tsuccess\t\\N\n" } else { "\\\\x$hex32\t\\\\x$hex64\t(42, 0)\turl\t\\N\t$it\t0\tpayto://x-taler-bank/localhost/10\tpermanent_failure\tfailure\n" } }, "taler_exchange_incoming(type, metadata, bank_transaction)" to { val hex = token32.rand().encodeHex() if (it % 2 == 0) { "reserve\t\\\\x$hex\t${it*2}\n" } else { "kyc\t\\\\x$hex\t${it*2}\n" } }, "bank_stats(timeframe, start_time)" to { val instant = Instant.ofEpochSecond(it.toLong()) val date = LocalDateTime.ofInstant(instant, ZoneId.of("UTC")) "day\t$date\n" }, "cashout_operations(request_uid,amount_debit,amount_credit,subject,creation_time,bank_account,local_transaction)" to { val account = if (it > mid) customerAccount else it+4 val hex = token32.rand().encodeHex() "\\\\x$hex\t(0,0)\t(0,0)\tsubject\t0\t$account\t$it\n" } )) } @Test fun benchDb() = bench { AMOUNT -> bankSetup { db -> // Prepare customer accounts fillCashoutInfo("customer") setMaxDebt("customer", "KUDOS:1000000") // Generate data db.conn { genData(it, AMOUNT) } val accountPubs = List(AMOUNT) { EddsaPublicKey.randEdsaKeyPair() } // Warm HTTP client client.get("/config").assertOk() // Accounts measureAction("account_create") { client.post("/accounts") { json { "username" to "account_bench_$it" "password" to "account_bench_$it-password" "name" to "Bench Account $it" } }.assertOkJson().internal_payto_uri } measureAction("account_reconfig") { client.patchA("/accounts/account_bench_$it") { json { "name" to "New Bench Account $it" } }.assertNoContent() } measureAction("account_reconfig_auth") { client.patchA("/accounts/account_bench_$it/auth") { json { "old_password" to "account_bench_$it-password" "new_password" to "account_bench_$it-password" } }.assertNoContent() } measureAction("account_list") { client.getAdmin("/accounts").assertOk() } measureAction("account_list_class") { client.getAdmin("/accounts?conversion_rate_class=${it%10}").assertOk() } measureAction("account_list_name") { client.getAdmin("/accounts?name=Mr").assertOk() } measureAction("account_list_public") { client.get("/public-accounts").assertOk() } measureAction("account_get") { client.getA("/accounts/account_bench_$it").assertOk() } // Tokens val tokens = measureAction("token_create") { client.postPw("/accounts/customer/token") { json { "scope" to "readonly" "refreshable" to true } }.assertOkJson().access_token } measureAction("token_refresh") { client.post("/accounts/customer/token") { headers[HttpHeaders.Authorization] = "Bearer ${tokens[it]}" json { "scope" to "readonly" } }.assertOk() } measureAction("token_list") { client.getA("/accounts/customer/tokens").assertOk() } measureAction("token_delete") { client.delete("/accounts/customer/token") { headers[HttpHeaders.Authorization] = "Bearer ${tokens[it]}" }.assertNoContent() } // Conversion rate classes val classes = measureAction("class_create") { client.postAdmin("/conversion-rate-classes") { json { "name" to "Gen class $it" } }.assertOkJson().conversion_rate_class_id } measureAction("class_patch") { client.patchAdmin("/conversion-rate-classes/${classes[it]}") { json { "name" to "Gen class $it" "description" to "test $it" } }.assertNoContent() } measureAction("class_get") { client.getAdmin("/conversion-rate-classes/${classes[it]}").assertOk() } measureAction("class_list") { client.getAdmin("/conversion-rate-classes").assertOk() } measureAction("class_delete") { client.deleteAdmin("/conversion-rate-classes/${classes[it]}").assertNoContent() } // Transaction val transactions = measureAction("transaction_create") { client.postA("/accounts/customer/transactions") { json { "payto_uri" to "$merchantPayto?receiver-name=Test&message=payout" "amount" to "KUDOS:0.0001" } }.assertOkJson().row_id } measureAction("transaction_get") { client.getA("/accounts/customer/transactions/${transactions[it]}").assertOk() } measureAction("transaction_history") { client.getA("/accounts/customer/transactions").assertOk() } measureAction("transaction_revenue") { client.getA("/accounts/merchant/taler-revenue/history").assertOk() } // Withdrawal val withdrawals = measureAction("withdrawal_create") { client.postA("/accounts/customer/withdrawals") { json { "amount" to "KUDOS:0.0001" } }.assertOkJson().withdrawal_id } measureAction("withdrawal_get") { client.get("/withdrawals/${withdrawals[it]}").assertOk() } measureAction("withdrawal_status") { client.get("/taler-integration/withdrawal-operation/${withdrawals[it]}").assertOk() } measureAction("withdrawal_select") { client.post("/taler-integration/withdrawal-operation/${withdrawals[it]}") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to exchangePayto } }.assertOk() } measureAction("withdrawal_confirm") { client.postA("/accounts/customer/withdrawals/${withdrawals[it]}/confirm") .assertNoContent() } measureAction("withdrawal_abort") { val uuid = client.postA("/accounts/customer/withdrawals") { json { "amount" to "KUDOS:0.0001" } }.assertOkJson().withdrawal_id client.postA("/accounts/customer/withdrawals/$uuid/abort") .assertNoContent() } // Cashout convert("KUDOS:0.1") val cashouts = measureAction("cashout_create") { client.postA("/accounts/customer/cashouts") { json { "request_uid" to ShortHashCode.rand() "amount_debit" to "KUDOS:0.1" "amount_credit" to convert("KUDOS:0.1") } }.assertOkJson().cashout_id } measureAction("cashout_get") { client.getA("/accounts/customer/cashouts/${cashouts[it]}").assertOk() } measureAction("cashout_history") { client.getA("/accounts/customer/cashouts").assertOk() } measureAction("cashout_history_admin") { client.getAdmin("/cashouts").assertOk() } // Wire gateway val transfers = measureAction("wg_transfer") { client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to "KUDOS:0.0001" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to customerPayto.canonical } }.assertOkJson().row_id } measureAction("wg_transfer_get") { client.getA("/accounts/exchange/taler-wire-gateway/transfers/${transfers[it]}").assertOk() } measureAction("wg_transfer_page") { client.getA("/accounts/exchange/taler-wire-gateway/transfers").assertOk() } measureAction("wg_transfer_page_filter") { client.getA("/accounts/exchange/taler-wire-gateway/transfers?status=success").assertOk() } measureAction("wg_add") { client.postA("/accounts/exchange/taler-wire-gateway/admin/add-incoming") { json { "amount" to "KUDOS:0.0001" "reserve_pub" to EddsaPublicKey.randEdsaKey() "debit_account" to customerPayto.canonical } }.assertOk() } measureAction("wg_incoming") { client.getA("/accounts/exchange/taler-wire-gateway/history/incoming") .assertOk() } measureAction("wg_outgoing") { client.getA("/accounts/exchange/taler-wire-gateway/history/outgoing") .assertOk() } // TAN challenges val challenges = measureAction("tan_send") { val res = client.patchA("/accounts/account_bench_$it") { json { "contact_data" to obj { "phone" to "+99" "email" to "email@example.com" } "tan_channel" to "sms" } }.assertAcceptedJson() val challenge = res.challenges[0] client.postA("/accounts/account_bench_$it/challenge/${challenge.challenge_id}").assertOk() val code = tanCode(challenge.tan_info) Pair(challenge.challenge_id, code) } measureAction("tan_confirm") { val (id, code) = challenges[it] client.postA("/accounts/account_bench_$it/challenge/$id/confirm") { json { "tan" to code } }.assertNoContent() } // Wire transfer /*measureAction("wt_register") { val (priv, pub) = accountPubs[it] val valid_req = obj { "credit_account" to exchangePayto "credit_amount" to "KUDOS:55" "type" to "reserve" "alg" to "EdDSA" "account_pub" to pub "authorization_pub" to pub "authorization_sig" to CryptoUtil.eddsaSign(pub.raw, priv) "recurrent" to false } client.post("/taler-prepared-transfer/registration") { json(valid_req) }.assertOkJson() client.post("/taler-prepared-transfer/registration") { json(valid_req) }.assertOkJson() } measureAction("wt_unregister") { val (priv, pub) = accountPubs[it] val now = Instant.now().toString() val valid_req = obj { "timestamp" to now "authorization_pub" to pub "authorization_sig" to CryptoUtil.eddsaSign(now.toByteArray(), priv) } client.post("/taler-prepared-transfer/unregistration") { json(valid_req) }.assertNoContent() client.post("/taler-prepared-transfer/unregistration") { json(valid_req) }.assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) }*/ // Delete accounts measureAction("account_delete") { client.deleteA("/accounts/account_bench_$it").assertNoContent() } // Other measureAction("monitor") { client.getAdmin("/monitor").assertOk() } db.gc.collect(Instant.now(), java.time.Duration.ZERO, java.time.Duration.ZERO, java.time.Duration.ZERO) measureAction("gc") { db.gc.collect(Instant.now(), java.time.Duration.ZERO, java.time.Duration.ZERO, java.time.Duration.ZERO) } } } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/PreparedTransferApiTest.kt0000664000175000017500000002743015221677432026437 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.test.* import java.time.Instant import kotlin.test.* class PreparedTransferApiTest { // GET /taler-prepared-transfer/config @Test fun config() = bankSetup { client.get("/taler-prepared-transfer/config").assertOkJson() } // POST /taler-prepared-transfer/registration @Test fun registration() = bankSetup { val (priv, pub) = EddsaPublicKey.randEdsaKeyPair() val amount = TalerAmount("KUDOS:1") val valid_req = SubjectRequest( exchangePayto, TransferType.reserve, false, amount, PublicKeyAlg.EdDSA, pub, pub, EddsaSignature.rand() ) val simpleSubject = TransferSubject.Simple("Taler MAP:$pub", amount) // Valid val subjects = client.post("/taler-prepared-transfer/registration") { json(valid_req.sign(priv)) }.assertOkJson { assertEquals(it.subjects[1], simpleSubject) assertIs(it.subjects[0]) }.subjects // Idempotent client.post("/taler-prepared-transfer/registration") { json(valid_req.sign(priv)) }.assertOkJson { assertEquals(it.subjects, subjects) } // KYC has a different withdrawal uri client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(type = TransferType.kyc).sign(priv)) }.assertOkJson { assertEquals(it.subjects[1], simpleSubject) val uriSubject = assertIs(it.subjects[0]) assertNotEquals(subjects[0], uriSubject) } // Recurrent only has simple subject client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(recurrent = true).sign(priv)) }.assertOkJson { assertEquals(it.subjects, listOf(simpleSubject)) } // Bad signature client.post("/taler-prepared-transfer/registration") { json(valid_req) }.assertForbidden(TalerErrorCode.BANK_BAD_SIGNATURE) // Not exchange client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(credit_account = merchantPayto).sign(priv)) }.assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE) // Unknown account client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(credit_account = unknownPayto).sign(priv)) }.assertConflict(TalerErrorCode.BANK_UNKNOWN_CREDITOR) assertBalance("customer", "+KUDOS:0") assertBalance("exchange", "+KUDOS:0") // Non recurrent accept on then bounce client.post("/taler-prepared-transfer/registration") { json(valid_req.sign(priv)) }.assertOkJson { val uuid = (it.subjects[0] as? TransferSubject.Uri)!!.uri.substringAfterLast('/') client.postA("/accounts/customer/withdrawals/$uuid/confirm").assertNoContent() // reserve tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // bounce tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // bounce assertBalance("customer", "-KUDOS:1") assertBalance("exchange", "+KUDOS:1") } // Withdrawal is aborted on completion client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(type = TransferType.kyc).sign(priv)) }.assertOkJson { val uuid = (it.subjects[0] as? TransferSubject.Uri)!!.uri.substringAfterLast('/') println("UUID $uuid") tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // kyc tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // bounce client.postA("/accounts/customer/withdrawals/$uuid/confirm") .assertConflict(TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT) // aborted assertBalance("customer", "-KUDOS:2") assertBalance("exchange", "+KUDOS:2") } // Recurrent accept one and delay others val newKey = EddsaPublicKey.randEdsaKey() client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(account_pub = newKey, recurrent = true).sign(priv)) } tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // reserve tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // pending tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // pending tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // pending tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // pending assertBalance("customer", "-KUDOS:7") assertBalance("exchange", "+KUDOS:7") // Complete pending on recurrent update val kycKey = EddsaPublicKey.randEdsaKey() client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(type= TransferType.kyc, account_pub = kycKey, recurrent = true).sign(priv)) }.assertOkJson() client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(account_pub = kycKey, recurrent = true).sign(priv)) }.assertOkJson() assertBalance("customer", "-KUDOS:7") assertBalance("exchange", "+KUDOS:7") // Kyc key reuse keep pending ones tx("customer", "KUDOS:1", "exchange", "Taler KYC:$kycKey") assertBalance("customer", "-KUDOS:8") assertBalance("exchange", "+KUDOS:8") // Switching to non recurrent cancel pending client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(type= TransferType.kyc, account_pub = kycKey).sign(priv)) }.assertOkJson() assertBalance("customer", "-KUDOS:6") assertBalance("exchange", "+KUDOS:6") // Check authorization field in incoming history val (testPriv, testAuth) = EddsaPublicKey.randEdsaKeyPair() val testKey = EddsaPublicKey.randEdsaKey() val qr = subjectFmtQrBill(testAuth) client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(account_pub=testKey, authorization_pub=testAuth, recurrent=true).sign(testPriv)) }.assertOkJson() tx("customer", "KUDOS:0.1", "exchange", "Taler MAP:$testAuth") tx("customer", "KUDOS:0.1", "exchange", "Taler MAP:$testAuth") tx("customer", "KUDOS:0.1", "exchange", "Taler MAP:$testAuth") client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(type=TransferType.kyc, account_pub=testKey, authorization_pub=testAuth, recurrent=true).sign(testPriv)) }.assertOkJson() val otherPub = EddsaPublicKey.randEdsaKey() client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(account_pub=otherPub, authorization_pub=testAuth, recurrent=true).sign(testPriv)) }.assertOkJson() val lastPub = EddsaPublicKey.randEdsaKey() tx("customer", "KUDOS:0.1", "exchange", "Taler $lastPub") tx("customer", "KUDOS:0.1", "exchange", "Taler KYC:$lastPub") val history = client.getA("/accounts/exchange/taler-wire-gateway/history/incoming?limit=-5") .assertOkJson().incoming_transactions.map { when (it) { is IncomingKycAuthTransaction -> Pair(it.account_pub, it.authorization_pub) is IncomingReserveTransaction -> Pair(it.reserve_pub, it.authorization_pub) else -> throw UnsupportedOperationException() } } assertContentEquals(history, listOf( Pair(lastPub, null), Pair(lastPub, null), Pair(otherPub, testAuth), Pair(testKey, testAuth), Pair(testKey, testAuth) )) } // DELETE /taler-prepared-transfer/registration @Test fun unregistration() = bankSetup { val (priv, pub) = EddsaPublicKey.randEdsaKeyPair() val valid_req = SubjectRequest( exchangePayto, TransferType.reserve, false, TalerAmount("KUDOS:1"), PublicKeyAlg.EdDSA, pub, pub, EddsaSignature.rand() ).sign(priv) val now = TalerTimestamp(Instant.now()) val req = Unregistration( now, pub, EddsaSignature.rand() ).sign(priv) // Unknown client.post("/taler-prepared-transfer/unregistration") { json(req) }.assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Know client.post("/taler-prepared-transfer/registration") { json(valid_req) }.assertOkJson() client.post("/taler-prepared-transfer/unregistration") { json(req) }.assertNoContent() // Idempotent client.post("/taler-prepared-transfer/unregistration") { json(req) }.assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Bad signature client.post("/taler-prepared-transfer/unregistration") { json( Unregistration( now, pub, EddsaSignature.rand() ) ) }.assertForbidden(TalerErrorCode.BANK_BAD_SIGNATURE) // Old timestamp client.post("/taler-prepared-transfer/unregistration") { json( Unregistration( TalerTimestamp(Instant.now().minusSeconds(1000000)), pub, EddsaSignature.rand() ).sign(priv) ) }.assertConflict(TalerErrorCode.BANK_OLD_TIMESTAMP) // Unknown bounce assertBalance("customer", "+KUDOS:0") assertBalance("exchange", "+KUDOS:0") tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // bounce assertBalance("customer", "+KUDOS:0") assertBalance("exchange", "+KUDOS:0") // Pending bounced after deletion val newKey = EddsaPublicKey.randEdsaKey() client.post("/taler-prepared-transfer/registration") { json(valid_req.copy(account_pub=newKey, recurrent=true).sign(priv)) }.assertOkJson() tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // reserve tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // pending tx("customer", "KUDOS:1", "exchange", "Taler MAP:$pub") // pending assertBalance("customer", "-KUDOS:3") assertBalance("exchange", "+KUDOS:3") client.post("/taler-prepared-transfer/unregistration") { json(req) }.assertNoContent() assertBalance("customer", "-KUDOS:1") assertBalance("exchange", "+KUDOS:1") } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/StatsTest.kt0000664000175000017500000002256215122266731023631 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import org.junit.Test import tech.libeufin.bank.MonitorParams import tech.libeufin.bank.MonitorResponse import tech.libeufin.bank.MonitorWithConversion import tech.libeufin.bank.Timeframe import tech.libeufin.common.ShortHashCode import tech.libeufin.common.TalerAmount import tech.libeufin.common.assertOkJson import tech.libeufin.common.db.* import tech.libeufin.common.micros import tech.libeufin.common.test.* import java.time.Instant import java.time.LocalDateTime import java.time.ZoneOffset import kotlin.test.assertEquals class StatsTest { @Test fun register() = bankSetup { db -> setMaxDebt("merchant", "KUDOS:1000") setMaxDebt("exchange", "KUDOS:1000") setMaxDebt("customer", "KUDOS:1000") suspend fun cashin(amount: String) { db.conn { conn -> val stmt = conn.talerStatement("SELECT 0 FROM cashin(?, ?, (?, ?)::taler_amount, ?)") stmt.bind(Instant.now()) stmt.bind(ShortHashCode.rand()) val amount = TalerAmount(amount) stmt.bind(amount) stmt.bind("") stmt.executeQueryCheck() } } suspend fun monitor( dbCount: (MonitorWithConversion) -> Long, count: Long, regionalVolume: (MonitorWithConversion) -> TalerAmount, regionalAmount: String, fiatVolume: ((MonitorWithConversion) -> TalerAmount)? = null, fiatAmount: String? = null ) { Timeframe.entries.forEach { timeframe -> client.getAdmin("/monitor?timestamp=${timeframe.name}").assertOkJson { val resp = it as MonitorWithConversion assertEquals(count, dbCount(resp)) assertEquals(TalerAmount(regionalAmount), regionalVolume(resp)) fiatVolume?.run { assertEquals(TalerAmount(fiatAmount!!), this(resp)) } } } } suspend fun monitorTalerIn(count: Long, amount: String) = 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, 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") monitorCashin(0, "KUDOS:0", "EUR:0") monitorCashout(0, "KUDOS:0", "EUR:0") addIncoming("KUDOS:3") monitorTalerIn(1, "KUDOS:3") addIncoming("KUDOS:7.6") monitorTalerIn(2, "KUDOS:10.6") addIncoming("KUDOS:12.3") monitorTalerIn(3, "KUDOS:22.9") // KYC are ignored addKyc("KUDOS:3") monitorTalerIn(3, "KUDOS:22.9") transfer("KUDOS:10.0") monitorTalerOut(1, "KUDOS:10.0") transfer("KUDOS:30.5") monitorTalerOut(2, "KUDOS:40.5") transfer("KUDOS:42") monitorTalerOut(3, "KUDOS:82.5") cashin("EUR:10") monitorCashin(1, "KUDOS:7.98", "EUR:10") monitorTalerIn(4, "KUDOS:30.88") cashin("EUR:20") monitorCashin(2, "KUDOS:23.96", "EUR:30") monitorTalerIn(5, "KUDOS:46.86") cashin("EUR:40") monitorCashin(3, "KUDOS:55.94", "EUR:70") monitorTalerIn(6, "KUDOS:78.84") cashout("KUDOS:3") monitorCashout(1, "KUDOS:3", "EUR:3.77") cashout("KUDOS:7.6") monitorCashout(2, "KUDOS:10.6", "EUR:13.34") cashout("KUDOS:12.3") monitorCashout(3, "KUDOS:22.9", "EUR:28.83") monitorTalerIn(6, "KUDOS:78.84") monitorTalerOut(3, "KUDOS:82.5") monitorCashin(3, "KUDOS:55.94", "EUR:70") monitorCashout(3, "KUDOS:22.9", "EUR:28.83") } @Test fun timeframe() = bankSetup { db -> db.conn { conn -> fun register(timestamp: LocalDateTime, amount: TalerAmount) { val stmt = conn.talerStatement( "CALL stats_register_payment('taler_out', ?::timestamp, (?, ?)::taler_amount, null)" ) stmt.bind(timestamp) stmt.bind(amount) stmt.executeUpdate() } suspend fun check( params: MonitorParams, count: Long, amount: TalerAmount ) { val res = db.monitor(params) assertEquals(count, res.talerOutCount, "taler count") assertEquals(amount, res.talerOutVolume, "taler volume") } suspend fun checkSimple( timestamp: LocalDateTime, timeframe: Timeframe, count: Long, amount: TalerAmount ) = check(MonitorParams(timeframe, timestamp), count, amount) suspend fun checkWhich( timestamp: LocalDateTime, timeframe: Timeframe, which: Int, count: Long, amount: TalerAmount ) = check(MonitorParams(timeframe, timestamp, which), count, amount) suspend fun checkDate( secs: Long, timeframe: Timeframe, count: Long, amount: TalerAmount ) = check(MonitorParams(timeframe, secs), count, amount) val now = LocalDateTime.now(ZoneOffset.UTC) val otherHour = now.withHour((now.hour + 1) % 24) val otherDay = now.withDayOfMonth((now.dayOfMonth) % 28 + 1) val otherMonth = now.withMonth((now.monthValue) % 12 + 1) val otherYear = now.minusYears(1) register(now, TalerAmount("KUDOS:10.0")) register(otherHour, TalerAmount("KUDOS:20.0")) register(otherDay, TalerAmount("KUDOS:35.0")) register(otherMonth, TalerAmount("KUDOS:40.0")) register(otherYear, TalerAmount("KUDOS:50.0")) // Check with timestamp and truncating checkSimple(now, Timeframe.hour, 1, TalerAmount("KUDOS:10.0")) checkSimple(otherHour, Timeframe.hour, 1, TalerAmount("KUDOS:20.0")) checkSimple(otherDay, Timeframe.day, 1, TalerAmount("KUDOS:35.0")) checkSimple(otherMonth, Timeframe.month, 1, TalerAmount("KUDOS:40.0")) checkSimple(otherYear, Timeframe.year, 1, TalerAmount("KUDOS:50.0")) // Check with timestamp and intervals checkWhich(now, Timeframe.hour, now.hour, 1, TalerAmount("KUDOS:10.0")) checkWhich(now, Timeframe.hour, otherHour.hour, 1, TalerAmount("KUDOS:20.0")) checkWhich(now, Timeframe.day, otherDay.dayOfMonth, 1, TalerAmount("KUDOS:35.0")) checkWhich(now, Timeframe.month, otherMonth.monthValue, 1, TalerAmount("KUDOS:40.0")) checkWhich(now, Timeframe.year, otherYear.year, 1, TalerAmount("KUDOS:50.0")) // Check with date seconds checkDate(now.toEpochSecond(ZoneOffset.UTC), Timeframe.hour, 1, TalerAmount("KUDOS:10.0")) checkDate(otherHour.toEpochSecond(ZoneOffset.UTC), Timeframe.hour, 1, TalerAmount("KUDOS:20.0")) checkDate(otherDay.toEpochSecond(ZoneOffset.UTC), Timeframe.day, 1, TalerAmount("KUDOS:35.0")) checkDate(otherMonth.toEpochSecond(ZoneOffset.UTC), Timeframe.month, 1, TalerAmount("KUDOS:40.0")) checkDate(otherYear.toEpochSecond(ZoneOffset.UTC), Timeframe.year, 1, TalerAmount("KUDOS:50.0")) // Check timestamp aggregation checkSimple(now, Timeframe.day, 2, TalerAmount("KUDOS:30.0")) checkSimple(now, Timeframe.month, 3, TalerAmount("KUDOS:65.0")) checkSimple(now, Timeframe.year, 4, TalerAmount("KUDOS:105.0")) checkWhich(now, Timeframe.day, now.dayOfMonth, 2, TalerAmount("KUDOS:30.0")) checkWhich(now, Timeframe.month, now.monthValue, 3, TalerAmount("KUDOS:65.0")) checkWhich(now, Timeframe.year, now.year, 4, TalerAmount("KUDOS:105.0")) checkDate(now.toEpochSecond(ZoneOffset.UTC), Timeframe.day, 2, TalerAmount("KUDOS:30.0")) checkDate(now.toEpochSecond(ZoneOffset.UTC), Timeframe.month, 3, TalerAmount("KUDOS:65.0")) checkDate(now.toEpochSecond(ZoneOffset.UTC), Timeframe.year, 4, TalerAmount("KUDOS:105.0")) } } } libeufin-1.6.8/libeufin-bank/src/test/kotlin/ObservabilityTest.kt0000664000175000017500000000351515122266731025346 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import io.ktor.client.request.* import org.junit.Test import tech.libeufin.bank.* import tech.libeufin.common.* import tech.libeufin.common.test.* class ObservabilityApiTest { // GET /taler-observability/config @Test fun config() = bankSetup { client.get("/taler-observability/config").assertOkJson() } // GET /taler-observability/metrics @Test fun metrics() = bankSetup { db -> authRoutine(HttpMethod.Get, "/taler-observability/metrics", requireAdmin = true) client.getAdmin("/taler-observability/metrics").assertOk() // Check observability token val response = client.post("/accounts/admin/token") { pwAuth() json { "scope" to "observability" "duration" to obj { "d_us" to "forever" } } }.assertOkJson() client.get("/taler-observability/metrics") { headers[HttpHeaders.Authorization] = "Bearer ${response.access_token}" }.assertOk() } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/BankIntegrationApiTest.kt0000664000175000017500000002753615156463305026255 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import org.junit.Test import tech.libeufin.bank.BankAccountCreateWithdrawalResponse import tech.libeufin.bank.BankWithdrawalOperationPostResponse import tech.libeufin.bank.BankWithdrawalOperationStatus import tech.libeufin.bank.WithdrawalStatus import tech.libeufin.common.* import tech.libeufin.common.test.* import java.util.* import kotlin.test.assertEquals class BankIntegrationApiTest { // GET /taler-integration/config @Test fun config() = bankSetup { client.get("/taler-integration/config").assertOk() } // GET /taler-integration/withdrawal-operation/UUID @Test fun get() = bankSetup { // Check OK for (valid in listOf( Pair(null, null), Pair("KUDOS:1.0", null), Pair(null, "KUDOS:2.0") , Pair("KUDOS:3.0", "KUDOS:4.0") )) { val amount = valid.first?.run(::TalerAmount) val suggested = valid.second?.run(::TalerAmount) client.postA("/accounts/merchant/withdrawals") { json { "amount" to amount "suggested_amount" to suggested } }.assertOkJson { val uuid = it.taler_withdraw_uri.split("/").last() client.get("/taler-integration/withdrawal-operation/$uuid") .assertOkJson { assert(!it.selection_done) assert(!it.aborted) assert(!it.transfer_done) assertEquals(it.card_fees, TalerAmount.zero("KUDOS")) assertEquals(it.min_amount, TalerAmount.zero("KUDOS")) assertEquals(it.max_amount, TalerAmount("KUDOS:10")) assertEquals(amount, it.amount) assertEquals(suggested, it.suggested_amount) assertEquals(listOf("iban"), it.wire_types) assertEquals("KUDOS", it.currency) } } } // Check polling statusRoutine("/taler-integration/withdrawal-operation") { it.status } // Check unknown client.get("/taler-integration/withdrawal-operation/${UUID.randomUUID()}") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Check bad UUID client.get("/taler-integration/withdrawal-operation/chocolate") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) } // POST /taler-integration/withdrawal-operation/UUID @Test fun select() = bankSetup { val reserve_pub = EddsaPublicKey.randEdsaKey() val req = obj { "reserve_pub" to reserve_pub "selected_exchange" to exchangePayto.canonical } // Check bad UUID client.post("/taler-integration/withdrawal-operation/chocolate") { json(req) }.assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Check unknown client.post("/taler-integration/withdrawal-operation/${UUID.randomUUID()}") { json(req) }.assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id // Check OK client.post("/taler-integration/withdrawal-operation/$uuid") { json(req) }.assertOkJson { assertEquals(WithdrawalStatus.selected, it.status) assertEquals("http://localhost:8080/webui/#/operation/$uuid", it.confirm_transfer_url) } // Check idempotence client.post("/taler-integration/withdrawal-operation/$uuid") { json(req) }.assertOkJson { assertEquals(WithdrawalStatus.selected, it.status) assertEquals("http://localhost:8080/webui/#/operation/$uuid", it.confirm_transfer_url) } // Check already selected client.post("/taler-integration/withdrawal-operation/$uuid") { json(req) { "reserve_pub" to EddsaPublicKey.randEdsaKey() } }.assertConflict(TalerErrorCode.BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT) } client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id // Check reserve_pub_reuse client.post("/taler-integration/withdrawal-operation/$uuid") { json(req) }.assertConflict(TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT) // Check amount differs client.post("/taler-integration/withdrawal-operation/$uuid") { json(req) { "amount" to "KUDOS:2" } }.assertConflict(TalerErrorCode.BANK_AMOUNT_DIFFERS) // Check unknown account client.post("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to unknownPayto } }.assertConflict(TalerErrorCode.BANK_UNKNOWN_ACCOUNT) // Check account not exchange client.post("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to merchantPayto } }.assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE) client.post("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to exchangePayto.canonical "amount" to "KUDOS:1" } }.assertOkJson() } // Check select aborted client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() // Check error client.postA("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to exchangePayto.canonical } }.assertConflict(TalerErrorCode.BANK_UPDATE_ABORT_CONFLICT) } client.postA("/accounts/merchant/withdrawals") { json {} }.assertOkJson { val uuid = it.withdrawal_id // Check insufficient fund client.post("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to exchangePayto.canonical "amount" to "KUDOS:11" } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) client.post("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to exchangePayto.canonical "amount" to "KUDOS:1.1" } }.assertOkJson() client.get("/taler-integration/withdrawal-operation/$uuid") .assertOkJson { assertEquals(TalerAmount("KUDOS:1.1"), it.amount) assertEquals(TalerAmount("KUDOS:10"), it.max_amount) } } } @Test fun selectWithFee() = bankSetup(conf = "test_with_fees.conf") { val uuid = client.postA("/accounts/merchant/withdrawals") { json {} }.assertOkJson().withdrawal_id // Check insufficient fund for (amount in listOf("KUDOS:11", "KUDOS:10", "KUDOS:0", "KUDOS:150")) { client.post("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to exchangePayto.canonical "amount" to amount } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) } // Check OK client.post("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to EddsaPublicKey.randEdsaKey() "selected_exchange" to exchangePayto.canonical "amount" to "KUDOS:9" } }.assertOk() } // POST /taler-integration/withdrawal-operation/UUID/abort @Test fun abort() = bankSetup { // Check abort created client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id // Check OK client.postA("/taler-integration/withdrawal-operation/$uuid/abort").assertNoContent() // Check idempotence client.postA("/taler-integration/withdrawal-operation/$uuid/abort").assertNoContent() } // Check abort selected client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) // Check OK client.postA("/taler-integration/withdrawal-operation/$uuid/abort").assertNoContent() // Check idempotence client.postA("/taler-integration/withdrawal-operation/$uuid/abort").assertNoContent() } // Check abort confirmed client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) client.postA("/accounts/merchant/withdrawals/$uuid/confirm").assertNoContent() // Check error client.postA("/taler-integration/withdrawal-operation/$uuid/abort") .assertConflict(TalerErrorCode.BANK_ABORT_CONFIRM_CONFLICT) } // Check bad UUID client.postA("/taler-integration/withdrawal-operation/chocolate/abort") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Check unknown client.postA("/taler-integration/withdrawal-operation/${UUID.randomUUID()}/abort") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/JsonTest.kt0000664000175000017500000000601715122266731023441 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.junit.Test import tech.libeufin.bank.CreditDebitInfo import tech.libeufin.common.RelativeTime import tech.libeufin.common.TalerAmount import tech.libeufin.common.TalerTimestamp import java.time.Duration import java.time.Instant import java.time.temporal.ChronoUnit @Serializable data class MyJsonType( val content: String, val n: Int ) // Running (de)serialization, only checking that no exceptions are raised. class JsonTest { @Test fun serializationTest() { Json.encodeToString(MyJsonType("Lorem Ipsum", 3)) } @Test fun deserializationTest() { val serialized = """ {"content": "Lorem Ipsum", "n": 3} """.trimIndent() Json.decodeFromString(serialized) } /** * Testing the custom absolute and relative time serializers. */ @Test fun timeSerializers() { // from JSON to time types assert(Json.decodeFromString("{\"d_us\": 3}").duration.toNanos() == 3000L) assert(Json.decodeFromString("{\"d_us\": \"forever\"}").duration == ChronoUnit.FOREVER.duration) assert(Json.decodeFromString("{\"t_s\": 3}").instant == Instant.ofEpochSecond(3)) assert(Json.decodeFromString("{\"t_s\": \"never\"}").instant == Instant.MAX) // from time types to JSON val oneDay = RelativeTime(Duration.of(1, ChronoUnit.DAYS)) val oneDaySerial = Json.encodeToString(oneDay) assert(Json.decodeFromString(oneDaySerial).duration == oneDay.duration) val forever = RelativeTime(ChronoUnit.FOREVER.duration) val foreverSerial = Json.encodeToString(forever) assert(Json.decodeFromString(foreverSerial).duration == forever.duration) } @Test fun enumSerializer() { assert("\"credit\"" == Json.encodeToString(CreditDebitInfo.credit)) assert("\"debit\"" == Json.encodeToString(CreditDebitInfo.debit)) } // Testing JSON <--> TalerAmount @Test fun amountSerializer() { val amt = Json.decodeFromString("\"KUDOS:4.4\"") assert(Json.encodeToString(amt) == "\"KUDOS:4.4\"") } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/PaytoTest.kt0000664000175000017500000000641615122266731023627 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import org.junit.Test import tech.libeufin.bank.BankAccountTransactionInfo import tech.libeufin.bank.RegisterAccountResponse import tech.libeufin.bank.TransactionCreateResponse import tech.libeufin.common.* import tech.libeufin.common.test.* import kotlin.test.assertEquals class PaytoTest { // x-taler-bank @Test fun xTalerBank() = bankSetup("test_x_taler_bank.conf") { // Check Ok client.post("/accounts") { json { "username" to "john" "password" to "john-password" "name" to "John" } }.assertOkJson { assertEquals("payto://x-taler-bank/localhost/john?receiver-name=John", it.internal_payto_uri) } // Bad IBAN payto client.post("/accounts") { json { "username" to "foo" "password" to "foo-password" "name" to "Jane" "payto_uri" to IbanPayto.rand() } }.assertBadRequest() // Bad payto username client.post("/accounts") { json { "username" to "foo" "password" to "foo-password" "name" to "Jane" "payto_uri" to "payto://x-taler-bank/localhost/not-foo" } }.assertBadRequest() // Check Ok client.post("/accounts") { json { "username" to "foo" "password" to "foo-password" "name" to "Jane" "payto_uri" to "payto://x-taler-bank/localhost/foo" } }.assertOkJson { assertEquals("payto://x-taler-bank/localhost/foo?receiver-name=Jane", it.internal_payto_uri) } // Check payto canonicalisation client.postA("/accounts/john/transactions") { json { "payto_uri" to "payto://x-taler-bank/ignored/foo?message=payout&amount=KUDOS:0.3" } }.assertOkJson { client.getA("/accounts/john/transactions/${it.row_id}") .assertOkJson { tx -> assertEquals("payout", tx.subject) assertEquals("payto://x-taler-bank/localhost/foo?receiver-name=Jane", tx.creditor_payto_uri) assertEquals("payto://x-taler-bank/localhost/john?receiver-name=John", tx.debtor_payto_uri) assertEquals(TalerAmount("KUDOS:0.3"), tx.amount) } } } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/DatabaseTest.kt0000664000175000017500000001137115122266731024233 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import kotlinx.coroutines.* import org.junit.Test import tech.libeufin.bank.* import tech.libeufin.bank.db.AccountDAO.AccountCreationResult import tech.libeufin.bank.db.TanDAO.* import tech.libeufin.common.* import tech.libeufin.common.assertOk import tech.libeufin.common.db.* import tech.libeufin.common.json import tech.libeufin.common.test.* import java.time.Duration import java.time.Instant import java.time.temporal.ChronoUnit import java.util.UUID import java.util.concurrent.TimeUnit import kotlin.test.assertEquals import kotlin.test.assertIs import kotlin.test.assertNull class DatabaseTest { // Testing the helper that creates the admin account. @Test fun createAdmin() = setup { db, ctx -> // Create admin account assertIs(createAdminAccount(db, ctx)) // Checking idempotency assertEquals(AccountCreationResult.UsernameReuse, createAdminAccount(db, ctx)) } @Test fun tanChallenge() = bankSetup { db -> db.conn { conn -> val validityPeriod = Duration.ofHours(1) val retransmissionPeriod: Duration = Duration.ofMinutes(1) val retryCounter = 3 suspend fun create(code: String, timestamp: Instant): UUID { return db.tan.new( hbody = Base32Crockford64B.rand(), salt = Base32Crockford16B.rand(), username = "customer", op = Operation.withdrawal, code = code, timestamp = timestamp, retryCounter = retryCounter, validityPeriod = validityPeriod, tanChannel = TanChannel.sms, tanInfo = "+88" ) } suspend fun markSent(id: UUID, timestamp: Instant) { db.tan.markSent(id, timestamp + retransmissionPeriod) } suspend fun send(id: UUID, code: String, timestamp: Instant): String? { return (db.tan.send( id, timestamp, 10 ) as? TanSendResult.Send)?.tanCode } val now = Instant.now() val expired = now + validityPeriod val retransmit = now + retransmissionPeriod // Check basic create("good-code", now).run { // Bad code assertEquals(TanSolveResult.BadCode, db.tan.solve(this, "bad-code", now)) // Good code assertIs(db.tan.solve(this, "good-code", now)) // Never resend a confirmed challenge assertEquals(TanSendResult.Solved, db.tan.send(this, now, 10)) // Confirmed challenge always ok assertIs(db.tan.solve(this, "good-code", now)) } // Check retry create("good-code", now).run { markSent(this, now) // Bad code repeat(retryCounter-1) { assertEquals(TanSolveResult.BadCode, db.tan.solve(this, "bad-code", now)) } assertEquals(TanSolveResult.NoRetry, db.tan.solve(this, "bad-code", now)) // Good code fail assertEquals(TanSolveResult.NoRetry, db.tan.solve(this, "good-code", now)) // New code assertIs(db.tan.send(this, now, 10)) } // Check retransmission create("good-code", now).run { // Failed to send retransmit assertIs(db.tan.send(this, now, 10)) // Code successfully sent and still valid markSent(this, now) assertIs(db.tan.send(this, now, 10)) // Code is still valid but should be resent assertIs(db.tan.send(this, retransmit, 10)) // Good code fail because expired assertEquals(TanSolveResult.Expired, db.tan.solve(this, "good-code", expired)) // No code because expired assertIs(db.tan.send(this, retransmit, 10)) } }} }libeufin-1.6.8/libeufin-bank/src/test/kotlin/AmountTest.kt0000664000175000017500000004526615122266731024004 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.common.test.* import kotlin.test.* class AmountTest { // Test amount computation in db @Test fun computationTest() = bankSetup { db -> db.conn { conn -> conn.execSQLUpdate("UPDATE libeufin_bank.bank_accounts SET balance.val = 100000 WHERE internal_payto = '${customerPayto.canonical}'") val stmt = conn.talerStatement(""" UPDATE libeufin_bank.bank_accounts SET balance = (?, ?)::taler_amount ,has_debt = ? ,max_debt = (?, ?)::taler_amount WHERE internal_payto = '${merchantPayto.canonical}' """) suspend fun routine( balance: TalerAmount, hasDebt: Boolean, maxDebt: TalerAmount, amount: TalerAmount ): Boolean { stmt.bind(balance) stmt.bind(hasDebt) stmt.bind(maxDebt) // Check bank transaction stmt.executeUpdate() val txRes = client.postA("/accounts/merchant/transactions") { json { "payto_uri" to "$customerPayto?message=" "amount" to amount } } val txBool = when { txRes.isStatus(HttpStatusCode.OK, null) -> true txRes.isStatus(HttpStatusCode.Conflict, TalerErrorCode.BANK_UNALLOWED_DEBIT) -> false else -> throw Exception("Unexpected error $txRes") } // Check whithdraw stmt.bind(balance) stmt.bind(hasDebt) stmt.bind(maxDebt) stmt.executeUpdate() for ((amount, suggested) in listOf(Pair(amount, null), Pair(null, amount), Pair(amount, amount))) { val wRes = client.postA("/accounts/merchant/withdrawals") { json { "amount" to amount "suggested_amount" to suggested } } val wBool = when { wRes.isStatus(HttpStatusCode.OK, null) -> true wRes.isStatus(HttpStatusCode.Conflict, TalerErrorCode.BANK_UNALLOWED_DEBIT) -> false else -> throw Exception("Unexpected error $wRes") } // Logic must be the same assertEquals(wBool, txBool) } return txBool } // Balance enough, assert for true assert(routine( balance = TalerAmount(10, 0, "KUDOS"), hasDebt = false, maxDebt = TalerAmount(100, 0, "KUDOS"), amount = TalerAmount(8, 0, "KUDOS"), )) // Balance still sufficient, thanks for big enough debt permission. Assert true. assert(routine( balance = TalerAmount(10, 0, "KUDOS"), hasDebt = false, maxDebt = TalerAmount(100, 0, "KUDOS"), amount = TalerAmount(80, 0, "KUDOS"), )) // Balance not enough, max debt cannot cover, asserting for false. assert(!routine( balance = TalerAmount(10, 0, "KUDOS"), hasDebt = true, maxDebt = TalerAmount(50, 0, "KUDOS"), amount = TalerAmount(80, 0, "KUDOS"), )) // Balance becomes enough, due to a larger max debt, asserting for true. assert(routine( balance = TalerAmount(10, 0, "KUDOS"), hasDebt = false, maxDebt = TalerAmount(70, 0, "KUDOS"), amount = TalerAmount(80, 0, "KUDOS"), )) // Max debt not enough for the smallest fraction, asserting for false assert(!routine( balance = TalerAmount(0, 0, "KUDOS"), hasDebt = false, maxDebt = TalerAmount(0, 1, "KUDOS"), amount = TalerAmount(0, 2, "KUDOS"), )) // Same as above, but already in debt. assert(!routine( balance = TalerAmount(0, 1, "KUDOS"), hasDebt = true, maxDebt = TalerAmount(0, 1, "KUDOS"), amount = TalerAmount(0, 1, "KUDOS"), )) }} // Max withdrawal amount computation in db @Test fun maxComputationTest() = bankSetup { db -> db.conn { conn -> val update = conn.talerStatement(""" UPDATE libeufin_bank.bank_accounts SET balance = (?, ?)::taler_amount ,has_debt = ? ,max_debt = (?, ?)::taler_amount WHERE bank_account_id = 1 """) val select = conn.talerStatement(""" SELECT (max_amount).val as max_amount_val ,(max_amount).frac as max_amount_frac FROM account_max_amount(1, (?, ?)::taler_amount) AS max_amount """) suspend fun routine( balance: TalerAmount, hasDebt: Boolean, maxDebt: TalerAmount ): TalerAmount { update.apply { bind(balance) bind(hasDebt) bind(maxDebt) executeUpdate() } select.bind(TalerAmount.max("KUDOS")) return select.one { it.getAmount("max_amount", "KUDOS") } } // Without debt assertEquals(TalerAmount(110, 3, "KUDOS"), routine( balance = TalerAmount(10, 1, "KUDOS"), hasDebt = false, maxDebt = TalerAmount(100, 2, "KUDOS"), )) // With debt assertEquals(TalerAmount(90, 1, "KUDOS"), routine( balance = TalerAmount(10, 1, "KUDOS"), hasDebt = true, maxDebt = TalerAmount(100, 2, "KUDOS"), )) }} @Test fun parseRoundTrip() { for (amount in listOf("EUR:4", "EUR:0.02", "EUR:4.12")) { assertEquals(amount, TalerAmount(amount).toString()) } } @Test fun normalize() = dbSetup { db -> db.conn { conn -> val stmt = conn.talerStatement("SELECT normalized.val, normalized.frac FROM amount_normalize((?, ?)::taler_amount) as normalized") fun TalerAmount.db(): TalerAmount { stmt.bind(value) stmt.bind(frac) return stmt.one { TalerAmount( it.getLong(1), it.getInt(2), "EUR" ) } } fun assertNormalize(from: TalerAmount, to: TalerAmount) { val normalized = from.normalize() assertEquals(to, normalized, "Bad normalization") val dbNormalized = from.db() assertEquals(normalized, dbNormalized, "DB vs code behavior") } fun assertErr(from: TalerAmount, msg: String) { assertFails { from.normalize() } assertException(msg) { from.db() } } assertNormalize(TalerAmount(4L, 2 * TalerAmount.FRACTION_BASE, "EUR"), TalerAmount("EUR:6")) assertNormalize(TalerAmount(4L, 2 * TalerAmount.FRACTION_BASE + 1, "EUR"), TalerAmount("EUR:6.00000001")) assertNormalize(TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999"), TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999")) assertErr(TalerAmount(Long.MAX_VALUE, TalerAmount.FRACTION_BASE, "EUR"), "ERROR: bigint out of range") assertErr(TalerAmount(TalerAmount.MAX_VALUE, TalerAmount.FRACTION_BASE , "EUR"), "ERROR: amount value overflowed") for (amount in listOf(TalerAmount.max("EUR"), TalerAmount.zero("EUR"))) { assertNormalize(amount, amount) } } } @Test fun add() = dbSetup { db -> db.conn { conn -> val stmt = conn.talerStatement("SELECT sum.val, sum.frac FROM amount_add((?, ?)::taler_amount, (?, ?)::taler_amount) as sum") fun TalerAmount.db(increment: TalerAmount): TalerAmount { stmt.bind(value) stmt.bind(frac) stmt.bind(increment) return stmt.one { TalerAmount( it.getLong(1), it.getInt(2), "EUR" ) } } fun assertAdd(a: TalerAmount, b: TalerAmount, sum: TalerAmount) { val codeSum = a + b assertEquals(sum, codeSum, "Bad sum") val dbSum = a.db(b) assertEquals(codeSum, dbSum, "DB vs code behavior") } fun assertErr(a: TalerAmount, b: TalerAmount, msg: String) { assertFails { a + b } assertException(msg) { a.db(b) } } assertAdd(TalerAmount.max("EUR"), TalerAmount.zero("EUR"), TalerAmount.max("EUR")) assertAdd(TalerAmount.zero("EUR"), TalerAmount.zero("EUR"), TalerAmount.zero("EUR")) assertAdd(TalerAmount("EUR:6.41"), TalerAmount("EUR:4.69"), TalerAmount("EUR:11.1")) assertAdd(TalerAmount("EUR:${TalerAmount.MAX_VALUE}"), TalerAmount("EUR:0.99999999"), TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999")) assertErr(TalerAmount(TalerAmount.MAX_VALUE - 5, 0, "EUR"), TalerAmount(6, 0, "EUR"), "ERROR: amount value overflowed") assertErr(TalerAmount(Long.MAX_VALUE, 0, "EUR"), TalerAmount(1, 0, "EUR"), "ERROR: bigint out of range") assertErr(TalerAmount(TalerAmount.MAX_VALUE - 5, TalerAmount.FRACTION_BASE - 1, "EUR"), TalerAmount(5, 2, "EUR"), "ERROR: amount value overflowed") assertErr(TalerAmount(0, Int.MAX_VALUE, "EUR"), TalerAmount(0, 1, "EUR"), "ERROR: integer out of range") } } @Test fun conversionApply() = dbSetup { db -> db.conn { conn -> fun apply(nb: TalerAmount, times: DecimalNumber, tiny: DecimalNumber = DecimalNumber("0.00000001"), roundingMode: String = "zero"): TalerAmount { val stmt = conn.talerStatement("SELECT (result).val, (result).frac FROM conversion_apply_ratio((?, ?)::taler_amount, (?, ?)::taler_amount, (0, 0)::taler_amount, (?, ?)::taler_amount, ?::rounding_mode)") stmt.bind(nb) stmt.bind(times) stmt.bind(tiny) stmt.bind(roundingMode) return stmt.one { TalerAmount( it.getLong(1), it.getInt(2), nb.currency ) } } assertEquals(TalerAmount("EUR:30.0629"), apply(TalerAmount("EUR:6.41"), DecimalNumber("4.69"))) assertEquals(TalerAmount("EUR:6.41000641"), apply(TalerAmount("EUR:6.41"), DecimalNumber("1.000001"))) assertEquals(TalerAmount("EUR:2.49999997"), apply(TalerAmount("EUR:0.99999999"), DecimalNumber("2.5"))) assertEquals(TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999"), apply(TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999"), DecimalNumber("1"))) assertEquals(TalerAmount("EUR:${TalerAmount.MAX_VALUE}"), apply(TalerAmount("EUR:${TalerAmount.MAX_VALUE/4}"), DecimalNumber("4"))) assertException("ERROR: amount value overflowed") { apply(TalerAmount(TalerAmount.MAX_VALUE/3, 0, "EUR"), DecimalNumber("3.00000001")) } assertException("ERROR: amount value overflowed") { apply(TalerAmount((TalerAmount.MAX_VALUE+2)/2, 0, "EUR"), DecimalNumber("2")) } assertException("ERROR: numeric field overflow") { apply(TalerAmount(Long.MAX_VALUE, 0, "EUR"), DecimalNumber("1")) } // Check rounding mode for ((mode, rounding) in listOf( Pair("zero", listOf(Pair(1, listOf(10, 11, 12, 12, 14, 15, 16, 17, 18, 19)))), Pair("up", listOf(Pair(1, listOf(10)), Pair(2, listOf(11, 12, 12, 14, 15, 16, 17, 18, 19)))), Pair("nearest", listOf(Pair(1, listOf(10, 11, 12, 12, 14)), Pair(2, listOf(15, 16, 17, 18, 19)))) )) { for ((rounded, amounts) in rounding) { for (amount in amounts) { // Check euro assertEquals(TalerAmount("EUR:0.0$rounded"), apply(TalerAmount("EUR:$amount"), DecimalNumber("0.001"), DecimalNumber("0.01"), mode)) // Check kudos assertEquals(TalerAmount("KUDOS:0.0000000$rounded"), apply(TalerAmount("KUDOS:0.$amount"), DecimalNumber("0.0000001"), roundingMode = mode)) } } } // Check hungarian rounding for ((mode, rounding) in listOf( Pair("zero", listOf(Pair(10, listOf(10, 11, 12, 13, 14)), Pair(15, listOf(15, 16, 17, 18, 19)))), Pair("up", listOf(Pair(10, listOf(10)), Pair(15, listOf(11, 12, 13, 14, 15)), Pair(20, listOf(16, 17, 18, 19)))), Pair("nearest", listOf(Pair(10, listOf(10, 11, 12)), Pair(15, listOf(13, 14, 15, 16, 17)), Pair(20, listOf(18, 19)))) )) { for ((rounded, amounts) in rounding) { for (amount in amounts) { assertEquals(TalerAmount("HUF:$rounded"), apply(TalerAmount("HUF:$amount"), DecimalNumber("1"), DecimalNumber("5"), mode)) } } } for (mode in listOf("zero", "up", "nearest")) { assertEquals(TalerAmount("HUF:5"), apply(TalerAmount("HUF:5"), DecimalNumber("1"), DecimalNumber("1"), mode)) } } } @Test fun conversionRevert() = dbSetup { db -> db.conn { conn -> val applyStmt = conn.talerStatement("SELECT (result).val, (result).frac FROM conversion_apply_ratio((?, ?)::taler_amount, (?, ?)::taler_amount, (0, 0)::taler_amount, (?, ?)::taler_amount, ?::rounding_mode)") fun TalerAmount.apply(ratio: DecimalNumber, tiny: DecimalNumber = DecimalNumber("0.00000001"), roundingMode: String = "zero"): TalerAmount { applyStmt.bind(this) applyStmt.bind(ratio) applyStmt.bind(tiny) applyStmt.bind(roundingMode) return applyStmt.one { TalerAmount( it.getLong(1), it.getInt(2), currency ) } } val revertStmt = conn.talerStatement("SELECT (result).val, (result).frac FROM conversion_revert_ratio((?, ?)::taler_amount, (?, ?)::taler_amount, (0, 0)::taler_amount, (?, ?)::taler_amount, ?::rounding_mode, (?, ?)::taler_amount)") fun TalerAmount.revert(ratio: DecimalNumber, tiny: DecimalNumber = DecimalNumber("0.00000001"), roundingMode: String = "zero", reverseTiny: DecimalNumber = DecimalNumber("0.00000001")): TalerAmount { revertStmt.bind(this) revertStmt.bind(ratio) revertStmt.bind(tiny) revertStmt.bind(roundingMode) revertStmt.bind(reverseTiny) return revertStmt.one { TalerAmount( it.getLong(1), it.getInt(2), currency ) } } assertEquals(TalerAmount("EUR:6.41"), TalerAmount("EUR:30.0629").revert(DecimalNumber("4.69"))) assertEquals(TalerAmount("EUR:6.41"), TalerAmount("EUR:6.41000641").revert(DecimalNumber("1.000001"))) assertEquals(TalerAmount("EUR:1"), TalerAmount("EUR:2.49999998").revert(DecimalNumber("2.5"))) assertEquals(TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999"), TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999").revert(DecimalNumber("1"))) assertEquals(TalerAmount("EUR:${TalerAmount.MAX_VALUE}"), TalerAmount("EUR:${TalerAmount.MAX_VALUE/4}").revert(DecimalNumber("0.25"))) assertException("ERROR: amount value overflowed") { TalerAmount(TalerAmount.MAX_VALUE/4, 0, "EUR").revert(DecimalNumber("0.24999999")) } assertException("ERROR: amount value overflowed") { TalerAmount((TalerAmount.MAX_VALUE+2)/2, 0, "EUR").revert(DecimalNumber("0.5")) } assertException("ERROR: numeric field overflow") { TalerAmount(Long.MAX_VALUE, 0, "EUR").revert(DecimalNumber("1")) } for (mode in sequenceOf("zero", "up", "nearest")) { for (tiny in sequenceOf("0.01", "0.00000001", "1", "2", "3", "5").map(::DecimalNumber)) { for (amount in sequenceOf(10, 11, 12, 12, 14, 15, 16, 17, 18, 19).map { TalerAmount("EUR:$it") }) { for (ratio in sequenceOf("1", "1.25", "1.26", "0.01", "0.001", "0.00000001").map(::DecimalNumber)) { for (reverseTiny in sequenceOf("0.01", "0.00000001", "1").map(::DecimalNumber)) { // Apply ratio val rounded = amount.apply(ratio, tiny, mode) // Revert ratio val revert = rounded.revert(ratio, tiny, mode, reverseTiny) // Check applying ratio again give the same result val check = revert.apply(ratio, tiny, mode) println("$amount $rounded $revert $check $ratio $tiny $mode") assertEquals(rounded, check) } } } } } } } @Test fun apiError() = bankSetup { val base = obj { "payto_uri" to "$exchangePayto?message=payout" } // Check OK client.postA("/accounts/merchant/transactions") { json(base) { "amount" to "KUDOS:0.3ABC" } }.assertBadRequest(TalerErrorCode.BANK_BAD_FORMAT_AMOUNT) client.postA("/accounts/merchant/transactions") { json(base) { "amount" to "KUDOS:999999999999999999" } }.assertBadRequest(TalerErrorCode.BANK_NUMBER_TOO_BIG) } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/CommonApiTest.kt0000664000175000017500000000231115122266731024403 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.http.* import org.junit.Test import tech.libeufin.common.TalerErrorCode import tech.libeufin.common.assertNotFound import tech.libeufin.common.assertStatus class CommonApiTest { @Test fun commonErr() = bankSetup { client.get("/unknown").assertNotFound(TalerErrorCode.GENERIC_ENDPOINT_UNKNOWN) client.post("/config").assertStatus(HttpStatusCode.MethodNotAllowed, TalerErrorCode.GENERIC_METHOD_INVALID) } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/OpenApiTest.kt0000664000175000017500000000412615204341712024054 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import org.junit.Test import sun.misc.Unsafe import tech.libeufin.bank.bankConfig import tech.libeufin.bank.corebankWebApp import tech.libeufin.bank.db.Database import tech.libeufin.common.* import java.io.File import kotlin.io.path.Path import kotlin.test.* class OpenApiTest { private fun fakeDatabase(): Database { val field = Unsafe::class.java.getDeclaredField("theUnsafe") field.isAccessible = true val unsafe = field.get(null) as Unsafe return unsafe.allocateInstance(Database::class.java) as Database } @Test fun generateSpec() { val cfg = bankConfig(Path("conf/test.conf")) testApplication { application { corebankWebApp(fakeDatabase(), cfg, serveSpec = true) } val resp = client.get("/openapi.yaml") resp.assertOk() val spec = resp.bodyAsText() assertTrue(spec.contains("openapi: 3.1.0"), "Response should be a valid OpenAPI spec") assertTrue(spec.contains("LibEuFin Bank API"), "Spec should contain the API title") val outFile = File("build/openapi.yaml") outFile.writeText(spec) println("OpenAPI spec written to ${outFile.absolutePath}") } } } libeufin-1.6.8/libeufin-bank/src/test/kotlin/routines.kt0000664000175000017500000001451715156463305023547 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.http.* import io.ktor.server.testing.* import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.serialization.json.JsonObject import tech.libeufin.bank.BankAccountCreateWithdrawalResponse import tech.libeufin.bank.WithdrawalStatus import tech.libeufin.common.* import tech.libeufin.common.test.* import kotlin.test.assertEquals // Test endpoint is correctly authenticated suspend fun ApplicationTestBuilder.authRoutine( method: HttpMethod, path: String, body: JsonObject? = null, requireExchange: Boolean = false, requireAdmin: Boolean = false, allowAdmin: Boolean = false, optional: Boolean = false ) { // No body when authentication must happen before parsing the body if (!optional) { // No header client.request(path) { this.method = method if (body != null) json(body) }.assertUnauthorized(TalerErrorCode.GENERIC_PARAMETER_MISSING) } // Bad header client.request(path) { this.method = method if (body != null) json(body) headers[HttpHeaders.Authorization] = "WTF" }.assertBadRequest(TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED) if (requireAdmin) { // Not an admin account client.request(path) { this.method = method if (body != null) json(body) tokenAuth(client, "merchant") }.assertForbidden() } else if (!allowAdmin) { // Check no admin client.request(path) { this.method = method if (body != null) json(body) tokenAuth(client, "admin") }.assertStatus(HttpStatusCode.Forbidden, null) } if (requireExchange) { // Not exchange account client.request(path) { this.method = method if (body != null) json(body) tokenAuth(client, if (requireAdmin) "admin" else "merchant") }.assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE) } } suspend inline fun ApplicationTestBuilder.historyRoutine( url: String, crossinline ids: (B) -> List, registered: List Unit>, ignored: List Unit> = listOf(), polling: Boolean = true, auth: String? = null ) { abstractHistoryRoutine(ids, registered, ignored, polling) { params: String -> client.getA("$url?$params") { tokenAuth(client, auth) } } } suspend inline fun ApplicationTestBuilder.statusRoutine( url: String, crossinline status: (B) -> WithdrawalStatus ) { val amount = TalerAmount("KUDOS:9.0") client.postA("/accounts/customer/withdrawals") { json { "amount" to amount } }.assertOkJson { resp -> val aborted_uuid = resp.taler_withdraw_uri.split("/").last() val confirmed_uuid = client.postA("/accounts/customer/withdrawals") { json { "amount" to amount } }.assertOkJson() .taler_withdraw_uri.split("/").last() // Check no useless polling assertTime(0, 500) { client.get("$url/$confirmed_uuid?timeout_ms=1000&old_state=selected") .assertOkJson { assertEquals(WithdrawalStatus.pending, status(it)) } } // Polling selected coroutineScope { launch { // Check polling succeed assertTime(100, 500) { client.get("$url/$confirmed_uuid?timeout_ms=1000") .assertOkJson { assertEquals(WithdrawalStatus.selected, status(it)) } } } launch { // Check polling succeed assertTime(100, 500) { client.get("$url/$aborted_uuid?timeout_ms=1000") .assertOkJson { assertEquals(WithdrawalStatus.selected, status(it)) } } } delay(100) withdrawalSelect(confirmed_uuid) withdrawalSelect(aborted_uuid) } // Polling confirmed coroutineScope { launch { // Check polling succeed assertTime(100, 500) { client.get("$url/$confirmed_uuid?timeout_ms=1000&old_state=selected") .assertOkJson { assertEquals(WithdrawalStatus.confirmed, status(it))} } } launch { // Check polling timeout assertTime(200, 500) { client.get("$url/$aborted_uuid?timeout_ms=200&old_state=selected") .assertOkJson { assertEquals(WithdrawalStatus.selected, status(it)) } } } delay(100) client.postA("/accounts/customer/withdrawals/$confirmed_uuid/confirm").assertNoContent() } // Polling abort coroutineScope { launch { assertTime(200, 500) { client.get("$url/$confirmed_uuid?timeout_ms=200&old_state=confirmed") .assertOkJson { assertEquals(WithdrawalStatus.confirmed, status(it))} } } launch { assertTime(100, 500) { client.get("$url/$aborted_uuid?timeout_ms=1000&old_state=selected") .assertOkJson { assertEquals(WithdrawalStatus.aborted, status(it)) } } } delay(100) client.post("/taler-integration/withdrawal-operation/$aborted_uuid/abort").assertNoContent() } } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/GcTest.kt0000664000175000017500000001535415156463305023070 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import org.junit.Test import tech.libeufin.bank.* import tech.libeufin.bank.db.CashoutDAO.CashoutCreationResult import tech.libeufin.bank.db.ExchangeDAO.TransferResult import tech.libeufin.bank.db.TransactionDAO.BankTransactionResult import tech.libeufin.bank.db.WithdrawalDAO.* import tech.libeufin.common.* import tech.libeufin.common.test.* import tech.libeufin.common.db.* import java.time.Duration import java.time.Instant import java.util.* import kotlin.test.assertEquals import kotlin.test.assertIs class GcTest { @Test fun gc() = bankSetup { db -> db.conn { conn -> fun assertNb(nb: Int, stmt: String) { assertEquals(nb, conn.talerStatement(stmt).one { it.getInt(1) }) } fun assertNbAccount(nb: Int) = assertNb(nb, "SELECT count(*) from bank_accounts") fun assertNbTokens(nb: Int) = assertNb(nb, "SELECT count(*) from bearer_tokens") fun assertNbTan(nb: Int) = assertNb(nb, "SELECT count(*) from tan_challenges") fun assertNbCashout(nb: Int) = assertNb(nb, "SELECT count(*) from cashout_operations") fun assertNbWithdrawal(nb: Int) = assertNb(nb, "SELECT count(*) from taler_withdrawal_operations") fun assertNbBankTx(nb: Int) = assertNb(nb, "SELECT count(*) from bank_transaction_operations") fun assertNbTx(nb: Int) = assertNb(nb, "SELECT count(*) from bank_account_transactions") fun assertNbIncoming(nb: Int) = assertNb(nb, "SELECT count(*) from taler_exchange_incoming") fun assertNbOutgoing(nb: Int) = assertNb(nb, "SELECT count(*) from taler_exchange_outgoing") val ZERO = TalerAmount.zero("KUDOS") val MAX = TalerAmount.max("KUDOS") // Time calculation val abortAfter = Duration.ofMinutes(15) val cleanAfter = Duration.ofDays(14) val deleteAfter = Duration.ofDays(350) val now = Instant.now() val abort = now.minus(abortAfter) val clean = now.minus(cleanAfter) val delete = now.minus(deleteAfter) // Create test accounts val payto = IbanPayto.rand() client.post("/accounts") { json { "username" to "old_account" "password" to "old_account-password" "name" to "Old Account" "cashout_payto_uri" to payto } }.assertOkJson().internal_payto_uri client.post("/accounts") { json { "username" to "recent_account" "password" to "recent_account-password" "name" to "Recent Account" "cashout_payto_uri" to payto } }.assertOkJson().internal_payto_uri assertNbAccount(6) // Create test tokens for (time in listOf(now, clean)) { for (account in listOf("old_account", "recent_account")) { db.token.create(account, ByteArray(32).rand(), time, time, TokenScope.readonly, false, null, true) db.tan.new(account, Operation.cashout, Base32Crockford64B.rand(), Base32Crockford16B.rand(), "", time, 0, Duration.ZERO, TanChannel.sms, "") } } assertNbTokens(5) assertNbTan(4) // Create test operations val from = TalerAmount("KUDOS:1") val to = convert("KUDOS:1") for ((account, times) in listOf( Pair("old_account", listOf(delete)), Pair("recent_account", listOf(now, abort, clean, delete)) )) { for (time in times) { val uuid = UUID.randomUUID() assertEquals( db.withdrawal.create(account, uuid, from, null, false, time, ZERO, ZERO, MAX), WithdrawalCreationResult.Success ) assertIs( db.withdrawal.setDetails(uuid, exchangePayto, EddsaPublicKey.randEdsaKey(), null, ZERO, ZERO, MAX) ) assertEquals( db.withdrawal.confirm(account, uuid, time, null, false, ZERO, ZERO, MAX), WithdrawalConfirmationResult.Success ) assertIs( db.cashout.create(account, ShortHashCode.rand(), from, to, "", time, false), ) assertIs( db.transaction.create(customerPayto, account, "", from, time, false, ShortHashCode.rand(), ZERO, ZERO, MAX), ) } for (time in listOf(now, abort, clean, delete)) { assertEquals( db.withdrawal.create(account, UUID.randomUUID(), from, null, false, time, ZERO, ZERO, MAX), WithdrawalCreationResult.Success ) } } for (time in listOf(now, abort, clean, delete)) { assertIs( db.exchange.transfer( TransferRequest(HashCode.rand(), from, BaseURL.parse("http://localhost/"), ShortHashCode.rand(), customerPayto), "exchange", time, false ) ) } assertNbTx(38) assertNbCashout(5) assertNbBankTx(5) assertNbWithdrawal(13) assertNbIncoming(5) assertNbOutgoing(4) // Check soft delete conn.execSQLUpdate("UPDATE bank_accounts SET balance = (0, 0)::taler_amount") for (account in listOf("old_account", "recent_account")) { client.deleteA("/accounts/$account").assertNoContent() } assertNbAccount(6) db.gc.collect( Instant.now(), abortAfter, cleanAfter, deleteAfter ) // Check hard delete assertNbAccount(5) assertNbTokens(3) assertNbTan(1) assertNbTx(24) assertNbCashout(3) assertNbBankTx(3) assertNbWithdrawal(4) assertNbIncoming(3) assertNbOutgoing(3) }} }libeufin-1.6.8/libeufin-bank/src/test/kotlin/WireGatewayApiTest.kt0000664000175000017500000005223615221677432025422 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import io.ktor.server.testing.* import io.ktor.client.request.* import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.test.* import kotlin.test.* class WireGatewayApiTest { // GET /accounts/{USERNAME}/taler-wire-gateway/config @Test fun config() = bankSetup { client.get("/accounts/merchant/taler-wire-gateway/config").assertOk() } // POST /accounts/{USERNAME}/taler-wire-gateway/transfer @Test fun transfer() = bankSetup { val valid_req = obj { "request_uid" to HashCode.rand() "amount" to "KUDOS:55" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to merchantPayto.canonical } authRoutine(HttpMethod.Post, "/accounts/merchant/taler-wire-gateway/transfer", valid_req) // Checking exchange debt constraint. client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) // Giving debt allowance and checking the OK case. setMaxDebt("exchange", "KUDOS:1000") client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) }.assertOk() // check idempotency client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) }.assertOk() val with_metadata = obj(valid_req) { "request_uid" to HashCode.rand() "metadata" to "ID" "wtid" to ShortHashCode.rand() } client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(with_metadata) }.assertOk() client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(with_metadata) }.assertOk() // Malformed metadata listOf("bad_id", "bad id", "bad@id.com", "A".repeat(41)).forEach { client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "metadata" to it } }.assertBadRequest() } val new_req = obj(valid_req) { "request_uid" to HashCode.rand() "wtid" to ShortHashCode.rand() "credit_account" to adminPayto } // Check conversion bounce client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(new_req) }.assertOk() // check idempotency client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(new_req) }.assertOk() // Trigger conflict due to reused request_uid client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "wtid" to ShortHashCode.rand() "exchange_base_url" to "http://different-exchange.example.com/" } }.assertConflict(TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED) // Trigger conflict due to reused wtid client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to HashCode.rand() } }.assertConflict(TalerErrorCode.BANK_TRANSFER_WTID_REUSED) // Currency mismatch client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "amount" to "EUR:33" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Same account client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to HashCode.rand() "wtid" to ShortHashCode.rand() "credit_account" to exchangePayto } }.assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE) // Bad BASE32 wtid client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "wtid" to "I love chocolate" } }.assertBadRequest() // Bad BASE32 len wtid client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "wtid" to randBase32Crockford(31) } }.assertBadRequest() // Bad BASE32 request_uid client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to "I love chocolate" } }.assertBadRequest() // Bad BASE32 len wtid client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to randBase32Crockford(65) } }.assertBadRequest() // Bad baseURL for (bad in sequenceOf("not-a-url", "file://not.http.com/", "no.transport.com/", "https://not.a/base/url")) { client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "exchange_base_url" to bad } }.assertBadRequest() } } @Test fun transferNoConversion() = bankSetup("test_no_conversion.conf") { val valid_req = obj { "request_uid" to HashCode.rand() "amount" to "KUDOS:55" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to merchantPayto.canonical } setMaxDebt("exchange", "KUDOS:1000") // Transfer works for common accounts client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) }.assertOk() // But fails to admin accounts client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "credit_account" to adminPayto "request_uid" to HashCode.rand() "wtid" to ShortHashCode.rand() } }.assertConflict(TalerErrorCode.BANK_ADMIN_CREDITOR) } // GET /accounts/{USERNAME}/taler-wire-gateway/transfers/{ROW_ID} @Test fun transferById() = bankSetup { var wtid = ShortHashCode.rand() val valid_req = obj { "request_uid" to HashCode.rand() "amount" to "KUDOS:0.12" "exchange_base_url" to "http://exchange.example.com/" "wtid" to wtid "credit_account" to merchantPayto.canonical } authRoutine(HttpMethod.Get, "/accounts/merchant/taler-wire-gateway/transfers/1", requireExchange = true) val resp = client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) }.assertOkJson() // Check OK client.getA("/accounts/exchange/taler-wire-gateway/transfers/${resp.row_id}") .assertOkJson { tx -> assertEquals(TransferStatusState.success, tx.status) assertEquals(TalerAmount("KUDOS:0.12"), tx.amount) assertEquals("http://exchange.example.com/", tx.origin_exchange_url) assertNull(tx.metadata) assertEquals(wtid, tx.wtid) assertEquals(resp.timestamp, tx.timestamp) } client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to HashCode.rand() "metadata" to "ID" "wtid" to ShortHashCode.rand() } }.assertOkJson { client.getA("/accounts/exchange/taler-wire-gateway/transfers/${it.row_id}") .assertOkJson { tx -> assertEquals(tx.metadata, "ID") } } // Unknown account wtid = ShortHashCode.rand() client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json(valid_req) { "request_uid" to HashCode.rand() "wtid" to wtid "credit_account" to unknownPayto } }.assertOkJson { resp -> client.getA("/accounts/exchange/taler-wire-gateway/transfers/${resp.row_id}") .assertOkJson { tx -> assertEquals(TransferStatusState.permanent_failure, tx.status) assertEquals(TalerAmount("KUDOS:0.12"), tx.amount) assertEquals("http://exchange.example.com/", tx.origin_exchange_url) assertEquals(wtid, tx.wtid) assertEquals(resp.timestamp, tx.timestamp) } } // Check unknown transaction client.getA("/accounts/exchange/taler-wire-gateway/transfers/42") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Check another user's transaction client.getA("/accounts/merchant/taler-wire-gateway/transfers/${resp.row_id}") .assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE) } // GET /accounts/{USERNAME}/taler-wire-gateway/transfers @Test fun transferPage() = bankSetup { authRoutine(HttpMethod.Get, "/accounts/merchant/taler-wire-gateway/transfers", requireExchange = true) client.getA("/accounts/exchange/taler-wire-gateway/transfers").assertNoContent() repeat(5) { client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to "KUDOS:0.12" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to merchantPayto } }.assertOkJson() } client.getA("/accounts/exchange/taler-wire-gateway/transfers") .assertOkJson { assertEquals(5, it.transfers.size) assertEquals( it, client.getA("/accounts/exchange/taler-wire-gateway/transfers?status=success").assertOkJson() ) } client.getA("/accounts/exchange/taler-wire-gateway/transfers?status=pending").assertNoContent() client.getA("/accounts/exchange/taler-wire-gateway/transfers?status=permanent_failure").assertNoContent() client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to "KUDOS:0.12" "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to unknownPayto } }.assertOkJson() client.getA("/accounts/exchange/taler-wire-gateway/transfers").assertOkJson { assertEquals(6, it.transfers.size) } client.getA("/accounts/exchange/taler-wire-gateway/transfers?status=success").assertOkJson { assertEquals(5, it.transfers.size) } client.getA("/accounts/exchange/taler-wire-gateway/transfers?status=permanent_failure").assertOkJson { assertEquals(1, it.transfers.size) } } // GET /accounts/{USERNAME}/taler-wire-gateway/history/incoming @Test fun historyIncoming() = bankSetup { // Give Foo reasonable debt allowance: setMaxDebt("merchant", "KUDOS:1000") authRoutine(HttpMethod.Get, "/accounts/merchant/taler-wire-gateway/history/incoming", requireExchange = true) historyRoutine( url = "/accounts/exchange/taler-wire-gateway/history/incoming", ids = { it.incoming_transactions.map { it.row_id } }, registered = listOf( // Reserve transactions using clean add incoming logic { addIncoming("KUDOS:10") }, // Reserve transactions using raw bank transaction logic { tx("merchant", "KUDOS:10", "exchange", "history test with ${EddsaPublicKey.randEdsaKey()} reserve pub") }, // Reserve transactions using withdraw logic { withdrawal("KUDOS:9") }, // KYC transaction using clean add incoming logic { addKyc("KUDOS:2") }, // KYC transactions using raw bank transaction logic { tx("merchant", "KUDOS:2", "exchange", "history test with KYC:${EddsaPublicKey.randEdsaKey()} account pub") }, ), ignored = listOf( // Ignore malformed incoming transaction { tx("merchant", "KUDOS:10", "exchange", "ignored") }, // Ignore malformed outgoing transaction { tx("exchange", "KUDOS:10", "merchant", "ignored") }, ) ) } // GET /accounts/{USERNAME}/taler-wire-gateway/history/outgoing @Test fun historyOutgoing() = bankSetup { setMaxDebt("exchange", "KUDOS:1000000") authRoutine(HttpMethod.Get, "/accounts/merchant/taler-wire-gateway/history/outgoing", requireExchange = true) historyRoutine( url = "/accounts/exchange/taler-wire-gateway/history/outgoing", ids = { it.outgoing_transactions.map { it.row_id } }, registered = listOf( // Transactions using clean add incoming logic { transfer("KUDOS:10") }, // And with metadata { transfer("KUDOS:12", metadata = "CON:ID") } ), ignored = listOf( // Failed transfer { transfer("KUDOS:10", unknownPayto) }, // Ignore manual outgoing transaction { tx("exchange", "KUDOS:10", "merchant", "${ShortHashCode.rand()} http://exchange.example.com/") }, // Ignore malformed incoming transaction { tx("merchant", "KUDOS:10", "exchange", "ignored") }, // Ignore malformed outgoing transaction { tx("exchange", "KUDOS:10", "merchant", "ignored") }, ) ) assertContentEquals( client.getA("/accounts/exchange/taler-wire-gateway/history/outgoing?limit=2") .assertOkJson() .outgoing_transactions .map { it.amount.toString() to it.metadata } ,listOf( "KUDOS:10" to null, "KUDOS:12" to "CON:ID", ) ) } suspend fun ApplicationTestBuilder.talerAddIncomingRoutine(type: IncomingType) { val (path, key) = when (type) { IncomingType.reserve -> Pair("add-incoming", "reserve_pub") IncomingType.kyc -> Pair("add-kycauth", "account_pub") IncomingType.map -> Pair("add-mapped", "authorization_pub") } val (priv, pub) = EddsaPublicKey.randEdsaKeyPair() client.post("/taler-prepared-transfer/registration") { json(SubjectRequest( exchangePayto, TransferType.reserve, false, TalerAmount("KUDOS:44"), PublicKeyAlg.EdDSA, pub, pub, EddsaSignature.rand() ).sign(priv)) }.assertOkJson() val valid_req = obj { "amount" to "KUDOS:44" key to pub "debit_account" to merchantPayto.canonical } authRoutine(HttpMethod.Post, "/accounts/merchant/taler-wire-gateway/admin/$path", valid_req, requireAdmin = true) // Checking exchange debt constraint. client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) // Giving debt allowance and checking the OK case. setMaxDebt("merchant", "KUDOS:1000") client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) }.assertOk() when (type) { IncomingType.reserve -> { // Trigger conflict due to reused reserve_pub client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) }.assertConflict(TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT) } IncomingType.kyc -> { // Non conflict on reuse client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) }.assertOk() } IncomingType.map -> { // Trigger conflict due to reused authorization_pub client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) }.assertConflict(TalerErrorCode.BANK_TRANSFER_MAPPING_REUSED) // Trigger conflict due to unknown authorization_pub client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) { key to EddsaPublicKey.randEdsaKey() } }.assertConflict(TalerErrorCode.BANK_TRANSFER_MAPPING_UNKNOWN) } } // Currency mismatch client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) { "amount" to "EUR:33" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Unknown account client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) { key to EddsaPublicKey.randEdsaKey() "debit_account" to unknownPayto } }.assertConflict(TalerErrorCode.BANK_UNKNOWN_DEBTOR) // Same account client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) { key to EddsaPublicKey.randEdsaKey() "debit_account" to exchangePayto } }.assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE) // Bad BASE32 reserve_pub client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) { key to "I love chocolate" } }.assertBadRequest() // Bad BASE32 len reserve_pub client.postA("/accounts/exchange/taler-wire-gateway/admin/$path") { json(valid_req) { key to randBase32Crockford(31) } }.assertBadRequest() } // POST /accounts/{USERNAME}/taler-wire-gateway/admin/add-incoming @Test fun addIncoming() = bankSetup { talerAddIncomingRoutine(IncomingType.reserve) } // POST /accounts/{USERNAME}/taler-wire-gateway/admin/add-kycauth @Test fun addKycAuth() = bankSetup { talerAddIncomingRoutine(IncomingType.kyc) } // POST /accounts/{USERNAME}/taler-wire-gateway/admin/add-mapped @Test fun addMapped() = bankSetup { talerAddIncomingRoutine(IncomingType.map) } @Test fun addIncomingMix() = bankSetup { addIncoming("KUDOS:1") addKyc("KUDOS:2") tx("merchant", "KUDOS:3", "exchange", "test with ${EddsaPublicKey.randEdsaKey()} reserve pub") tx("merchant", "KUDOS:4", "exchange", "test with KYC:${EddsaPublicKey.randEdsaKey()} account pub") client.getA("/accounts/exchange/taler-wire-gateway/history/incoming?limit=25").assertOkJson { assertEquals(4, it.incoming_transactions.size) it.incoming_transactions.forEachIndexed { i, tx -> assertEquals(TalerAmount("KUDOS:${i+1}"), tx.amount) if (i % 2 == 1) { assertIs(tx) } else { assertIs(tx) } } } } // POST /taler-wire-gateway/account/check @Test fun accountCheck() = bankSetup { client.getA("/accounts/exchange/taler-wire-gateway/account/check").assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MISSING) client.getA("/accounts/exchange/taler-wire-gateway/account/check?account=$unknownPayto").assertNotFound(TalerErrorCode.BANK_UNKNOWN_ACCOUNT) client.getA("/accounts/exchange/taler-wire-gateway/account/check?account=$merchantPayto").assertOkJson() } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/ConversionApiTest.kt0000664000175000017500000002407515122266731025313 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.http.* import org.junit.Test import tech.libeufin.bank.* import tech.libeufin.common.* import tech.libeufin.common.test.* import kotlin.test.assertEquals class ConversionApiTest { // GET /conversion-info/config @Test fun config() = bankSetup { client.get("/conversion-info/config").assertOkJson() client.get("/conversion-rate-classes/1/conversion-info/config").assertOkJson() client.get("/accounts/merchant/conversion-info/config").assertOkJson() } // POST /conversion-info/conversion-rate @Test fun conversionRate() = bankSetup { val ok = obj { "cashin_ratio" to "0.8" "cashin_fee" to "KUDOS:0.02" "cashin_tiny_amount" to "KUDOS:0.01" "cashin_rounding_mode" to "nearest" "cashin_min_amount" to "EUR:0" "cashout_ratio" to "1.25" "cashout_fee" to "EUR:0.003" "cashout_tiny_amount" to "EUR:0.01" "cashout_rounding_mode" to "zero" "cashout_min_amount" to "KUDOS:0.1" } authRoutine(HttpMethod.Post, "/conversion-info/conversion-rate", requireAdmin = true) authRoutine(HttpMethod.Post, "/accounts/merchant/conversion-info/conversion-rate", requireAdmin = true) authRoutine(HttpMethod.Post, "/conversion-rate-classes/1/conversion-info/conversion-rate", requireAdmin = true) for (prefix in sequenceOf("", "/conversion-rate-classes/1", "/accounts/merchant")) { // Good rates client.postAdmin("$prefix/conversion-info/conversion-rate") { json(ok) }.assertNoContent() // Bad currency client.postAdmin("$prefix/conversion-info/conversion-rate") { json(ok) { "cashout_fee" to "CHF:0.003" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Zero tiny amount client.postAdmin("$prefix/conversion-info/conversion-rate") { json(ok) { "cashout_tiny_amount" to "EUR:0" } }.assertBadRequest(TalerErrorCode.GENERIC_JSON_INVALID) client.postAdmin("$prefix/conversion-info/conversion-rate") { json(ok) { "cashin_tiny_amount" to "KUDOS:0" } }.assertBadRequest(TalerErrorCode.GENERIC_JSON_INVALID) // Subcent cashout tiny amount client.postAdmin("$prefix/conversion-info/conversion-rate") { json(ok) { "cashout_tiny_amount" to "EUR:0.0001" } }.assertBadRequest(TalerErrorCode.GENERIC_JSON_INVALID) } } // GET /conversion-info/rate @Test fun userRate() = bankSetup { authRoutine(HttpMethod.Get, "/accounts/merchant/conversion-info/rate", allowAdmin = true, optional = true) authRoutine(HttpMethod.Get, "/conversion-rate-classes/1/conversion-info/rate", requireAdmin = true) client.get("/conversion-info/rate").assertOkJson() client.getA("/accounts/merchant/conversion-info/rate").assertOkJson() client.get("/accounts/exchange/conversion-info/rate").assertOkJson() client.getAdmin("/conversion-rate-classes/1/conversion-info/rate").assertOkJson() } // GET /conversion-info/cashout-rate @Test fun cashoutRate() = bankSetup { authRoutine(HttpMethod.Get, "/accounts/merchant/conversion-info/cashout-rate?amount_debit=KUDOS:1", allowAdmin = true) authRoutine(HttpMethod.Get, "/conversion-rate-classes/1/conversion-info/cashout-rate?amount_debit=KUDOS:1", requireAdmin = true) for (prefix in sequenceOf("", "/conversion-rate-classes/1", "/accounts/merchant")) { // Check conversion to client.getAdmin("$prefix/conversion-info/cashout-rate?amount_debit=KUDOS:1").assertOkJson { assertEquals(TalerAmount("KUDOS:1"), it.amount_debit) assertEquals(TalerAmount("EUR:1.25"), it.amount_credit) } // Check conversion from client.getAdmin("$prefix/conversion-info/cashout-rate?amount_credit=EUR:1.257").assertOkJson { assertEquals(TalerAmount("KUDOS:1.01"), it.amount_debit) assertEquals(TalerAmount("EUR:1.257"), it.amount_credit) } // Too small client.getAdmin("$prefix/conversion-info/cashout-rate?amount_debit=KUDOS:0.0008") .assertConflict(TalerErrorCode.BANK_BAD_CONVERSION) // No amount client.getAdmin("$prefix/conversion-info/cashout-rate") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MISSING) // Both amount client.getAdmin("$prefix/conversion-info/cashout-rate?amount_debit=EUR:1&amount_credit=KUDOS:1") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Wrong format client.getAdmin("$prefix/conversion-info/cashout-rate?amount_debit=1") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) client.getAdmin("$prefix/conversion-info/cashout-rate?amount_credit=1") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Wrong currency client.getAdmin("$prefix/conversion-info/cashout-rate?amount_debit=EUR:1") .assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) client.getAdmin("$prefix/conversion-info/cashout-rate?amount_credit=KUDOS:1") .assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) } client.getA("/accounts/exchange/conversion-info/cashout-rate?amount_debit=KUDOS:1") .assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE) } // GET /conversion-info/cashin-rate @Test fun cashinRate() = bankSetup { authRoutine(HttpMethod.Get, "/conversion-rate-classes/1/conversion-info/cashin-rate?amount_debit=EUR:1", requireAdmin = true) for (prefix in sequenceOf("", "/conversion-rate-classes/1", "/accounts/exchange")) { for ((amount, converted) in listOf( Pair(0.75, 0.58), Pair(0.32, 0.24), Pair(0.66, 0.51) )) { // Check conversion to client.getAdmin("$prefix/conversion-info/cashin-rate?amount_debit=EUR:$amount").assertOkJson { assertEquals(TalerAmount("KUDOS:$converted"), it.amount_credit) assertEquals(TalerAmount("EUR:$amount"), it.amount_debit) } // Check conversion from client.getAdmin("$prefix/conversion-info/cashin-rate?amount_credit=KUDOS:$converted").assertOkJson { assertEquals(TalerAmount("KUDOS:$converted"), it.amount_credit) assertEquals(TalerAmount("EUR:$amount"), it.amount_debit) } } // No amount client.getAdmin("$prefix/conversion-info/cashin-rate") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MISSING) // Both amount client.getAdmin("$prefix/conversion-info/cashin-rate?amount_debit=KUDOS:1&amount_credit=EUR:1") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Wrong format client.getAdmin("$prefix/conversion-info/cashin-rate?amount_debit=1") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) client.getAdmin("$prefix/conversion-info/cashin-rate?amount_credit=1") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Wrong currency client.getAdmin("$prefix/conversion-info/cashin-rate?amount_debit=KUDOS:1") .assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) client.getAdmin("$prefix/conversion-info/cashin-rate?amount_credit=EUR:1") .assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) } client.get("/accounts/merchant/conversion-info/cashin-rate?amount_debit=EUR:1") .assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE) } @Test fun noRate() = bankSetup { db -> db.serializable("DELETE FROM config WHERE key='conversion_rate'") { executeUpdate() } for (prefix in sequenceOf("", "/conversion-rate-classes/1", "/accounts/merchant")) { client.getAdmin("$prefix/conversion-info/config") .assertOkJson() client.getAdmin("$prefix/conversion-info/cashout-rate") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MISSING) client.getAdmin("$prefix/conversion-info/cashout-rate?amount_credit=EUR:1") .assertConflict(TalerErrorCode.BANK_BAD_CONVERSION) } } @Test fun notImplemented() = bankSetup("test_no_conversion.conf") { for (prefix in sequenceOf("", "/conversion-rate-classes/1", "/accounts/merchant")) { client.get("$prefix/conversion-info/cashin-rate") .assertNotImplemented() client.get("$prefix/conversion-info/cashout-rate") .assertNotImplemented() } } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/helpers.kt0000664000175000017500000003324715173736052023343 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import kotlinx.coroutines.runBlocking import tech.libeufin.bank.* import tech.libeufin.bank.db.AccountDAO.AccountCreationResult import tech.libeufin.bank.db.Database import tech.libeufin.common.* import tech.libeufin.common.test.* import tech.libeufin.common.db.dbInit import tech.libeufin.common.db.pgDataSource import java.nio.file.NoSuchFileException import kotlin.io.path.Path import kotlin.io.path.deleteExisting import kotlin.io.path.readText import kotlin.random.Random import kotlin.test.assertEquals import kotlin.test.assertIs import kotlin.test.assertNotNull import java.time.Duration import java.time.Instant /* ----- Setup ----- */ val merchantPayto = IbanPayto.rand() val exchangePayto = IbanPayto.rand() val customerPayto = IbanPayto.rand() val unknownPayto = IbanPayto.rand() var tmpPayTo = IbanPayto.rand() lateinit var adminPayto: String val paytos = mapOf( "merchant" to merchantPayto, "exchange" to exchangePayto, "customer" to customerPayto ) fun genTmpPayTo(): IbanPayto { tmpPayTo = IbanPayto.rand() return tmpPayTo } fun setup( conf: String = "test.conf", lambda: suspend (Database, BankConfig) -> Unit ) = runBlocking { globalTestTokens.clear() val cfg = bankConfig(Path("conf/$conf")) pgDataSource(cfg.dbCfg.dbConnStr).run { dbInit(cfg.dbCfg, "libeufin-bank", true) dbInit(cfg.dbCfg, "libeufin-nexus", true) } cfg.withDb { db, cfg -> db.conn { conn -> val sqlProcedures = Path("${cfg.dbCfg.sqlDir}/libeufin-conversion-setup.sql") conn.execSQLUpdate(sqlProcedures.readText()) } lambda(db, cfg) } } fun bankSetup( conf: String = "test.conf", lambda: suspend ApplicationTestBuilder.(Database) -> Unit ) = setup(conf) { db, cfg -> // Creating the exchange and merchant accounts first. val bonus = TalerAmount.zero("KUDOS") assertIs(db.account.create( username = "merchant", password = "merchant-password", name = "Merchant", internalPayto = merchantPayto, maxDebt = TalerAmount("KUDOS:10"), isTalerExchange = false, isPublic = false, bonus = bonus, checkPaytoIdempotent = false, email = null, phone = null, cashoutPayto = null, tanChannels = emptySet(), conversionRateClassId = null, pwCrypto = cfg.pwCrypto )) assertIs(db.account.create( username = "exchange", password = "exchange-password", name = "Exchange", internalPayto = exchangePayto, maxDebt = TalerAmount("KUDOS:10"), isTalerExchange = true, isPublic = false, bonus = bonus, checkPaytoIdempotent = false, email = null, phone = null, cashoutPayto = null, tanChannels = emptySet(), conversionRateClassId = null, pwCrypto = cfg.pwCrypto )) assertIs(db.account.create( username = "customer", password = "customer-password", name = "Customer", internalPayto = customerPayto, maxDebt = TalerAmount("KUDOS:10"), isTalerExchange = false, isPublic = false, bonus = bonus, checkPaytoIdempotent = false, email = null, phone = null, cashoutPayto = null, tanChannels = emptySet(), conversionRateClassId = null, pwCrypto = cfg.pwCrypto )) // Create admin account val result = assertIs(createAdminAccount(db, cfg, "admin-password")) adminPayto = result.payto testApplication { application { corebankWebApp(db, cfg) } if (cfg.allowConversion) { // Set conversion rates client.postAdmin("/conversion-info/conversion-rate") { json { "cashin_ratio" to "0.8" "cashin_fee" to "KUDOS:0.02" "cashin_tiny_amount" to "KUDOS:0.01" "cashin_rounding_mode" to "nearest" "cashin_min_amount" to "EUR:0" "cashout_ratio" to "1.26" "cashout_fee" to "EUR:0.003" "cashout_tiny_amount" to "EUR:0.01" "cashout_rounding_mode" to "zero" "cashout_min_amount" to "KUDOS:0.1" } }.assertNoContent() } lambda(db) // GC everything db.gc.collect(Instant.now(), Duration.ZERO, Duration.ZERO, Duration.ZERO) } } fun dbSetup(lambda: suspend (Database) -> Unit) = setup { db, _ -> lambda(db) } /* ----- Common actions ----- */ /** Set [account] debit threshold to [maxDebt] amount */ suspend fun ApplicationTestBuilder.setMaxDebt(account: String, maxDebt: String) { client.patchAdmin("/accounts/$account") { json { "debit_threshold" to maxDebt } }.assertNoContent() } /** Check [account] balance is [amount], [amount] is prefixed with + for credit and - for debit */ suspend fun ApplicationTestBuilder.assertBalance(account: String, amount: String) { client.getAdmin("/accounts/$account").assertOkJson { val balance = it.balance val fmt = "${if (balance.credit_debit_indicator == CreditDebitInfo.debit) '-' else '+'}${balance.amount}" assertEquals(amount, fmt, "For $account") } } /** Check [account] tan channel and info */ suspend fun ApplicationTestBuilder.tanInfo(account: String): Pair { val res = client.getA("/accounts/$account").assertOkJson() val channel: TanChannel? = res.tan_channel return Pair(channel, when (channel) { TanChannel.sms -> res.contact_data!!.phone.get() TanChannel.email -> res.contact_data!!.email.get() null -> null }) } /** Perform a bank transaction of [amount] [from] account [to] account with [subject} */ suspend fun ApplicationTestBuilder.tx(from: String, amount: String, to: String, subject: String = "payout"): Long { return client.postA("/accounts/$from/transactions") { json { "payto_uri" to "${paytos[to] ?: tmpPayTo}?message=${subject.encodeURLParameter()}&amount=$amount" } }.maybeChallenge().assertOkJson().row_id } /** Perform a taler outgoing transaction of [amount] from exchange to merchant */ suspend fun ApplicationTestBuilder.transfer(amount: String, payto: IbanPayto = merchantPayto, metadata: String? = null) { client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to TalerAmount(amount) "exchange_base_url" to "http://exchange.example.com/" "wtid" to ShortHashCode.rand() "credit_account" to payto "metadata" to metadata } }.assertOk() } /** Perform a taler incoming transaction of [amount] from merchant to exchange */ suspend fun ApplicationTestBuilder.addIncoming(amount: String) { client.postA("/accounts/exchange/taler-wire-gateway/admin/add-incoming") { json { "amount" to TalerAmount(amount) "reserve_pub" to EddsaPublicKey.randEdsaKey() "debit_account" to merchantPayto } }.assertOk() } /** Perform a taler kyc transaction of [amount] from merchant to exchange */ suspend fun ApplicationTestBuilder.addKyc(amount: String) { client.postA("/accounts/exchange/taler-wire-gateway/admin/add-kycauth") { json { "amount" to TalerAmount(amount) "account_pub" to EddsaPublicKey.randEdsaKey() "debit_account" to merchantPayto } }.assertOk() } /** Perform a cashout operation of [amount] from customer */ suspend fun ApplicationTestBuilder.cashout(amount: String) { val res = client.postA("/accounts/customer/cashouts") { json { "request_uid" to ShortHashCode.rand() "amount_debit" to amount "amount_credit" to convert(amount) } } if (res.status == HttpStatusCode.Conflict) { // Retry with cashout info fillCashoutInfo("customer") client.postA("/accounts/customer/cashouts") { json { "request_uid" to ShortHashCode.rand() "amount_debit" to amount "amount_credit" to convert(amount) } } } else { res }.assertOk() } /** Perform a whithrawal operation of [amount] from customer */ suspend fun ApplicationTestBuilder.withdrawal(amount: String) { client.postA("/accounts/merchant/withdrawals") { json { "amount" to amount } }.assertOkJson { val uuid = it.taler_withdraw_uri.split("/").last() withdrawalSelect(uuid) client.postA("/accounts/merchant/withdrawals/${uuid}/confirm") .assertNoContent() } } suspend fun ApplicationTestBuilder.fillCashoutInfo(account: String) { client.patchAdmin("/accounts/$account") { json { "cashout_payto_uri" to unknownPayto "contact_data" to obj { "phone" to "+99" } } }.assertNoContent() } suspend fun ApplicationTestBuilder.fillTanInfo(username: String) { // Create a token before we require 2fa for it client.cachedToken(username) client.patchAdmin("/accounts/$username") { json { "contact_data" to obj { "phone" to "+${Random.nextInt(0, 10000)}" } "tan_channel" to "sms" } }.assertNoContent() } suspend fun ApplicationTestBuilder.withdrawalSelect(uuid: String): EddsaPublicKey { val reservePub = EddsaPublicKey.randEdsaKey() client.post("/taler-integration/withdrawal-operation/$uuid") { json { "reserve_pub" to reservePub "selected_exchange" to exchangePayto } }.assertOk() return reservePub } private var nbClass = 0; suspend fun ApplicationTestBuilder.createConversionRateClass( cashout_min_amount: TalerAmount? = null ): Long { nbClass += 1 return client.postAdmin("/conversion-rate-classes") { json { "name" to "Gen class $nbClass" "cashout_min_amount" to cashout_min_amount } }.assertOkJson().conversion_rate_class_id } suspend fun ApplicationTestBuilder.convert(amount: String): TalerAmount { return client.get("/conversion-info/cashout-rate?amount_debit=$amount") .assertOkJson().amount_credit } fun tanCode(info: String): String? { try { val file = Path("/tmp/tan-$info.txt") val code = file.readText().split(" ", limit=2).first() file.deleteExisting() return code } catch (e: Exception) { if (e is NoSuchFileException) return null throw e } } /* ----- Assert ----- */ suspend fun HttpResponse.maybeChallenge(): HttpResponse { return if (this.status == HttpStatusCode.Accepted) { this.assertChallenge() } else { this } } suspend fun HttpResponse.assertChallenge( check: suspend (ChallengeResponse) -> Unit = {} ): HttpResponse { val res = assertAcceptedJson() val username = call.request.url.segments[1] val challenge = res.challenges.random() if (res.combi_and) { for (challenge in res.challenges) { call.client.postA("/accounts/$username/challenge/${challenge.challenge_id}").assertOk() } } else { call.client.postA("/accounts/$username/challenge/${challenge.challenge_id}").assertOk() } check(res) if (res.combi_and) { for (challenge in res.challenges) { val code = assertNotNull(tanCode(challenge.tan_info)) call.client.postA("/accounts/$username/challenge/${challenge.challenge_id}/confirm") { json { "tan" to code } }.assertNoContent() } } else { val code = assertNotNull(tanCode(challenge.tan_info)) call.client.postA("/accounts/$username/challenge/${challenge.challenge_id}/confirm") { json { "tan" to code } }.assertNoContent() } // Recover body from request val requestBody = this.request.content val ids = res.challenges.map { it.challenge_id }.joinToString(", ") return call.client.request(this.call.request.url) { tokenAuth(call.client, username) method = call.request.method headers[TALER_CHALLENGE_IDS] = ids setBody(requestBody) } } fun assertException(msg: String, lambda: () -> Unit) { try { lambda() throw Exception("Expected failure") } catch (e: Exception) { assert(e.message!!.startsWith(msg)) { "${e.message}" } } } /* ----- Random data generation ----- */ fun randBase32Crockford(length: Int) = Base32Crockford.encode(ByteArray(length).rand()) libeufin-1.6.8/libeufin-bank/src/test/kotlin/CoreBankApiTest.kt0000664000175000017500000026536015156463305024661 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import kotlinx.serialization.json.JsonElement import org.junit.Test import tech.libeufin.bank.* import tech.libeufin.bank.auth.TOKEN_PREFIX import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.db.* import tech.libeufin.common.test.* import java.time.Duration import java.time.Instant import java.util.* import kotlin.test.* class CoreBankSecurityTest { @Test fun passwordUpdate() = bankSetup { db -> suspend fun currentHash(): String { return db.serializable( "SELECT password_hash FROM customers WHERE username='customer'" ) { one { it.getString(1) } } } // Set outdated hash val password = "customer-password" val pwh = CryptoUtil.hashStringSHA256(password).encodeBase64() val hash = "sha256\$$pwh" db.serializable( "UPDATE customers SET password_hash=? WHERE username='customer'" ) { bind(hash) executeUpdate() } assertEquals(hash, currentHash()) // Check hash is updated client.getA("/accounts/customer").assertOk() val newHash = currentHash() assert(hash != newHash) // Check hash stay the same client.getA("/accounts/customer").assertOk() assertEquals(newHash, currentHash()) } } class CoreBankConfigTest { // GET /config @Test fun config() = bankSetup { client.get("/config").assertOk() } // GET /monitor @Test fun monitor() = bankSetup { authRoutine(HttpMethod.Get, "/monitor", requireAdmin = true) // Check OK client.getAdmin("/monitor?timeframe=day&which=25").assertOk() client.getAdmin("/monitor?timeframe=day=which=25").assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) } } class CoreBankTokenApiTest { // POST /accounts/USERNAME/token @Test fun post() = bankSetup { db -> authRoutine(HttpMethod.Post, "/accounts/merchant/token") // Unknown account client.post("/accounts/merchant/token") { basicAuth("unknown", "password") }.assertUnauthorized() // Wrong password client.post("/accounts/merchant/token") { basicAuth("merchant", "wrong-password") }.assertUnauthorized() // Wrong account client.post("/accounts/merchant/token") { basicAuth("exchange", "merchant-password") }.assertUnauthorized() // New default token client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertOkJson { // Checking that the token lifetime defaulted to 24 hours. val token = db.token.access(Base32Crockford.decode(it.access_token.removePrefix(TOKEN_PREFIX)), Instant.now()) val lifeTime = Duration.between(token!!.creationTime, token.expirationTime) assertEquals(Duration.ofDays(1), lifeTime) } // Check default duration client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertOkJson { // Checking that the token lifetime defaulted to 24 hours. val token = db.token.access(Base32Crockford.decode(it.access_token.removePrefix(TOKEN_PREFIX)), Instant.now()) val lifeTime = Duration.between(token!!.creationTime, token.expirationTime) assertEquals(Duration.ofDays(1), lifeTime) } // Check valid refresh scope for ((fromScope, toScope) in listOf( "readwrite" to "readwrite", "readonly" to "readonly", "revenue" to "revenue", "readwrite" to "readonly", "readwrite" to "revenue", "readonly" to "revenue", )) { client.postPw("/accounts/merchant/token") { json { "scope" to fromScope "refreshable" to true } }.assertOkJson { val token = it.access_token client.post("/accounts/merchant/token") { headers[HttpHeaders.Authorization] = "Bearer $token" json { "scope" to toScope } }.assertOk() } } // Check invalid refresh scope for ((fromScope, toScope) in listOf( "readonly" to "readwrite", "revenue" to "readonly", "revenue" to "readwrite" )) { client.postPw("/accounts/merchant/token") { json { "scope" to fromScope "refreshable" to true } }.assertOkJson { val token = it.access_token client.post("/accounts/merchant/token") { headers[HttpHeaders.Authorization] = "Bearer $token" json { "scope" to toScope } }.assertForbidden(TalerErrorCode.GENERIC_TOKEN_PERMISSION_INSUFFICIENT) } } // Check no refreshable client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertOkJson { val token = it.access_token client.post("/accounts/merchant/token") { headers[HttpHeaders.Authorization] = "Bearer $token" json { "scope" to "readonly" } }.assertForbidden(TalerErrorCode.GENERIC_TOKEN_PERMISSION_INSUFFICIENT) } // Check 'forever' case. client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" "duration" to obj { "d_us" to "forever" } } }.assertOkJson { assertEquals(Instant.MAX, it.expiration.instant) } // Check too big or invalid durations client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" "duration" to obj { "d_us" to "invalid" } } }.assertBadRequest() client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" "duration" to obj { "d_us" to Long.MAX_VALUE } } }.assertBadRequest() client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" "duration" to obj { "d_us" to -1 } } }.assertBadRequest() } @Test fun post2FA() = bankSetup { db -> // Setup a known phone 2FA client.patchA("/accounts/merchant") { json { "contact_data" to obj { "phone" to "+12345" } "tan_channel" to "sms" } }.assertChallenge().assertNoContent() // Check creating a token requires to solve an unauthenticated challenge val challenge = client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertAcceptedJson().challenges[0] client.post("/accounts/merchant/challenge/${challenge.challenge_id}") .assertOk() assertEquals("REDACTED", challenge.tan_info) // Check phone number is hidden val code = tanCode("+12345") client.post("/accounts/merchant/challenge/${challenge.challenge_id}/confirm") { json { "tan" to code } }.assertNoContent() client.postPw("/accounts/merchant/token") { headers[TALER_CHALLENGE_IDS] = "${challenge.challenge_id}" json { "scope" to "readonly" } }.assertOkJson() } @Test fun locked() = bankSetup { db -> // Setup a known phone 2FA client.patchA("/accounts/merchant") { json { "contact_data" to obj { "phone" to "+12345" } "tan_channel" to "sms" } }.assertChallenge().assertNoContent() suspend fun blockAccount() { var counter = MAX_TOKEN_CREATION_ATTEMPTS + 1 while (counter > 0) { val challenge = client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertAcceptedJson().challenges[0] client.post("/accounts/merchant/challenge/${challenge.challenge_id}") .assertOk() while (counter > 0) { val error = client.post("/accounts/merchant/challenge/${challenge.challenge_id}/confirm"){ json { "tan" to "bad code" } }.json() counter -= 1 when (error.code) { TalerErrorCode.BANK_TAN_CHALLENGE_FAILED.code -> continue TalerErrorCode.BANK_TAN_RATE_LIMITED.code, TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED.code -> break else -> throw Exception("$error") } } } client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertForbidden(TalerErrorCode.BANK_ACCOUNT_LOCKED) } blockAccount() // Check token still works client.getA("/accounts/merchant").assertOkJson { assertTrue(it.is_locked) } // Check admin can unlock client.patchAdmin("/accounts/merchant/auth") { json { "new_password" to "merchant-password" } }.assertNoContent() client.getA("/accounts/merchant").assertOkJson { assertFalse(it.is_locked) } blockAccount() // Check token can unlock client.patchA("/accounts/merchant/auth") { json { "old_password" to "merchant-password" "new_password" to "merchant-password" } }.assertChallenge().assertNoContent() client.getA("/accounts/merchant").assertOkJson { assertFalse(it.is_locked) } } // DELETE /accounts/USERNAME/token @Test fun delete() = bankSetup { val token = client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertOkJson().access_token // Check OK client.delete("/accounts/merchant/token") { headers[HttpHeaders.Authorization] = "Bearer $token" }.assertNoContent() // Check token no longer work client.delete("/accounts/merchant/token") { headers[HttpHeaders.Authorization] = "Bearer $token" }.assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) } // DELETE /accounts/USERNAME/tokens/TOKEN_ID @Test fun deleteById() = bankSetup { authRoutine(HttpMethod.Delete, "/accounts/merchant/tokens/1t", allowAdmin = true) val token = client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertOkJson().access_token // Check OK client.deleteA("/accounts/merchant/tokens/2").assertNoContent() client.deleteA("/accounts/merchant/tokens/2").assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Check token no longer work client.delete("/accounts/merchant/token") { headers[HttpHeaders.Authorization] = "Bearer $token" }.assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) } // GET /accounts/USERNAME/tokens @Test fun get() = bankSetup { // Check OK for (account in listOf("merchant", "customer")) { client.getA("/accounts/$account/tokens").assertOkJson { assertEquals(1, it.tokens.size) } } client.postPw("/accounts/merchant/token") { json { "scope" to "readonly" } }.assertOk() client.postPw("/accounts/merchant/token") { json { "scope" to "readwrite" } }.assertOk() client.postPw("/accounts/customer/token") { json { "scope" to "revenue" "description" to "description" } }.assertOk() client.getA("/accounts/merchant/tokens").assertOkJson { assertEquals(3, it.tokens.size) for (token in it.tokens) { assertNull(token.description) } } client.getA("/accounts/customer/tokens").assertOkJson { assertEquals(2, it.tokens.size) assertEquals("description", it.tokens[0].description) } } } class CoreBankAccountsApiTest { // POST /accounts @Test fun create() = bankSetup { // Check generated payto obj { "username" to "john" "password" to "password" "name" to "John" }.let { req -> // Check Ok val payto = client.post("/accounts") { json(req) }.assertOkJson().internal_payto_uri // Check idempotency client.post("/accounts") { json(req) }.assertOkJson { assertEquals(payto, it.internal_payto_uri) } // Check idempotency with payto client.post("/accounts") { json(req) { "payto_uri" to payto } }.assertOk() // Check payto conflict client.post("/accounts") { json(req) { "payto_uri" to IbanPayto.rand() } }.assertConflict(TalerErrorCode.BANK_REGISTER_USERNAME_REUSE) } // Check given payto val payto = IbanPayto.rand() val req = obj { "username" to "foo" "password" to "password" "name" to "Jane" "is_public" to true "payto_uri" to payto "is_taler_exchange" to true } // Check Ok client.post("/accounts") { json(req) }.assertOkJson { assertEquals(payto.full("Jane"), it.internal_payto_uri) } // Testing idempotency client.post("/accounts") { json(req) }.assertOkJson { assertEquals(payto.full("Jane"), it.internal_payto_uri) } // Check admin only debit_threshold obj { "username" to "bat" "password" to "password" "name" to "Bat" "debit_threshold" to "KUDOS:42" }.let { req -> client.post("/accounts") { json(req) }.assertConflict(TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT) client.postAdmin("/accounts") { json(req) }.assertOk() } // Check admin only conversion_rate_class_id createConversionRateClass() obj { "username" to "bat2" "password" to "password" "name" to "Bat" "conversion_rate_class_id" to 1 }.let { req -> client.post("/accounts") { json(req) }.assertConflict(TalerErrorCode.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS) client.postAdmin("/accounts") { json(req) }.assertOk() } // Check admin only tan_channel obj { "username" to "bat3" "password" to "password" "name" to "Bat" "contact_data" to obj { "phone" to "+456" } "tan_channel" to "sms" }.let { req -> client.post("/accounts") { json(req) }.assertConflict(TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL) client.postAdmin("/accounts") { json(req) }.assertOk() } // Check both tan channels client.postAdmin("/accounts") { json { "username" to "bat2" "password" to "password" "name" to "Bat" "tan_channel" to "sms" "tan_channels" to emptyList() } }.assertBadRequest() // Check tan info val channels = listOf("sms", "email") for (channel in channels) { client.postAdmin("/accounts") { json { "username" to "bat2" "password" to "password" "name" to "Bat" "tan_channel" to channel } }.assertConflict(TalerErrorCode.BANK_MISSING_TAN_INFO) client.postAdmin("/accounts") { json { "username" to "bat2" "password" to "password" "name" to "Bat" "tan_channels" to listOf(channel) } }.assertConflict(TalerErrorCode.BANK_MISSING_TAN_INFO) } client.postAdmin("/accounts") { json { "username" to "bat2" "password" to "password" "name" to "Bat" "tan_channels" to channels } }.assertConflict(TalerErrorCode.BANK_MISSING_TAN_INFO) // Check unknown conversion rate class client.postAdmin("/accounts") { json { "username" to "new_account" "password" to "password" "name" to "New Account" "conversion_rate_class_id" to 42 } }.assertConflict(TalerErrorCode.BANK_CONVERSION_RATE_CLASS_UNKNOWN) // Reserved account RESERVED_ACCOUNTS.forEach { client.post("/accounts") { json { "username" to it "password" to "password" "name" to "John Smith" } }.assertConflict(TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT) } // Malformed username listOf("bad@username", "long".repeat(50)).forEach { client.post("/accounts") { json { "username" to it "password" to "password" "name" to "John Smith" } }.assertBadRequest() } // Non exchange account client.post("/accounts") { json { "username" to "exchange" "password" to "password" "name" to "Exchange" } }.assertConflict(TalerErrorCode.END) // Testing username conflict client.post("/accounts") { json(req) { "name" to "Foo" } }.assertConflict(TalerErrorCode.BANK_REGISTER_USERNAME_REUSE) // Testing payto conflict client.post("/accounts") { json(req) { "username" to "bar" } }.assertConflict(TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE) client.getAdmin("/accounts/bar").assertNotFound(TalerErrorCode.BANK_UNKNOWN_ACCOUNT) // Testing bad payto kind client.post("/accounts") { json(req) { "username" to "bar" "password" to "bar-password" "name" to "Mr Bar" "payto_uri" to "payto://x-taler-bank/bank.hostname.test/bar" } }.assertBadRequest() // Testing short password client.post("/accounts") { json(req) { "password" to "short" } }.assertConflict(TalerErrorCode.BANK_PASSWORD_TOO_SHORT) // Testing long password client.post("/accounts") { json(req) { "password" to "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong-password" } }.assertConflict(TalerErrorCode.BANK_PASSWORD_TOO_LONG) // Check cashout payto receiver name logic client.post("/accounts") { json { "username" to "cashout_guess" "password" to "cashout_guess-password" "name" to "Mr Guess My Name" "cashout_payto_uri" to payto } }.assertOk() client.getA("/accounts/cashout_guess").assertOkJson { assertEquals(payto.full("Mr Guess My Name"), it.cashout_payto_uri) } client.post("/accounts") { json { "username" to "cashout_keep" "password" to "cashout_keep-password" "name" to "Mr Keep My Name" "cashout_payto_uri" to payto.full("Santa Claus") } }.assertOk() client.getA("/accounts/cashout_keep").assertOkJson { assertEquals(payto.full("Mr Keep My Name"), it.cashout_payto_uri) } // Check input restrictions obj { "username" to "username" "password" to "password" "name" to "Name" }.let { req -> client.post("/accounts") { json(req) { "username" to "bad/username" } }.assertBadRequest() client.post("/accounts") { json(req) { "username" to " spaces " } }.assertBadRequest() client.post("/accounts") { json(req) { "contact_data" to obj { "phone" to " +456" } } }.assertBadRequest() client.post("/accounts") { json(req) { "contact_data" to obj { "phone" to " test@mail.com" } } }.assertBadRequest() } } // Test account created with bonus @Test fun createBonus() = bankSetup(conf = "test_bonus.conf") { val req = obj { "username" to "foo" "password" to "password-xyz" "name" to "Mallory" } setMaxDebt("admin", "KUDOS:10000") // Check ok repeat(100) { client.postAdmin("/accounts") { json(req) { "username" to "foo$it" } }.assertOk() assertBalance("foo$it", "+KUDOS:100") } assertBalance("admin", "-KUDOS:10000") // Check insufficient fund client.postAdmin("/accounts") { json(req) { "username" to "bar" } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) client.getAdmin("/accounts/bar").assertNotFound(TalerErrorCode.BANK_UNKNOWN_ACCOUNT) } // Test admin-only account creation @Test fun createRestricted() = bankSetup(conf = "test_restrict.conf") { authRoutine(HttpMethod.Post, "/accounts", requireAdmin = true) client.postAdmin("/accounts") { json { "username" to "baz" "password" to "password-xyz" "name" to "Mallory" } }.assertOk() } // Test admin-only account creation @Test fun createTanErr() = bankSetup(conf = "test_tan_err.conf") { client.postAdmin("/accounts") { json { "username" to "baz" "password" to "xyz" "name" to "Mallory" "tan_channel" to "email" } }.assertConflict(TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED) } // POST /accounts @Test fun createNoCheck() = bankSetup("test_no_password_check.conf") { // Testing short password client.post("/accounts") { json { "username" to "short" "name" to "John Smith" "password" to "short" } }.assertOk() // Testing long password client.post("/accounts") { json { "username" to "long" "name" to "Jane Smith" "password" to "loooooooooooooooooooooooooooooooooooooooooooooooooooooooong-password" } }.assertOk() } // DELETE /accounts/USERNAME @Test fun delete() = bankSetup { db -> authRoutine(HttpMethod.Delete, "/accounts/merchant", allowAdmin = true) // Reserved account RESERVED_ACCOUNTS.forEach { client.deleteAdmin("/accounts/$it") .assertConflict(TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT) } client.deleteA("/accounts/exchange") .assertConflict(TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT) client.post("/accounts") { json { "username" to "john" "password" to "john-password" "name" to "John" "payto_uri" to genTmpPayTo() } }.assertOk() fillTanInfo("john") // Fail to delete, due to a non-zero balance. tx("customer", "KUDOS:1", "john") client.deleteA("/accounts/john") .assertConflict(TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO) // Successful deletion tx("john", "KUDOS:1", "customer") client.deleteA("/accounts/john") .assertChallenge() .assertNoContent() // Account no longer exists client.deleteA("/accounts/john") .assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) client.deleteAdmin("/accounts/john") .assertNotFound(TalerErrorCode.BANK_UNKNOWN_ACCOUNT) } @Test fun softDelete() = bankSetup { db -> // Create all kind of operations val token = client.postPw("/accounts/customer/token") { json { "scope" to "readonly" } }.assertOkJson().access_token val tx_id = client.postA("/accounts/customer/transactions") { json { "payto_uri" to "$exchangePayto?message=payout" "amount" to "KUDOS:0.3" } }.assertOkJson().row_id val withdrawal_id = client.postA("/accounts/customer/withdrawals") { json { "amount" to "KUDOS:9.0" } }.assertOkJson().withdrawal_id fillCashoutInfo("customer") val cashout_id = client.postA("/accounts/customer/cashouts") { json { "request_uid" to ShortHashCode.rand() "amount_debit" to "KUDOS:1" "amount_credit" to convert("KUDOS:1") } }.assertOkJson().cashout_id fillTanInfo("customer") client.postA("/accounts/customer/transactions") { json { "payto_uri" to "$exchangePayto?message=payout" "amount" to "KUDOS:0.3" } }.assertAcceptedJson() // Delete account tx("merchant", "KUDOS:1", "customer") assertBalance("customer", "+KUDOS:0") client.deleteA("/accounts/customer") .assertChallenge() .assertNoContent() // Check account can no longer username client.delete("/accounts/customer/token") { headers[HttpHeaders.Authorization] = "Bearer $token" }.assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) client.getA("/accounts/customer/transactions/$tx_id") .assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) client.getA("/accounts/customer/cashouts/$cashout_id") .assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) client.postA("/accounts/customer/withdrawals/$withdrawal_id/confirm") .assertUnauthorized(TalerErrorCode.GENERIC_TOKEN_UNKNOWN) // But admin can still see existing operations client.getAdmin("/accounts/customer/transactions/$tx_id") .assertOkJson() client.getAdmin("/accounts/customer/cashouts/$cashout_id") .assertOkJson() client.get("/withdrawals/$withdrawal_id") .assertOkJson() // GC db.gc.collect(Instant.now(), Duration.ZERO, Duration.ZERO, Duration.ZERO) client.getAdmin("/accounts/customer/transactions/$tx_id") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) client.getAdmin("/accounts/customer/cashouts/$cashout_id") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) client.get("/withdrawals/$withdrawal_id") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } // Test admin-only account deletion @Test fun deleteRestricted() = bankSetup(conf = "test_restrict.conf") { authRoutine(HttpMethod.Post, "/accounts", requireAdmin = true) // Exchange is still restricted client.deleteAdmin("/accounts/exchange") { }.assertConflict(TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT) } // Test delete exchange account @Test fun deleteNoConversion() = bankSetup(conf = "test_no_conversion.conf") { // Exchange is no longer restricted client.deleteA("/accounts/exchange").assertNoContent() } suspend fun ApplicationTestBuilder.checkAdminOnly( req: JsonElement, error: TalerErrorCode ) { // Check restricted client.patchA("/accounts/merchant") { json(req) }.assertConflict(error) // Check admin always can client.patchAdmin("/accounts/merchant") { json(req) }.assertNoContent() // Check idempotent client.patchA("/accounts/merchant") { json(req) }.assertNoContent() } // PATCH /accounts/USERNAME @Test fun reconfig() = bankSetup { authRoutine(HttpMethod.Patch, "/accounts/merchant", allowAdmin = true) // Check tan info val channels = listOf("sms", "email") for (channel in channels) { client.patchA("/accounts/merchant") { json { "tan_channel" to channel } }.assertConflict(TalerErrorCode.BANK_MISSING_TAN_INFO) client.patchA("/accounts/merchant") { json { "tan_channels" to listOf(channel) } }.assertConflict(TalerErrorCode.BANK_MISSING_TAN_INFO) } client.patchA("/accounts/merchant") { json { "tan_channels" to channels } }.assertConflict(TalerErrorCode.BANK_MISSING_TAN_INFO) // Successful attempt now val cashout = IbanPayto.rand() val req = obj { "cashout_payto_uri" to cashout "name" to "Roger" "is_public" to true "contact_data" to obj { "phone" to "+99" "email" to "foo@example.com" } } client.patchA("/accounts/merchant") { json(req) }.assertNoContent() // Checking idempotence client.patchA("/accounts/merchant") { json(req) }.assertNoContent() checkAdminOnly( obj(req) { "debit_threshold" to "KUDOS:100" }, TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT ) createConversionRateClass() checkAdminOnly( obj(req) { "conversion_rate_class_id" to 1 }, TalerErrorCode.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS ) // Check unknown conversion rate class client.patchAdmin("/accounts/merchant") { json(req) { "conversion_rate_class_id" to 42} }.assertConflict(TalerErrorCode.BANK_CONVERSION_RATE_CLASS_UNKNOWN) // Check currency client.patchAdmin("/accounts/merchant") { json(req) { "debit_threshold" to "EUR:100" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Check patch client.getA("/accounts/merchant").assertOkJson { obj -> assertEquals("Roger", obj.name) assertEquals(cashout.full(obj.name), obj.cashout_payto_uri) assertEquals("+99", obj.contact_data?.phone?.get()) assertEquals("foo@example.com", obj.contact_data?.email?.get()) assertEquals(TalerAmount("KUDOS:100"), obj.debit_threshold) assert(obj.is_public) assert(!obj.is_taler_exchange) } // Check keep values when there is no changes client.patchA("/accounts/merchant") { json { } }.assertNoContent() client.getA("/accounts/merchant").assertOkJson { obj -> assertEquals("Roger", obj.name) assertEquals(cashout.full(obj.name), obj.cashout_payto_uri) assertEquals("+99", obj.contact_data?.phone?.get()) assertEquals("foo@example.com", obj.contact_data?.email?.get()) assertEquals(TalerAmount("KUDOS:100"), obj.debit_threshold) assert(obj.is_public) assert(!obj.is_taler_exchange) } // Admin cannot be public client.patchA("/accounts/admin") { json { "is_public" to true } }.assertConflict(TalerErrorCode.END) // Exchange must be exchange client.patchA("/accounts/exchange") { json { "is_taler_exchange" to false } }.assertConflict(TalerErrorCode.END) // Check cashout payto receiver name logic client.post("/accounts") { json { "username" to "cashout" "password" to "cashout-password" "name" to "Mr Cashout Cashout" } }.assertOk() val canonical = Payto.parse(cashout.canonical).expectIban() for ((cashout, name, expect) in listOf( Triple(cashout.canonical, null, canonical.full("Mr Cashout Cashout")), Triple(cashout.canonical, "New name", canonical.full("New name")), Triple(cashout.full("Full name"), null, cashout.full("New name")), Triple(cashout.full("Full second name"), "Another name", cashout.full("Another name")) )) { client.patchAdmin("/accounts/cashout") { json { "cashout_payto_uri" to cashout if (name != null) "name" to name } }.assertNoContent() client.getA("/accounts/cashout").assertOkJson { obj -> assertEquals(expect, obj.cashout_payto_uri) } } // Check 2FA fillTanInfo("merchant") client.patchA("/accounts/merchant") { json { "is_public" to false } }.assertChallenge { client.getA("/accounts/merchant").assertOkJson { obj -> assert(obj.is_public) } }.assertNoContent() client.getA("/accounts/merchant").assertOkJson { obj -> assert(!obj.is_public) } } // Test admin-only account patch @Test fun patchRestricted() = bankSetup(conf = "test_restrict.conf") { // Check restricted checkAdminOnly( obj { "name" to "Another Foo" }, TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME ) checkAdminOnly( obj { "cashout_payto_uri" to IbanPayto.rand() }, TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT ) // Check idempotent client.getA("/accounts/merchant").assertOkJson { obj -> client.patchA("/accounts/merchant") { json { "name" to obj.name "cashout_payto_uri" to obj.cashout_payto_uri "debit_threshold" to obj.debit_threshold } }.assertNoContent() } } // Test TAN check account patch @Test fun patchTanErr() = bankSetup(conf = "test_tan_err.conf") { // Check unsupported TAN channel client.patchA("/accounts/customer") { json { "tan_channel" to "email" } }.assertConflict(TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED) } // PATCH /accounts/USERNAME/auth @Test fun passwordChange() = bankSetup { authRoutine(HttpMethod.Patch, "/accounts/merchant/auth", allowAdmin = true) // Changing the password. client.patchA("/accounts/customer/auth") { json { "old_password" to "customer-password" "new_password" to "new-password" } }.assertNoContent() // Previous password should fail. client.post("/accounts/customer/token") { basicAuth("customer", "customer-password") }.assertUnauthorized() // New password should succeed. client.post("/accounts/customer/token") { basicAuth("customer", "new-password") json { "scope" to "readonly" } }.assertOk() client.patchA("/accounts/customer/auth") { json { "old_password" to "new-password" "new_password" to "customer-password" } }.assertNoContent() // Check require test old password client.patchA("/accounts/customer/auth") { json { "old_password" to "bad-password" "new_password" to "new-password" } }.assertConflict(TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD) // Check require old password for user client.patchA("/accounts/customer/auth") { json { "new_password" to "new-password" } }.assertConflict(TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD) // Testing short password client.patchA("/accounts/merchant/auth") { json { "old_password" to "ignored" "new_password" to "short" } }.assertConflict(TalerErrorCode.BANK_PASSWORD_TOO_SHORT) // Testing long password client.patchA("/accounts/merchant/auth") { json { "old_password" to "ignored" "new_password" to "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong-password" } }.assertConflict(TalerErrorCode.BANK_PASSWORD_TOO_LONG) // Check admin client.patchAdmin("/accounts/customer/auth") { json { "new_password" to "customer-password" } }.assertNoContent() // Check 2FA fillTanInfo("customer") client.patchA("/accounts/customer/auth") { json { "old_password" to "customer-password" "new_password" to "it-password" } }.assertChallenge().assertNoContent() client.patchAdmin("/accounts/customer/auth") { json { "new_password" to "new-password" } }.assertNoContent() // Check 2FA after password check client.patchA("/accounts/customer/auth") { json { "old_password" to "password" "new_password" to "new-password" } }.assertConflict(TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD) } // PATCH /accounts/USERNAME/auth @Test fun passwordChangeNoCheck() = bankSetup("test_no_password_check.conf") { // Testing short password client.patchA("/accounts/merchant/auth") { json { "old_password" to "merchant-password" "new_password" to "short" } }.assertNoContent() // Testing long password client.patchA("/accounts/merchant/auth") { json { "old_password" to "short" "new_password" to "looooooooooooooooooooooooooooooooooooooooooooooooooooooooong-password" } }.assertNoContent() } // GET /public-accounts and GET /accounts @Test fun list() = bankSetup(conf = "test_no_conversion.conf") { db -> authRoutine(HttpMethod.Get, "/accounts", requireAdmin = true) // Remove default accounts val defaultAccounts = listOf("merchant", "exchange", "customer") defaultAccounts.forEach { client.deleteAdmin("/accounts/$it").assertNoContent() } client.getAdmin("/accounts").assertOkJson { for (account in it.accounts) { assertNull(account.conversion_rate) if (defaultAccounts.contains(account.username)) { assertEquals(AccountStatus.deleted, account.status) } else { assertEquals(AccountStatus.active, account.status) } } } db.gc.collect(Instant.now(), Duration.ZERO, Duration.ZERO, Duration.ZERO) // Check error when no public accounts client.get("/public-accounts").assertNoContent() client.getAdmin("/accounts").assertOkJson() } @Test fun listConversionClass() = bankSetup(conf = "test.conf") { db -> repeat(3) { createConversionRateClass() } // Gen some public and private accounts repeat(5) { client.postAdmin("/accounts") { val mod = it%3 val rateClassId = if (mod in 1..3) mod else null json { "username" to "$it" "password" to "password" "name" to "Mr 1$it" "is_public" to (it%2 == 0) "conversion_rate_class_id" to rateClassId } }.assertOk() } // All public client.get("/public-accounts").assertOkJson { assertEquals(3, it.public_accounts.size) it.public_accounts.forEach { assertEquals(0, (it.username.toInt() - 10) % 2) } } // Conversion rate client.getAdmin("/accounts").assertOkJson { for (account in it.accounts) { val rate = client.getAdmin("/accounts/${account.username}/conversion-info/rate").assertOkJson() assertEquals(account.conversion_rate, rate) } } // Filtering suspend fun checkIds(query: String, vararg ids: String) { val res = client.getAdmin("/accounts?$query") val list = listOf(*ids) if (list.isEmpty()) { res.assertNoContent() } else { res.assertOkJson { assertEquals(list, it.accounts.map { it.username }) } } } checkIds("", "4", "3", "2", "1", "0", "admin", "customer", "exchange", "merchant") checkIds("filter_name=1", "4", "3", "2", "1", "0") checkIds("filter_name=3", "3") checkIds("conversion_rate_class_id=1", "4", "1") checkIds("conversion_rate_class_id=2", "2") checkIds("conversion_rate_class_id=3") checkIds("conversion_rate_class_id=4") checkIds("conversion_rate_class_id=0", "3", "0", "admin", "customer", "exchange", "merchant") checkIds("conversion_rate_class_id=0&filter_name=1", "3", "0") for ((id, num) in mapOf(1 to 2, 2 to 1, 3 to 0)) { client.getAdmin("/conversion-rate-classes/$id").assertOkJson { assertEquals(it.num_users, num) } } } // GET /accounts/USERNAME @Test fun get() = bankSetup { authRoutine(HttpMethod.Get, "/accounts/merchant", allowAdmin = true) // Check ok client.getA("/accounts/merchant").assertOkJson { assertEquals("Merchant", it.name) } } } class CoreBankTransactionsApiTest { // GET /transactions @Test fun history() = bankSetup { authRoutine(HttpMethod.Get, "/accounts/merchant/transactions", allowAdmin = true) historyRoutine( url = "/accounts/customer/transactions", ids = { it.transactions.map { it.row_id } }, registered = listOf( { // Transactions from merchant to exchange tx("merchant", "KUDOS:0.1", "customer") }, { // Transactions from exchange to merchant tx("customer", "KUDOS:0.1", "merchant") }, { // Transactions from merchant to exchange tx("merchant", "KUDOS:0.1", "customer") }, { // Cashout from merchant cashout("KUDOS:0.1") } ), ignored = listOf( { // Ignore transactions of other accounts tx("merchant", "KUDOS:0.1", "exchange") }, { // Ignore transactions of other accounts tx("exchange", "KUDOS:0.1", "merchant") } ) ) } // GET /transactions/T_ID @Test fun testById() = bankSetup { authRoutine(HttpMethod.Get, "/accounts/merchant/transactions/42", allowAdmin = true) // Create transaction tx("merchant", "KUDOS:0.3", "exchange", "tx") // Check OK client.getA("/accounts/merchant/transactions/1") .assertOkJson { tx -> assertEquals("tx", tx.subject) assertEquals(TalerAmount("KUDOS:0.3"), tx.amount) } // Check unknown transaction client.getA("/accounts/merchant/transactions/3") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Check another user's transaction client.getA("/accounts/merchant/transactions/2") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } // POST /transactions @Test fun create() = bankSetup { db -> authRoutine(HttpMethod.Post, "/accounts/merchant/transactions") val valid_req = obj { "payto_uri" to "$exchangePayto?message=payout" "amount" to "KUDOS:0.3" } // Check OK client.postA("/accounts/merchant/transactions") { json(valid_req) }.assertOkJson { client.getA("/accounts/merchant/transactions/${it.row_id}") .assertOkJson { tx -> assertEquals("payout", tx.subject) assertEquals(TalerAmount("KUDOS:0.3"), tx.amount) } } // Check idempotency ShortHashCode.rand().let { requestUid -> val id = client.postA("/accounts/merchant/transactions") { json(valid_req) { "request_uid" to requestUid } }.assertOkJson().row_id client.postA("/accounts/merchant/transactions") { json(valid_req) { "request_uid" to requestUid } }.assertOkJson { assertEquals(id, it.row_id) } client.postA("/accounts/merchant/transactions") { json(valid_req) { "request_uid" to requestUid "amount" to "KUDOS:42" } }.assertConflict(TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED) } // Check amount in payto_uri client.postA("/accounts/merchant/transactions") { json { "payto_uri" to "$exchangePayto?message=payout2&amount=KUDOS:1.05" } }.assertOkJson { client.getA("/accounts/merchant/transactions/${it.row_id}") .assertOkJson { tx -> assertEquals("payout2", tx.subject) assertEquals(TalerAmount("KUDOS:1.05"), tx.amount) } } // Check amount in payto_uri precedence client.postA("/accounts/merchant/transactions") { json { "payto_uri" to "$exchangePayto?message=payout3&amount=KUDOS:1.05" "amount" to "KUDOS:10.003" } }.assertOkJson { client.getA("/accounts/merchant/transactions/${it.row_id}") .assertOkJson { tx -> assertEquals("payout3", tx.subject) assertEquals(TalerAmount("KUDOS:1.05"), tx.amount) } } // Testing the wrong currency client.postA("/accounts/merchant/transactions") { json(valid_req) { "amount" to "EUR:3.3" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Surpassing the debt limit client.postA("/accounts/merchant/transactions") { json(valid_req) { "amount" to "KUDOS:555" } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) // Missing message client.postA("/accounts/merchant/transactions") { json(valid_req) { "payto_uri" to "$exchangePayto" } }.assertBadRequest() // Unknown creditor client.postA("/accounts/merchant/transactions") { json(valid_req) { "payto_uri" to "$unknownPayto?message=payout" } }.assertConflict(TalerErrorCode.BANK_UNKNOWN_CREDITOR) // Transaction to self client.postA("/accounts/merchant/transactions") { json(valid_req) { "payto_uri" to "$merchantPayto?message=payout" } }.assertConflict(TalerErrorCode.BANK_SAME_ACCOUNT) // Transaction to admin val adminPayto = client.getA("/accounts/admin") .assertOkJson().payto_uri client.postA("/accounts/merchant/transactions") { json(valid_req) { "payto_uri" to "$adminPayto&message=payout" } }.assertConflict(TalerErrorCode.BANK_ADMIN_CREDITOR) // Init state assertBalance("merchant", "+KUDOS:0") assertBalance("customer", "+KUDOS:0") // Send 2 times 3 repeat(2) { tx("merchant", "KUDOS:3", "customer") } client.postA("/accounts/merchant/transactions") { json { "payto_uri" to "$customerPayto?message=payout2&amount=KUDOS:5" } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) assertBalance("merchant", "-KUDOS:6") assertBalance("customer", "+KUDOS:6") // Send through debt tx("customer", "KUDOS:10", "merchant") assertBalance("merchant", "+KUDOS:4") assertBalance("customer", "-KUDOS:4") tx("merchant", "KUDOS:4", "customer") // Check bounce assertBalance("merchant", "+KUDOS:0") assertBalance("exchange", "+KUDOS:0") tx("merchant", "KUDOS:1", "exchange", "") // Bounce common to transaction tx("merchant", "KUDOS:1", "exchange", "Malformed") // Bounce malformed transaction tx("merchant", "KUDOS:1", "exchange", "ADMIN BALANCE ADJUST") // Bounce admin balance adjust val reservePub = EddsaPublicKey.randEdsaKey() tx("merchant", "KUDOS:1", "exchange", fmtIncomingSubject(IncomingType.reserve, reservePub)) // Accept incoming tx("merchant", "KUDOS:1", "exchange", fmtIncomingSubject(IncomingType.reserve, reservePub)) // Bounce reserve_pub reuse assertBalance("merchant", "-KUDOS:1") assertBalance("exchange", "+KUDOS:1") // Check warn assertBalance("merchant", "-KUDOS:1") assertBalance("exchange", "+KUDOS:1") tx("exchange", "KUDOS:1", "merchant", "") // Warn common to transaction tx("exchange", "KUDOS:1", "merchant", "Malformed") // Warn malformed transaction val wtid = ShortHashCode.rand() val exchange = BaseURL.parse("http://exchange.example.com/") tx("exchange", "KUDOS:1", "merchant", fmtOutgoingSubject(wtid, exchange)) // Accept outgoing tx("exchange", "KUDOS:1", "merchant", fmtOutgoingSubject(wtid, exchange)) // Warn wtid reuse assertBalance("merchant", "+KUDOS:3") assertBalance("exchange", "-KUDOS:3") // Check 2fa fillTanInfo("merchant") assertBalance("merchant", "+KUDOS:3") assertBalance("customer", "+KUDOS:0") client.postA("/accounts/merchant/transactions") { json { "payto_uri" to "$customerPayto?message=tan+check&amount=KUDOS:1" } }.assertChallenge { assertBalance("merchant", "+KUDOS:3") assertBalance("customer", "+KUDOS:0") }.assertOkJson { assertBalance("merchant", "+KUDOS:2") assertBalance("customer", "+KUDOS:1") } // Check 2fa idempotency val req = obj { "payto_uri" to "$customerPayto?message=tan+check&amount=KUDOS:1" "request_uid" to ShortHashCode.rand() } val id = client.postA("/accounts/merchant/transactions") { json(req) }.assertChallenge { assertBalance("merchant", "+KUDOS:2") assertBalance("customer", "+KUDOS:1") }.assertOkJson { assertBalance("merchant", "+KUDOS:1") assertBalance("customer", "+KUDOS:2") }.row_id client.postA("/accounts/merchant/transactions") { json(req) }.assertOkJson { assertEquals(id, it.row_id) } client.postA("/accounts/merchant/transactions") { json(req) { "payto_uri" to "$customerPayto?message=tan+chec2k&amount=KUDOS:1" } }.assertConflict(TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED) } @Test fun createWithFee() = bankSetup(conf = "test_with_fees.conf") { // Init state assertBalance("merchant", "+KUDOS:0") assertBalance("customer", "+KUDOS:0") assertBalance("admin", "+KUDOS:0") // Check fee are sent to admin tx("merchant", "KUDOS:3", "customer") assertBalance("merchant", "-KUDOS:3.1") assertBalance("customer", "+KUDOS:3") assertBalance("admin", "+KUDOS:0.1") // Check amount with fee and min & max are checked for (amount in listOf("KUDOS:7", "KUDOS:6.9", "KUDOS:0", "KUDOS:150")) { client.postA("/accounts/merchant/transactions") { json { "payto_uri" to "$customerPayto?message=payout2&amount=$amount" } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) } // Check empty account tx("merchant", "KUDOS:6.8", "customer") assertBalance("merchant", "-KUDOS:10") assertBalance("customer", "+KUDOS:9.8") assertBalance("admin", "+KUDOS:0.2") // Admin check no fee tx("admin", "KUDOS:0.35", "merchant") assertBalance("merchant", "-KUDOS:9.65") assertBalance("admin", "-KUDOS:0.15") // Admin recover from debt tx("customer", "KUDOS:1", "merchant") assertBalance("admin", "-KUDOS:0.05") tx("customer", "KUDOS:1", "merchant") assertBalance("merchant", "-KUDOS:7.65") assertBalance("customer", "+KUDOS:7.6") assertBalance("admin", "+KUDOS:0.05") } } class CoreBankWithdrawalApiTest { // POST /accounts/USERNAME/withdrawals @Test fun create() = bankSetup { authRoutine(HttpMethod.Post, "/accounts/merchant/withdrawals") // Check OK for (valid in listOf( obj {}, obj { "amount" to "KUDOS:1.0" }, obj { "suggested_amount" to "KUDOS:2.0" }, obj { "amount" to "KUDOS:3.0" "suggested_amount" to "KUDOS:4.0" } )) { // Check OK client.postA("/accounts/merchant/withdrawals") { json(valid) }.assertOkJson { assertEquals("taler+http://withdraw/localhost:8080/taler-integration/${it.withdrawal_id}", it.taler_withdraw_uri) } } // Check exchange account client.postA("/accounts/exchange/withdrawals") { json { "amount" to "KUDOS:9.0" } }.assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE) // Check insufficient fund client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:90" } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) client.postA("/accounts/merchant/withdrawals") { json { "suggested_amount" to "KUDOS:90" } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) // Check wrong currency client.postA("/accounts/merchant/withdrawals") { json { "amount" to "EUR:90" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) client.postA("/accounts/merchant/withdrawals") { json { "suggested_amount" to "EUR:90" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) } @Test fun createWithFee() = bankSetup(conf = "test_with_fees.conf") { // Check insufficient fund for (amount in listOf("KUDOS:11", "KUDOS:10", "KUDOS:0", "KUDOS:150")) { for (name in listOf("amount", "suggested_amount")) { client.postA("/accounts/merchant/withdrawals") { json { name to amount } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) } } // Check OK for (name in listOf("amount", "suggested_amount")) { client.postA("/accounts/merchant/withdrawals") { json { name to "KUDOS:9.9" } }.assertOk() } } // GET /withdrawals/withdrawal_id @Test fun get() = bankSetup { // Check OK for (valid in listOf( Pair(null, null), Pair("KUDOS:1.0", null), Pair(null, "KUDOS:2.0") , Pair("KUDOS:3.0", "KUDOS:4.0") )) { val amount = valid.first?.run(::TalerAmount) val suggested = valid.second?.run(::TalerAmount) client.postA("/accounts/merchant/withdrawals") { json { "amount" to amount "suggested_amount" to suggested } }.assertOkJson { client.get("/withdrawals/${it.withdrawal_id}") .assertOkJson { assertEquals(amount, it.amount) assertEquals(suggested, it.suggested_amount) } } } // Check polling statusRoutine("/withdrawals") { it.status } // Check bad UUID client.get("/withdrawals/chocolate").assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Check unknown client.get("/withdrawals/${UUID.randomUUID()}") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } // POST /accounts/USERNAME/withdrawals/withdrawal_id/abort @Test fun abort() = bankSetup { authRoutine(HttpMethod.Post, "/accounts/merchant/withdrawals/42/abort") // Check abort created client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id // Check OK client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() // Check idempotence client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() } // Check abort selected client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) // Check OK client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() // Check idempotence client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() } // Check abort confirmed client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) client.postA("/accounts/merchant/withdrawals/$uuid/confirm").assertNoContent() // Check error client.postA("/accounts/merchant/withdrawals/$uuid/abort") .assertConflict(TalerErrorCode.BANK_ABORT_CONFIRM_CONFLICT) } // Check bad UUID client.postA("/accounts/merchant/withdrawals/chocolate/abort") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Check unknown client.postA("/accounts/merchant/withdrawals/${UUID.randomUUID()}/abort") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } // POST /accounts/USERNAME/withdrawals/withdrawal_id/confirm @Test fun confirm() = bankSetup { authRoutine(HttpMethod.Post, "/accounts/merchant/withdrawals/42/confirm") // Check confirm created client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id // Check err client.postA("/accounts/merchant/withdrawals/$uuid/confirm") .assertConflict(TalerErrorCode.BANK_CONFIRM_INCOMPLETE) } // Check confirm selected client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) // Check amount differs client.postA("/accounts/merchant/withdrawals/$uuid/confirm") { json { "amount" to "KUDOS:2" } }.assertConflict(TalerErrorCode.BANK_AMOUNT_DIFFERS) // Check OK client.postA("/accounts/merchant/withdrawals/$uuid/confirm").assertNoContent() // Check idempotence client.postA("/accounts/merchant/withdrawals/$uuid/confirm").assertNoContent() // Check amount differs client.postA("/accounts/merchant/withdrawals/$uuid/confirm") { json { "amount" to "KUDOS:2" } }.assertConflict(TalerErrorCode.BANK_AMOUNT_DIFFERS) } // Check confirm with amount client.postA("/accounts/merchant/withdrawals") { json {} }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) // Check missing amount client.postA("/accounts/merchant/withdrawals/$uuid/confirm") .assertConflict(TalerErrorCode.BANK_AMOUNT_REQUIRED) // Check OK client.postA("/accounts/merchant/withdrawals/$uuid/confirm") { json { "amount" to "KUDOS:1" } }.assertNoContent() // Check idempotence client.postA("/accounts/merchant/withdrawals/$uuid/confirm") { json { "amount" to "KUDOS:1" } }.assertNoContent() // Check amount differs client.postA("/accounts/merchant/withdrawals/$uuid/confirm") { json { "amount" to "KUDOS:2" } }.assertConflict(TalerErrorCode.BANK_AMOUNT_DIFFERS) } // Check confirm aborted client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() // Check error client.postA("/accounts/merchant/withdrawals/$uuid/confirm") .assertConflict(TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT) } // Check reserve pub reuse client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:5" } }.assertOkJson { val uuid = it.withdrawal_id val reservePub = withdrawalSelect(uuid) tx("customer", "KUDOS:5", "exchange", "Taler $reservePub") client.postA("/accounts/merchant/withdrawals/$uuid/confirm") .assertConflict(TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT) } // Check balance insufficient client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:5" } }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) // Send too much money tx("merchant", "KUDOS:5", "customer") client.postA("/accounts/merchant/withdrawals/$uuid/confirm") .assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) // Check can abort because not confirmed client.postA("/accounts/merchant/withdrawals/$uuid/abort").assertNoContent() } // Check bad UUID client.postA("/accounts/merchant/withdrawals/chocolate/confirm") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Check unknown client.postA("/accounts/merchant/withdrawals/${UUID.randomUUID()}/confirm") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Check 2fa without body fillTanInfo("merchant") assertBalance("merchant", "-KUDOS:7") client.postA("/accounts/merchant/withdrawals") { json { "amount" to "KUDOS:1" } }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) client.postA("/accounts/merchant/withdrawals/$uuid/confirm") .assertChallenge { assertBalance("merchant", "-KUDOS:7") }.assertNoContent() } // Check 2fa with body fillTanInfo("merchant") assertBalance("merchant", "-KUDOS:8") client.postA("/accounts/merchant/withdrawals") { json {} }.assertOkJson { val uuid = it.withdrawal_id withdrawalSelect(uuid) client.postA("/accounts/merchant/withdrawals/$uuid/confirm") { json { "amount" to "KUDOS:1" } } .assertChallenge { assertBalance("merchant", "-KUDOS:8") }.assertNoContent() } assertBalance("merchant", "-KUDOS:9") } @Test fun confirmWithFee() = bankSetup(conf = "test_with_fees.conf") { db -> suspend fun run(amount: TalerAmount): HttpResponse { val uuid = UUID.randomUUID() // Create a selected withdrawal directly in the database to bypass checks db.serializable(""" INSERT INTO taler_withdrawal_operations(withdrawal_uuid,amount,exchange_bank_account,selection_done,wallet_bank_account,creation_date) VALUES (?, (?, ?)::taler_amount, 2, true, 3, 0) """) { bind(uuid) bind(amount) executeUpdate() } return client.postA("/accounts/customer/withdrawals/$uuid/confirm") } // Check insufficient fund for (amount in listOf("KUDOS:11", "KUDOS:10", "KUDOS:0", "KUDOS:150")) { run(TalerAmount(amount)).assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) } // Check OK run(TalerAmount("KUDOS:9.9")) } } class CoreBankCashoutApiTest { // POST /accounts/{USERNAME}/cashouts @Test fun create() = bankSetup { authRoutine(HttpMethod.Post, "/accounts/merchant/cashouts") val req = obj { "request_uid" to ShortHashCode.rand() "amount_debit" to "KUDOS:1" "amount_credit" to convert("KUDOS:1") } // Missing info client.postA("/accounts/customer/cashouts") { json(req) }.assertConflict(TalerErrorCode.BANK_CONFIRM_INCOMPLETE) fillCashoutInfo("customer") // Check OK val id = client.postA("/accounts/customer/cashouts") { json(req) }.assertOkJson().cashout_id // Check idempotent client.postA("/accounts/customer/cashouts") { json(req) }.assertOkJson { assertEquals(id, it.cashout_id) } // Trigger conflict due to reused request_uid client.postA("/accounts/customer/cashouts") { json(req) { "amount_debit" to "KUDOS:2" "amount_credit" to convert("KUDOS:2") } }.assertConflict(TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED) // Check exchange account client.postA("/accounts/exchange/cashouts") { json(req) }.assertConflict(TalerErrorCode.BANK_ACCOUNT_IS_EXCHANGE) // Check insufficient fund client.postA("/accounts/customer/cashouts") { json(req) { "request_uid" to ShortHashCode.rand() "amount_debit" to "KUDOS:75" "amount_credit" to convert("KUDOS:75") } }.assertConflict(TalerErrorCode.BANK_UNALLOWED_DEBIT) // Check wrong conversion client.postA("/accounts/customer/cashouts") { json(req) { "amount_credit" to convert("KUDOS:2") } }.assertConflict(TalerErrorCode.BANK_BAD_CONVERSION) // Check min amount client.postA("/accounts/customer/cashouts") { json(req) { "amount_debit" to "KUDOS:0.09" } }.assertConflict(TalerErrorCode.BANK_CONVERSION_AMOUNT_TO_SMALL) // Check custom min account createConversionRateClass(cashout_min_amount = TalerAmount("KUDOS:10")) client.patchAdmin("/accounts/customer") { json { "conversion_rate_class_id" to 1 } }.assertNoContent() client.postA("/accounts/customer/cashouts") { json(req) { "amount_debit" to "KUDOS:5" "amount_credit" to convert("KUDOS:5") } }.assertConflict(TalerErrorCode.BANK_CONVERSION_AMOUNT_TO_SMALL) client.patchAdmin("/accounts/customer") { json { "conversion_rate_class_id" to (null as Long?) } }.assertNoContent() // Check wrong currency client.postA("/accounts/customer/cashouts") { json(req) { "amount_debit" to "EUR:1" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) client.postA("/accounts/customer/cashouts") { json(req) { "amount_credit" to "KUDOS:1" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Check 2fa fillTanInfo("customer") assertBalance("customer", "-KUDOS:1") client.postA("/accounts/customer/cashouts") { json(req) { "request_uid" to ShortHashCode.rand() } }.assertChallenge { assertBalance("customer", "-KUDOS:1") }.assertOkJson { assertBalance("customer", "-KUDOS:2") } } // GET /accounts/{USERNAME}/cashouts/{CASHOUT_ID} @Test fun get() = bankSetup { authRoutine(HttpMethod.Get, "/accounts/merchant/cashouts/42", allowAdmin = true) fillCashoutInfo("customer") val amountDebit = TalerAmount("KUDOS:1.5") val amountCredit = convert("KUDOS:1.5") val req = obj { "amount_debit" to amountDebit "amount_credit" to amountCredit } // Check confirm client.postA("/accounts/customer/cashouts") { json(req) { "request_uid" to ShortHashCode.rand() } }.assertOkJson { val id = it.cashout_id client.getA("/accounts/customer/cashouts/$id") .assertOkJson { assertEquals(amountDebit, it.amount_debit) assertEquals(amountCredit, it.amount_credit) } } // Check bad UUID client.getA("/accounts/customer/cashouts/chocolate") .assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // Check unknown client.getA("/accounts/customer/cashouts/42") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Check get another user's operation client.postA("/accounts/customer/cashouts") { json(req) { "request_uid" to ShortHashCode.rand() } }.assertOkJson { val id = it.cashout_id // Check error client.getA("/accounts/merchant/cashouts/$id") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } } // GET /accounts/{USERNAME}/cashouts @Test fun history() = bankSetup { authRoutine(HttpMethod.Get, "/accounts/merchant/cashouts", allowAdmin = true) historyRoutine( url = "/accounts/customer/cashouts", ids = { it.cashouts.map { it.cashout_id } }, registered = listOf { cashout("KUDOS:0.1") }, polling = false ) } // GET /cashouts @Test fun globalHistory() = bankSetup { authRoutine(HttpMethod.Get, "/cashouts", requireAdmin = true) historyRoutine( url = "/cashouts", ids = { it.cashouts.map { it.cashout_id } }, registered = listOf { cashout("KUDOS:0.1") }, polling = false, auth = "admin" ) } @Test fun notImplemented() = bankSetup("test_no_conversion.conf") { client.get("/accounts/customer/cashouts") .assertNotImplemented() } } class CoreBankTanApiTest { // POST /accounts/{USERNAME}/challenge/{challenge_id} @Test fun send() = bankSetup { suspend fun HttpResponse.expectMfa(vararg tans: Pair): HttpResponse { return assertChallenge { res -> assertEquals(setOf(*tans), res.challenges.map { it.tan_channel to it.tan_info }.toSet()) assertFalse(res.combi_and) } } suspend fun HttpResponse.expectValidation(vararg tans: Pair): HttpResponse { return assertChallenge { res -> assertEquals(setOf(*tans), res.challenges.map { it.tan_channel to it.tan_info }.toSet()) assertTrue(res.combi_and) } } // Set up 2fa client.patchA("/accounts/merchant") { json { "contact_data" to obj { "phone" to "+99" "email" to "email@example.com" } "tan_channel" to "sms" } }.expectValidation(TanChannel.sms to "+99") .assertNoContent() // Update 2fa settings - first 2FA challenge then new tan channel check client.patchA("/accounts/merchant") { json { // Info change "contact_data" to obj { "phone" to "+98" } } }.expectValidation(TanChannel.sms to "+99", TanChannel.sms to "+98") .assertNoContent() client.patchA("/accounts/merchant") { json { // Channel change "tan_channel" to "email" } }.expectValidation(TanChannel.sms to "+98", TanChannel.email to "email@example.com") .assertNoContent() client.patchA("/accounts/merchant") { json { // Both change "contact_data" to obj { "phone" to "+97" } "tan_channel" to "sms" } }.expectValidation(TanChannel.email to "email@example.com", TanChannel.sms to "+97") .assertNoContent() // Disable 2fa client.patchA("/accounts/merchant") { json { "tan_channel" to null as String? } }.expectValidation(TanChannel.sms to "+97") .assertNoContent() // Update mfa settings - first mfa challenge then new tan channel check client.patchA("/accounts/merchant") { json { // All channels "tan_channels" to setOf("sms", "email") } }.expectValidation(TanChannel.sms to "+97", TanChannel.email to "email@example.com") .assertNoContent() client.patchA("/accounts/merchant") { json { // All info changes "contact_data" to obj { "phone" to "+99" "email" to "email2@example.com" } } }.expectMfa(TanChannel.sms to "+97", TanChannel.email to "email@example.com") .expectValidation(TanChannel.sms to "+99", TanChannel.email to "email2@example.com") .assertNoContent() // Disable mfa client.patchA("/accounts/merchant") { json { "tan_channels" to emptySet() } }.expectMfa(TanChannel.sms to "+99", TanChannel.email to "email2@example.com") .assertNoContent() // Admin has no 2FA client.patchAdmin("/accounts/merchant") { json { "contact_data" to obj { "phone" to "+99" } "tan_channel" to "sms" } }.assertNoContent() client.patchAdmin("/accounts/merchant") { json { "tan_channel" to "email" } }.assertNoContent() client.patchAdmin("/accounts/merchant") { json { "tan_channel" to null as String? } }.assertNoContent() // Check retry and invalidate client.patchA("/accounts/merchant") { json { "contact_data" to obj { "phone" to "+88" } "tan_channel" to "sms" } }.assertChallenge().assertNoContent() client.patchA("/accounts/merchant") { json { "is_public" to false } }.assertAcceptedJson { val challenge = it.challenges[0] // Check ok client.postA("/accounts/merchant/challenge/${challenge.challenge_id}") .assertOk() val code = tanCode("+88") assertNotNull(code) // Check retry client.postA("/accounts/merchant/challenge/${challenge.challenge_id}") .assertOk() assertNull(tanCode("+88")) // Idempotent patch does nothing client.patchA("/accounts/merchant") { json { "contact_data" to obj { "phone" to "+88" } "tan_channel" to "sms" } } client.postA("/accounts/merchant/challenge/${challenge.challenge_id}") .assertOk() assertNull(tanCode("+88")) // Change 2fa settings client.patchA("/accounts/merchant") { json { "tan_channel" to "email" } }.expectValidation(TanChannel.sms to "+88", TanChannel.email to "email2@example.com") .assertNoContent() // Check invalidated client.postA("/accounts/merchant/challenge/${challenge.challenge_id}/confirm") { json { "tan" to code } }.assertNotFound(TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED) client.patchA("/accounts/merchant") { headers[TALER_CHALLENGE_IDS] = "${challenge.challenge_id}" json { "is_public" to false } }.expectValidation(TanChannel.email to "email2@example.com") .assertNoContent() } // Unknown challenge client.postA("/accounts/merchant/challenge/${UUID.randomUUID()}") .assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } @Test fun sendRateLimited() = bankSetup { fillTanInfo("merchant") suspend fun ApplicationTestBuilder.txChallenge() = client.postA("/accounts/merchant/transactions") { json { "payto_uri" to "$customerPayto?message=tx&amount=KUDOS:0.1" } }.assertAcceptedJson().challenges[0] suspend fun ApplicationTestBuilder.submit(challenge: Challenge) = client.postA("/accounts/merchant/challenge/${challenge.challenge_id}") .assertOkJson() // Start a legitimate challenge and submit it val oldChallenge = txChallenge() submit(oldChallenge) val tanCode = tanCode(oldChallenge.tan_info) // Challenge creation is not rate limited repeat(MAX_ACTIVE_CHALLENGES*2) { txChallenge() } // Challenge submission is rate limited repeat(MAX_ACTIVE_CHALLENGES-1) { submit(txChallenge()) } val challenge = txChallenge() client.postA("/accounts/merchant/challenge/${challenge.challenge_id}") .assertTooManyRequests(TalerErrorCode.BANK_TAN_RATE_LIMITED) // Old already submitted challenge still works val transmission = submit(oldChallenge) client.postA("/accounts/merchant/challenge/${oldChallenge.challenge_id}/confirm") { json { "tan" to tanCode } }.assertNoContent() // Now an active challenge slot have been freed submit(challenge) // We are rate limited again val newChallenge = txChallenge() client.postA("/accounts/merchant/challenge/${newChallenge.challenge_id}") .assertTooManyRequests(TalerErrorCode.BANK_TAN_RATE_LIMITED) } // POST /accounts/{USERNAME}/challenge/{challenge_id} @Test fun sendTanErr() = bankSetup("test_tan_err.conf") { // Check fail fillTanInfo("merchant") client.patchA("/accounts/merchant") { json { "is_public" to false } }.assertAcceptedJson { val challenge = it.challenges[0] client.postA("/accounts/merchant/challenge/${challenge.challenge_id}") .assertStatus(HttpStatusCode.BadGateway, TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED) } } // POST /accounts/{USERNAME}/challenge/{challenge_id}/confirm @Test fun confirm() = bankSetup { fillTanInfo("merchant") // Check simple case client.patchA("/accounts/merchant") { json { "is_public" to false } }.assertAcceptedJson { val challenge = it.challenges[0] val id = challenge.challenge_id client.postA("/accounts/merchant/challenge/$id") .assertOkJson() val code = tanCode(challenge.tan_info) // Check bad TAN code client.postA("/accounts/merchant/challenge/$id/confirm") { json { "tan" to "nice-try" } }.assertConflict(TalerErrorCode.BANK_TAN_CHALLENGE_FAILED) // Check wrong account client.postA("/accounts/customer/challenge/$id/confirm") { json { "tan" to "nice-try" } }.assertConflict(TalerErrorCode.BANK_TAN_CHALLENGE_FAILED) // Check OK client.postA("/accounts/merchant/challenge/$id/confirm") { json { "tan" to code } }.assertNoContent() // Check idempotence client.postA("/accounts/merchant/challenge/$id/confirm") { json { "tan" to code } }.assertNoContent() // Unknown challenge client.postA("/accounts/merchant/challenge/${UUID.randomUUID()}/confirm") { json { "tan" to code } }.assertNotFound(TalerErrorCode.BANK_CHALLENGE_NOT_FOUND) } // Check invalidation client.patchA("/accounts/merchant") { json { "is_public" to true } }.assertAcceptedJson { val challenge = it.challenges[0] val id = challenge.challenge_id client.postA("/accounts/merchant/challenge/$id") .assertOkJson() // Check invalidated fillTanInfo("merchant") client.postA("/accounts/merchant/challenge/$id/confirm") { json { "tan" to tanCode(challenge.tan_info) } }.assertNotFound(TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED) client.postA("/accounts/merchant/challenge/$id") .assertNotFound(TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED) } } } class CoreBankConversionApiTest { // POST /conversion-rate-classes // GET /conversion-rate-classes // GET /conversion-rate-classes/{CLASS_ID} @Test fun classes() = bankSetup() { authRoutine(HttpMethod.Post, "/conversion-rate-classes", requireAdmin = true) authRoutine(HttpMethod.Get, "/conversion-rate-classes", requireAdmin = true) authRoutine(HttpMethod.Get, "/conversion-rate-classes/1", requireAdmin = true) val fullInput = obj { "description" to "A nice little class" "cashin_ratio" to "0.1" "cashin_fee" to "KUDOS:0.2" "cashin_tiny_amount" to "KUDOS:0.3" "cashin_rounding_mode" to "nearest" "cashin_min_amount" to "EUR:0" "cashout_ratio" to "0.4" "cashout_fee" to "EUR:0.5" "cashout_tiny_amount" to "EUR:0.6" "cashout_rounding_mode" to "zero" "cashout_min_amount" to "KUDOS:0.7" } // Check no classes client.getAdmin("/conversion-rate-classes").assertNoContent() client.getAdmin("/conversion-rate-classes/1").assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) client.patchAdmin("/conversion-rate-classes/1") { json(fullInput) { "name" to "Class" } }.assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) client.deleteAdmin("/conversion-rate-classes/1").assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) // Create full val full = client.postAdmin("/conversion-rate-classes") { json(fullInput) { "name" to "Class n°1" } }.assertOkJson { assertEquals(it.conversion_rate_class_id, 1) val rate = client.getAdmin("/conversion-rate-classes/${it.conversion_rate_class_id}").assertOkJson() client.patchAdmin("/conversion-rate-classes/${it.conversion_rate_class_id}") { json { "name" to "Class n°1" } }.assertNoContent() it.conversion_rate_class_id } // Create empty val empty = client.postAdmin("/conversion-rate-classes") { json { "name" to "Class n°2" } }.assertOkJson { assertEquals(it.conversion_rate_class_id, 2) val rate = client.getAdmin("/conversion-rate-classes/${it.conversion_rate_class_id}").assertOkJson() client.patchAdmin("/conversion-rate-classes/${it.conversion_rate_class_id}") { json(fullInput) { "name" to "Class n°2" } }.assertNoContent() it.conversion_rate_class_id } // Bad currency client.postAdmin("/conversion-rate-classes") { json(fullInput) { "name" to "Bad currency" "cashout_fee" to "CHF:0.003" } }.assertBadRequest(TalerErrorCode.GENERIC_CURRENCY_MISMATCH) // Name reuse currency client.postAdmin("/conversion-rate-classes") { json(fullInput) { "name" to "Class n°1" } }.assertConflict(TalerErrorCode.BANK_NAME_REUSE) client.patchAdmin("/conversion-rate-classes/2") { json(fullInput) { "name" to "Class n°1" } }.assertConflict(TalerErrorCode.BANK_NAME_REUSE) client.patchAdmin("/conversion-rate-classes/1") { json(fullInput) { "name" to "Class n°1" } }.assertNoContent() // Page client.getAdmin("/conversion-rate-classes").assertOkJson { assertEquals(it.classes.size, 2) } val generated = (0 until 5).map { createConversionRateClass() } client.getAdmin("/conversion-rate-classes").assertOkJson { assertEquals(it.classes.size, 7) } client.getAdmin("/conversion-rate-classes?filter_name=Gen").assertOkJson { assertEquals(it.classes.size, 5) } // Delete all for (id in listOf(full.conversion_rate_class_id, empty.conversion_rate_class_id) + generated) { client.deleteAdmin("/conversion-rate-classes/$id").assertNoContent() client.deleteAdmin("/conversion-rate-classes/$id").assertNotFound(TalerErrorCode.BANK_TRANSACTION_NOT_FOUND) } client.getAdmin("/conversion-rate-classes").assertNoContent() } @Test fun notImplemented() = bankSetup("test_no_conversion.conf") { client.getAdmin("conversion-rate-classes/1").assertNotImplemented() client.getAdmin("conversion-rate-classes").assertNotImplemented() } }libeufin-1.6.8/libeufin-bank/src/test/kotlin/RevenueApiTest.kt0000664000175000017500000000405515122266731024573 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import io.ktor.client.request.* import org.junit.Test import tech.libeufin.common.RevenueIncomingHistory import tech.libeufin.common.assertOk import tech.libeufin.common.test.* class RevenueApiTest { // GET /accounts/{USERNAME}/taler-revenue/config @Test fun config() = bankSetup { client.get("/accounts/merchant/taler-revenue/config").assertOk() } // GET /accounts/{USERNAME}/taler-revenue/history @Test fun history() = bankSetup { setMaxDebt("exchange", "KUDOS:1000000") authRoutine(HttpMethod.Get, "/accounts/merchant/taler-revenue/history") historyRoutine( url = "/accounts/merchant/taler-revenue/history", ids = { it.incoming_transactions.map { it.row_id } }, registered = listOf( { // Transactions using clean transfer logic transfer("KUDOS:10") }, { // Common credit transactions tx("exchange", "KUDOS:10", "merchant", "ignored") } ), ignored = listOf( { // Ignore debit transactions tx("merchant", "KUDOS:10", "customer") } ) ) } }libeufin-1.6.8/libeufin-bank/build.gradle0000664000175000017500000000430015204341712020524 0ustar grothoffgrothoffplugins { id("kotlin") id("application") id("com.gradleup.shadow") version "$shadow_version" id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version" } version = rootProject.version java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } compileKotlin.kotlinOptions.jvmTarget = "17" compileTestKotlin.kotlinOptions.jvmTarget = "17" sourceSets.main.java.srcDirs = ["src/main/kotlin"] dependencies { // Core language libraries implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") implementation(project(":libeufin-common")) implementation("org.postgresql:postgresql:$postgres_version") implementation("com.github.ajalt.clikt:clikt:$clikt_version") implementation("com.github.ajalt.mordant:mordant:3.0.2") // Metrics implementation("io.prometheus:prometheus-metrics-core:$prometheus_version") implementation("io.prometheus:prometheus-metrics-instrumentation-jvm:$prometheus_version") implementation("io.prometheus:prometheus-metrics-exposition-formats:$prometheus_version") implementation("io.ktor:ktor-server-core:$ktor_version") implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") // OpenAPI spec generation implementation("io.github.smiley4:ktor-openapi:5.6.0") implementation("io.github.smiley4:schema-kenerator-core:2.6.0") // UNIX domain sockets support (used to connect to PostgreSQL) implementation("com.kohlschutter.junixsocket:junixsocket-core:$junixsocket_version") testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version") testImplementation("io.ktor:ktor-server-test-host:$ktor_version") testImplementation(project(":libeufin-common")) } application { mainClass = "tech.libeufin.bank.MainKt" } shadowJar { version = "" minimize { // Kotlin serialization exclude(dependency("io.ktor:ktor-serialization-kotlinx-json:.*")) // Postgres unix socket driver exclude(dependency("com.kohlschutter.junixsocket:junixsocket-core:.*")) // CLI exclude(dependency("com.github.ajalt.mordant:mordant:.*")) // Crypto exclude(dependency("org.bouncycastle:.*")) } }libeufin-1.6.8/libeufin-bank/README0000664000175000017500000000137415122266731017143 0ustar grothoffgrothoffDescription =========== The Libeufin bank implements a simple core banking system with account and REST APIs, including REST APIs for a Web interface and REST APIs to interact with GNU Taler components. It also will provide a server side implementation of multiple banking protocols currently used in the European Union. Notably, the EBICS, FinTS, and the major protocols that banks will employ to respect the PSD2 regulation: https://ec.europa.eu/info/law/payment-services-psd-2-directive-eu-2015-2366_en Running the Bank =================== Run the Bank with the following command $ cd $ ./gradlew bank:run --console=plain --args=serve [--db-name=] Documentation ============= See https://docs.taler.net/ for the documentation. libeufin-1.6.8/libeufin-bank/conf/0000775000175000017500000000000015236145704017205 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-bank/conf/test_no_password_check.conf0000664000175000017500000000042315122266731024603 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = iban IBAN_PAYTO_BIC = SANDBOXX ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes PWD_HASH_CONFIG = { "cost": 4 } PWD_CHECK = no [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufinchecklibeufin-1.6.8/libeufin-bank/conf/test_no_conversion.conf0000664000175000017500000000040415122266731023770 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = iban IBAN_PAYTO_BIC = SANDBOXX ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes PWD_HASH_CONFIG = { "cost": 4 } [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufinchecklibeufin-1.6.8/libeufin-bank/conf/test_bonus.conf0000664000175000017500000000044315122266731022240 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = iban IBAN_PAYTO_BIC = SANDBOXX REGISTRATION_BONUS = KUDOS:100 ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes PWD_HASH_CONFIG = { "cost": 4 } [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufinchecklibeufin-1.6.8/libeufin-bank/conf/test_x_taler_bank.conf0000664000175000017500000000067115122266731023546 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = x-taler-bank X_TALER_BANK_PAYTO_HOSTNAME = bank.hostname.test DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes ALLOW_EDIT_NAME = yes ALLOW_EDIT_CASHOUT_PAYTO_URI = yes PWD_HASH_CONFIG = { "cost": 4 } [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufincheck libeufin-1.6.8/libeufin-bank/conf/test_tan_err.conf0000664000175000017500000000075415122266731022551 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = iban IBAN_PAYTO_BIC = SANDBOXX DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com allow_conversion = YES FIAT_CURRENCY = EUR ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes ALLOW_EDIT_CASHOUT_PAYTO_URI = yes tan_sms = libeufin-tan-fail.sh PWD_HASH_CONFIG = { "cost": 4 } [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufincheck [nexus-ebics] currency = EUR libeufin-1.6.8/libeufin-bank/conf/test_restrict.conf0000664000175000017500000000043015122266731022745 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = iban IBAN_PAYTO_BIC = SANDBOXX DEFAULT_DEBT_LIMIT = KUDOS:100 allow_conversion = YES FIAT_CURRENCY = EUR PWD_HASH_CONFIG = { "cost": 4 } [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufinchecklibeufin-1.6.8/libeufin-bank/conf/test.conf0000664000175000017500000000075315221677432021042 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = iban DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes ALLOW_EDIT_NAME = yes ALLOW_EDIT_CASHOUT_PAYTO_URI = yes allow_conversion = YES FIAT_CURRENCY = EUR tan_sms = libeufin-tan-file.sh tan_email = libeufin-tan-file.sh PWD_HASH_CONFIG = { "cost": 4 } [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufincheck libeufin-1.6.8/libeufin-bank/conf/test_with_fees.conf0000664000175000017500000000115715122266731023072 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = iban IBAN_PAYTO_BIC = SANDBOXX DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes ALLOW_EDIT_NAME = yes ALLOW_EDIT_CASHOUT_PAYTO_URI = yes allow_conversion = YES FIAT_CURRENCY = EUR tan_sms = libeufin-tan-file.sh tan_email = libeufin-tan-file.sh wire_transfer_fees = KUDOS:0.1 min_wire_transfer_amount = KUDOS:0.01 max_wire_transfer_amount = KUDOS:100 PWD_HASH_CONFIG = { "cost": 4 } [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufincheck libeufin-1.6.8/COPYING0000644000175000017500000010333014674637415014615 0ustar grothoffgrothoff GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . libeufin-1.6.8/.gitignore0000664000175000017500000000076415122266731015547 0ustar grothoffgrothoff.idea/* .vscode libeufin-nexus/test common/tmp testbench/test testbench/config.json configure build/ .gradle .kotlin out *.sqlite3 *.swp presentation/*.log presentation/*.nav presentation/*.aux presentation/*.out presentation/*.snm presentation/*.toc .idea/misc.xml .idea/modules/ __pycache__ *.log .DS_Store *.mk common/src/main/resources/version.txt debian/libeufin-bank debian/libeufin-common debian/libeufin-nexus debian/libeufin-ebisync debian/files debian/*.substvars debian/*debhelper* azuritelibeufin-1.6.8/settings.gradle0000664000175000017500000000026615122266731016574 0ustar grothoffgrothoffrootProject.name = 'libeufin' include("libeufin-bank") include("libeufin-nexus") include("libeufin-common") include("libeufin-ebics") include("libeufin-ebisync") include("testbench")libeufin-1.6.8/RELEASE.md0000644000175000017500000000102414674637415015161 0ustar grothoffgrothoff# Release Process ## Checklist - [ ] bump version in build.gradle - [ ] add entry to debian/changelog - [ ] check CI (contrib/ci, buildbot.taler.net) - [ ] tag with dev tag, test in staging environment - [ ] tag with release tag - [ ] upload to GNU mirrors - [ ] upload Debian packages to deb.taler.net ## Versioning Releases use `$major.$minor.$patch` semantic versions. The corresponding git tag is `v$major.minor.$patch`. Versions that are tested in staging environments typically use `v$major.$minor.$patch-dev.$n` tags. libeufin-1.6.8/API_CHANGES.md0000664000175000017500000000702115236062741015634 0ustar grothoffgrothoff# API Changes This files contains all the API changes for the current release: ## bank serve - POST /accounts: now returns RegisterAccountResponse with IBAN on http code 200 instead of 201 - CREATE /accounts: new debit_threshold field similar to the one of PATH /accounts - GET /config: new default_debit_threshold field for the default debt limit for newly created accounts - GET /config: new supported_tan_channels field which lists all the TAN channels supported by the server - GET /config: new allow_edit_name and allow_edit_cashout_payto_uri fields for path authorisation - POST /accounts: rename challenge_contact_data to contact_data and internal_payto_uri to payto_uri - PATCH /accounts/USERNAME: add is_public, remove is_taler_exchange and rename challenge_contact_data to contact_data - GET /accounts: add payto_uri, is_public and is_taler_exchange - GET /accounts/USERNAME: add is_public and is_taler_exchange - GET /public-accounts: add is_taler_exchange and rename account_name to username - PATCH /accounts: fix PATCH semantic - PATCH /accounts: restrict PATCH contact_data to admin - POST /accounts/USERNAME/transactions: prohibit transaction to admin account - Deprecate POST /accounts/USERNAME/withdrawals/WITHDRAWAL_ID/abort - Add POST /taler-integration/withdrawal-operation/WITHDRAWAL_ID/abort - Add 2FA logic - Remove POST /accounts/USERNAME/cashouts/CASHOUT_ID/abort - Remove POST /accounts/USERNAME/cashouts/CASHOUT_ID/confirm - Add POST /accounts/USERNAME/challenge/CHALLENGE_ID - Add POST /accounts/USERNAME/challenge/CHALLENGE_ID/confirm - POST /accounts/USERNAME/cashouts: remove tan_channel field - POST /accounts/USERNAME/cashouts/CASHOUT_ID: remove confirmation_time, tan_channel, tan_info and status fields - POST /accounts/USERNAME/cashouts: remove status field - POST /cashouts: remove status field - PATCH /accounts/USERNAME: add tan_channel - GET /accounts/USERNAME: add tan_channel - Add GET /accounts/USERNAME/taler-revenue/config - Add GET /accounts/USERNAME/taler-wire-gateway/config - Change GET /accounts/USERNAME/taler-revenue/history logic and body type - GET /config: new wire_type field for the bank supported payment target type - GET /accounts: add row_id field - GET /public-accounts: add row_id field - GET /config: new bank_name field for the bank name - POST /accounts/USERNAME/transactions: new request_uid field for idempotency and new idempotency error - GET /accounts: new status field - GET /accounts/USERNAME: new status field - GET /monitor: new date_s params - GET /config: new base_url field for the advertised base URL - POST /accounts: add min_cashout field for the custom minimum cashout amount - PATCH /accounts/USERNAME: add min_cashout field for the custom minimum cashout amount - GET /accounts: add min_cashout field for the custom minimum cashout amount - GET /accounts/USERNAME: add min_cashout field for the custom minimum cashout amount - GET /config: new wire_transfer_fees field for transaction fees - POST /accounts/USERNAME/withdrawals: drop card_fees field - GET /withdrawals/WITHDRAWAL_ID: make amount optional and add suggested_amount - POST /accounts/USERNAME/token: add optional description field - Add GET /accounts/USERNAME/tokens - GET /accounts/USERNAME/tokens: add missing row_id field - GET /withdrawals/WITHDRAWAL_ID: add min_amount - Paginated endpoints: reject a 'limit' (or 'delta') below -MAX_PAGE_SIZE, mirroring the pre-existing upper bound ## bank cli ## nexus - Paginated endpoints: reject a 'limit' (or 'delta') below -MAX_PAGE_SIZE, mirroring the pre-existing upper bound libeufin-1.6.8/contrib/0000775000175000017500000000000015236145704015212 5ustar grothoffgrothofflibeufin-1.6.8/contrib/libeufin-tan-sms.sh0000775000175000017500000000122115110430114020701 0ustar grothoffgrothoff#!/bin/bash # This file is in the public domain. # Send an SMS set -eu if [ $# -ne 1 ] then echo "Usage: $0 " 1>&2 exit 1 fi SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_NAME=$(basename "$0") BASE="${SCRIPT_NAME%.sh}" PHONE_NUMBER="$1" MESSAGE=$(cat -) # List of sub-scripts to try. PROVIDERS="telesign clicksend" for PROVIDER in $PROVIDERS do SCRIPT_PATH="$SCRIPT_DIR/${BASE}-${PROVIDER}.sh" if [ -x "$SCRIPT_PATH" ] then if echo "$MESSAGE" | "$SCRIPT_PATH" "$PHONE_NUMBER" then exit 0 else echo "$PROVIDER failed." 1>&2 fi fi done echo "All SMS providers failed." 1>&2 exit 1 libeufin-1.6.8/contrib/libeufin-tan-sms-telesign.sh0000775000175000017500000000736715077270636022561 0ustar grothoffgrothoff#!/bin/bash # This file is in the public domain. # Send an SMS using Telesign API set -eu # Check shared secrets if [ -x "$TELESIGN_AUTH_TOKEN" ] then echo "TELESIGN_AUTH_TOKEN not set in environment" exit 1 fi if [ $# -ne 1 ]; then echo "Usage: $0 " 1>&2 exit 1 fi PHONE_NUMBER="$1" MESSAGE=$(cat -) TMPFILE=$(mktemp /tmp/telesign-sms-logging-XXXXXX) RESPONSE=$(curl --silent --show-error --fail \ --url https://rest-api.telesign.com/v1/messaging \ --request POST \ --header "Authorization: Basic $TELESIGN_AUTH_TOKEN" \ --header "Content-Type: application/x-www-form-urlencoded" \ --data account_livecycle_event=transact \ --data "phone_number=$PHONE_NUMBER" \ --data-urlencode "message=$MESSAGE" \ --data "message_type=OTP") echo "$RESPONSE" > "$TMPFILE" REFERENCE_ID=$(jq -r '.reference_id' "$TMPFILE") if [ "$REFERENCE_ID" == "null" ]; then echo "Failed to retrieve reference ID." 1>&2 exit 1 fi STATUS_CODE=$(echo "$RESPONSE" | jq -r '.status.code') case "$STATUS_CODE" in "200") # Delivered to headset. Should basically never happen here. exit 0 ;; "203"|"292"|"295") # Delivered to gateway sleep 2 ;; "207"|"211"|"220"|"221"|"222"|"231"|"237"|"238") # Failure to deliver (hard) echo "Could not deliver" 1>&2 exit 1 ;; "210") # Temporary phone error ;; "250") # Final status unknown echo "Final status unknown, assuming success" 1>&2 exit 0 ;; "290") # Message in progress, go into loop below sleep 2 ;; "502"|"503"|"504"|"505"|"506"|"507"|"508"|"509"|"510"|"511"|"512"|"513"|"514"|"515"|"517"|"520"|"521") echo "Carrier problem ($STATUS_CODE)" 1>&2 exit 1 ;; "10000") # Internal error at telesign... echo "Telesign internal error" 1>&2 exit 1 ;; "10019"|"10020") # Rate limit exceeded. Treating as hard failure for now. echo "Rate limit exceeded" 1>&2 exit 1 ;; *) # Many possible status codes for failure... echo "Message delivery failed: $STATUS_CODE" 1>&2 exit 1 ;; esac MAX_ITERATIONS=12 # Poll for message status echo "Polling message status (reference_id: $REFERENCE_ID)..." 1>&2 for N in $(seq 1 "$MAX_ITERATIONS") do STATUS_RESPONSE=$(curl --silent --show-error --fail \ --url "https://rest-api.telesign.com/v1/messaging/$REFERENCE_ID" \ --header "Authorization: Basic $TELESIGN_AUTH_TOKEN") echo "$STATUS_RESPONSE" >> "$TMPFILE" STATUS_CODE=$(echo "$STATUS_RESPONSE" | jq -r '.status.code') DESCRIPTION=$(echo "$STATUS_RESPONSE" | jq -r '.status.description') case "$STATUS_CODE" in "200") # Delivered to headset. Great! echo "Delivered to headset" 1>&2 exit 0 ;; "203"|"290"|"292"|"295") # Delivered to gateway, wait a bit for an update sleep 2 ;; "210") # Temporary phone error sleep 15 ;; "207"|"211"|"220"|"221"|"222"|"231"|"237"|"238") # Failure to deliver (hard) echo "Could not deliver" 1>&2 exit 1 ;; "250") # Final status unknown echo "Final status unknown, assuming success" 1>&2 exit 0 ;; "502"|"503"|"504"|"505"|"506"|"507"|"508"|"509"|"510"|"511"|"512"|"513"|"514"|"515"|"517"|"520"|"521") echo "Carrier problem ($STATUS_CODE)" 1>&2 exit 1 ;; "10000") # Internal error at telesign... echo "Telesign internal error" 1>&2 exit 1 ;; "10019"|"10020") # Rate limit exceeded. Treating as hard failure for now. echo "Rate limit exceeded" 1>&2 exit 1 ;; *) # Many possible status codes for failure... echo "Message delivery failed: $STATUS_CODE" 1>&2 exit 1 ;; esac done echo "Unclear message delivery status $STATUS_CODE ($DESCRIPTION) after $MAX_ITERATIONS iterations. Assuming failure." 1>&2 exit 1 libeufin-1.6.8/contrib/libeufin-ebisync-dbconfig0000775000175000017500000000742615122266731022147 0ustar grothoffgrothoff#!/bin/bash # This file is part of GNU TALER. # Copyright (C) 2025 Taler Systems SA # # TALER is free software; you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free Software # Foundation; either version 2.1, or (at your option) any later version. # # TALER is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License along with # TALER; see the file COPYING. If not, see # Error checking on set -eu # 1 is true, 0 is false RESET_DB=0 FORCE_PERMS=0 SKIP_INIT=0 DBUSER="libeufin-ebisync" CFGFILE="/etc/libeufin-ebisync/libeufin-ebisync.conf" function exit_fail() { echo "$@" >&2 exit 1 } # Parse command-line options while getopts 'c:g:hprsu:' OPTION; do case "$OPTION" in c) CFGFILE="$OPTARG" ;; g) DBGROUP="$OPTARG" ;; h) echo 'Supported options:' echo " -c FILENAME -- use configuration FILENAME (default: $CFGFILE)" echo " -h -- print this help text" echo " -r -- reset database (dangerous)" echo " -p -- force permission setup even without database initialization" echo " -s -- skip database initialization" echo " -u USER -- libeufin-ebisync to be run by USER (default: $DBUSER)" exit 0 ;; p) FORCE_PERMS="1" ;; r) RESET_DB="1" ;; s) SKIP_INIT="1" ;; u) DBUSER="$OPTARG" ;; ?) echo "Unrecognized command line option '$OPTION'" 1 &>2 exit 1 ;; esac done if ! id postgres >/dev/null; then exit_fail "Could not find 'postgres' user. Please install Postgresql first" fi if ! libeufin-ebisync --version 2>/dev/null; then exit_fail "Required 'libeufin-ebisync' not found. Please fix your installation." fi if [ "$(id -u)" -ne 0 ]; then exit_fail "This script must be run as root" fi # Check OS users exist if ! id "$DBUSER" >/dev/null; then exit_fail "Could not find '$DBUSER' user. Please set it up first" fi # Create DB user matching OS user name echo "Setting up database user '$DBUSER'." 1>&2 if ! sudo -i -u postgres createuser "$DBUSER" 2>/dev/null; then echo "Database user '$DBUSER' already existed. Continuing anyway." 1>&2 fi # Check database name DBPATH=$(libeufin-ebisync config get -c "$CFGFILE" ebisyncdb-postgres CONFIG) if ! echo "$DBPATH" | grep "\(postgres\|postgresql\)://" >/dev/null; then exit_fail "Invalid database configuration value '$DBPATH'." fi DBNAME=$(echo "$DBPATH" | sed -e 's|.*://.*/||' -e 's|?.*||') if sudo -i -u postgres psql "$DBNAME" /dev/null; then if [ 1 = "$RESET_DB" ]; then echo "Deleting existing database '$DBNAME'." 1>&2 if ! sudo -i -u postgres dropdb "$DBNAME"; then exit_fail "Failed to delete existing database '$DBNAME'" fi DO_CREATE=1 else echo "Database '$DBNAME' already exists, continuing anyway." DO_CREATE=0 fi else DO_CREATE=1 fi # Create database if [ 1 = "$DO_CREATE" ]; then echo "Creating database '$DBNAME'." 1>&2 if ! sudo -i -u postgres createdb -O "$DBUSER" "$DBNAME"; then exit_fail "Failed to create database '$DBNAME'" fi else if ! echo "GRANT ALL PRIVILEGES ON DATABASE $DBNAME TO \"$DBUSER\"" | sudo -i -u postgres psql "$DBNAME"; then exit_fail "Failed to grant access to database '$DBNAME' to '$DBUSER'." fi fi # Run dbinit if [ 0 = "$SKIP_INIT" ]; then echo "Initialize database schema" if ! sudo -u "$DBUSER" libeufin-ebisync dbinit -c "$CFGFILE"; then exit_fail "Failed to initialize database schema" fi fi echo "Database configuration finished." 1>&2 libeufin-1.6.8/contrib/bank-spa.lock0000664000175000017500000000000615204341712017544 0ustar grothoffgrothoff1.5.14libeufin-1.6.8/contrib/libeufin-load-sql0000755000175000017500000000642214674637415020463 0ustar grothoffgrothoff#!/bin/bash # NOTE: THIS FILE CONSIDERS _ONLY_ THE OBSOLETE NEXUS # SQL FILES. THIS FILE WILL BE DISCARDED AS SOON AS NEXUS # WILL GET ITS SQL REFACTORED. set -eu fail () { echo $1 exit 1 } usage_and_exit () { echo Usage: libeufin-load-sql OPTIONS echo echo By default, this command creates and/or patches the LibEuFin tables. echo One particular LibEuFin service could be selected via the '-s' option. echo Pass '-r' to delete tables and schemas. echo echo 'Supported options:' echo " -s SERVICE -- specify 'sandbox' or 'nexus', according to which set of tables are to be setup or dropped. If missing both sets will be setup or dropped on the same database." echo ' -d DB_CONN -- required. Pass DB_CONN as the postgres connection string. Passed verbatim to Psql' echo ' -l LOC -- required. Pass LOC as the SQL files location. Typically $prefix/share/libeufin/sql' echo ' -h -- print this help' echo ' -r -- drop all the tables and schema(s)' exit 0 } run_sql_file () { # -q doesn't hide all the output, hence the # redirection to /dev/null. psql -d $DB_CONNECTION \ -q \ -f $1 \ --set ON_ERROR_STOP=1 > /dev/null } get_patch_path () { echo "$PATCHES_LOCATION/$1" } # The real check happens (by the caller) # by checking the returned text. check_patch_applied () { psql -d $DB_CONNECTION \ -t \ -c "SELECT applied_by FROM _v.patches WHERE patch_name = '$1' LIMIT 1" } # Iterates over the .sql migration files and applies # the new ones. iterate_over_patches () { component="$1" cd $PATCHES_LOCATION for patch_filename in $(ls -1 -v $component-[0-9][0-9][0-9][0-9].sql); do patch_name=$(echo $patch_filename | cut -f1 -d.) # drops the final .sql echo Checking patch: "$patch_name" maybe_applied=$(check_patch_applied "$patch_name") if test -n "$maybe_applied"; then continue; fi # patch not applied, apply it. echo Patch $patch_name not applied, applying it. run_sql_file $patch_filename done cd - > /dev/null # cd to previous location. } if test $# -eq 0; then usage_and_exit fi while getopts ":d:l:hs:r" OPTION; do case "$OPTION" in d) DB_CONNECTION="$OPTARG" # only one required. ;; l) PATCHES_LOCATION="$OPTARG" ;; s) if test "$OPTARG" != sandbox -a "$OPTARG" != nexus; then fail "Invalid -s value: $OPTARG. Please pass 'sandbox' or 'nexus'." fi SERVICE="$OPTARG" ;; r) DROP="YES" ;; h) usage_and_exit ;; ?) fail 'Unrecognized command line option' ;; esac done # Checking required options. if test -z "${PATCHES_LOCATION:-}"; then # This value is substituted by GNU make at installation time. PATCHES_LOCATION=__STATIC_PATCHES_LOCATION__ fi if test -z "${DB_CONNECTION:-}"; then fail "Required option '-d' was missing." fi run_sql_file $(get_patch_path "versioning.sql") if test -z "${SERVICE:-}"; then # impact both services. # Maybe drop. if test "${DROP:-}" = "YES"; then run_sql_file $(get_patch_path "nexus-drop.sql") exit 0 fi iterate_over_patches nexus exit 0 fi # Maybe drop if test "${DROP:-}" = "YES"; then run_sql_file $(get_patch_path "${SERVICE}-drop.sql") exit 0 fi iterate_over_patches $SERVICE # helper checks the argument sanity. libeufin-1.6.8/contrib/libeufin-bank-dbinit0000755000175000017500000000010314674637415021117 0ustar grothoffgrothoff#!/bin/sh DIR=$(dirname $0) exec ${DIR}/libeufin-bank dbinit "$@" libeufin-1.6.8/contrib/indent-sql-sh0000755000175000017500000000160414674637415017637 0ustar grothoffgrothoff#!/bin/bash set -eu # This script indents the output of Exposed SQL logger. # Usage: ./indent.sh filename # Remove leading "^SQL: " that Exposed uses. crop_leading_sql () { sed 's/^SQL: //' } # Inserts new line & two spaces before the first "(" # and last ")", and before each comma. Only triggers on # "CREATE TABLE"-lines. indent_create_table () { sed '/^CREATE/s/, /,/g' \ | sed '/^CREATE/s/\(,\|)$\)/\n \1/g' \ | sed '/^CREATE/s/(/\n (/' } # Inserts new line & two spaces before each "ALTER TABLE" # statement indent_alter_table () { sed 's/^ALTER TABLE \(.*\)/ALTER TABLE\n \1/' } # Inserts a blank line after between each CREATE/ALTER TABLE statement. blank_line_after_statement () { sed '/^CREATE TABLE/s/\(.*\)/\n\1/' \ | sed '/^ALTER TABLE/s/\(.*\)/\n\1/' } crop_leading_sql < $1 \ | indent_create_table \ | indent_alter_table \ | blank_line_after_statement libeufin-1.6.8/contrib/ci/0000775000175000017500000000000015236145704015605 5ustar grothoffgrothofflibeufin-1.6.8/contrib/ci/ci.sh0000775000175000017500000000212215122266731016532 0ustar grothoffgrothoff#!/bin/bash set -exvuo pipefail # Requires podman # Fails if not found in PATH OCI_RUNTIME=$(which podman) REPO_NAME=$(basename "${PWD}") JOB_NAME="${1}" NATIVE_ARCH=$(dpkg --print-architecture) JOB_ARCH=$((grep CONTAINER_ARCH contrib/ci/jobs/${JOB_NAME}/config.ini | cut -d' ' -f 3) || echo "${2:-$NATIVE_ARCH}") JOB_CONTAINER=$((grep CONTAINER_NAME contrib/ci/jobs/${JOB_NAME}/config.ini | cut -d' ' -f 3) || echo "localhost/${REPO_NAME}:${JOB_ARCH}") CONTAINER_BUILD=$((grep CONTAINER_BUILD contrib/ci/jobs/${JOB_NAME}/config.ini | cut -d' ' -f 3) || echo "True") echo "Image name: ${JOB_CONTAINER}" if [ "${CONTAINER_BUILD}" = "True" ] ; then "${OCI_RUNTIME}" build \ --arch "${JOB_ARCH}" \ -t "${JOB_CONTAINER}" \ -f contrib/ci/Containerfile . fi "${OCI_RUNTIME}" run \ --rm \ -ti \ --arch "${JOB_ARCH}" \ --env CI_COMMIT_REF="$(git rev-parse HEAD)" \ --volume "${PWD}":/workdir \ --volume "${HOME}/.gradle/caches:/root/.gradle/caches" \ --workdir /workdir \ "${JOB_CONTAINER}" \ contrib/ci/jobs/"${JOB_NAME}"/job.sh top_dir=$(dirname "${BASH_SOURCE[0]}") #"${top_dir}"/build.sh libeufin-1.6.8/contrib/ci/Containerfile0000664000175000017500000000111615074137503020307 0ustar grothoffgrothoffFROM docker.io/library/debian:trixie ENV DEBIAN_FRONTEND=noninteractive \ # Persistent gradle cache GRADLE_USER_HOME=/workdir/.gradle RUN apt-get update -yq && \ apt-get upgrade -yq && \ apt-get install -yq \ unzip \ default-jdk-headless \ make \ po-debconf \ build-essential \ debhelper-compat \ devscripts \ git-buildpackage \ postgresql \ sudo WORKDIR /workdir CMD ["bash", "/workdir/ci/ci.sh"] libeufin-1.6.8/contrib/ci/run-all-jobs.sh0000755000175000017500000000015114752333625020447 0ustar grothoffgrothoff#!/bin/bash set -eax for JOB in $(ls $(dirname $0)/jobs | sort -n); do $(dirname $0)/ci.sh $JOB; done; libeufin-1.6.8/contrib/ci/jobs/0000775000175000017500000000000015236145704016542 5ustar grothoffgrothofflibeufin-1.6.8/contrib/ci/jobs/1-build/0000775000175000017500000000000015236145704017777 5ustar grothoffgrothofflibeufin-1.6.8/contrib/ci/jobs/1-build/job.sh0000775000175000017500000000014515110141204021066 0ustar grothoffgrothoff#!/bin/bash set -exuo pipefail # Update system apt-get update -yq apt-get upgrade -yq # Build make libeufin-1.6.8/contrib/ci/jobs/4-deb/0000775000175000017500000000000015236145704017435 5ustar grothoffgrothofflibeufin-1.6.8/contrib/ci/jobs/4-deb/version.sh0000775000175000017500000000120215110141204021432 0ustar grothoffgrothoff#!/bin/sh set -ex BRANCH=$(git name-rev --name-only HEAD) if [ -z "${BRANCH}" ]; then exit 1 else # "Unshallow" our checkout, but only our current branch, and exclude the submodules. git fetch --no-recurse-submodules --tags --depth=1000 origin "${BRANCH}" RECENT_VERSION_TAG=$(git describe --tags --match 'v*.*.*' --exclude '*-dev*' --always --abbrev=0 HEAD || exit 1) commits="$(git rev-list ${RECENT_VERSION_TAG}..HEAD --count)" if [ "${commits}" = "0" ]; then git describe --tag HEAD | sed -r 's/^v//' || exit 1 else echo $(echo ${RECENT_VERSION_TAG} | sed -r 's/^v//')-${commits}-$(git rev-parse --short=8 HEAD) fi fi libeufin-1.6.8/contrib/ci/jobs/4-deb/job.sh0000775000175000017500000000104515156463305020547 0ustar grothoffgrothoff#!/bin/bash set -exuo pipefail # Update system apt-get update -yq apt-get upgrade -yq # Build package export VERSION="$(./contrib/ci/jobs/4-deb-package/version.sh)" echo "Building package version ${VERSION}" EMAIL=none gbp dch --dch-opt=-b --ignore-branch --debian-tag="%(version)s" --git-author --new-version="${VERSION}" make deb # Test package sudo ./contrib/ci/deb-test.sh # Move to artifact ls -alh ../*.deb mkdir -p /artifacts/libeufin/${CI_COMMIT_REF} # Variable comes from CI environment mv ../*.deb /artifacts/libeufin/${CI_COMMIT_REF}/ libeufin-1.6.8/contrib/ci/jobs/2-test/0000775000175000017500000000000015236145704017660 5ustar grothoffgrothofflibeufin-1.6.8/contrib/ci/jobs/2-test/job.sh0000775000175000017500000000066715122266731021000 0ustar grothoffgrothoff#!/bin/bash set -exuo pipefail # Update system apt-get update -yq apt-get upgrade -yq ./bootstrap ./configure --prefix /usr # Setup postgres cluster sudo -u postgres pg_ctlcluster 17 main start sudo -u postgres createuser root --superuser sudo -u postgres createdb -O root libeufincheck check_command() { make check &> test-suite.log || make check &> test-suite.log } if ! check_command ; then cat test-suite.log exit 1 filibeufin-1.6.8/contrib/ci/jobs/3-docs/0000775000175000017500000000000015236145704017632 5ustar grothoffgrothofflibeufin-1.6.8/contrib/ci/jobs/3-docs/job.sh0000775000175000017500000000022615122266731020741 0ustar grothoffgrothoff#!/bin/bash set -exuo pipefail # Update system apt-get update -yq apt-get upgrade -yq # Build documentation # Why is doc always failling # make doc libeufin-1.6.8/contrib/ci/jobs/5-deploy/0000775000175000017500000000000015236145704020200 5ustar grothoffgrothofflibeufin-1.6.8/contrib/ci/jobs/5-deploy/config.ini0000664000175000017500000000016615110141204022127 0ustar grothoffgrothoff[build] HALT_ON_FAILURE = True WARN_ON_FAILURE = True CONTAINER_BUILD = False CONTAINER_NAME = nixery.dev/shell/rsync libeufin-1.6.8/contrib/ci/jobs/5-deploy/job.sh0000775000175000017500000000050015110141204021262 0ustar grothoffgrothoff#!/bin/bash set -exuo pipefail ARTIFACT_PATH="/artifacts/libeufin/${CI_COMMIT_REF}/*.deb" RSYNC_HOST="taler.host.internal" RSYNC_PORT=424242 RSYNC_PATH="incoming_packages/trixie-taler-ci/" RSYNC_DEST="rsync://${RSYNC_HOST}/${RSYNC_PATH}" rsync -vP \ --port ${RSYNC_PORT} \ ${ARTIFACT_PATH} ${RSYNC_DEST} libeufin-1.6.8/contrib/ci/jobs/0-codespell/0000775000175000017500000000000015236145704020651 5ustar grothoffgrothofflibeufin-1.6.8/contrib/ci/jobs/0-codespell/dictionary.txt0000664000175000017500000000056415156463305023565 0ustar grothoffgrothoff# List of "words" that codespell should ignore in our sources. # # Note: The word sensitivity depends on how the to-be-ignored word is # spelled in codespell_lib/data/dictionary.txt. F.e. if there is a word # 'foo' and you add 'Foo' _here_, codespell will continue to complain # about 'Foo'. # ifset bu fIDN ECT complet ges UE Te optin claus pres haa registerIn checkInlibeufin-1.6.8/contrib/ci/jobs/0-codespell/config.ini0000644000175000017500000000017314771233107022614 0ustar grothoffgrothoff[build] HALT_ON_FAILURE = False WARN_ON_FAILURE = True CONTAINER_BUILD = False CONTAINER_NAME = nixery.dev/shell/codespell libeufin-1.6.8/contrib/ci/jobs/0-codespell/job.sh0000775000175000017500000000114615122266731021762 0ustar grothoffgrothoff#!/bin/bash set -exuo pipefail job_dir=$(dirname "${BASH_SOURCE[0]}") skip=$(cat <&2 } ITEMS="libeufin-bank libeufin-nexus libeufin-ebisync" step "Install libeufin" dpkg -i ../libeufin*.deb step "Install libeufin again" dpkg -i ../libeufin*.deb step "Start postgres cluster" sudo -u postgres pg_ctlcluster 17 main start for BIN in $ITEMS; do step "$BIN version:" $BIN --version done for USER in $ITEMS; do step "$USER user:" id $USER done step "Run dbconfig" libeufin-dbconfig -r -c testbench/conf/mini.conf libeufin-ebisync-dbconfig -r -c testbench/conf/mini.conf for USER in $ITEMS; do step "Check $USER db access" sudo -u $USER psql -d libeufincheck -c "SELECT 1;" &> /dev/null done step "Check man pages" for BIN in $ITEMS; do man $BIN > /dev/null man $BIN.conf > /dev/null done step "Remove libeufin" dpkg --remove libeufin* step "Reinstall libeufin" dpkg -i ../libeufin*.deb step "Purge libeufin:" dpkg --purge libeufin* step "Reinstall libeufin" dpkg -i ../libeufin*.deblibeufin-1.6.8/contrib/libeufin-tan-fail.sh0000755000175000017500000000006614674637415021051 0ustar grothoffgrothoff#!/bin/sh # This file is in the public domain. exit 1 libeufin-1.6.8/contrib/libeufin-dbconfig0000775000175000017500000002014715140725607020512 0ustar grothoffgrothoff#!/bin/bash # This file is part of GNU TALER. # Copyright (C) 2023,2024,2025 Taler Systems SA # # TALER is free software; you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free Software # Foundation; either version 2.1, or (at your option) any later version. # # TALER is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License along with # TALER; see the file COPYING. If not, see # # @author Christian Grothoff # @author Florian Dold # Error checking on set -eu # 1 is true, 0 is false RESET_DB=0 FORCE_PERMS=0 SKIP_INIT=0 SKIP_NEXUS=0 SKIP_BANK=0 NEXUS_DBUSER="libeufin-nexus" BANK_DBUSER="libeufin-bank" NEXUS_CFGFILE="/etc/libeufin/libeufin-nexus.conf" BANK_CFGFILE="/etc/libeufin/libeufin-bank.conf" function exit_fail() { echo "$@" >&2 exit 1 } short_opts=c:b:hrn:psu:v: long_opts=bank-config:,help,nexus-config:,reset,skip,permissions,nexus-user:,bank-user:,only-nexus,only-bank if ! VALID_ARGS=$(getopt -o "$short_opts" -l "$long_opts" -n "$0" -- "$@"); then exit 1 fi eval set -- "$VALID_ARGS" function usage { cat - </dev/null; then exit_fail "Could not find 'postgres' user. Please install Postgresql first" fi if [ "$(id -u)" -ne 0 ]; then exit_fail "This script must be run as root" fi # Check tools availability if they are going to be used function check_availability { if ! $1 --help 1>/dev/null; then exit_fail "Required '$1' not found. Please fix your installation." fi which "$1" } if [ 0 = "$SKIP_INIT" ]; then if [ 0 = "$SKIP_BANK" ]; then BANK_DBINIT=$(check_availability libeufin-bank-dbinit) fi if [ 0 = "$SKIP_NEXUS" ]; then NEXUS_DBINIT=$(check_availability libeufin-nexus-dbinit) fi fi # Check OS users exist function check_os_user { if ! id "$1" >/dev/null; then exit_fail "Could not find '$1' user. Cannot continue" fi } if [ 0 = "$SKIP_BANK" ]; then check_os_user "$BANK_DBUSER"; fi if [ 0 = "$SKIP_NEXUS" ]; then check_os_user "$NEXUS_DBUSER"; fi # Create DB users matching OS users names function create_db_user { echo "Setting up database user '$1'." 1>&2 if ! sudo -i -u postgres createuser "$1" 2>/dev/null; then echo "Database user '$1' already existed. Continuing anyway." 1>&2 fi } if [ 0 = "$SKIP_BANK" ]; then create_db_user "$BANK_DBUSER"; fi if [ 0 = "$SKIP_NEXUS" ]; then create_db_user "$NEXUS_DBUSER"; fi # Check database name function get_db_name { if ! echo "$1" | grep "\(postgres\|postgresql\)://" >/dev/null; then exit_fail "Invalid libeufin-$2 database configuration value '$1'." fi # Remove URI, host and query from postgres URI. echo "$1" | sed -e 's|.*://.*/||' -e 's|?.*||' } if [ 0 = "$SKIP_BANK" ]; then BANK_DBNAME=$(get_db_name "$(libeufin-bank config get -c "$BANK_CFGFILE" libeufin-bankdb-postgres CONFIG)" "bank") fi if [ 0 = "$SKIP_NEXUS" ]; then NEXUS_DBNAME=$(get_db_name "$(libeufin-nexus config get -c "$NEXUS_CFGFILE" nexus-postgres CONFIG 2>/dev/null || libeufin-nexus config get -c "$NEXUS_CFGFILE" libeufin-nexusdb-postgres CONFIG)" "nexus") fi # If using both components they must use the same database if [[ 0 == "$SKIP_BANK" && 0 == "$SKIP_NEXUS" && $NEXUS_DBNAME != "$BANK_DBNAME" ]]; then exit_fail "Database names for libeufin-bank and libeufin-nexus must match ($NEXUS_DBNAME vs $BANK_DBNAME)" fi if [ 0 = "$SKIP_BANK" ]; then DBNAME=$BANK_DBNAME DBUSER=$BANK_DBUSER else DBNAME=$NEXUS_DBNAME DBUSER=$NEXUS_DBUSER fi if sudo -i -u postgres psql "$DBNAME" /dev/null; then if [ 1 = "$RESET_DB" ]; then echo "Deleting existing database '$DBNAME'." 1>&2 if ! sudo -i -u postgres dropdb "$DBNAME"; then exit_fail "Failed to delete existing database '$DBNAME'" fi DO_CREATE=1 else echo "Database '$DBNAME' already exists, continuing anyway." DO_CREATE=0 fi else DO_CREATE=1 fi if [ 1 = "$DO_CREATE" ]; then echo "Creating database '$DBNAME'." 1>&2 if ! sudo -i -u postgres createdb -O "$DBUSER" "$DBNAME"; then exit_fail "Failed to create database '$DBNAME'" fi fi function grant_db_access { if ! echo "GRANT ALL PRIVILEGES ON DATABASE $DBNAME TO \"$1\"" | sudo -i -u postgres psql "$DBNAME"; then exit_fail "Failed to grant access to database '$DBNAME' to '$1'." fi } function grant_schema_access { if ! echo "GRANT ALL ON SCHEMA $2 TO \"$1\"" | sudo -i -u postgres psql "$DBNAME"; then exit_fail "Failed to grant usage privilege on schema '$2' to '$1'." fi if ! echo "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA $2 TO \"$1\"" | sudo -i -u postgres psql "$DBNAME"; then exit_fail "Failed to grant access to schema '$2' to '$1'." fi } # Init database with one of the users to create the _v schema if [ 0 = "$SKIP_INIT" ]; then if [ 0 = "$SKIP_BANK" ]; then echo "Initializing database '$DBNAME' for libeufin-bank." 1>&2 sudo -u "$BANK_DBUSER" "$BANK_DBINIT" -c "$BANK_CFGFILE" else echo "Initializing database '$DBNAME' for libeufin-nexus." 1>&2 sudo -u "$NEXUS_DBUSER" "$NEXUS_DBINIT" -c "$NEXUS_CFGFILE" fi fi # nexus permission to access db and _v schema if bank init the database if [[ 0 == "$SKIP_INIT" || 1 == "$FORCE_PERMS" ]] && [[ 0 == "$SKIP_BANK" && 0 == "$SKIP_NEXUS" ]]; then echo "Setting postgres permissions for '$NEXUS_DBUSER'" 1>&2 grant_db_access "$NEXUS_DBUSER" grant_schema_access "$NEXUS_DBUSER" "_v" grant_schema_access "$NEXUS_DBUSER" "libeufin_bank" fi # DB initialization for nexus if both component are setup if [[ 0 == "$SKIP_INIT" && 0 == "$SKIP_BANK" && 0 == "$SKIP_NEXUS" ]]; then echo "Initializing database '$DBNAME' for libeufin-nexus." 1>&2 sudo -u "$NEXUS_DBUSER" "$NEXUS_DBINIT" -c "$NEXUS_CFGFILE" fi # bank permission to access nexus schema if both component are setup if [[ 0 == "$SKIP_INIT" || 1 == "$FORCE_PERMS" ]] && [[ 0 == "$SKIP_BANK" && 0 == "$SKIP_NEXUS" ]]; then echo "Setting postgres permissions for '$BANK_DBUSER'" 1>&2 if ! echo "GRANT \"$NEXUS_DBUSER\" TO \"$BANK_DBUSER\"" | sudo -i -u postgres psql "$DBNAME"; then exit_fail "Failed to grant \"$NEXUS_DBUSER\" privilege to \"$BANK_DBUSER\"" fi fi echo "Database configuration finished." 1>&2 libeufin-1.6.8/contrib/libeufin-tan-sms-clicksend.sh0000775000175000017500000000627615077270636022704 0ustar grothoffgrothoff#!/bin/bash # This file is in the public domain. # Send an SMS using ClickSend API set -eu # Check shared secrets if [ -x "$CLICKSEND_USERNAME" ] then echo "CLICKSEND_USERNAME not set in environment" exit 1 fi if [ -x "$CLICKSEND_API_KEY" ] then echo "CLICKSEND_API_KEY not set in environment" exit 1 fi if [ $# -ne 1 ] then echo "Usage: $0 " 1>&2 exit 1 fi PHONE_NUMBER="$1" MESSAGE=$(cat -) TMPFILE=$(mktemp /tmp/clicksend-sms-logging-XXXXXX) RESPONSE=$(curl --silent --show-error --fail \ --url https://rest.clicksend.com/v3/sms/send \ --request POST \ --header 'Content-Type: application/json' \ --user "$CLICKSEND_USERNAME:$CLICKSEND_API_KEY" \ --data "{ \"messages\": [{ \"source\": \"bash-script\", \"to\": \"$PHONE_NUMBER\", \"body\": \"$MESSAGE\" }] }") echo "$RESPONSE" > "$TMPFILE" RESPONSE_CODE=$(echo "$RESPONSE" | jq -r '.response_code') if [ "$RESPONSE_CODE" != "SUCCESS" ]; then echo "Failed to send message, got response code $RESPONSE_CODE." 1>&2 exit 1 fi MESSAGE_ID=$(echo "$RESPONSE" | jq -r '.data.messages[0].message_id') if [ "$MESSAGE_ID" == "null" ]; then echo "Failed to retrieve message ID." 1>&2 exit 1 fi MESSAGE_STATUS=$(echo "$RESPONSE" | jq -r '.data.messages[0].status') if [ "$MESSAGE_STATUS" == "SUCCESS" ]; then echo "Message delivered successfully." 1>&2 exit 0 fi MAX_ITERATIONS=12 # Poll message status echo "Polling message status (message_id: $MESSAGE_ID)..." 1>&2 for N in $(seq 1 "$MAX_ITERATIONS") do STATUS_RESPONSE=$(curl --silent --show-error --fail \ --url "https://rest.clicksend.com/v3/sms/receipts/$MESSAGE_ID" \ --user "$CLICKSEND_USERNAME:$CLICKSEND_API_KEY") echo "$STATUS_RESPONSE" >> "$TMPFILE" RESPONSE_CODE=$(echo "$RESPONSE" | jq -r '.response_code') if [ "$RESPONSE_CODE" != "SUCCESS" ]; then echo "Failed to get message status, assuming failure." 1>&2 exit 1 fi STATUS_CODE=$(echo "$STATUS_RESPONSE" | jq -r '.data.status_code') STATUS_TEXT=$(echo "$STATUS_RESPONSE" | jq -r '.data.status_text') STATUS=$(echo "$STATUS_TEXT" | awk --field-separator ':' '{print $1}') case "$STATUS_CODE" in "200") case "$STATUS" in "Success"|"Sent") # Message sent to the network for delivery, wait a bit sleep 1 ;; "Queued"|"Scheduled") # queued for delivery, sleep a bit longer sleep 10 ;; "WaitApproval") # Human in the loop (strange), sleep even longer sleep 120 ;; *) # Unexpected status, keep trying sleep 5 ;; esac ;; "201") # Message delivered to the handset echo "Message delivered successfully." 1>&2 exit 0 ;; "300") # Temporary network error, clicksend will retry automatically, sleep a bit sleep 20 ;; "301") # Delivery failed echo "Message delivery failed: $DESCRIPTION" 1>&2 exit 1 ;; "FAILED"|"INVALID_RECIPIENT") exit 1 ;; *) sleep 5 ;; esac done echo "Unclear message delivery status $STATUS_CODE ($DESCRIPTION) after $MAX_ITERATIONS iterations. Assuming failure." 1>&2 exit 1 libeufin-1.6.8/contrib/bank.conf0000664000175000017500000000731115110141204016754 0ustar grothoffgrothoff[libeufin-bank] # Internal currency of the libeufin-bank CURRENCY = # Supported payment target type, this can either be iban or x-taler-bank WIRE_TYPE = # The bank base URL # BASE_URL = https://bank.example.com/ # Bank BIC used in generated iban payto URI. Required if WIRE_TYPE = iban # IBAN_PAYTO_BIC = # Bank hostname used in generated x-taler-bank payto URI. Required if WIRE_TYPE = x-taler-bank # Deprecated, BASE_URL hostname is used instead # X_TALER_BANK_PAYTO_HOSTNAME = bank.$FOO.taler.net # Bank display name, used in webui and TAN messages. Default is "Taler Bank" # NAME = "Custom Bank" # Wire transfer execution fees. Only applies to bank transactions and withdrawals. # WIRE_TRANSFER_FEES = KUDOS:0 # Minimum wire transfer amount allowed. Only applies to bank transactions and withdrawals. # MIN_WIRE_TRANSFER_AMOUNT = KUDOS:0 # Maximum wire transfer amount allowed. Only applies to bank transactions and withdrawals. # MAX_WIRE_TRANSFER_AMOUNT = KUDOS:0 # Default debt limit for newly created accounts. Default is CURRENCY:0 # DEFAULT_DEBT_LIMIT = KUDOS:200 # Value of the registration bonus for new users. Default is CURRENCY:0 # REGISTRATION_BONUS = KUDOS:100 # Allow account registration by anyone. # ALLOW_REGISTRATION = no # Allow an account to delete itself # ALLOW_ACCOUNT_DELETION = no # Allow accounts to edit their name # ALLOW_EDIT_NAME = no # Allow accounts to edit their cashout account # ALLOW_EDIT_CASHOUT_PAYTO_URI = no # Enable regional currency conversion # ALLOW_CONVERSION = no # External currency used during cashin and cashout # FIAT_CURRENCY = EUR # Path to TAN challenge transmission script via sms. If not specified, this TAN channel will not be supported. # TAN_SMS = libeufin-tan-sms.sh # Path to TAN challenge transmission script via email. If not specified, this TAN channel will not be supported. # TAN_EMAIL = libeufin-tan-email.sh # Environment variables for the sms TAN script as a single-line JSON object # TAN_SMS_ENV = { "AUTH_TOKEN": "secret-token" } # Environment variables for the email TAN script as a single-line JSON object # TAN_EMAIL_ENV = { "AUTH_TOKEN": "secret-token" } # How "libeufin-bank serve" serves its API, this can either be tcp or unix SERVE = tcp # Port on which the HTTP server listens, e.g. 9967. Only used if SERVE is tcp. PORT = 8080 # Which IP address should we bind to? E.g. ``127.0.0.1`` or ``::1``for loopback. Can also be given as a hostname. Only used if SERVE is tcp. BIND_TO = 0.0.0.0 # Which unix domain path should we bind to? Only used if SERVE is unix. # UNIXPATH = libeufin-bank.sock # Path to spa files SPA = $DATADIR/spa/ # Exchange that is suggested to wallets when withdrawing. # SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.demo.taler.net/ # Password hash algorithm, this can only be bcrypt PWD_HASH_ALGORITHM = bcrypt # Password hash algorithm configuration as a single-line JSON object # When PWD_HASH_ALGORITHM = bcrypt you can configure cost PWD_HASH_CONFIG = { "cost": 8 } # Whether to check password quality # Unstable flag, will become a non configurable default in a future version PWD_CHECK = yes # Whether to allow password auth everywhere # Unstable flag, will become a non configurable default in a future version PWD_AUTH_COMPAT = no # Time after which pending operations are aborted during garbage collection GC_ABORT_AFTER = 15m # Time after which aborted operations and expired items are deleted during garbage collection GC_CLEAN_AFTER = 14d # Time after which all bank transactions, operations and deleted accounts are deleted during garbage collection GC_DELETE_AFTER = 10year [libeufin-bankdb-postgres] # Where are the SQL files to setup our tables? SQL_DIR = $DATADIR/sql/ # DB connection string CONFIG = postgres:///libeufin libeufin-1.6.8/contrib/libeufin-nexus-dbinit0000755000175000017500000000010314674637415021346 0ustar grothoffgrothoff#!/bin/sh DIR=$(dirname $0) exec ${DIR}/libeufin-nexus dbinit "$@" libeufin-1.6.8/contrib/libeufin-tan-file.sh0000755000175000017500000000010514674637415021047 0ustar grothoffgrothoff#!/bin/sh # This file is in the public domain. cat > /tmp/tan-$1.txt libeufin-1.6.8/contrib/currencies.conf0000644000175000017500000000410114760713600020212 0ustar grothoffgrothoff[currency-euro] ENABLED = YES name = "Euro" code = "EUR" fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"€"} [currency-swiss-francs] ENABLED = YES name = "Swiss Francs" code = "CHF" fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"Fr.","-2":"Rp."} [currency-forint] ENABLED = NO name = "Hungarian Forint" code = "HUF" fractional_input_digits = 0 fractional_normal_digits = 0 fractional_trailing_zero_digits = 0 alt_unit_names = {"0":"Ft"} [currency-us-dollar] ENABLED = NO name = "US Dollar" code = "USD" fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"$"} [currency-kudos] ENABLED = YES name = "Kudos (Taler Demonstrator)" code = "KUDOS" fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"ク"} [currency-testkudos] ENABLED = YES name = "Test-kudos (Taler Demonstrator)" code = "TESTKUDOS" fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"テ","3":"kテ","-3":"mテ"} [currency-japanese-yen] ENABLED = NO name = "Japanese Yen" code = "JPY" fractional_input_digits = 2 fractional_normal_digits = 0 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"¥"} [currency-bitcoin-mainnet] ENABLED = NO name = "Bitcoin (Mainnet)" code = "BITCOINBTC" fractional_input_digits = 8 fractional_normal_digits = 3 fractional_trailing_zero_digits = 0 alt_unit_names = {"0":"BTC","-3":"mBTC"} [currency-ethereum] ENABLED = NO name = "WAI-ETHER (Ethereum)" code = "EthereumWAI" 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"} [currency-netzbon] ENABLED=YES name=NetzBon code=NETZBON fractional_input_digits=2 fractional_normal_digits=2 fractional_trailing_zero_digits=2 alt_unit_names = {"0":"NETZBON"} libeufin-1.6.8/contrib/populate-stats.sh0000755000175000017500000000477014752333625020547 0ustar grothoffgrothoff#!/bin/bash # This script populates the stats table, to test the /monitor API. usage() { echo "Usage: ./populate-stats.sh CONFIG_FILE [--one]" echo echo "Populates the stats table with random data" echo echo Parameters: echo echo --one instead of random amounts, it always uses 1.0 } # Detecting the help case. if test "$1" = "--help" -o "$1" = "-h" -o -z ${1:-}; then usage exit fi HAS_ONE=0 if test "$2" = "--one"; then HAS_ONE=1 fi set -eu DB_NAME=$(taler-exchange-config -c $1 -s libeufin-bankdb-postgres -o config) echo Running on the database: $DB_NAME # random number in range $1-$2 rnd () { shuf -i $1-$2 -n1 } insert_stat_one () { echo " SET search_path TO libeufin_bank; CALL libeufin_bank.stats_register_payment ( 'taler_in'::text ,TO_TIMESTAMP($1)::timestamp ,(1, 0)::taler_amount ,null ); CALL libeufin_bank.stats_register_payment ( 'taler_out'::text ,TO_TIMESTAMP($1)::timestamp ,(1, 0)::taler_amount ,null ); CALL libeufin_bank.stats_register_payment ( 'cashin'::text ,TO_TIMESTAMP($1)::timestamp ,(1, 0)::taler_amount ,(1, 0)::taler_amount ); CALL libeufin_bank.stats_register_payment ( 'cashout'::text ,TO_TIMESTAMP($1)::timestamp ,(1, 0)::taler_amount ,(1, 0)::taler_amount );" } insert_stat_rand () { echo " SET search_path TO libeufin_bank; CALL libeufin_bank.stats_register_payment ( 'taler_in'::text ,TO_TIMESTAMP($1)::timestamp ,($(rnd 0 99999999), $(rnd 0 99999999))::taler_amount ,null ); CALL libeufin_bank.stats_register_payment ( 'taler_out'::text ,TO_TIMESTAMP($1)::timestamp ,($(rnd 0 99999999), $(rnd 0 99999999))::taler_amount ,null ); CALL libeufin_bank.stats_register_payment ( 'cashin'::text ,TO_TIMESTAMP($1)::timestamp ,($(rnd 0 99999999), $(rnd 0 99999999))::taler_amount ,($(rnd 0 99999999), $(rnd 0 99999999))::taler_amount ); CALL libeufin_bank.stats_register_payment ( 'cashout'::text ,TO_TIMESTAMP($1)::timestamp ,($(rnd 0 99999999), $(rnd 0 99999999))::taler_amount ,($(rnd 0 99999999), $(rnd 0 99999999))::taler_amount );" } for n_hour_ago in `seq 1 100`; do echo -n . TIMESTAMP=$(date --date="${n_hour_ago} hour ago" +%s) if test $HAS_ONE = 1; then psql $DB_NAME -c "$(insert_stat_one ${TIMESTAMP})" > /dev/null else psql $DB_NAME -c "$(insert_stat_rand ${TIMESTAMP})" > /dev/null fi done libeufin-1.6.8/contrib/libeufin-tan-email.sh0000755000175000017500000000012714674637415021223 0ustar grothoffgrothoff#!/bin/sh # This file is in the public domain. exec mail -s "Libeufin" -r noreply "$1" libeufin-1.6.8/contrib/check-prebuilt0000755000175000017500000000072515007500353020032 0ustar grothoffgrothoff#!/usr/bin/env python3 import os import sys contrib = os.path.abspath(os.path.dirname(__file__)) bank_ver_lock = open(contrib + "/" + "bank-spa.lock").read().strip() bank_ver_prebuilt = open(contrib + "/" + "wallet-core/bank/version.txt").read().strip() if bank_ver_lock != bank_ver_prebuilt: print("bank SPA version mismatch: bank-spa.lock") print("lockfile has version", bank_ver_lock) print("prebuilt has version", bank_ver_prebuilt) sys.exit(1) libeufin-1.6.8/contrib/wallet-core/0000775000175000017500000000000015236145704017430 5ustar grothoffgrothofflibeufin-1.6.8/contrib/wallet-core/bank/0000775000175000017500000000000015236145704020343 5ustar grothoffgrothofflibeufin-1.6.8/contrib/wallet-core/bank/version.txt0000664000175000017500000000000615204341712022555 0ustar grothoffgrothoff1.5.14libeufin-1.6.8/contrib/wallet-core/bank/bof0000664000175000017500000000013115156463305021030 0ustar grothoffgrothoffbuild-metadata.json index.css index.css.map index.html index.js index.js.map version.txt libeufin-1.6.8/contrib/wallet-core/bank/index.js.map0000664000175000017500002557510115204341712022574 0ustar grothoffgrothoff{ "version": 3, "sources": ["../../../../node_modules/.pnpm/big-integer@1.6.52/node_modules/big-integer/BigInteger.js", "../../../../node_modules/.pnpm/jed@1.1.1/node_modules/jed/jed.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/util.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/options.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/create-element.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/component.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/create-context.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/constants.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/diff/children.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/diff/props.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/diff/index.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/render.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/clone-element.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/src/diff/catch-error.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/src/index.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/util.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/PureComponent.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/memo.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/forwardRef.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/Children.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/suspense.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/suspense-list.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/portals.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/render.js", "../../../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/src/index.js", "../../../../node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.min.js", "../../../../node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store/shim/index.js", "../../../../node_modules/.pnpm/qrcode-generator@1.4.4/node_modules/qrcode-generator/qrcode.js", "../../../taler-util/src/nacl-fast.ts", "../../../taler-util/src/prng-browser.ts", "../../../taler-util/src/punycode.ts", "../../../taler-util/src/whatwg-url.ts", "../../../taler-util/src/url.ts", "../../../taler-util/src/helpers.ts", "../../../taler-util/src/logging.ts", "../../../taler-util/src/codec.ts", "../../../taler-util/src/CancellationToken.ts", "../../../taler-util/src/taler-error-codes.ts", "../../../taler-util/src/time.ts", "../../../taler-util/src/errors.ts", "../../../taler-util/src/http-common.ts", "../../../taler-util/src/libtool-version.ts", "../../../taler-util/src/types-taler-common.ts", "../../../taler-util/src/operation.ts", "../../../taler-util/src/amounts.ts", "../../../taler-util/src/http-impl.missing.ts", "../../../taler-util/src/http.ts", "../../../taler-util/src/base64.ts", "../../../taler-util/src/taler-crypto.ts", "../../../taler-util/src/sha256.ts", "../../../taler-util/src/kdf.ts", "../../../taler-util/src/taler_signatures.ts", "../../../taler-util/src/result.ts", "../../../taler-util/src/bech32.ts", "../../../taler-util/src/segwit_addr.ts", "../../../taler-util/src/bitcoin.ts", "../../../taler-util/src/iban.ts", "../../../taler-util/src/payto.ts", "../../../taler-util/src/types-taler-exchange.ts", "../../../taler-util/src/http-client/utils.ts", "../../../taler-util/src/bank-api-client.ts", "../../../taler-util/src/types-taler-wallet.ts", "../../../taler-util/src/types-taler-merchant.ts", "../../../taler-util/src/contract-terms.ts", "../../../taler-util/src/fnutils.ts", "../../../taler-util/src/http-status-codes.ts", "../../../taler-util/src/types-taler-bank-conversion.ts", "../../../taler-util/src/http-client/bank-conversion.ts", "../../../taler-util/src/types-taler-corebank.ts", "../../../taler-util/src/taleruri.ts", "../../../taler-util/src/http-client/bank-core.ts", "../../../taler-util/src/types-taler-bank-integration.ts", "../../../taler-util/src/http-client/bank-integration.ts", "../../../taler-util/src/types-taler-revenue.ts", "../../../taler-util/src/http-client/bank-revenue.ts", "../../../taler-util/src/types-taler-wire-gateway.ts", "../../../taler-util/src/http-client/bank-wire.ts", "../../../taler-util/src/types-taler-prepared-transfer.ts", "../../../taler-util/src/http-client/bank-prepared.ts", "../../../taler-util/src/types-taler-challenger.ts", "../../../taler-util/src/http-client/challenger.ts", "../../../taler-util/src/types-donau.ts", "../../../taler-util/src/http-client/donau-client.ts", "../../../taler-util/src/http-client/exchange-client.ts", "../../../taler-util/src/http-client/mailbox.ts", "../../../taler-util/src/http-client/merchant.ts", "../../../taler-util/src/i18n.ts", "../../../taler-util/src/promises.ts", "../../../taler-util/src/longpool-queue.ts", "../../../taler-util/src/notifications.ts", "../../../taler-util/src/timer.ts", "../../../taler-util/src/observability.ts", "../../../taler-util/src/performance.ts", "../../../taler-util/src/RequestThrottler.ts", "../../../taler-util/src/ReserveTransaction.ts", "../../../taler-util/src/TaskThrottler.ts", "../../../taler-util/src/types-taler-wallet-transactions.ts", "../../../taler-util/src/transaction-test-data.ts", "../../../taler-util/src/types-taler-mailbox.ts", "../../../taler-util/src/taler-account-properties.ts", "../../../taler-util/src/taler-signatures.ts", "../../../taler-util/src/aml/properties.ts", "../../../taler-util/src/aml/events.ts", "../../../taler-util/src/aml/reporting.ts", "../../../taler-util/src/index.browser.ts", "../../../../node_modules/.pnpm/qrcode-generator@1.4.4/node_modules/qrcode-generator/qrcode.js", "../../../web-util/src/components/utils.ts", "../../../web-util/src/components/Attention.tsx", "../../../web-util/src/components/CopyButton.tsx", "../../../web-util/src/components/ErrorLoading.tsx", "../../../web-util/src/components/LangSelector.tsx", "../../../web-util/src/components/Loading.tsx", "../../../web-util/src/components/Header.tsx", "../../../web-util/src/components/Footer.tsx", "../../../web-util/src/components/Button.tsx", "../../../web-util/src/components/ShowInputErrorLabel.tsx", "../../../web-util/src/components/NotificationBanner.tsx", "../../../web-util/src/components/ToastBanner.tsx", "../../../web-util/src/components/Time.tsx", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/add/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfDay/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameDay/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isDate/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarMonths/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarYears/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInDays/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMilliseconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/roundingMethods/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInHours/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMinutes/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfDay/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfMonth/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isLastDayOfMonth/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMonths/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInSeconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInYears/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachDayOfInterval/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMonth/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCDayOfYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeekYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeekYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeekYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeekYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/lightFormatters/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/formatters/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/longFormatters/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/protectedTokens/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatDistance/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildFormatLongFn/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatLong/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatRelative/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildLocalizeFn/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/localize/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchFn/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchPatternFn/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/match/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/format/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/assign/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDuration/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatISO/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getHours/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getMinutes/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getMonth/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getSeconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/intervalToDuration/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isFuture/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Setter.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/EraParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/YearParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalWeekYearParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOWeekYearParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ExtendedYearParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/QuarterParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneQuarterParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/MonthParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneMonthParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalWeekParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCISOWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOWeekParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DateParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayOfYearParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCDay/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalDayParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneLocalDayParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCISODay/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISODayParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/AMPMParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/AMPMMidnightParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayPeriodParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour1to12Parser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour0to23Parser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour0To11Parser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour1To24Parser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/MinuteParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/SecondParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/FractionOfSecondParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOTimezoneWithZParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOTimezoneParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/TimestampSecondsParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/TimestampMillisecondsParser.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameMonth/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subDays/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parseISO/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setHours/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMonths/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/sub/index.js", "../../../web-util/src/components/RenderAmount.tsx", "../../../web-util/src/components/Pagination.tsx", "../../../web-util/src/components/QR.tsx", "../../../web-util/src/components/NotificationCardBulma.tsx", "../../../web-util/src/context/api.ts", "../../../web-util/src/utils/base64.ts", "../../../web-util/src/utils/request.ts", "../../../web-util/src/context/translation.ts", "../../../web-util/src/hooks/useAsync.ts", "../../../web-util/src/hooks/useAsyncAsHook.ts", "../../../web-util/src/hooks/useForm.ts", "../../../web-util/src/hooks/useLocalStorage.ts", "../../../web-util/src/utils/observable.ts", "../../../web-util/src/hooks/useLang.ts", "../../../web-util/src/hooks/useChallenge.ts", "../../../web-util/src/hooks/useMemoryStorage.ts", "../../../web-util/src/hooks/useNotifications.ts", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/de/_lib/formatDistance/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/de/_lib/formatLong/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/de/_lib/formatRelative/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/de/_lib/localize/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/de/_lib/match/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/de/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-GB/_lib/formatLong/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-GB/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/es/_lib/formatDistance/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/es/_lib/formatLong/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/es/_lib/formatRelative/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/es/_lib/localize/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/es/_lib/match/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/es/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/fr/_lib/formatDistance/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/fr/_lib/formatLong/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/fr/_lib/formatRelative/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/fr/_lib/localize/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/fr/_lib/match/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/fr/index.js", "../../../web-util/src/context/bank-api.ts", "../../../web-util/src/context/activity.ts", "../../../web-util/src/context/challenger-api.ts", "../../../web-util/src/context/merchant-api.ts", "../../../web-util/src/context/exchange-api.ts", "../../../web-util/src/context/navigation.ts", "../../../web-util/src/utils/route.ts", "../../../web-util/src/context/common-preferences.ts", "../../../web-util/src/context/wallet-integration.ts", "../../../web-util/src/forms/gana/accept-tos.ts", "../../../web-util/src/forms/gana/challenger_email.ts", "../../../web-util/src/forms/gana/challenger_postal.ts", "../../../web-util/src/forms/gana/challenger_sms.ts", "../../../web-util/src/forms/gana/generic_note.ts", "../../../web-util/src/forms/gana/gls_merchant_onboarding.ts", "../../../web-util/src/utils/select-ui-lists.ts", "../../../web-util/src/forms/gana/gls_wallet_confirmation.ts", "../../../web-util/src/forms/gana/multi_upload.ts", "../../../web-util/src/forms/gana/nameAndBirthdate.ts", "../../../web-util/src/forms/gana/simplest.ts", "../../../web-util/src/forms/gana/VQF_902_11_customer.ts", "../../../web-util/src/forms/gana/VQF_902_11_officer.ts", "../../../web-util/src/forms/gana/VQF_902_14.ts", "../../../web-util/src/forms/gana/VQF_902_1_customer.ts", "../../../web-util/src/forms/gana/VQF_902_1_officer.ts", "../../../web-util/src/forms/gana/VQF_902_4.ts", "../../../web-util/src/forms/gana/VQF_902_5.ts", "../../../web-util/src/forms/gana/VQF_902_9_customer.ts", "../../../web-util/src/forms/gana/VQF_902_9_officer.ts", "../../../web-util/src/forms/Calendar.tsx", "../../../web-util/src/forms/Caption.tsx", "../../../web-util/src/forms/fields/InputLine.tsx", "../../../web-util/src/forms/fields/InputArray.tsx", "../../../web-util/src/forms/Dialog.tsx", "../../../web-util/src/forms/fields/ExternalLink.tsx", "../../../web-util/src/forms/fields/InputAbsoluteTime.tsx", "../../../web-util/src/forms/fields/InputAmount.tsx", "../../../web-util/src/forms/fields/InputChoiceHorizontal.tsx", "../../../web-util/src/forms/fields/InputChoiceStacked.tsx", "../../../web-util/src/forms/fields/InputDownloadLink.tsx", "../../../web-util/src/forms/fields/InputDrilldown.tsx", "../../../web-util/src/forms/fields/InputSelectOne.tsx", "../../../web-util/src/forms/fields/InputDuration.tsx", "../../../web-util/src/forms/fields/InputDurationText.tsx", "../../../web-util/src/forms/fields/InputFile.tsx", "../../../web-util/src/forms/fields/InputInteger.tsx", "../../../web-util/src/forms/fields/InputIsoDate.tsx", "../../../web-util/src/forms/fields/InputSecret.tsx", "../../../web-util/src/forms/fields/InputSelectMultiple.tsx", "../../../web-util/src/forms/fields/InputText.tsx", "../../../web-util/src/forms/fields/InputTextArea.tsx", "../../../web-util/src/forms/fields/InputToggle.tsx", "../../../web-util/src/forms/Group.tsx", "../../../web-util/src/forms/forms-ui.tsx", "../../../web-util/src/forms/forms-utils.ts", "../../../web-util/src/forms/HtmlIframe.tsx", "../../../web-util/src/forms/fields/InputPhone.tsx", "../../../web-util/src/forms/field-types.ts", "../../../web-util/src/forms/forms-types.ts", "../../../web-util/src/forms/TimePicker.tsx", "../../../web-util/src/forms/index.ts", "../../../web-util/src/stories-utils.tsx", "../../../web-util/src/utils/http-impl.browser.ts", "../../../web-util/src/utils/http-impl.sw.ts", "../../../web-util/src/utils/buildPaginatedResult.ts", "../../src/app.tsx", "../../../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/core/dist/index.mjs", "../../../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/_internal/dist/index.mjs", "../../src/Routing.tsx", "../../src/pages/LoginForm.tsx", "../../src/utils.ts", "../../src/pages/PaytoWireTransferForm.tsx", "../../src/pages/SolveMFA.tsx", "../../src/pages/regional/CreateCashout.tsx", "../../src/hooks/account.ts", "../../src/hooks/regional.ts", "../../src/pages/RegistrationPage.tsx", "../../src/context/settings.ts", "../../src/hooks/preferences.ts", "../../src/pages/rnd.ts", "../../src/hooks/session.ts", "../../src/pages/AccountPage/state.ts", "../../src/pages/AccountPage/views.tsx", "../../src/components/Transactions/state.ts", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isDate/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCDayOfYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeekYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeekYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeekYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeekYear/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeek/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/lightFormatters/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/formatters/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/longFormatters/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/protectedTokens/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatDistance/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildFormatLongFn/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatLong/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatRelative/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildLocalizeFn/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/localize/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchFn/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchPatternFn/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/match/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/format/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subDays/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMonths/index.js", "../../../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/sub/index.js", "../../src/components/Transactions/views.tsx", "../../src/components/Transactions/index.ts", "../../src/pages/PaymentOptions.tsx", "../../src/pages/WalletWithdrawForm.tsx", "../../src/hooks/bank-state.ts", "../../src/pages/OperationState/state.ts", "../../src/pages/OperationState/views.tsx", "../../src/components/QR.tsx", "../../src/pages/WithdrawalConfirmationQuestion.tsx", "../../src/pages/OperationState/index.ts", "../../src/pages/AccountPage/index.ts", "../../src/pages/BankFrame.tsx", "../../src/pages/ConversionRateClassDetails.tsx", "../../src/hooks/form.ts", "../../src/pages/admin/ConversionClassList.tsx", "../../src/pages/regional/ConversionConfig.tsx", "../../src/pages/ProfileNavigation.tsx", "../../src/pages/NewConversionRateClass.tsx", "../../src/pages/admin/ConversionRateClassForm.tsx", "../../src/pages/PublicHistoriesPage.tsx", "../../src/pages/ShowNotifications.tsx", "../../src/pages/WireTransfer.tsx", "../../src/pages/WithdrawalOperationPage.tsx", "../../src/pages/WithdrawalQRCode.tsx", "../../src/pages/QrCodeSection.tsx", "../../src/pages/account/CashoutListForAccount.tsx", "../../src/components/Cashouts/state.ts", "../../src/components/Cashouts/views.tsx", "../../src/components/Cashouts/index.ts", "../../src/pages/account/ShowAccountDetails.tsx", "../../src/pages/admin/AccountForm.tsx", "../../src/pages/account/UpdateAccountPassword.tsx", "../../src/pages/admin/AdminHome.tsx", "../../src/pages/admin/AccountList.tsx", "../../src/pages/admin/CreateNewAccount.tsx", "../../src/pages/admin/DownloadStats.tsx", "../../src/pages/admin/RemoveAccount.tsx", "../../src/pages/regional/ShowCashoutDetails.tsx", "../../src/i18n/strings.ts", "../../src/settings.ts", "../../src/index.tsx"], "sourcesContent": ["var bigInt = (function (undefined) {\r\n \"use strict\";\r\n\r\n var BASE = 1e7,\r\n LOG_BASE = 7,\r\n MAX_INT = 9007199254740992,\r\n MAX_INT_ARR = smallToArray(MAX_INT),\r\n DEFAULT_ALPHABET = \"0123456789abcdefghijklmnopqrstuvwxyz\";\r\n\r\n var supportsNativeBigInt = typeof BigInt === \"function\";\r\n\r\n function Integer(v, radix, alphabet, caseSensitive) {\r\n if (typeof v === \"undefined\") return Integer[0];\r\n if (typeof radix !== \"undefined\") return +radix === 10 && !alphabet ? parseValue(v) : parseBase(v, radix, alphabet, caseSensitive);\r\n return parseValue(v);\r\n }\r\n\r\n function BigInteger(value, sign) {\r\n this.value = value;\r\n this.sign = sign;\r\n this.isSmall = false;\r\n }\r\n BigInteger.prototype = Object.create(Integer.prototype);\r\n\r\n function SmallInteger(value) {\r\n this.value = value;\r\n this.sign = value < 0;\r\n this.isSmall = true;\r\n }\r\n SmallInteger.prototype = Object.create(Integer.prototype);\r\n\r\n function NativeBigInt(value) {\r\n this.value = value;\r\n }\r\n NativeBigInt.prototype = Object.create(Integer.prototype);\r\n\r\n function isPrecise(n) {\r\n return -MAX_INT < n && n < MAX_INT;\r\n }\r\n\r\n function smallToArray(n) { // For performance reasons doesn't reference BASE, need to change this function if BASE changes\r\n if (n < 1e7)\r\n return [n];\r\n if (n < 1e14)\r\n return [n % 1e7, Math.floor(n / 1e7)];\r\n return [n % 1e7, Math.floor(n / 1e7) % 1e7, Math.floor(n / 1e14)];\r\n }\r\n\r\n function arrayToSmall(arr) { // If BASE changes this function may need to change\r\n trim(arr);\r\n var length = arr.length;\r\n if (length < 4 && compareAbs(arr, MAX_INT_ARR) < 0) {\r\n switch (length) {\r\n case 0: return 0;\r\n case 1: return arr[0];\r\n case 2: return arr[0] + arr[1] * BASE;\r\n default: return arr[0] + (arr[1] + arr[2] * BASE) * BASE;\r\n }\r\n }\r\n return arr;\r\n }\r\n\r\n function trim(v) {\r\n var i = v.length;\r\n while (v[--i] === 0);\r\n v.length = i + 1;\r\n }\r\n\r\n function createArray(length) { // function shamelessly stolen from Yaffle's library https://github.com/Yaffle/BigInteger\r\n var x = new Array(length);\r\n var i = -1;\r\n while (++i < length) {\r\n x[i] = 0;\r\n }\r\n return x;\r\n }\r\n\r\n function truncate(n) {\r\n if (n > 0) return Math.floor(n);\r\n return Math.ceil(n);\r\n }\r\n\r\n function add(a, b) { // assumes a and b are arrays with a.length >= b.length\r\n var l_a = a.length,\r\n l_b = b.length,\r\n r = new Array(l_a),\r\n carry = 0,\r\n base = BASE,\r\n sum, i;\r\n for (i = 0; i < l_b; i++) {\r\n sum = a[i] + b[i] + carry;\r\n carry = sum >= base ? 1 : 0;\r\n r[i] = sum - carry * base;\r\n }\r\n while (i < l_a) {\r\n sum = a[i] + carry;\r\n carry = sum === base ? 1 : 0;\r\n r[i++] = sum - carry * base;\r\n }\r\n if (carry > 0) r.push(carry);\r\n return r;\r\n }\r\n\r\n function addAny(a, b) {\r\n if (a.length >= b.length) return add(a, b);\r\n return add(b, a);\r\n }\r\n\r\n function addSmall(a, carry) { // assumes a is array, carry is number with 0 <= carry < MAX_INT\r\n var l = a.length,\r\n r = new Array(l),\r\n base = BASE,\r\n sum, i;\r\n for (i = 0; i < l; i++) {\r\n sum = a[i] - base + carry;\r\n carry = Math.floor(sum / base);\r\n r[i] = sum - carry * base;\r\n carry += 1;\r\n }\r\n while (carry > 0) {\r\n r[i++] = carry % base;\r\n carry = Math.floor(carry / base);\r\n }\r\n return r;\r\n }\r\n\r\n BigInteger.prototype.add = function (v) {\r\n var n = parseValue(v);\r\n if (this.sign !== n.sign) {\r\n return this.subtract(n.negate());\r\n }\r\n var a = this.value, b = n.value;\r\n if (n.isSmall) {\r\n return new BigInteger(addSmall(a, Math.abs(b)), this.sign);\r\n }\r\n return new BigInteger(addAny(a, b), this.sign);\r\n };\r\n BigInteger.prototype.plus = BigInteger.prototype.add;\r\n\r\n SmallInteger.prototype.add = function (v) {\r\n var n = parseValue(v);\r\n var a = this.value;\r\n if (a < 0 !== n.sign) {\r\n return this.subtract(n.negate());\r\n }\r\n var b = n.value;\r\n if (n.isSmall) {\r\n if (isPrecise(a + b)) return new SmallInteger(a + b);\r\n b = smallToArray(Math.abs(b));\r\n }\r\n return new BigInteger(addSmall(b, Math.abs(a)), a < 0);\r\n };\r\n SmallInteger.prototype.plus = SmallInteger.prototype.add;\r\n\r\n NativeBigInt.prototype.add = function (v) {\r\n return new NativeBigInt(this.value + parseValue(v).value);\r\n }\r\n NativeBigInt.prototype.plus = NativeBigInt.prototype.add;\r\n\r\n function subtract(a, b) { // assumes a and b are arrays with a >= b\r\n var a_l = a.length,\r\n b_l = b.length,\r\n r = new Array(a_l),\r\n borrow = 0,\r\n base = BASE,\r\n i, difference;\r\n for (i = 0; i < b_l; i++) {\r\n difference = a[i] - borrow - b[i];\r\n if (difference < 0) {\r\n difference += base;\r\n borrow = 1;\r\n } else borrow = 0;\r\n r[i] = difference;\r\n }\r\n for (i = b_l; i < a_l; i++) {\r\n difference = a[i] - borrow;\r\n if (difference < 0) difference += base;\r\n else {\r\n r[i++] = difference;\r\n break;\r\n }\r\n r[i] = difference;\r\n }\r\n for (; i < a_l; i++) {\r\n r[i] = a[i];\r\n }\r\n trim(r);\r\n return r;\r\n }\r\n\r\n function subtractAny(a, b, sign) {\r\n var value;\r\n if (compareAbs(a, b) >= 0) {\r\n value = subtract(a, b);\r\n } else {\r\n value = subtract(b, a);\r\n sign = !sign;\r\n }\r\n value = arrayToSmall(value);\r\n if (typeof value === \"number\") {\r\n if (sign) value = -value;\r\n return new SmallInteger(value);\r\n }\r\n return new BigInteger(value, sign);\r\n }\r\n\r\n function subtractSmall(a, b, sign) { // assumes a is array, b is number with 0 <= b < MAX_INT\r\n var l = a.length,\r\n r = new Array(l),\r\n carry = -b,\r\n base = BASE,\r\n i, difference;\r\n for (i = 0; i < l; i++) {\r\n difference = a[i] + carry;\r\n carry = Math.floor(difference / base);\r\n difference %= base;\r\n r[i] = difference < 0 ? difference + base : difference;\r\n }\r\n r = arrayToSmall(r);\r\n if (typeof r === \"number\") {\r\n if (sign) r = -r;\r\n return new SmallInteger(r);\r\n } return new BigInteger(r, sign);\r\n }\r\n\r\n BigInteger.prototype.subtract = function (v) {\r\n var n = parseValue(v);\r\n if (this.sign !== n.sign) {\r\n return this.add(n.negate());\r\n }\r\n var a = this.value, b = n.value;\r\n if (n.isSmall)\r\n return subtractSmall(a, Math.abs(b), this.sign);\r\n return subtractAny(a, b, this.sign);\r\n };\r\n BigInteger.prototype.minus = BigInteger.prototype.subtract;\r\n\r\n SmallInteger.prototype.subtract = function (v) {\r\n var n = parseValue(v);\r\n var a = this.value;\r\n if (a < 0 !== n.sign) {\r\n return this.add(n.negate());\r\n }\r\n var b = n.value;\r\n if (n.isSmall) {\r\n return new SmallInteger(a - b);\r\n }\r\n return subtractSmall(b, Math.abs(a), a >= 0);\r\n };\r\n SmallInteger.prototype.minus = SmallInteger.prototype.subtract;\r\n\r\n NativeBigInt.prototype.subtract = function (v) {\r\n return new NativeBigInt(this.value - parseValue(v).value);\r\n }\r\n NativeBigInt.prototype.minus = NativeBigInt.prototype.subtract;\r\n\r\n BigInteger.prototype.negate = function () {\r\n return new BigInteger(this.value, !this.sign);\r\n };\r\n SmallInteger.prototype.negate = function () {\r\n var sign = this.sign;\r\n var small = new SmallInteger(-this.value);\r\n small.sign = !sign;\r\n return small;\r\n };\r\n NativeBigInt.prototype.negate = function () {\r\n return new NativeBigInt(-this.value);\r\n }\r\n\r\n BigInteger.prototype.abs = function () {\r\n return new BigInteger(this.value, false);\r\n };\r\n SmallInteger.prototype.abs = function () {\r\n return new SmallInteger(Math.abs(this.value));\r\n };\r\n NativeBigInt.prototype.abs = function () {\r\n return new NativeBigInt(this.value >= 0 ? this.value : -this.value);\r\n }\r\n\r\n\r\n function multiplyLong(a, b) {\r\n var a_l = a.length,\r\n b_l = b.length,\r\n l = a_l + b_l,\r\n r = createArray(l),\r\n base = BASE,\r\n product, carry, i, a_i, b_j;\r\n for (i = 0; i < a_l; ++i) {\r\n a_i = a[i];\r\n for (var j = 0; j < b_l; ++j) {\r\n b_j = b[j];\r\n product = a_i * b_j + r[i + j];\r\n carry = Math.floor(product / base);\r\n r[i + j] = product - carry * base;\r\n r[i + j + 1] += carry;\r\n }\r\n }\r\n trim(r);\r\n return r;\r\n }\r\n\r\n function multiplySmall(a, b) { // assumes a is array, b is number with |b| < BASE\r\n var l = a.length,\r\n r = new Array(l),\r\n base = BASE,\r\n carry = 0,\r\n product, i;\r\n for (i = 0; i < l; i++) {\r\n product = a[i] * b + carry;\r\n carry = Math.floor(product / base);\r\n r[i] = product - carry * base;\r\n }\r\n while (carry > 0) {\r\n r[i++] = carry % base;\r\n carry = Math.floor(carry / base);\r\n }\r\n return r;\r\n }\r\n\r\n function shiftLeft(x, n) {\r\n var r = [];\r\n while (n-- > 0) r.push(0);\r\n return r.concat(x);\r\n }\r\n\r\n function multiplyKaratsuba(x, y) {\r\n var n = Math.max(x.length, y.length);\r\n\r\n if (n <= 30) return multiplyLong(x, y);\r\n n = Math.ceil(n / 2);\r\n\r\n var b = x.slice(n),\r\n a = x.slice(0, n),\r\n d = y.slice(n),\r\n c = y.slice(0, n);\r\n\r\n var ac = multiplyKaratsuba(a, c),\r\n bd = multiplyKaratsuba(b, d),\r\n abcd = multiplyKaratsuba(addAny(a, b), addAny(c, d));\r\n\r\n var product = addAny(addAny(ac, shiftLeft(subtract(subtract(abcd, ac), bd), n)), shiftLeft(bd, 2 * n));\r\n trim(product);\r\n return product;\r\n }\r\n\r\n // The following function is derived from a surface fit of a graph plotting the performance difference\r\n // between long multiplication and karatsuba multiplication versus the lengths of the two arrays.\r\n function useKaratsuba(l1, l2) {\r\n return -0.012 * l1 - 0.012 * l2 + 0.000015 * l1 * l2 > 0;\r\n }\r\n\r\n BigInteger.prototype.multiply = function (v) {\r\n var n = parseValue(v),\r\n a = this.value, b = n.value,\r\n sign = this.sign !== n.sign,\r\n abs;\r\n if (n.isSmall) {\r\n if (b === 0) return Integer[0];\r\n if (b === 1) return this;\r\n if (b === -1) return this.negate();\r\n abs = Math.abs(b);\r\n if (abs < BASE) {\r\n return new BigInteger(multiplySmall(a, abs), sign);\r\n }\r\n b = smallToArray(abs);\r\n }\r\n if (useKaratsuba(a.length, b.length)) // Karatsuba is only faster for certain array sizes\r\n return new BigInteger(multiplyKaratsuba(a, b), sign);\r\n return new BigInteger(multiplyLong(a, b), sign);\r\n };\r\n\r\n BigInteger.prototype.times = BigInteger.prototype.multiply;\r\n\r\n function multiplySmallAndArray(a, b, sign) { // a >= 0\r\n if (a < BASE) {\r\n return new BigInteger(multiplySmall(b, a), sign);\r\n }\r\n return new BigInteger(multiplyLong(b, smallToArray(a)), sign);\r\n }\r\n SmallInteger.prototype._multiplyBySmall = function (a) {\r\n if (isPrecise(a.value * this.value)) {\r\n return new SmallInteger(a.value * this.value);\r\n }\r\n return multiplySmallAndArray(Math.abs(a.value), smallToArray(Math.abs(this.value)), this.sign !== a.sign);\r\n };\r\n BigInteger.prototype._multiplyBySmall = function (a) {\r\n if (a.value === 0) return Integer[0];\r\n if (a.value === 1) return this;\r\n if (a.value === -1) return this.negate();\r\n return multiplySmallAndArray(Math.abs(a.value), this.value, this.sign !== a.sign);\r\n };\r\n SmallInteger.prototype.multiply = function (v) {\r\n return parseValue(v)._multiplyBySmall(this);\r\n };\r\n SmallInteger.prototype.times = SmallInteger.prototype.multiply;\r\n\r\n NativeBigInt.prototype.multiply = function (v) {\r\n return new NativeBigInt(this.value * parseValue(v).value);\r\n }\r\n NativeBigInt.prototype.times = NativeBigInt.prototype.multiply;\r\n\r\n function square(a) {\r\n //console.assert(2 * BASE * BASE < MAX_INT);\r\n var l = a.length,\r\n r = createArray(l + l),\r\n base = BASE,\r\n product, carry, i, a_i, a_j;\r\n for (i = 0; i < l; i++) {\r\n a_i = a[i];\r\n carry = 0 - a_i * a_i;\r\n for (var j = i; j < l; j++) {\r\n a_j = a[j];\r\n product = 2 * (a_i * a_j) + r[i + j] + carry;\r\n carry = Math.floor(product / base);\r\n r[i + j] = product - carry * base;\r\n }\r\n r[i + l] = carry;\r\n }\r\n trim(r);\r\n return r;\r\n }\r\n\r\n BigInteger.prototype.square = function () {\r\n return new BigInteger(square(this.value), false);\r\n };\r\n\r\n SmallInteger.prototype.square = function () {\r\n var value = this.value * this.value;\r\n if (isPrecise(value)) return new SmallInteger(value);\r\n return new BigInteger(square(smallToArray(Math.abs(this.value))), false);\r\n };\r\n\r\n NativeBigInt.prototype.square = function (v) {\r\n return new NativeBigInt(this.value * this.value);\r\n }\r\n\r\n function divMod1(a, b) { // Left over from previous version. Performs faster than divMod2 on smaller input sizes.\r\n var a_l = a.length,\r\n b_l = b.length,\r\n base = BASE,\r\n result = createArray(b.length),\r\n divisorMostSignificantDigit = b[b_l - 1],\r\n // normalization\r\n lambda = Math.ceil(base / (2 * divisorMostSignificantDigit)),\r\n remainder = multiplySmall(a, lambda),\r\n divisor = multiplySmall(b, lambda),\r\n quotientDigit, shift, carry, borrow, i, l, q;\r\n if (remainder.length <= a_l) remainder.push(0);\r\n divisor.push(0);\r\n divisorMostSignificantDigit = divisor[b_l - 1];\r\n for (shift = a_l - b_l; shift >= 0; shift--) {\r\n quotientDigit = base - 1;\r\n if (remainder[shift + b_l] !== divisorMostSignificantDigit) {\r\n quotientDigit = Math.floor((remainder[shift + b_l] * base + remainder[shift + b_l - 1]) / divisorMostSignificantDigit);\r\n }\r\n // quotientDigit <= base - 1\r\n carry = 0;\r\n borrow = 0;\r\n l = divisor.length;\r\n for (i = 0; i < l; i++) {\r\n carry += quotientDigit * divisor[i];\r\n q = Math.floor(carry / base);\r\n borrow += remainder[shift + i] - (carry - q * base);\r\n carry = q;\r\n if (borrow < 0) {\r\n remainder[shift + i] = borrow + base;\r\n borrow = -1;\r\n } else {\r\n remainder[shift + i] = borrow;\r\n borrow = 0;\r\n }\r\n }\r\n while (borrow !== 0) {\r\n quotientDigit -= 1;\r\n carry = 0;\r\n for (i = 0; i < l; i++) {\r\n carry += remainder[shift + i] - base + divisor[i];\r\n if (carry < 0) {\r\n remainder[shift + i] = carry + base;\r\n carry = 0;\r\n } else {\r\n remainder[shift + i] = carry;\r\n carry = 1;\r\n }\r\n }\r\n borrow += carry;\r\n }\r\n result[shift] = quotientDigit;\r\n }\r\n // denormalization\r\n remainder = divModSmall(remainder, lambda)[0];\r\n return [arrayToSmall(result), arrayToSmall(remainder)];\r\n }\r\n\r\n function divMod2(a, b) { // Implementation idea shamelessly stolen from Silent Matt's library http://silentmatt.com/biginteger/\r\n // Performs faster than divMod1 on larger input sizes.\r\n var a_l = a.length,\r\n b_l = b.length,\r\n result = [],\r\n part = [],\r\n base = BASE,\r\n guess, xlen, highx, highy, check;\r\n while (a_l) {\r\n part.unshift(a[--a_l]);\r\n trim(part);\r\n if (compareAbs(part, b) < 0) {\r\n result.push(0);\r\n continue;\r\n }\r\n xlen = part.length;\r\n highx = part[xlen - 1] * base + part[xlen - 2];\r\n highy = b[b_l - 1] * base + b[b_l - 2];\r\n if (xlen > b_l) {\r\n highx = (highx + 1) * base;\r\n }\r\n guess = Math.ceil(highx / highy);\r\n do {\r\n check = multiplySmall(b, guess);\r\n if (compareAbs(check, part) <= 0) break;\r\n guess--;\r\n } while (guess);\r\n result.push(guess);\r\n part = subtract(part, check);\r\n }\r\n result.reverse();\r\n return [arrayToSmall(result), arrayToSmall(part)];\r\n }\r\n\r\n function divModSmall(value, lambda) {\r\n var length = value.length,\r\n quotient = createArray(length),\r\n base = BASE,\r\n i, q, remainder, divisor;\r\n remainder = 0;\r\n for (i = length - 1; i >= 0; --i) {\r\n divisor = remainder * base + value[i];\r\n q = truncate(divisor / lambda);\r\n remainder = divisor - q * lambda;\r\n quotient[i] = q | 0;\r\n }\r\n return [quotient, remainder | 0];\r\n }\r\n\r\n function divModAny(self, v) {\r\n var value, n = parseValue(v);\r\n if (supportsNativeBigInt) {\r\n return [new NativeBigInt(self.value / n.value), new NativeBigInt(self.value % n.value)];\r\n }\r\n var a = self.value, b = n.value;\r\n var quotient;\r\n if (b === 0) throw new Error(\"Cannot divide by zero\");\r\n if (self.isSmall) {\r\n if (n.isSmall) {\r\n return [new SmallInteger(truncate(a / b)), new SmallInteger(a % b)];\r\n }\r\n return [Integer[0], self];\r\n }\r\n if (n.isSmall) {\r\n if (b === 1) return [self, Integer[0]];\r\n if (b == -1) return [self.negate(), Integer[0]];\r\n var abs = Math.abs(b);\r\n if (abs < BASE) {\r\n value = divModSmall(a, abs);\r\n quotient = arrayToSmall(value[0]);\r\n var remainder = value[1];\r\n if (self.sign) remainder = -remainder;\r\n if (typeof quotient === \"number\") {\r\n if (self.sign !== n.sign) quotient = -quotient;\r\n return [new SmallInteger(quotient), new SmallInteger(remainder)];\r\n }\r\n return [new BigInteger(quotient, self.sign !== n.sign), new SmallInteger(remainder)];\r\n }\r\n b = smallToArray(abs);\r\n }\r\n var comparison = compareAbs(a, b);\r\n if (comparison === -1) return [Integer[0], self];\r\n if (comparison === 0) return [Integer[self.sign === n.sign ? 1 : -1], Integer[0]];\r\n\r\n // divMod1 is faster on smaller input sizes\r\n if (a.length + b.length <= 200)\r\n value = divMod1(a, b);\r\n else value = divMod2(a, b);\r\n\r\n quotient = value[0];\r\n var qSign = self.sign !== n.sign,\r\n mod = value[1],\r\n mSign = self.sign;\r\n if (typeof quotient === \"number\") {\r\n if (qSign) quotient = -quotient;\r\n quotient = new SmallInteger(quotient);\r\n } else quotient = new BigInteger(quotient, qSign);\r\n if (typeof mod === \"number\") {\r\n if (mSign) mod = -mod;\r\n mod = new SmallInteger(mod);\r\n } else mod = new BigInteger(mod, mSign);\r\n return [quotient, mod];\r\n }\r\n\r\n BigInteger.prototype.divmod = function (v) {\r\n var result = divModAny(this, v);\r\n return {\r\n quotient: result[0],\r\n remainder: result[1]\r\n };\r\n };\r\n NativeBigInt.prototype.divmod = SmallInteger.prototype.divmod = BigInteger.prototype.divmod;\r\n\r\n\r\n BigInteger.prototype.divide = function (v) {\r\n return divModAny(this, v)[0];\r\n };\r\n NativeBigInt.prototype.over = NativeBigInt.prototype.divide = function (v) {\r\n return new NativeBigInt(this.value / parseValue(v).value);\r\n };\r\n SmallInteger.prototype.over = SmallInteger.prototype.divide = BigInteger.prototype.over = BigInteger.prototype.divide;\r\n\r\n BigInteger.prototype.mod = function (v) {\r\n return divModAny(this, v)[1];\r\n };\r\n NativeBigInt.prototype.mod = NativeBigInt.prototype.remainder = function (v) {\r\n return new NativeBigInt(this.value % parseValue(v).value);\r\n };\r\n SmallInteger.prototype.remainder = SmallInteger.prototype.mod = BigInteger.prototype.remainder = BigInteger.prototype.mod;\r\n\r\n BigInteger.prototype.pow = function (v) {\r\n var n = parseValue(v),\r\n a = this.value,\r\n b = n.value,\r\n value, x, y;\r\n if (b === 0) return Integer[1];\r\n if (a === 0) return Integer[0];\r\n if (a === 1) return Integer[1];\r\n if (a === -1) return n.isEven() ? Integer[1] : Integer[-1];\r\n if (n.sign) {\r\n return Integer[0];\r\n }\r\n if (!n.isSmall) throw new Error(\"The exponent \" + n.toString() + \" is too large.\");\r\n if (this.isSmall) {\r\n if (isPrecise(value = Math.pow(a, b)))\r\n return new SmallInteger(truncate(value));\r\n }\r\n x = this;\r\n y = Integer[1];\r\n while (true) {\r\n if (b & 1 === 1) {\r\n y = y.times(x);\r\n --b;\r\n }\r\n if (b === 0) break;\r\n b /= 2;\r\n x = x.square();\r\n }\r\n return y;\r\n };\r\n SmallInteger.prototype.pow = BigInteger.prototype.pow;\r\n\r\n NativeBigInt.prototype.pow = function (v) {\r\n var n = parseValue(v);\r\n var a = this.value, b = n.value;\r\n var _0 = BigInt(0), _1 = BigInt(1), _2 = BigInt(2);\r\n if (b === _0) return Integer[1];\r\n if (a === _0) return Integer[0];\r\n if (a === _1) return Integer[1];\r\n if (a === BigInt(-1)) return n.isEven() ? Integer[1] : Integer[-1];\r\n if (n.isNegative()) return new NativeBigInt(_0);\r\n var x = this;\r\n var y = Integer[1];\r\n while (true) {\r\n if ((b & _1) === _1) {\r\n y = y.times(x);\r\n --b;\r\n }\r\n if (b === _0) break;\r\n b /= _2;\r\n x = x.square();\r\n }\r\n return y;\r\n }\r\n\r\n BigInteger.prototype.modPow = function (exp, mod) {\r\n exp = parseValue(exp);\r\n mod = parseValue(mod);\r\n if (mod.isZero()) throw new Error(\"Cannot take modPow with modulus 0\");\r\n var r = Integer[1],\r\n base = this.mod(mod);\r\n if (exp.isNegative()) {\r\n exp = exp.multiply(Integer[-1]);\r\n base = base.modInv(mod);\r\n }\r\n while (exp.isPositive()) {\r\n if (base.isZero()) return Integer[0];\r\n if (exp.isOdd()) r = r.multiply(base).mod(mod);\r\n exp = exp.divide(2);\r\n base = base.square().mod(mod);\r\n }\r\n return r;\r\n };\r\n NativeBigInt.prototype.modPow = SmallInteger.prototype.modPow = BigInteger.prototype.modPow;\r\n\r\n function compareAbs(a, b) {\r\n if (a.length !== b.length) {\r\n return a.length > b.length ? 1 : -1;\r\n }\r\n for (var i = a.length - 1; i >= 0; i--) {\r\n if (a[i] !== b[i]) return a[i] > b[i] ? 1 : -1;\r\n }\r\n return 0;\r\n }\r\n\r\n BigInteger.prototype.compareAbs = function (v) {\r\n var n = parseValue(v),\r\n a = this.value,\r\n b = n.value;\r\n if (n.isSmall) return 1;\r\n return compareAbs(a, b);\r\n };\r\n SmallInteger.prototype.compareAbs = function (v) {\r\n var n = parseValue(v),\r\n a = Math.abs(this.value),\r\n b = n.value;\r\n if (n.isSmall) {\r\n b = Math.abs(b);\r\n return a === b ? 0 : a > b ? 1 : -1;\r\n }\r\n return -1;\r\n };\r\n NativeBigInt.prototype.compareAbs = function (v) {\r\n var a = this.value;\r\n var b = parseValue(v).value;\r\n a = a >= 0 ? a : -a;\r\n b = b >= 0 ? b : -b;\r\n return a === b ? 0 : a > b ? 1 : -1;\r\n }\r\n\r\n BigInteger.prototype.compare = function (v) {\r\n // See discussion about comparison with Infinity:\r\n // https://github.com/peterolson/BigInteger.js/issues/61\r\n if (v === Infinity) {\r\n return -1;\r\n }\r\n if (v === -Infinity) {\r\n return 1;\r\n }\r\n\r\n var n = parseValue(v),\r\n a = this.value,\r\n b = n.value;\r\n if (this.sign !== n.sign) {\r\n return n.sign ? 1 : -1;\r\n }\r\n if (n.isSmall) {\r\n return this.sign ? -1 : 1;\r\n }\r\n return compareAbs(a, b) * (this.sign ? -1 : 1);\r\n };\r\n BigInteger.prototype.compareTo = BigInteger.prototype.compare;\r\n\r\n SmallInteger.prototype.compare = function (v) {\r\n if (v === Infinity) {\r\n return -1;\r\n }\r\n if (v === -Infinity) {\r\n return 1;\r\n }\r\n\r\n var n = parseValue(v),\r\n a = this.value,\r\n b = n.value;\r\n if (n.isSmall) {\r\n return a == b ? 0 : a > b ? 1 : -1;\r\n }\r\n if (a < 0 !== n.sign) {\r\n return a < 0 ? -1 : 1;\r\n }\r\n return a < 0 ? 1 : -1;\r\n };\r\n SmallInteger.prototype.compareTo = SmallInteger.prototype.compare;\r\n\r\n NativeBigInt.prototype.compare = function (v) {\r\n if (v === Infinity) {\r\n return -1;\r\n }\r\n if (v === -Infinity) {\r\n return 1;\r\n }\r\n var a = this.value;\r\n var b = parseValue(v).value;\r\n return a === b ? 0 : a > b ? 1 : -1;\r\n }\r\n NativeBigInt.prototype.compareTo = NativeBigInt.prototype.compare;\r\n\r\n BigInteger.prototype.equals = function (v) {\r\n return this.compare(v) === 0;\r\n };\r\n NativeBigInt.prototype.eq = NativeBigInt.prototype.equals = SmallInteger.prototype.eq = SmallInteger.prototype.equals = BigInteger.prototype.eq = BigInteger.prototype.equals;\r\n\r\n BigInteger.prototype.notEquals = function (v) {\r\n return this.compare(v) !== 0;\r\n };\r\n NativeBigInt.prototype.neq = NativeBigInt.prototype.notEquals = SmallInteger.prototype.neq = SmallInteger.prototype.notEquals = BigInteger.prototype.neq = BigInteger.prototype.notEquals;\r\n\r\n BigInteger.prototype.greater = function (v) {\r\n return this.compare(v) > 0;\r\n };\r\n NativeBigInt.prototype.gt = NativeBigInt.prototype.greater = SmallInteger.prototype.gt = SmallInteger.prototype.greater = BigInteger.prototype.gt = BigInteger.prototype.greater;\r\n\r\n BigInteger.prototype.lesser = function (v) {\r\n return this.compare(v) < 0;\r\n };\r\n NativeBigInt.prototype.lt = NativeBigInt.prototype.lesser = SmallInteger.prototype.lt = SmallInteger.prototype.lesser = BigInteger.prototype.lt = BigInteger.prototype.lesser;\r\n\r\n BigInteger.prototype.greaterOrEquals = function (v) {\r\n return this.compare(v) >= 0;\r\n };\r\n NativeBigInt.prototype.geq = NativeBigInt.prototype.greaterOrEquals = SmallInteger.prototype.geq = SmallInteger.prototype.greaterOrEquals = BigInteger.prototype.geq = BigInteger.prototype.greaterOrEquals;\r\n\r\n BigInteger.prototype.lesserOrEquals = function (v) {\r\n return this.compare(v) <= 0;\r\n };\r\n NativeBigInt.prototype.leq = NativeBigInt.prototype.lesserOrEquals = SmallInteger.prototype.leq = SmallInteger.prototype.lesserOrEquals = BigInteger.prototype.leq = BigInteger.prototype.lesserOrEquals;\r\n\r\n BigInteger.prototype.isEven = function () {\r\n return (this.value[0] & 1) === 0;\r\n };\r\n SmallInteger.prototype.isEven = function () {\r\n return (this.value & 1) === 0;\r\n };\r\n NativeBigInt.prototype.isEven = function () {\r\n return (this.value & BigInt(1)) === BigInt(0);\r\n }\r\n\r\n BigInteger.prototype.isOdd = function () {\r\n return (this.value[0] & 1) === 1;\r\n };\r\n SmallInteger.prototype.isOdd = function () {\r\n return (this.value & 1) === 1;\r\n };\r\n NativeBigInt.prototype.isOdd = function () {\r\n return (this.value & BigInt(1)) === BigInt(1);\r\n }\r\n\r\n BigInteger.prototype.isPositive = function () {\r\n return !this.sign;\r\n };\r\n SmallInteger.prototype.isPositive = function () {\r\n return this.value > 0;\r\n };\r\n NativeBigInt.prototype.isPositive = SmallInteger.prototype.isPositive;\r\n\r\n BigInteger.prototype.isNegative = function () {\r\n return this.sign;\r\n };\r\n SmallInteger.prototype.isNegative = function () {\r\n return this.value < 0;\r\n };\r\n NativeBigInt.prototype.isNegative = SmallInteger.prototype.isNegative;\r\n\r\n BigInteger.prototype.isUnit = function () {\r\n return false;\r\n };\r\n SmallInteger.prototype.isUnit = function () {\r\n return Math.abs(this.value) === 1;\r\n };\r\n NativeBigInt.prototype.isUnit = function () {\r\n return this.abs().value === BigInt(1);\r\n }\r\n\r\n BigInteger.prototype.isZero = function () {\r\n return false;\r\n };\r\n SmallInteger.prototype.isZero = function () {\r\n return this.value === 0;\r\n };\r\n NativeBigInt.prototype.isZero = function () {\r\n return this.value === BigInt(0);\r\n }\r\n\r\n BigInteger.prototype.isDivisibleBy = function (v) {\r\n var n = parseValue(v);\r\n if (n.isZero()) return false;\r\n if (n.isUnit()) return true;\r\n if (n.compareAbs(2) === 0) return this.isEven();\r\n return this.mod(n).isZero();\r\n };\r\n NativeBigInt.prototype.isDivisibleBy = SmallInteger.prototype.isDivisibleBy = BigInteger.prototype.isDivisibleBy;\r\n\r\n function isBasicPrime(v) {\r\n var n = v.abs();\r\n if (n.isUnit()) return false;\r\n if (n.equals(2) || n.equals(3) || n.equals(5)) return true;\r\n if (n.isEven() || n.isDivisibleBy(3) || n.isDivisibleBy(5)) return false;\r\n if (n.lesser(49)) return true;\r\n // we don't know if it's prime: let the other functions figure it out\r\n }\r\n\r\n function millerRabinTest(n, a) {\r\n var nPrev = n.prev(),\r\n b = nPrev,\r\n r = 0,\r\n d, t, i, x;\r\n while (b.isEven()) b = b.divide(2), r++;\r\n next: for (i = 0; i < a.length; i++) {\r\n if (n.lesser(a[i])) continue;\r\n x = bigInt(a[i]).modPow(b, n);\r\n if (x.isUnit() || x.equals(nPrev)) continue;\r\n for (d = r - 1; d != 0; d--) {\r\n x = x.square().mod(n);\r\n if (x.isUnit()) return false;\r\n if (x.equals(nPrev)) continue next;\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n // Set \"strict\" to true to force GRH-supported lower bound of 2*log(N)^2\r\n BigInteger.prototype.isPrime = function (strict) {\r\n var isPrime = isBasicPrime(this);\r\n if (isPrime !== undefined) return isPrime;\r\n var n = this.abs();\r\n var bits = n.bitLength();\r\n if (bits <= 64)\r\n return millerRabinTest(n, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]);\r\n var logN = Math.log(2) * bits.toJSNumber();\r\n var t = Math.ceil((strict === true) ? (2 * Math.pow(logN, 2)) : logN);\r\n for (var a = [], i = 0; i < t; i++) {\r\n a.push(bigInt(i + 2));\r\n }\r\n return millerRabinTest(n, a);\r\n };\r\n NativeBigInt.prototype.isPrime = SmallInteger.prototype.isPrime = BigInteger.prototype.isPrime;\r\n\r\n BigInteger.prototype.isProbablePrime = function (iterations, rng) {\r\n var isPrime = isBasicPrime(this);\r\n if (isPrime !== undefined) return isPrime;\r\n var n = this.abs();\r\n var t = iterations === undefined ? 5 : iterations;\r\n for (var a = [], i = 0; i < t; i++) {\r\n a.push(bigInt.randBetween(2, n.minus(2), rng));\r\n }\r\n return millerRabinTest(n, a);\r\n };\r\n NativeBigInt.prototype.isProbablePrime = SmallInteger.prototype.isProbablePrime = BigInteger.prototype.isProbablePrime;\r\n\r\n BigInteger.prototype.modInv = function (n) {\r\n var t = bigInt.zero, newT = bigInt.one, r = parseValue(n), newR = this.abs(), q, lastT, lastR;\r\n while (!newR.isZero()) {\r\n q = r.divide(newR);\r\n lastT = t;\r\n lastR = r;\r\n t = newT;\r\n r = newR;\r\n newT = lastT.subtract(q.multiply(newT));\r\n newR = lastR.subtract(q.multiply(newR));\r\n }\r\n if (!r.isUnit()) throw new Error(this.toString() + \" and \" + n.toString() + \" are not co-prime\");\r\n if (t.compare(0) === -1) {\r\n t = t.add(n);\r\n }\r\n if (this.isNegative()) {\r\n return t.negate();\r\n }\r\n return t;\r\n };\r\n\r\n NativeBigInt.prototype.modInv = SmallInteger.prototype.modInv = BigInteger.prototype.modInv;\r\n\r\n BigInteger.prototype.next = function () {\r\n var value = this.value;\r\n if (this.sign) {\r\n return subtractSmall(value, 1, this.sign);\r\n }\r\n return new BigInteger(addSmall(value, 1), this.sign);\r\n };\r\n SmallInteger.prototype.next = function () {\r\n var value = this.value;\r\n if (value + 1 < MAX_INT) return new SmallInteger(value + 1);\r\n return new BigInteger(MAX_INT_ARR, false);\r\n };\r\n NativeBigInt.prototype.next = function () {\r\n return new NativeBigInt(this.value + BigInt(1));\r\n }\r\n\r\n BigInteger.prototype.prev = function () {\r\n var value = this.value;\r\n if (this.sign) {\r\n return new BigInteger(addSmall(value, 1), true);\r\n }\r\n return subtractSmall(value, 1, this.sign);\r\n };\r\n SmallInteger.prototype.prev = function () {\r\n var value = this.value;\r\n if (value - 1 > -MAX_INT) return new SmallInteger(value - 1);\r\n return new BigInteger(MAX_INT_ARR, true);\r\n };\r\n NativeBigInt.prototype.prev = function () {\r\n return new NativeBigInt(this.value - BigInt(1));\r\n }\r\n\r\n var powersOfTwo = [1];\r\n while (2 * powersOfTwo[powersOfTwo.length - 1] <= BASE) powersOfTwo.push(2 * powersOfTwo[powersOfTwo.length - 1]);\r\n var powers2Length = powersOfTwo.length, highestPower2 = powersOfTwo[powers2Length - 1];\r\n\r\n function shift_isSmall(n) {\r\n return Math.abs(n) <= BASE;\r\n }\r\n\r\n BigInteger.prototype.shiftLeft = function (v) {\r\n var n = parseValue(v).toJSNumber();\r\n if (!shift_isSmall(n)) {\r\n throw new Error(String(n) + \" is too large for shifting.\");\r\n }\r\n if (n < 0) return this.shiftRight(-n);\r\n var result = this;\r\n if (result.isZero()) return result;\r\n while (n >= powers2Length) {\r\n result = result.multiply(highestPower2);\r\n n -= powers2Length - 1;\r\n }\r\n return result.multiply(powersOfTwo[n]);\r\n };\r\n NativeBigInt.prototype.shiftLeft = SmallInteger.prototype.shiftLeft = BigInteger.prototype.shiftLeft;\r\n\r\n BigInteger.prototype.shiftRight = function (v) {\r\n var remQuo;\r\n var n = parseValue(v).toJSNumber();\r\n if (!shift_isSmall(n)) {\r\n throw new Error(String(n) + \" is too large for shifting.\");\r\n }\r\n if (n < 0) return this.shiftLeft(-n);\r\n var result = this;\r\n while (n >= powers2Length) {\r\n if (result.isZero() || (result.isNegative() && result.isUnit())) return result;\r\n remQuo = divModAny(result, highestPower2);\r\n result = remQuo[1].isNegative() ? remQuo[0].prev() : remQuo[0];\r\n n -= powers2Length - 1;\r\n }\r\n remQuo = divModAny(result, powersOfTwo[n]);\r\n return remQuo[1].isNegative() ? remQuo[0].prev() : remQuo[0];\r\n };\r\n NativeBigInt.prototype.shiftRight = SmallInteger.prototype.shiftRight = BigInteger.prototype.shiftRight;\r\n\r\n function bitwise(x, y, fn) {\r\n y = parseValue(y);\r\n var xSign = x.isNegative(), ySign = y.isNegative();\r\n var xRem = xSign ? x.not() : x,\r\n yRem = ySign ? y.not() : y;\r\n var xDigit = 0, yDigit = 0;\r\n var xDivMod = null, yDivMod = null;\r\n var result = [];\r\n while (!xRem.isZero() || !yRem.isZero()) {\r\n xDivMod = divModAny(xRem, highestPower2);\r\n xDigit = xDivMod[1].toJSNumber();\r\n if (xSign) {\r\n xDigit = highestPower2 - 1 - xDigit; // two's complement for negative numbers\r\n }\r\n\r\n yDivMod = divModAny(yRem, highestPower2);\r\n yDigit = yDivMod[1].toJSNumber();\r\n if (ySign) {\r\n yDigit = highestPower2 - 1 - yDigit; // two's complement for negative numbers\r\n }\r\n\r\n xRem = xDivMod[0];\r\n yRem = yDivMod[0];\r\n result.push(fn(xDigit, yDigit));\r\n }\r\n var sum = fn(xSign ? 1 : 0, ySign ? 1 : 0) !== 0 ? bigInt(-1) : bigInt(0);\r\n for (var i = result.length - 1; i >= 0; i -= 1) {\r\n sum = sum.multiply(highestPower2).add(bigInt(result[i]));\r\n }\r\n return sum;\r\n }\r\n\r\n BigInteger.prototype.not = function () {\r\n return this.negate().prev();\r\n };\r\n NativeBigInt.prototype.not = SmallInteger.prototype.not = BigInteger.prototype.not;\r\n\r\n BigInteger.prototype.and = function (n) {\r\n return bitwise(this, n, function (a, b) { return a & b; });\r\n };\r\n NativeBigInt.prototype.and = SmallInteger.prototype.and = BigInteger.prototype.and;\r\n\r\n BigInteger.prototype.or = function (n) {\r\n return bitwise(this, n, function (a, b) { return a | b; });\r\n };\r\n NativeBigInt.prototype.or = SmallInteger.prototype.or = BigInteger.prototype.or;\r\n\r\n BigInteger.prototype.xor = function (n) {\r\n return bitwise(this, n, function (a, b) { return a ^ b; });\r\n };\r\n NativeBigInt.prototype.xor = SmallInteger.prototype.xor = BigInteger.prototype.xor;\r\n\r\n var LOBMASK_I = 1 << 30, LOBMASK_BI = (BASE & -BASE) * (BASE & -BASE) | LOBMASK_I;\r\n function roughLOB(n) { // get lowestOneBit (rough)\r\n // SmallInteger: return Min(lowestOneBit(n), 1 << 30)\r\n // BigInteger: return Min(lowestOneBit(n), 1 << 14) [BASE=1e7]\r\n var v = n.value,\r\n x = typeof v === \"number\" ? v | LOBMASK_I :\r\n typeof v === \"bigint\" ? v | BigInt(LOBMASK_I) :\r\n v[0] + v[1] * BASE | LOBMASK_BI;\r\n return x & -x;\r\n }\r\n\r\n function integerLogarithm(value, base) {\r\n if (base.compareTo(value) <= 0) {\r\n var tmp = integerLogarithm(value, base.square(base));\r\n var p = tmp.p;\r\n var e = tmp.e;\r\n var t = p.multiply(base);\r\n return t.compareTo(value) <= 0 ? { p: t, e: e * 2 + 1 } : { p: p, e: e * 2 };\r\n }\r\n return { p: bigInt(1), e: 0 };\r\n }\r\n\r\n BigInteger.prototype.bitLength = function () {\r\n var n = this;\r\n if (n.compareTo(bigInt(0)) < 0) {\r\n n = n.negate().subtract(bigInt(1));\r\n }\r\n if (n.compareTo(bigInt(0)) === 0) {\r\n return bigInt(0);\r\n }\r\n return bigInt(integerLogarithm(n, bigInt(2)).e).add(bigInt(1));\r\n }\r\n NativeBigInt.prototype.bitLength = SmallInteger.prototype.bitLength = BigInteger.prototype.bitLength;\r\n\r\n function max(a, b) {\r\n a = parseValue(a);\r\n b = parseValue(b);\r\n return a.greater(b) ? a : b;\r\n }\r\n function min(a, b) {\r\n a = parseValue(a);\r\n b = parseValue(b);\r\n return a.lesser(b) ? a : b;\r\n }\r\n function gcd(a, b) {\r\n a = parseValue(a).abs();\r\n b = parseValue(b).abs();\r\n if (a.equals(b)) return a;\r\n if (a.isZero()) return b;\r\n if (b.isZero()) return a;\r\n var c = Integer[1], d, t;\r\n while (a.isEven() && b.isEven()) {\r\n d = min(roughLOB(a), roughLOB(b));\r\n a = a.divide(d);\r\n b = b.divide(d);\r\n c = c.multiply(d);\r\n }\r\n while (a.isEven()) {\r\n a = a.divide(roughLOB(a));\r\n }\r\n do {\r\n while (b.isEven()) {\r\n b = b.divide(roughLOB(b));\r\n }\r\n if (a.greater(b)) {\r\n t = b; b = a; a = t;\r\n }\r\n b = b.subtract(a);\r\n } while (!b.isZero());\r\n return c.isUnit() ? a : a.multiply(c);\r\n }\r\n function lcm(a, b) {\r\n a = parseValue(a).abs();\r\n b = parseValue(b).abs();\r\n return a.divide(gcd(a, b)).multiply(b);\r\n }\r\n function randBetween(a, b, rng) {\r\n a = parseValue(a);\r\n b = parseValue(b);\r\n var usedRNG = rng || Math.random;\r\n var low = min(a, b), high = max(a, b);\r\n var range = high.subtract(low).add(1);\r\n if (range.isSmall) return low.add(Math.floor(usedRNG() * range));\r\n var digits = toBase(range, BASE).value;\r\n var result = [], restricted = true;\r\n for (var i = 0; i < digits.length; i++) {\r\n var top = restricted ? digits[i] + (i + 1 < digits.length ? digits[i + 1] / BASE : 0) : BASE;\r\n var digit = truncate(usedRNG() * top);\r\n result.push(digit);\r\n if (digit < digits[i]) restricted = false;\r\n }\r\n return low.add(Integer.fromArray(result, BASE, false));\r\n }\r\n\r\n var parseBase = function (text, base, alphabet, caseSensitive) {\r\n alphabet = alphabet || DEFAULT_ALPHABET;\r\n text = String(text);\r\n if (!caseSensitive) {\r\n text = text.toLowerCase();\r\n alphabet = alphabet.toLowerCase();\r\n }\r\n var length = text.length;\r\n var i;\r\n var absBase = Math.abs(base);\r\n var alphabetValues = {};\r\n for (i = 0; i < alphabet.length; i++) {\r\n alphabetValues[alphabet[i]] = i;\r\n }\r\n for (i = 0; i < length; i++) {\r\n var c = text[i];\r\n if (c === \"-\") continue;\r\n if (c in alphabetValues) {\r\n if (alphabetValues[c] >= absBase) {\r\n if (c === \"1\" && absBase === 1) continue;\r\n throw new Error(c + \" is not a valid digit in base \" + base + \".\");\r\n }\r\n }\r\n }\r\n base = parseValue(base);\r\n var digits = [];\r\n var isNegative = text[0] === \"-\";\r\n for (i = isNegative ? 1 : 0; i < text.length; i++) {\r\n var c = text[i];\r\n if (c in alphabetValues) digits.push(parseValue(alphabetValues[c]));\r\n else if (c === \"<\") {\r\n var start = i;\r\n do { i++; } while (text[i] !== \">\" && i < text.length);\r\n digits.push(parseValue(text.slice(start + 1, i)));\r\n }\r\n else throw new Error(c + \" is not a valid character\");\r\n }\r\n return parseBaseFromArray(digits, base, isNegative);\r\n };\r\n\r\n function parseBaseFromArray(digits, base, isNegative) {\r\n var val = Integer[0], pow = Integer[1], i;\r\n for (i = digits.length - 1; i >= 0; i--) {\r\n val = val.add(digits[i].times(pow));\r\n pow = pow.times(base);\r\n }\r\n return isNegative ? val.negate() : val;\r\n }\r\n\r\n function stringify(digit, alphabet) {\r\n alphabet = alphabet || DEFAULT_ALPHABET;\r\n if (digit < alphabet.length) {\r\n return alphabet[digit];\r\n }\r\n return \"<\" + digit + \">\";\r\n }\r\n\r\n function toBase(n, base) {\r\n base = bigInt(base);\r\n if (base.isZero()) {\r\n if (n.isZero()) return { value: [0], isNegative: false };\r\n throw new Error(\"Cannot convert nonzero numbers to base 0.\");\r\n }\r\n if (base.equals(-1)) {\r\n if (n.isZero()) return { value: [0], isNegative: false };\r\n if (n.isNegative())\r\n return {\r\n value: [].concat.apply([], Array.apply(null, Array(-n.toJSNumber()))\r\n .map(Array.prototype.valueOf, [1, 0])\r\n ),\r\n isNegative: false\r\n };\r\n\r\n var arr = Array.apply(null, Array(n.toJSNumber() - 1))\r\n .map(Array.prototype.valueOf, [0, 1]);\r\n arr.unshift([1]);\r\n return {\r\n value: [].concat.apply([], arr),\r\n isNegative: false\r\n };\r\n }\r\n\r\n var neg = false;\r\n if (n.isNegative() && base.isPositive()) {\r\n neg = true;\r\n n = n.abs();\r\n }\r\n if (base.isUnit()) {\r\n if (n.isZero()) return { value: [0], isNegative: false };\r\n\r\n return {\r\n value: Array.apply(null, Array(n.toJSNumber()))\r\n .map(Number.prototype.valueOf, 1),\r\n isNegative: neg\r\n };\r\n }\r\n var out = [];\r\n var left = n, divmod;\r\n while (left.isNegative() || left.compareAbs(base) >= 0) {\r\n divmod = left.divmod(base);\r\n left = divmod.quotient;\r\n var digit = divmod.remainder;\r\n if (digit.isNegative()) {\r\n digit = base.minus(digit).abs();\r\n left = left.next();\r\n }\r\n out.push(digit.toJSNumber());\r\n }\r\n out.push(left.toJSNumber());\r\n return { value: out.reverse(), isNegative: neg };\r\n }\r\n\r\n function toBaseString(n, base, alphabet) {\r\n var arr = toBase(n, base);\r\n return (arr.isNegative ? \"-\" : \"\") + arr.value.map(function (x) {\r\n return stringify(x, alphabet);\r\n }).join('');\r\n }\r\n\r\n BigInteger.prototype.toArray = function (radix) {\r\n return toBase(this, radix);\r\n };\r\n\r\n SmallInteger.prototype.toArray = function (radix) {\r\n return toBase(this, radix);\r\n };\r\n\r\n NativeBigInt.prototype.toArray = function (radix) {\r\n return toBase(this, radix);\r\n };\r\n\r\n BigInteger.prototype.toString = function (radix, alphabet) {\r\n if (radix === undefined) radix = 10;\r\n if (radix !== 10 || alphabet) return toBaseString(this, radix, alphabet);\r\n var v = this.value, l = v.length, str = String(v[--l]), zeros = \"0000000\", digit;\r\n while (--l >= 0) {\r\n digit = String(v[l]);\r\n str += zeros.slice(digit.length) + digit;\r\n }\r\n var sign = this.sign ? \"-\" : \"\";\r\n return sign + str;\r\n };\r\n\r\n SmallInteger.prototype.toString = function (radix, alphabet) {\r\n if (radix === undefined) radix = 10;\r\n if (radix != 10 || alphabet) return toBaseString(this, radix, alphabet);\r\n return String(this.value);\r\n };\r\n\r\n NativeBigInt.prototype.toString = SmallInteger.prototype.toString;\r\n\r\n NativeBigInt.prototype.toJSON = BigInteger.prototype.toJSON = SmallInteger.prototype.toJSON = function () { return this.toString(); }\r\n\r\n BigInteger.prototype.valueOf = function () {\r\n return parseInt(this.toString(), 10);\r\n };\r\n BigInteger.prototype.toJSNumber = BigInteger.prototype.valueOf;\r\n\r\n SmallInteger.prototype.valueOf = function () {\r\n return this.value;\r\n };\r\n SmallInteger.prototype.toJSNumber = SmallInteger.prototype.valueOf;\r\n NativeBigInt.prototype.valueOf = NativeBigInt.prototype.toJSNumber = function () {\r\n return parseInt(this.toString(), 10);\r\n }\r\n\r\n function parseStringValue(v) {\r\n if (isPrecise(+v)) {\r\n var x = +v;\r\n if (x === truncate(x))\r\n return supportsNativeBigInt ? new NativeBigInt(BigInt(x)) : new SmallInteger(x);\r\n throw new Error(\"Invalid integer: \" + v);\r\n }\r\n var sign = v[0] === \"-\";\r\n if (sign) v = v.slice(1);\r\n var split = v.split(/e/i);\r\n if (split.length > 2) throw new Error(\"Invalid integer: \" + split.join(\"e\"));\r\n if (split.length === 2) {\r\n var exp = split[1];\r\n if (exp[0] === \"+\") exp = exp.slice(1);\r\n exp = +exp;\r\n if (exp !== truncate(exp) || !isPrecise(exp)) throw new Error(\"Invalid integer: \" + exp + \" is not a valid exponent.\");\r\n var text = split[0];\r\n var decimalPlace = text.indexOf(\".\");\r\n if (decimalPlace >= 0) {\r\n exp -= text.length - decimalPlace - 1;\r\n text = text.slice(0, decimalPlace) + text.slice(decimalPlace + 1);\r\n }\r\n if (exp < 0) throw new Error(\"Cannot include negative exponent part for integers\");\r\n text += (new Array(exp + 1)).join(\"0\");\r\n v = text;\r\n }\r\n var isValid = /^([0-9][0-9]*)$/.test(v);\r\n if (!isValid) throw new Error(\"Invalid integer: \" + v);\r\n if (supportsNativeBigInt) {\r\n return new NativeBigInt(BigInt(sign ? \"-\" + v : v));\r\n }\r\n var r = [], max = v.length, l = LOG_BASE, min = max - l;\r\n while (max > 0) {\r\n r.push(+v.slice(min, max));\r\n min -= l;\r\n if (min < 0) min = 0;\r\n max -= l;\r\n }\r\n trim(r);\r\n return new BigInteger(r, sign);\r\n }\r\n\r\n function parseNumberValue(v) {\r\n if (supportsNativeBigInt) {\r\n return new NativeBigInt(BigInt(v));\r\n }\r\n if (isPrecise(v)) {\r\n if (v !== truncate(v)) throw new Error(v + \" is not an integer.\");\r\n return new SmallInteger(v);\r\n }\r\n return parseStringValue(v.toString());\r\n }\r\n\r\n function parseValue(v) {\r\n if (typeof v === \"number\") {\r\n return parseNumberValue(v);\r\n }\r\n if (typeof v === \"string\") {\r\n return parseStringValue(v);\r\n }\r\n if (typeof v === \"bigint\") {\r\n return new NativeBigInt(v);\r\n }\r\n return v;\r\n }\r\n // Pre-define numbers in range [-999,999]\r\n for (var i = 0; i < 1000; i++) {\r\n Integer[i] = parseValue(i);\r\n if (i > 0) Integer[-i] = parseValue(-i);\r\n }\r\n // Backwards compatibility\r\n Integer.one = Integer[1];\r\n Integer.zero = Integer[0];\r\n Integer.minusOne = Integer[-1];\r\n Integer.max = max;\r\n Integer.min = min;\r\n Integer.gcd = gcd;\r\n Integer.lcm = lcm;\r\n Integer.isInstance = function (x) { return x instanceof BigInteger || x instanceof SmallInteger || x instanceof NativeBigInt; };\r\n Integer.randBetween = randBetween;\r\n\r\n Integer.fromArray = function (digits, base, isNegative) {\r\n return parseBaseFromArray(digits.map(parseValue), parseValue(base || 10), isNegative);\r\n };\r\n\r\n return Integer;\r\n})();\r\n\r\n// Node.js check\r\nif (typeof module !== \"undefined\" && module.hasOwnProperty(\"exports\")) {\r\n module.exports = bigInt;\r\n}\r\n\r\n//amd check\r\nif (typeof define === \"function\" && define.amd) {\r\n define( function () {\r\n return bigInt;\r\n });\r\n}\r\n", "/**\n * @preserve jed.js https://github.com/SlexAxton/Jed\n */\n/*\n-----------\nA gettext compatible i18n library for modern JavaScript Applications\n\nby Alex Sexton - AlexSexton [at] gmail - @SlexAxton\n\nMIT License\n\nA jQuery Foundation project - requires CLA to contribute -\nhttps://contribute.jquery.org/CLA/\n\n\n\nJed offers the entire applicable GNU gettext spec'd set of\nfunctions, but also offers some nicer wrappers around them.\nThe api for gettext was written for a language with no function\noverloading, so Jed allows a little more of that.\n\nMany thanks to Joshua I. Miller - unrtst@cpan.org - who wrote\ngettext.js back in 2008. I was able to vet a lot of my ideas\nagainst his. I also made sure Jed passed against his tests\nin order to offer easy upgrades -- jsgettext.berlios.de\n*/\n(function (root, undef) {\n\n // Set up some underscore-style functions, if you already have\n // underscore, feel free to delete this section, and use it\n // directly, however, the amount of functions used doesn't\n // warrant having underscore as a full dependency.\n // Underscore 1.3.0 was used to port and is licensed\n // under the MIT License by Jeremy Ashkenas.\n var ArrayProto = Array.prototype,\n ObjProto = Object.prototype,\n slice = ArrayProto.slice,\n hasOwnProp = ObjProto.hasOwnProperty,\n nativeForEach = ArrayProto.forEach,\n breaker = {};\n\n // We're not using the OOP style _ so we don't need the\n // extra level of indirection. This still means that you\n // sub out for real `_` though.\n var _ = {\n forEach : function( obj, iterator, context ) {\n var i, l, key;\n if ( obj === null ) {\n return;\n }\n\n if ( nativeForEach && obj.forEach === nativeForEach ) {\n obj.forEach( iterator, context );\n }\n else if ( obj.length === +obj.length ) {\n for ( i = 0, l = obj.length; i < l; i++ ) {\n if ( i in obj && iterator.call( context, obj[i], i, obj ) === breaker ) {\n return;\n }\n }\n }\n else {\n for ( key in obj) {\n if ( hasOwnProp.call( obj, key ) ) {\n if ( iterator.call (context, obj[key], key, obj ) === breaker ) {\n return;\n }\n }\n }\n }\n },\n extend : function( obj ) {\n this.forEach( slice.call( arguments, 1 ), function ( source ) {\n for ( var prop in source ) {\n obj[prop] = source[prop];\n }\n });\n return obj;\n }\n };\n // END Miniature underscore impl\n\n // Jed is a constructor function\n var Jed = function ( options ) {\n // Some minimal defaults\n this.defaults = {\n \"locale_data\" : {\n \"messages\" : {\n \"\" : {\n \"domain\" : \"messages\",\n \"lang\" : \"en\",\n \"plural_forms\" : \"nplurals=2; plural=(n != 1);\"\n }\n // There are no default keys, though\n }\n },\n // The default domain if one is missing\n \"domain\" : \"messages\",\n // enable debug mode to log untranslated strings to the console\n \"debug\" : false\n };\n\n // Mix in the sent options with the default options\n this.options = _.extend( {}, this.defaults, options );\n this.textdomain( this.options.domain );\n\n if ( options.domain && ! this.options.locale_data[ this.options.domain ] ) {\n throw new Error('Text domain set to non-existent domain: `' + options.domain + '`');\n }\n };\n\n // The gettext spec sets this character as the default\n // delimiter for context lookups.\n // e.g.: context\\u0004key\n // If your translation company uses something different,\n // just change this at any time and it will use that instead.\n Jed.context_delimiter = String.fromCharCode( 4 );\n\n function getPluralFormFunc ( plural_form_string ) {\n return Jed.PF.compile( plural_form_string || \"nplurals=2; plural=(n != 1);\");\n }\n\n function Chain( key, i18n ){\n this._key = key;\n this._i18n = i18n;\n }\n\n // Create a chainable api for adding args prettily\n _.extend( Chain.prototype, {\n onDomain : function ( domain ) {\n this._domain = domain;\n return this;\n },\n withContext : function ( context ) {\n this._context = context;\n return this;\n },\n ifPlural : function ( num, pkey ) {\n this._val = num;\n this._pkey = pkey;\n return this;\n },\n fetch : function ( sArr ) {\n if ( {}.toString.call( sArr ) != '[object Array]' ) {\n sArr = [].slice.call(arguments, 0);\n }\n return ( sArr && sArr.length ? Jed.sprintf : function(x){ return x; } )(\n this._i18n.dcnpgettext(this._domain, this._context, this._key, this._pkey, this._val),\n sArr\n );\n }\n });\n\n // Add functions to the Jed prototype.\n // These will be the functions on the object that's returned\n // from creating a `new Jed()`\n // These seem redundant, but they gzip pretty well.\n _.extend( Jed.prototype, {\n // The sexier api start point\n translate : function ( key ) {\n return new Chain( key, this );\n },\n\n textdomain : function ( domain ) {\n if ( ! domain ) {\n return this._textdomain;\n }\n this._textdomain = domain;\n },\n\n gettext : function ( key ) {\n return this.dcnpgettext.call( this, undef, undef, key );\n },\n\n dgettext : function ( domain, key ) {\n return this.dcnpgettext.call( this, domain, undef, key );\n },\n\n dcgettext : function ( domain , key /*, category */ ) {\n // Ignores the category anyways\n return this.dcnpgettext.call( this, domain, undef, key );\n },\n\n ngettext : function ( skey, pkey, val ) {\n return this.dcnpgettext.call( this, undef, undef, skey, pkey, val );\n },\n\n dngettext : function ( domain, skey, pkey, val ) {\n return this.dcnpgettext.call( this, domain, undef, skey, pkey, val );\n },\n\n dcngettext : function ( domain, skey, pkey, val/*, category */) {\n return this.dcnpgettext.call( this, domain, undef, skey, pkey, val );\n },\n\n pgettext : function ( context, key ) {\n return this.dcnpgettext.call( this, undef, context, key );\n },\n\n dpgettext : function ( domain, context, key ) {\n return this.dcnpgettext.call( this, domain, context, key );\n },\n\n dcpgettext : function ( domain, context, key/*, category */) {\n return this.dcnpgettext.call( this, domain, context, key );\n },\n\n npgettext : function ( context, skey, pkey, val ) {\n return this.dcnpgettext.call( this, undef, context, skey, pkey, val );\n },\n\n dnpgettext : function ( domain, context, skey, pkey, val ) {\n return this.dcnpgettext.call( this, domain, context, skey, pkey, val );\n },\n\n // The most fully qualified gettext function. It has every option.\n // Since it has every option, we can use it from every other method.\n // This is the bread and butter.\n // Technically there should be one more argument in this function for 'Category',\n // but since we never use it, we might as well not waste the bytes to define it.\n dcnpgettext : function ( domain, context, singular_key, plural_key, val ) {\n // Set some defaults\n\n plural_key = plural_key || singular_key;\n\n // Use the global domain default if one\n // isn't explicitly passed in\n domain = domain || this._textdomain;\n\n var fallback;\n\n // Handle special cases\n\n // No options found\n if ( ! this.options ) {\n // There's likely something wrong, but we'll return the correct key for english\n // We do this by instantiating a brand new Jed instance with the default set\n // for everything that could be broken.\n fallback = new Jed();\n return fallback.dcnpgettext.call( fallback, undefined, undefined, singular_key, plural_key, val );\n }\n\n // No translation data provided\n if ( ! this.options.locale_data ) {\n throw new Error('No locale data provided.');\n }\n\n if ( ! this.options.locale_data[ domain ] ) {\n throw new Error('Domain `' + domain + '` was not found.');\n }\n\n if ( ! this.options.locale_data[ domain ][ \"\" ] ) {\n throw new Error('No locale meta information provided.');\n }\n\n // Make sure we have a truthy key. Otherwise we might start looking\n // into the empty string key, which is the options for the locale\n // data.\n if ( ! singular_key ) {\n throw new Error('No translation key found.');\n }\n\n var key = context ? context + Jed.context_delimiter + singular_key : singular_key,\n locale_data = this.options.locale_data,\n dict = locale_data[ domain ],\n defaultConf = (locale_data.messages || this.defaults.locale_data.messages)[\"\"],\n pluralForms = dict[\"\"].plural_forms || dict[\"\"][\"Plural-Forms\"] || dict[\"\"][\"plural-forms\"] || defaultConf.plural_forms || defaultConf[\"Plural-Forms\"] || defaultConf[\"plural-forms\"],\n val_list,\n res;\n\n var val_idx;\n if (val === undefined) {\n // No value passed in; assume singular key lookup.\n val_idx = 0;\n\n } else {\n // Value has been passed in; use plural-forms calculations.\n\n // Handle invalid numbers, but try casting strings for good measure\n if ( typeof val != 'number' ) {\n val = parseInt( val, 10 );\n\n if ( isNaN( val ) ) {\n throw new Error('The number that was passed in is not a number.');\n }\n }\n\n val_idx = getPluralFormFunc(pluralForms)(val);\n }\n\n // Throw an error if a domain isn't found\n if ( ! dict ) {\n throw new Error('No domain named `' + domain + '` could be found.');\n }\n\n val_list = dict[ key ];\n\n // If there is no match, then revert back to\n // english style singular/plural with the keys passed in.\n if ( ! val_list || val_idx > val_list.length ) {\n if (this.options.missing_key_callback) {\n this.options.missing_key_callback(key, domain);\n }\n res = [ singular_key, plural_key ];\n\n // collect untranslated strings\n if (this.options.debug===true) {\n console.log(res[ getPluralFormFunc(pluralForms)( val ) ]);\n }\n return res[ getPluralFormFunc()( val ) ];\n }\n\n res = val_list[ val_idx ];\n\n // This includes empty strings on purpose\n if ( ! res ) {\n res = [ singular_key, plural_key ];\n return res[ getPluralFormFunc()( val ) ];\n }\n return res;\n }\n });\n\n\n // We add in sprintf capabilities for post translation value interolation\n // This is not internally used, so you can remove it if you have this\n // available somewhere else, or want to use a different system.\n\n // We _slightly_ modify the normal sprintf behavior to more gracefully handle\n // undefined values.\n\n /**\n sprintf() for JavaScript 0.7-beta1\n http://www.diveintojavascript.com/projects/javascript-sprintf\n\n Copyright (c) Alexandru Marasteanu \n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n * Neither the name of sprintf() for JavaScript nor the\n names of its contributors may be used to endorse or promote products\n derived from this software without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY\n DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n var sprintf = (function() {\n function get_type(variable) {\n return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();\n }\n function str_repeat(input, multiplier) {\n for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}\n return output.join('');\n }\n\n var str_format = function() {\n if (!str_format.cache.hasOwnProperty(arguments[0])) {\n str_format.cache[arguments[0]] = str_format.parse(arguments[0]);\n }\n return str_format.format.call(null, str_format.cache[arguments[0]], arguments);\n };\n\n str_format.format = function(parse_tree, argv) {\n var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;\n for (i = 0; i < tree_length; i++) {\n node_type = get_type(parse_tree[i]);\n if (node_type === 'string') {\n output.push(parse_tree[i]);\n }\n else if (node_type === 'array') {\n match = parse_tree[i]; // convenience purposes only\n if (match[2]) { // keyword argument\n arg = argv[cursor];\n for (k = 0; k < match[2].length; k++) {\n if (!arg.hasOwnProperty(match[2][k])) {\n throw(sprintf('[sprintf] property \"%s\" does not exist', match[2][k]));\n }\n arg = arg[match[2][k]];\n }\n }\n else if (match[1]) { // positional argument (explicit)\n arg = argv[match[1]];\n }\n else { // positional argument (implicit)\n arg = argv[cursor++];\n }\n\n if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {\n throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));\n }\n\n // Jed EDIT\n if ( typeof arg == 'undefined' || arg === null ) {\n arg = '';\n }\n // Jed EDIT\n\n switch (match[8]) {\n case 'b': arg = arg.toString(2); break;\n case 'c': arg = String.fromCharCode(arg); break;\n case 'd': arg = parseInt(arg, 10); break;\n case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;\n case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;\n case 'o': arg = arg.toString(8); break;\n case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;\n case 'u': arg = Math.abs(arg); break;\n case 'x': arg = arg.toString(16); break;\n case 'X': arg = arg.toString(16).toUpperCase(); break;\n }\n arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);\n pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';\n pad_length = match[6] - String(arg).length;\n pad = match[6] ? str_repeat(pad_character, pad_length) : '';\n output.push(match[5] ? arg + pad : pad + arg);\n }\n }\n return output.join('');\n };\n\n str_format.cache = {};\n\n str_format.parse = function(fmt) {\n var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;\n while (_fmt) {\n if ((match = /^[^\\x25]+/.exec(_fmt)) !== null) {\n parse_tree.push(match[0]);\n }\n else if ((match = /^\\x25{2}/.exec(_fmt)) !== null) {\n parse_tree.push('%');\n }\n else if ((match = /^\\x25(?:([1-9]\\d*)\\$|\\(([^\\)]+)\\))?(\\+)?(0|'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {\n if (match[2]) {\n arg_names |= 1;\n var field_list = [], replacement_field = match[2], field_match = [];\n if ((field_match = /^([a-z_][a-z_\\d]*)/i.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {\n if ((field_match = /^\\.([a-z_][a-z_\\d]*)/i.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n }\n else if ((field_match = /^\\[(\\d+)\\]/.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n }\n else {\n throw('[sprintf] huh?');\n }\n }\n }\n else {\n throw('[sprintf] huh?');\n }\n match[2] = field_list;\n }\n else {\n arg_names |= 2;\n }\n if (arg_names === 3) {\n throw('[sprintf] mixing positional and named placeholders is not (yet) supported');\n }\n parse_tree.push(match);\n }\n else {\n throw('[sprintf] huh?');\n }\n _fmt = _fmt.substring(match[0].length);\n }\n return parse_tree;\n };\n\n return str_format;\n })();\n\n var vsprintf = function(fmt, argv) {\n argv.unshift(fmt);\n return sprintf.apply(null, argv);\n };\n\n Jed.parse_plural = function ( plural_forms, n ) {\n plural_forms = plural_forms.replace(/n/g, n);\n return Jed.parse_expression(plural_forms);\n };\n\n Jed.sprintf = function ( fmt, args ) {\n if ( {}.toString.call( args ) == '[object Array]' ) {\n return vsprintf( fmt, [].slice.call(args) );\n }\n return sprintf.apply(this, [].slice.call(arguments) );\n };\n\n Jed.prototype.sprintf = function () {\n return Jed.sprintf.apply(this, arguments);\n };\n // END sprintf Implementation\n\n // Start the Plural forms section\n // This is a full plural form expression parser. It is used to avoid\n // running 'eval' or 'new Function' directly against the plural\n // forms.\n //\n // This can be important if you get translations done through a 3rd\n // party vendor. I encourage you to use this instead, however, I\n // also will provide a 'precompiler' that you can use at build time\n // to output valid/safe function representations of the plural form\n // expressions. This means you can build this code out for the most\n // part.\n Jed.PF = {};\n\n Jed.PF.parse = function ( p ) {\n var plural_str = Jed.PF.extractPluralExpr( p );\n return Jed.PF.parser.parse.call(Jed.PF.parser, plural_str);\n };\n\n Jed.PF.compile = function ( p ) {\n // Handle trues and falses as 0 and 1\n function imply( val ) {\n return (val === true ? 1 : val ? val : 0);\n }\n\n var ast = Jed.PF.parse( p );\n return function ( n ) {\n return imply( Jed.PF.interpreter( ast )( n ) );\n };\n };\n\n Jed.PF.interpreter = function ( ast ) {\n return function ( n ) {\n var res;\n switch ( ast.type ) {\n case 'GROUP':\n return Jed.PF.interpreter( ast.expr )( n );\n case 'TERNARY':\n if ( Jed.PF.interpreter( ast.expr )( n ) ) {\n return Jed.PF.interpreter( ast.truthy )( n );\n }\n return Jed.PF.interpreter( ast.falsey )( n );\n case 'OR':\n return Jed.PF.interpreter( ast.left )( n ) || Jed.PF.interpreter( ast.right )( n );\n case 'AND':\n return Jed.PF.interpreter( ast.left )( n ) && Jed.PF.interpreter( ast.right )( n );\n case 'LT':\n return Jed.PF.interpreter( ast.left )( n ) < Jed.PF.interpreter( ast.right )( n );\n case 'GT':\n return Jed.PF.interpreter( ast.left )( n ) > Jed.PF.interpreter( ast.right )( n );\n case 'LTE':\n return Jed.PF.interpreter( ast.left )( n ) <= Jed.PF.interpreter( ast.right )( n );\n case 'GTE':\n return Jed.PF.interpreter( ast.left )( n ) >= Jed.PF.interpreter( ast.right )( n );\n case 'EQ':\n return Jed.PF.interpreter( ast.left )( n ) == Jed.PF.interpreter( ast.right )( n );\n case 'NEQ':\n return Jed.PF.interpreter( ast.left )( n ) != Jed.PF.interpreter( ast.right )( n );\n case 'MOD':\n return Jed.PF.interpreter( ast.left )( n ) % Jed.PF.interpreter( ast.right )( n );\n case 'VAR':\n return n;\n case 'NUM':\n return ast.val;\n default:\n throw new Error(\"Invalid Token found.\");\n }\n };\n };\n\n Jed.PF.extractPluralExpr = function ( p ) {\n // trim first\n p = p.replace(/^\\s\\s*/, '').replace(/\\s\\s*$/, '');\n\n if (! /;\\s*$/.test(p)) {\n p = p.concat(';');\n }\n\n var nplurals_re = /nplurals\\=(\\d+);/,\n plural_re = /plural\\=(.*);/,\n nplurals_matches = p.match( nplurals_re ),\n res = {},\n plural_matches;\n\n // Find the nplurals number\n if ( nplurals_matches.length > 1 ) {\n res.nplurals = nplurals_matches[1];\n }\n else {\n throw new Error('nplurals not found in plural_forms string: ' + p );\n }\n\n // remove that data to get to the formula\n p = p.replace( nplurals_re, \"\" );\n plural_matches = p.match( plural_re );\n\n if (!( plural_matches && plural_matches.length > 1 ) ) {\n throw new Error('`plural` expression not found: ' + p);\n }\n return plural_matches[ 1 ];\n };\n\n /* Jison generated parser */\n Jed.PF.parser = (function(){\n\nvar parser = {trace: function trace() { },\nyy: {},\nsymbols_: {\"error\":2,\"expressions\":3,\"e\":4,\"EOF\":5,\"?\":6,\":\":7,\"||\":8,\"&&\":9,\"<\":10,\"<=\":11,\">\":12,\">=\":13,\"!=\":14,\"==\":15,\"%\":16,\"(\":17,\")\":18,\"n\":19,\"NUMBER\":20,\"$accept\":0,\"$end\":1},\nterminals_: {2:\"error\",5:\"EOF\",6:\"?\",7:\":\",8:\"||\",9:\"&&\",10:\"<\",11:\"<=\",12:\">\",13:\">=\",14:\"!=\",15:\"==\",16:\"%\",17:\"(\",18:\")\",19:\"n\",20:\"NUMBER\"},\nproductions_: [0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]],\nperformAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {\n\nvar $0 = $$.length - 1;\nswitch (yystate) {\ncase 1: return { type : 'GROUP', expr: $$[$0-1] };\nbreak;\ncase 2:this.$ = { type: 'TERNARY', expr: $$[$0-4], truthy : $$[$0-2], falsey: $$[$0] };\nbreak;\ncase 3:this.$ = { type: \"OR\", left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 4:this.$ = { type: \"AND\", left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 5:this.$ = { type: 'LT', left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 6:this.$ = { type: 'LTE', left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 7:this.$ = { type: 'GT', left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 8:this.$ = { type: 'GTE', left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 9:this.$ = { type: 'NEQ', left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 10:this.$ = { type: 'EQ', left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 11:this.$ = { type: 'MOD', left: $$[$0-2], right: $$[$0] };\nbreak;\ncase 12:this.$ = { type: 'GROUP', expr: $$[$0-1] };\nbreak;\ncase 13:this.$ = { type: 'VAR' };\nbreak;\ncase 14:this.$ = { type: 'NUM', val: Number(yytext) };\nbreak;\n}\n},\ntable: [{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}],\ndefaultActions: {6:[2,1]},\nparseError: function parseError(str, hash) {\n throw new Error(str);\n},\nparse: function parse(input) {\n var self = this,\n stack = [0],\n vstack = [null], // semantic value stack\n lstack = [], // location stack\n table = this.table,\n yytext = '',\n yylineno = 0,\n yyleng = 0,\n recovering = 0,\n TERROR = 2,\n EOF = 1;\n\n //this.reductionCount = this.shiftCount = 0;\n\n this.lexer.setInput(input);\n this.lexer.yy = this.yy;\n this.yy.lexer = this.lexer;\n if (typeof this.lexer.yylloc == 'undefined')\n this.lexer.yylloc = {};\n var yyloc = this.lexer.yylloc;\n lstack.push(yyloc);\n\n if (typeof this.yy.parseError === 'function')\n this.parseError = this.yy.parseError;\n\n function popStack (n) {\n stack.length = stack.length - 2*n;\n vstack.length = vstack.length - n;\n lstack.length = lstack.length - n;\n }\n\n function lex() {\n var token;\n token = self.lexer.lex() || 1; // $end = 1\n // if token isn't its numeric value, convert\n if (typeof token !== 'number') {\n token = self.symbols_[token] || token;\n }\n return token;\n }\n\n var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;\n while (true) {\n // retreive state number from top of stack\n state = stack[stack.length-1];\n\n // use default actions if available\n if (this.defaultActions[state]) {\n action = this.defaultActions[state];\n } else {\n if (symbol == null)\n symbol = lex();\n // read action for current state and first input\n action = table[state] && table[state][symbol];\n }\n\n // handle parse error\n _handle_error:\n if (typeof action === 'undefined' || !action.length || !action[0]) {\n\n if (!recovering) {\n // Report error\n expected = [];\n for (p in table[state]) if (this.terminals_[p] && p > 2) {\n expected.push(\"'\"+this.terminals_[p]+\"'\");\n }\n var errStr = '';\n if (this.lexer.showPosition) {\n errStr = 'Parse error on line '+(yylineno+1)+\":\\n\"+this.lexer.showPosition()+\"\\nExpecting \"+expected.join(', ') + \", got '\" + this.terminals_[symbol]+ \"'\";\n } else {\n errStr = 'Parse error on line '+(yylineno+1)+\": Unexpected \" +\n (symbol == 1 /*EOF*/ ? \"end of input\" :\n (\"'\"+(this.terminals_[symbol] || symbol)+\"'\"));\n }\n this.parseError(errStr,\n {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});\n }\n\n // just recovered from another error\n if (recovering == 3) {\n if (symbol == EOF) {\n throw new Error(errStr || 'Parsing halted.');\n }\n\n // discard current lookahead and grab another\n yyleng = this.lexer.yyleng;\n yytext = this.lexer.yytext;\n yylineno = this.lexer.yylineno;\n yyloc = this.lexer.yylloc;\n symbol = lex();\n }\n\n // try to recover from error\n while (1) {\n // check for error recovery rule in this state\n if ((TERROR.toString()) in table[state]) {\n break;\n }\n if (state == 0) {\n throw new Error(errStr || 'Parsing halted.');\n }\n popStack(1);\n state = stack[stack.length-1];\n }\n\n preErrorSymbol = symbol; // save the lookahead token\n symbol = TERROR; // insert generic error symbol as new lookahead\n state = stack[stack.length-1];\n action = table[state] && table[state][TERROR];\n recovering = 3; // allow 3 real symbols to be shifted before reporting a new error\n }\n\n // this shouldn't happen, unless resolve defaults are off\n if (action[0] instanceof Array && action.length > 1) {\n throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);\n }\n\n switch (action[0]) {\n\n case 1: // shift\n //this.shiftCount++;\n\n stack.push(symbol);\n vstack.push(this.lexer.yytext);\n lstack.push(this.lexer.yylloc);\n stack.push(action[1]); // push state\n symbol = null;\n if (!preErrorSymbol) { // normal execution/no error\n yyleng = this.lexer.yyleng;\n yytext = this.lexer.yytext;\n yylineno = this.lexer.yylineno;\n yyloc = this.lexer.yylloc;\n if (recovering > 0)\n recovering--;\n } else { // error just occurred, resume old lookahead f/ before error\n symbol = preErrorSymbol;\n preErrorSymbol = null;\n }\n break;\n\n case 2: // reduce\n //this.reductionCount++;\n\n len = this.productions_[action[1]][1];\n\n // perform semantic action\n yyval.$ = vstack[vstack.length-len]; // default to $$ = $1\n // default location, uses first token for firsts, last for lasts\n yyval._$ = {\n first_line: lstack[lstack.length-(len||1)].first_line,\n last_line: lstack[lstack.length-1].last_line,\n first_column: lstack[lstack.length-(len||1)].first_column,\n last_column: lstack[lstack.length-1].last_column\n };\n r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);\n\n if (typeof r !== 'undefined') {\n return r;\n }\n\n // pop off stack\n if (len) {\n stack = stack.slice(0,-1*len*2);\n vstack = vstack.slice(0, -1*len);\n lstack = lstack.slice(0, -1*len);\n }\n\n stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)\n vstack.push(yyval.$);\n lstack.push(yyval._$);\n // goto new state = table[STATE][NONTERMINAL]\n newState = table[stack[stack.length-2]][stack[stack.length-1]];\n stack.push(newState);\n break;\n\n case 3: // accept\n return true;\n }\n\n }\n\n return true;\n}};/* Jison generated lexer */\nvar lexer = (function(){\n\nvar lexer = ({EOF:1,\nparseError:function parseError(str, hash) {\n if (this.yy.parseError) {\n this.yy.parseError(str, hash);\n } else {\n throw new Error(str);\n }\n },\nsetInput:function (input) {\n this._input = input;\n this._more = this._less = this.done = false;\n this.yylineno = this.yyleng = 0;\n this.yytext = this.matched = this.match = '';\n this.conditionStack = ['INITIAL'];\n this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};\n return this;\n },\ninput:function () {\n var ch = this._input[0];\n this.yytext+=ch;\n this.yyleng++;\n this.match+=ch;\n this.matched+=ch;\n var lines = ch.match(/\\n/);\n if (lines) this.yylineno++;\n this._input = this._input.slice(1);\n return ch;\n },\nunput:function (ch) {\n this._input = ch + this._input;\n return this;\n },\nmore:function () {\n this._more = true;\n return this;\n },\npastInput:function () {\n var past = this.matched.substr(0, this.matched.length - this.match.length);\n return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\\n/g, \"\");\n },\nupcomingInput:function () {\n var next = this.match;\n if (next.length < 20) {\n next += this._input.substr(0, 20-next.length);\n }\n return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\\n/g, \"\");\n },\nshowPosition:function () {\n var pre = this.pastInput();\n var c = new Array(pre.length + 1).join(\"-\");\n return pre + this.upcomingInput() + \"\\n\" + c+\"^\";\n },\nnext:function () {\n if (this.done) {\n return this.EOF;\n }\n if (!this._input) this.done = true;\n\n var token,\n match,\n col,\n lines;\n if (!this._more) {\n this.yytext = '';\n this.match = '';\n }\n var rules = this._currentRules();\n for (var i=0;i < rules.length; i++) {\n match = this._input.match(this.rules[rules[i]]);\n if (match) {\n lines = match[0].match(/\\n.*/g);\n if (lines) this.yylineno += lines.length;\n this.yylloc = {first_line: this.yylloc.last_line,\n last_line: this.yylineno+1,\n first_column: this.yylloc.last_column,\n last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}\n this.yytext += match[0];\n this.match += match[0];\n this.matches = match;\n this.yyleng = this.yytext.length;\n this._more = false;\n this._input = this._input.slice(match[0].length);\n this.matched += match[0];\n token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);\n if (token) return token;\n else return;\n }\n }\n if (this._input === \"\") {\n return this.EOF;\n } else {\n this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\\n'+this.showPosition(),\n {text: \"\", token: null, line: this.yylineno});\n }\n },\nlex:function lex() {\n var r = this.next();\n if (typeof r !== 'undefined') {\n return r;\n } else {\n return this.lex();\n }\n },\nbegin:function begin(condition) {\n this.conditionStack.push(condition);\n },\npopState:function popState() {\n return this.conditionStack.pop();\n },\n_currentRules:function _currentRules() {\n return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;\n },\ntopState:function () {\n return this.conditionStack[this.conditionStack.length-2];\n },\npushState:function begin(condition) {\n this.begin(condition);\n }});\nlexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {\n\nvar YYSTATE=YY_START;\nswitch($avoiding_name_collisions) {\ncase 0:/* skip whitespace */\nbreak;\ncase 1:return 20\nbreak;\ncase 2:return 19\nbreak;\ncase 3:return 8\nbreak;\ncase 4:return 9\nbreak;\ncase 5:return 6\nbreak;\ncase 6:return 7\nbreak;\ncase 7:return 11\nbreak;\ncase 8:return 13\nbreak;\ncase 9:return 10\nbreak;\ncase 10:return 12\nbreak;\ncase 11:return 14\nbreak;\ncase 12:return 15\nbreak;\ncase 13:return 16\nbreak;\ncase 14:return 17\nbreak;\ncase 15:return 18\nbreak;\ncase 16:return 5\nbreak;\ncase 17:return 'INVALID'\nbreak;\n}\n};\nlexer.rules = [/^\\s+/,/^[0-9]+(\\.[0-9]+)?\\b/,/^n\\b/,/^\\|\\|/,/^&&/,/^\\?/,/^:/,/^<=/,/^>=/,/^/,/^!=/,/^==/,/^%/,/^\\(/,/^\\)/,/^$/,/^./];\nlexer.conditions = {\"INITIAL\":{\"rules\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],\"inclusive\":true}};return lexer;})()\nparser.lexer = lexer;\nreturn parser;\n})();\n// End parser\n\n // Handle node, amd, and global systems\n if (typeof exports !== 'undefined') {\n if (typeof module !== 'undefined' && module.exports) {\n exports = module.exports = Jed;\n }\n exports.Jed = Jed;\n }\n else {\n if (typeof define === 'function' && define.amd) {\n define(function() {\n return Jed;\n });\n }\n // Leak a global regardless of module system\n root['Jed'] = Jed;\n }\n\n})(this);\n", "import { EMPTY_ARR } from \"./constants\";\n\n/**\n * Assign properties from `props` to `obj`\n * @template O, P The obj and props types\n * @param {O} obj The object to copy properties to\n * @param {P} props The object to copy properties from\n * @returns {O & P}\n */\nexport function assign(obj, props) {\n\t// @ts-ignore We change the type of `obj` to be `O & P`\n\tfor (let i in props) obj[i] = props[i];\n\treturn /** @type {O & P} */ (obj);\n}\n\n/**\n * Remove a child node from its parent if attached. This is a workaround for\n * IE11 which doesn't support `Element.prototype.remove()`. Using this function\n * is smaller than including a dedicated polyfill.\n * @param {Node} node The node to remove\n */\nexport function removeNode(node) {\n\tlet parentNode = node.parentNode;\n\tif (parentNode) parentNode.removeChild(node);\n}\n\nexport const slice = EMPTY_ARR.slice;\n", "import { _catchError } from './diff/catch-error';\n\n/**\n * The `option` object can potentially contain callback functions\n * that are called during various stages of our renderer. This is the\n * foundation on which all our addons like `preact/debug`, `preact/compat`,\n * and `preact/hooks` are based on. See the `Options` type in `internal.d.ts`\n * for a full list of available option hooks (most editors/IDEs allow you to\n * ctrl+click or cmd+click on mac the type definition below).\n * @type {import('./internal').Options}\n */\nconst options = {\n\t_catchError\n};\n\nexport default options;\n", "import { slice } from './util';\nimport options from './options';\n\nlet vnodeId = 0;\n\n/**\n * Create an virtual node (used for JSX)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component\n * constructor for this virtual node\n * @param {object | null | undefined} [props] The properties of the virtual node\n * @param {Array} [children] The children of the virtual node\n * @returns {import('./internal').VNode}\n */\nexport function createElement(type, props, children) {\n\tlet normalizedProps = {},\n\t\tkey,\n\t\tref,\n\t\ti;\n\tfor (i in props) {\n\t\tif (i == 'key') key = props[i];\n\t\telse if (i == 'ref') ref = props[i];\n\t\telse normalizedProps[i] = props[i];\n\t}\n\n\tif (arguments.length > 2) {\n\t\tnormalizedProps.children =\n\t\t\targuments.length > 3 ? slice.call(arguments, 2) : children;\n\t}\n\n\t// If a Component VNode, check for and apply defaultProps\n\t// Note: type may be undefined in development, must never error here.\n\tif (typeof type == 'function' && type.defaultProps != null) {\n\t\tfor (i in type.defaultProps) {\n\t\t\tif (normalizedProps[i] === undefined) {\n\t\t\t\tnormalizedProps[i] = type.defaultProps[i];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn createVNode(type, normalizedProps, key, ref, null);\n}\n\n/**\n * Create a VNode (used internally by Preact)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component\n * Constructor for this virtual node\n * @param {object | string | number | null} props The properties of this virtual node.\n * If this virtual node represents a text node, this is the text of the node (string or number).\n * @param {string | number | null} key The key for this virtual node, used when\n * diffing it against its children\n * @param {import('./internal').VNode[\"ref\"]} ref The ref property that will\n * receive a reference to its created child\n * @returns {import('./internal').VNode}\n */\nexport function createVNode(type, props, key, ref, original) {\n\t// V8 seems to be better at detecting type shapes if the object is allocated from the same call site\n\t// Do not inline into createElement and coerceToVNode!\n\tconst vnode = {\n\t\ttype,\n\t\tprops,\n\t\tkey,\n\t\tref,\n\t\t_children: null,\n\t\t_parent: null,\n\t\t_depth: 0,\n\t\t_dom: null,\n\t\t// _nextDom must be initialized to undefined b/c it will eventually\n\t\t// be set to dom.nextSibling which can return `null` and it is important\n\t\t// to be able to distinguish between an uninitialized _nextDom and\n\t\t// a _nextDom that has been set to `null`\n\t\t_nextDom: undefined,\n\t\t_component: null,\n\t\t_hydrating: null,\n\t\tconstructor: undefined,\n\t\t_original: original == null ? ++vnodeId : original\n\t};\n\n\t// Only invoke the vnode hook if this was *not* a direct copy:\n\tif (original == null && options.vnode != null) options.vnode(vnode);\n\n\treturn vnode;\n}\n\nexport function createRef() {\n\treturn { current: null };\n}\n\nexport function Fragment(props) {\n\treturn props.children;\n}\n\n/**\n * Check if a the argument is a valid Preact VNode.\n * @param {*} vnode\n * @returns {vnode is import('./internal').VNode}\n */\nexport const isValidElement = vnode =>\n\tvnode != null && vnode.constructor === undefined;\n", "import { assign } from './util';\nimport { diff, commitRoot } from './diff/index';\nimport options from './options';\nimport { Fragment } from './create-element';\n\n/**\n * Base Component class. Provides `setState()` and `forceUpdate()`, which\n * trigger rendering\n * @param {object} props The initial component props\n * @param {object} context The initial context from parent components'\n * getChildContext\n */\nexport function Component(props, context) {\n\tthis.props = props;\n\tthis.context = context;\n}\n\n/**\n * Update component state and schedule a re-render.\n * @this {import('./internal').Component}\n * @param {object | ((s: object, p: object) => object)} update A hash of state\n * properties to update with new values or a function that given the current\n * state and props returns a new partial state\n * @param {() => void} [callback] A function to be called once component state is\n * updated\n */\nComponent.prototype.setState = function(update, callback) {\n\t// only clone state when copying to nextState the first time.\n\tlet s;\n\tif (this._nextState != null && this._nextState !== this.state) {\n\t\ts = this._nextState;\n\t} else {\n\t\ts = this._nextState = assign({}, this.state);\n\t}\n\n\tif (typeof update == 'function') {\n\t\t// Some libraries like `immer` mark the current state as readonly,\n\t\t// preventing us from mutating it, so we need to clone it. See #2716\n\t\tupdate = update(assign({}, s), this.props);\n\t}\n\n\tif (update) {\n\t\tassign(s, update);\n\t}\n\n\t// Skip update if updater function returned null\n\tif (update == null) return;\n\n\tif (this._vnode) {\n\t\tif (callback) {\n\t\t\tthis._stateCallbacks.push(callback);\n\t\t}\n\t\tenqueueRender(this);\n\t}\n};\n\n/**\n * Immediately perform a synchronous re-render of the component\n * @this {import('./internal').Component}\n * @param {() => void} [callback] A function to be called after component is\n * re-rendered\n */\nComponent.prototype.forceUpdate = function(callback) {\n\tif (this._vnode) {\n\t\t// Set render mode so that we can differentiate where the render request\n\t\t// is coming from. We need this because forceUpdate should never call\n\t\t// shouldComponentUpdate\n\t\tthis._force = true;\n\t\tif (callback) this._renderCallbacks.push(callback);\n\t\tenqueueRender(this);\n\t}\n};\n\n/**\n * Accepts `props` and `state`, and returns a new Virtual DOM tree to build.\n * Virtual DOM is generally constructed via [JSX](http://jasonformat.com/wtf-is-jsx).\n * @param {object} props Props (eg: JSX attributes) received from parent\n * element/component\n * @param {object} state The component's current state\n * @param {object} context Context object, as returned by the nearest\n * ancestor's `getChildContext()`\n * @returns {import('./index').ComponentChildren | void}\n */\nComponent.prototype.render = Fragment;\n\n/**\n * @param {import('./internal').VNode} vnode\n * @param {number | null} [childIndex]\n */\nexport function getDomSibling(vnode, childIndex) {\n\tif (childIndex == null) {\n\t\t// Use childIndex==null as a signal to resume the search from the vnode's sibling\n\t\treturn vnode._parent\n\t\t\t? getDomSibling(vnode._parent, vnode._parent._children.indexOf(vnode) + 1)\n\t\t\t: null;\n\t}\n\n\tlet sibling;\n\tfor (; childIndex < vnode._children.length; childIndex++) {\n\t\tsibling = vnode._children[childIndex];\n\n\t\tif (sibling != null && sibling._dom != null) {\n\t\t\t// Since updateParentDomPointers keeps _dom pointer correct,\n\t\t\t// we can rely on _dom to tell us if this subtree contains a\n\t\t\t// rendered DOM node, and what the first rendered DOM node is\n\t\t\treturn sibling._dom;\n\t\t}\n\t}\n\n\t// If we get here, we have not found a DOM node in this vnode's children.\n\t// We must resume from this vnode's sibling (in it's parent _children array)\n\t// Only climb up and search the parent if we aren't searching through a DOM\n\t// VNode (meaning we reached the DOM parent of the original vnode that began\n\t// the search)\n\treturn typeof vnode.type == 'function' ? getDomSibling(vnode) : null;\n}\n\n/**\n * Trigger in-place re-rendering of a component.\n * @param {import('./internal').Component} component The component to rerender\n */\nfunction renderComponent(component) {\n\tlet vnode = component._vnode,\n\t\toldDom = vnode._dom,\n\t\tparentDom = component._parentDom;\n\n\tif (parentDom) {\n\t\tlet commitQueue = [];\n\t\tconst oldVNode = assign({}, vnode);\n\t\toldVNode._original = vnode._original + 1;\n\n\t\tdiff(\n\t\t\tparentDom,\n\t\t\tvnode,\n\t\t\toldVNode,\n\t\t\tcomponent._globalContext,\n\t\t\tparentDom.ownerSVGElement !== undefined,\n\t\t\tvnode._hydrating != null ? [oldDom] : null,\n\t\t\tcommitQueue,\n\t\t\toldDom == null ? getDomSibling(vnode) : oldDom,\n\t\t\tvnode._hydrating\n\t\t);\n\t\tcommitRoot(commitQueue, vnode);\n\n\t\tif (vnode._dom != oldDom) {\n\t\t\tupdateParentDomPointers(vnode);\n\t\t}\n\t}\n}\n\n/**\n * @param {import('./internal').VNode} vnode\n */\nfunction updateParentDomPointers(vnode) {\n\tif ((vnode = vnode._parent) != null && vnode._component != null) {\n\t\tvnode._dom = vnode._component.base = null;\n\t\tfor (let i = 0; i < vnode._children.length; i++) {\n\t\t\tlet child = vnode._children[i];\n\t\t\tif (child != null && child._dom != null) {\n\t\t\t\tvnode._dom = vnode._component.base = child._dom;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn updateParentDomPointers(vnode);\n\t}\n}\n\n/**\n * The render queue\n * @type {Array}\n */\nlet rerenderQueue = [];\n\n/*\n * The value of `Component.debounce` must asynchronously invoke the passed in callback. It is\n * important that contributors to Preact can consistently reason about what calls to `setState`, etc.\n * do, and when their effects will be applied. See the links below for some further reading on designing\n * asynchronous APIs.\n * * [Designing APIs for Asynchrony](https://blog.izs.me/2013/08/designing-apis-for-asynchrony)\n * * [Callbacks synchronous and asynchronous](https://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/)\n */\n\nlet prevDebounce;\n\n/**\n * Enqueue a rerender of a component\n * @param {import('./internal').Component} c The component to rerender\n */\nexport function enqueueRender(c) {\n\tif (\n\t\t(!c._dirty &&\n\t\t\t(c._dirty = true) &&\n\t\t\trerenderQueue.push(c) &&\n\t\t\t!process._rerenderCount++) ||\n\t\tprevDebounce !== options.debounceRendering\n\t) {\n\t\tprevDebounce = options.debounceRendering;\n\t\t(prevDebounce || setTimeout)(process);\n\t}\n}\n\n/** Flush the render queue by rerendering all queued components */\nfunction process() {\n\tlet queue;\n\twhile ((process._rerenderCount = rerenderQueue.length)) {\n\t\tqueue = rerenderQueue.sort((a, b) => a._vnode._depth - b._vnode._depth);\n\t\trerenderQueue = [];\n\t\t// Don't update `renderCount` yet. Keep its value non-zero to prevent unnecessary\n\t\t// process() calls from getting scheduled while `queue` is still being consumed.\n\t\tqueue.some(c => {\n\t\t\tif (c._dirty) renderComponent(c);\n\t\t});\n\t}\n}\n\nprocess._rerenderCount = 0;\n", "import { enqueueRender } from './component';\n\nexport let i = 0;\n\nexport function createContext(defaultValue, contextId) {\n\tcontextId = '__cC' + i++;\n\n\tconst context = {\n\t\t_id: contextId,\n\t\t_defaultValue: defaultValue,\n\t\t/** @type {import('./internal').FunctionComponent} */\n\t\tConsumer(props, contextValue) {\n\t\t\t// return props.children(\n\t\t\t// \tcontext[contextId] ? context[contextId].props.value : defaultValue\n\t\t\t// );\n\t\t\treturn props.children(contextValue);\n\t\t},\n\t\t/** @type {import('./internal').FunctionComponent} */\n\t\tProvider(props) {\n\t\t\tif (!this.getChildContext) {\n\t\t\t\tlet subs = [];\n\t\t\t\tlet ctx = {};\n\t\t\t\tctx[contextId] = this;\n\n\t\t\t\tthis.getChildContext = () => ctx;\n\n\t\t\t\tthis.shouldComponentUpdate = function(_props) {\n\t\t\t\t\tif (this.props.value !== _props.value) {\n\t\t\t\t\t\t// I think the forced value propagation here was only needed when `options.debounceRendering` was being bypassed:\n\t\t\t\t\t\t// https://github.com/preactjs/preact/commit/4d339fb803bea09e9f198abf38ca1bf8ea4b7771#diff-54682ce380935a717e41b8bfc54737f6R358\n\t\t\t\t\t\t// In those cases though, even with the value corrected, we're double-rendering all nodes.\n\t\t\t\t\t\t// It might be better to just tell folks not to use force-sync mode.\n\t\t\t\t\t\t// Currently, using `useContext()` in a class component will overwrite its `this.context` value.\n\t\t\t\t\t\t// subs.some(c => {\n\t\t\t\t\t\t// \tc.context = _props.value;\n\t\t\t\t\t\t// \tenqueueRender(c);\n\t\t\t\t\t\t// });\n\n\t\t\t\t\t\t// subs.some(c => {\n\t\t\t\t\t\t// \tc.context[contextId] = _props.value;\n\t\t\t\t\t\t// \tenqueueRender(c);\n\t\t\t\t\t\t// });\n\t\t\t\t\t\tsubs.some(enqueueRender);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tthis.sub = c => {\n\t\t\t\t\tsubs.push(c);\n\t\t\t\t\tlet old = c.componentWillUnmount;\n\t\t\t\t\tc.componentWillUnmount = () => {\n\t\t\t\t\t\tsubs.splice(subs.indexOf(c), 1);\n\t\t\t\t\t\tif (old) old.call(c);\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn props.children;\n\t\t}\n\t};\n\n\t// Devtools needs access to the context object when it\n\t// encounters a Provider. This is necessary to support\n\t// setting `displayName` on the context object instead\n\t// of on the component itself. See:\n\t// https://reactjs.org/docs/context.html#contextdisplayname\n\n\treturn (context.Provider._contextRef = context.Consumer.contextType = context);\n}\n", "export const EMPTY_OBJ = {};\nexport const EMPTY_ARR = [];\nexport const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;\n", "import { diff, unmount, applyRef } from './index';\nimport { createVNode, Fragment } from '../create-element';\nimport { EMPTY_OBJ, EMPTY_ARR } from '../constants';\nimport { getDomSibling } from '../component';\n\n/**\n * Diff the children of a virtual node\n * @param {import('../internal').PreactElement} parentDom The DOM element whose\n * children are being diffed\n * @param {import('../internal').ComponentChildren[]} renderResult\n * @param {import('../internal').VNode} newParentVNode The new virtual\n * node whose children should be diff'ed against oldParentVNode\n * @param {import('../internal').VNode} oldParentVNode The old virtual\n * node whose children should be diff'ed against newParentVNode\n * @param {object} globalContext The current context object - modified by getChildContext\n * @param {boolean} isSvg Whether or not this DOM node is an SVG node\n * @param {Array} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').PreactElement} oldDom The current attached DOM\n * element any new dom elements should be placed around. Likely `null` on first\n * render (except when hydrating). Can be a sibling DOM element when diffing\n * Fragments that have siblings. In most cases, it starts out as `oldChildren[0]._dom`.\n * @param {boolean} isHydrating Whether or not we are in hydration\n */\nexport function diffChildren(\n\tparentDom,\n\trenderResult,\n\tnewParentVNode,\n\toldParentVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\toldDom,\n\tisHydrating\n) {\n\tlet i, j, oldVNode, childVNode, newDom, firstChildDom, refs;\n\n\t// This is a compression of oldParentVNode!=null && oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR\n\t// as EMPTY_OBJ._children should be `undefined`.\n\tlet oldChildren = (oldParentVNode && oldParentVNode._children) || EMPTY_ARR;\n\n\tlet oldChildrenLength = oldChildren.length;\n\n\tnewParentVNode._children = [];\n\tfor (i = 0; i < renderResult.length; i++) {\n\t\tchildVNode = renderResult[i];\n\n\t\tif (childVNode == null || typeof childVNode == 'boolean') {\n\t\t\tchildVNode = newParentVNode._children[i] = null;\n\t\t}\n\t\t// If this newVNode is being reused (e.g.
{reuse}{reuse}
) in the same diff,\n\t\t// or we are rendering a component (e.g. setState) copy the oldVNodes so it can have\n\t\t// it's own DOM & etc. pointers\n\t\telse if (\n\t\t\ttypeof childVNode == 'string' ||\n\t\t\ttypeof childVNode == 'number' ||\n\t\t\t// eslint-disable-next-line valid-typeof\n\t\t\ttypeof childVNode == 'bigint'\n\t\t) {\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tnull,\n\t\t\t\tchildVNode,\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tchildVNode\n\t\t\t);\n\t\t} else if (Array.isArray(childVNode)) {\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tFragment,\n\t\t\t\t{ children: childVNode },\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tnull\n\t\t\t);\n\t\t} else if (childVNode._depth > 0) {\n\t\t\t// VNode is already in use, clone it. This can happen in the following\n\t\t\t// scenario:\n\t\t\t// const reuse =
\n\t\t\t//
{reuse}{reuse}
\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tchildVNode.type,\n\t\t\t\tchildVNode.props,\n\t\t\t\tchildVNode.key,\n\t\t\t\tchildVNode.ref ? childVNode.ref : null,\n\t\t\t\tchildVNode._original\n\t\t\t);\n\t\t} else {\n\t\t\tchildVNode = newParentVNode._children[i] = childVNode;\n\t\t}\n\n\t\t// Terser removes the `continue` here and wraps the loop body\n\t\t// in a `if (childVNode) { ... } condition\n\t\tif (childVNode == null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tchildVNode._parent = newParentVNode;\n\t\tchildVNode._depth = newParentVNode._depth + 1;\n\n\t\t// Check if we find a corresponding element in oldChildren.\n\t\t// If found, delete the array item by setting to `undefined`.\n\t\t// We use `undefined`, as `null` is reserved for empty placeholders\n\t\t// (holes).\n\t\toldVNode = oldChildren[i];\n\n\t\tif (\n\t\t\toldVNode === null ||\n\t\t\t(oldVNode &&\n\t\t\t\tchildVNode.key == oldVNode.key &&\n\t\t\t\tchildVNode.type === oldVNode.type)\n\t\t) {\n\t\t\toldChildren[i] = undefined;\n\t\t} else {\n\t\t\t// Either oldVNode === undefined or oldChildrenLength > 0,\n\t\t\t// so after this loop oldVNode == null or oldVNode is a valid value.\n\t\t\tfor (j = 0; j < oldChildrenLength; j++) {\n\t\t\t\toldVNode = oldChildren[j];\n\t\t\t\t// If childVNode is unkeyed, we only match similarly unkeyed nodes, otherwise we match by key.\n\t\t\t\t// We always match by type (in either case).\n\t\t\t\tif (\n\t\t\t\t\toldVNode &&\n\t\t\t\t\tchildVNode.key == oldVNode.key &&\n\t\t\t\t\tchildVNode.type === oldVNode.type\n\t\t\t\t) {\n\t\t\t\t\toldChildren[j] = undefined;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\toldVNode = null;\n\t\t\t}\n\t\t}\n\n\t\toldVNode = oldVNode || EMPTY_OBJ;\n\n\t\t// Morph the old element into the new one, but don't append it to the dom yet\n\t\tdiff(\n\t\t\tparentDom,\n\t\t\tchildVNode,\n\t\t\toldVNode,\n\t\t\tglobalContext,\n\t\t\tisSvg,\n\t\t\texcessDomChildren,\n\t\t\tcommitQueue,\n\t\t\toldDom,\n\t\t\tisHydrating\n\t\t);\n\n\t\tnewDom = childVNode._dom;\n\n\t\tif ((j = childVNode.ref) && oldVNode.ref != j) {\n\t\t\tif (!refs) refs = [];\n\t\t\tif (oldVNode.ref) refs.push(oldVNode.ref, null, childVNode);\n\t\t\trefs.push(j, childVNode._component || newDom, childVNode);\n\t\t}\n\n\t\tif (newDom != null) {\n\t\t\tif (firstChildDom == null) {\n\t\t\t\tfirstChildDom = newDom;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\ttypeof childVNode.type == 'function' &&\n\t\t\t\tchildVNode._children === oldVNode._children\n\t\t\t) {\n\t\t\t\tchildVNode._nextDom = oldDom = reorderChildren(\n\t\t\t\t\tchildVNode,\n\t\t\t\t\toldDom,\n\t\t\t\t\tparentDom\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\toldDom = placeChild(\n\t\t\t\t\tparentDom,\n\t\t\t\t\tchildVNode,\n\t\t\t\t\toldVNode,\n\t\t\t\t\toldChildren,\n\t\t\t\t\tnewDom,\n\t\t\t\t\toldDom\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (typeof newParentVNode.type == 'function') {\n\t\t\t\t// Because the newParentVNode is Fragment-like, we need to set it's\n\t\t\t\t// _nextDom property to the nextSibling of its last child DOM node.\n\t\t\t\t//\n\t\t\t\t// `oldDom` contains the correct value here because if the last child\n\t\t\t\t// is a Fragment-like, then oldDom has already been set to that child's _nextDom.\n\t\t\t\t// If the last child is a DOM VNode, then oldDom will be set to that DOM\n\t\t\t\t// node's nextSibling.\n\t\t\t\tnewParentVNode._nextDom = oldDom;\n\t\t\t}\n\t\t} else if (\n\t\t\toldDom &&\n\t\t\toldVNode._dom == oldDom &&\n\t\t\toldDom.parentNode != parentDom\n\t\t) {\n\t\t\t// The above condition is to handle null placeholders. See test in placeholder.test.js:\n\t\t\t// `efficiently replace null placeholders in parent rerenders`\n\t\t\toldDom = getDomSibling(oldVNode);\n\t\t}\n\t}\n\n\tnewParentVNode._dom = firstChildDom;\n\n\t// Remove remaining oldChildren if there are any.\n\tfor (i = oldChildrenLength; i--; ) {\n\t\tif (oldChildren[i] != null) {\n\t\t\tunmount(oldChildren[i], oldChildren[i]);\n\t\t}\n\t}\n\n\t// Set refs only after unmount\n\tif (refs) {\n\t\tfor (i = 0; i < refs.length; i++) {\n\t\t\tapplyRef(refs[i], refs[++i], refs[++i]);\n\t\t}\n\t}\n}\n\nfunction reorderChildren(childVNode, oldDom, parentDom) {\n\t// Note: VNodes in nested suspended trees may be missing _children.\n\tlet c = childVNode._children;\n\tlet tmp = 0;\n\tfor (; c && tmp < c.length; tmp++) {\n\t\tlet vnode = c[tmp];\n\t\tif (vnode) {\n\t\t\t// We typically enter this code path on sCU bailout, where we copy\n\t\t\t// oldVNode._children to newVNode._children. If that is the case, we need\n\t\t\t// to update the old children's _parent pointer to point to the newVNode\n\t\t\t// (childVNode here).\n\t\t\tvnode._parent = childVNode;\n\n\t\t\tif (typeof vnode.type == 'function') {\n\t\t\t\toldDom = reorderChildren(vnode, oldDom, parentDom);\n\t\t\t} else {\n\t\t\t\toldDom = placeChild(parentDom, vnode, vnode, c, vnode._dom, oldDom);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn oldDom;\n}\n\n/**\n * Flatten and loop through the children of a virtual node\n * @param {import('../index').ComponentChildren} children The unflattened\n * children of a virtual node\n * @returns {import('../internal').VNode[]}\n */\nexport function toChildArray(children, out) {\n\tout = out || [];\n\tif (children == null || typeof children == 'boolean') {\n\t} else if (Array.isArray(children)) {\n\t\tchildren.some(child => {\n\t\t\ttoChildArray(child, out);\n\t\t});\n\t} else {\n\t\tout.push(children);\n\t}\n\treturn out;\n}\n\nfunction placeChild(\n\tparentDom,\n\tchildVNode,\n\toldVNode,\n\toldChildren,\n\tnewDom,\n\toldDom\n) {\n\tlet nextDom;\n\tif (childVNode._nextDom !== undefined) {\n\t\t// Only Fragments or components that return Fragment like VNodes will\n\t\t// have a non-undefined _nextDom. Continue the diff from the sibling\n\t\t// of last DOM child of this child VNode\n\t\tnextDom = childVNode._nextDom;\n\n\t\t// Eagerly cleanup _nextDom. We don't need to persist the value because\n\t\t// it is only used by `diffChildren` to determine where to resume the diff after\n\t\t// diffing Components and Fragments. Once we store it the nextDOM local var, we\n\t\t// can clean up the property\n\t\tchildVNode._nextDom = undefined;\n\t} else if (\n\t\toldVNode == null ||\n\t\tnewDom != oldDom ||\n\t\tnewDom.parentNode == null\n\t) {\n\t\touter: if (oldDom == null || oldDom.parentNode !== parentDom) {\n\t\t\tparentDom.appendChild(newDom);\n\t\t\tnextDom = null;\n\t\t} else {\n\t\t\t// `j href (xlink:href was removed from SVG and isn't needed)\n\t\t\t// - className --> class\n\t\t\tname = name.replace(/xlink(H|:h)/, 'h').replace(/sName$/, 's');\n\t\t} else if (\n\t\t\tname !== 'href' &&\n\t\t\tname !== 'list' &&\n\t\t\tname !== 'form' &&\n\t\t\t// Default value in browsers is `-1` and an empty string is\n\t\t\t// cast to `0` instead\n\t\t\tname !== 'tabIndex' &&\n\t\t\tname !== 'download' &&\n\t\t\tname in dom\n\t\t) {\n\t\t\ttry {\n\t\t\t\tdom[name] = value == null ? '' : value;\n\t\t\t\t// labelled break is 1b smaller here than a return statement (sorry)\n\t\t\t\tbreak o;\n\t\t\t} catch (e) {}\n\t\t}\n\n\t\t// ARIA-attributes have a different notion of boolean values.\n\t\t// The value `false` is different from the attribute not\n\t\t// existing on the DOM, so we can't remove it. For non-boolean\n\t\t// ARIA-attributes we could treat false as a removal, but the\n\t\t// amount of exceptions would cost us too many bytes. On top of\n\t\t// that other VDOM frameworks also always stringify `false`.\n\n\t\tif (typeof value === 'function') {\n\t\t\t// never serialize functions as attribute values\n\t\t} else if (value != null && (value !== false || name.indexOf('-') != -1)) {\n\t\t\tdom.setAttribute(name, value);\n\t\t} else {\n\t\t\tdom.removeAttribute(name);\n\t\t}\n\t}\n}\n\n/**\n * Proxy an event to hooked event handlers\n * @param {Event} e The event object from the browser\n * @private\n */\nfunction eventProxy(e) {\n\tthis._listeners[e.type + false](options.event ? options.event(e) : e);\n}\n\nfunction eventProxyCapture(e) {\n\tthis._listeners[e.type + true](options.event ? options.event(e) : e);\n}\n", "import { EMPTY_OBJ } from '../constants';\nimport { Component, getDomSibling } from '../component';\nimport { Fragment } from '../create-element';\nimport { diffChildren } from './children';\nimport { diffProps, setProperty } from './props';\nimport { assign, removeNode, slice } from '../util';\nimport options from '../options';\n\n/**\n * Diff two virtual nodes and apply proper changes to the DOM\n * @param {import('../internal').PreactElement} parentDom The parent of the DOM element\n * @param {import('../internal').VNode} newVNode The new virtual node\n * @param {import('../internal').VNode} oldVNode The old virtual node\n * @param {object} globalContext The current context object. Modified by getChildContext\n * @param {boolean} isSvg Whether or not this element is an SVG node\n * @param {Array} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').PreactElement} oldDom The current attached DOM\n * element any new dom elements should be placed around. Likely `null` on first\n * render (except when hydrating). Can be a sibling DOM element when diffing\n * Fragments that have siblings. In most cases, it starts out as `oldChildren[0]._dom`.\n * @param {boolean} [isHydrating] Whether or not we are in hydration\n */\nexport function diff(\n\tparentDom,\n\tnewVNode,\n\toldVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\toldDom,\n\tisHydrating\n) {\n\tlet tmp,\n\t\tnewType = newVNode.type;\n\n\t// When passing through createElement it assigns the object\n\t// constructor as undefined. This to prevent JSON-injection.\n\tif (newVNode.constructor !== undefined) return null;\n\n\t// If the previous diff bailed out, resume creating/hydrating.\n\tif (oldVNode._hydrating != null) {\n\t\tisHydrating = oldVNode._hydrating;\n\t\toldDom = newVNode._dom = oldVNode._dom;\n\t\t// if we resume, we want the tree to be \"unlocked\"\n\t\tnewVNode._hydrating = null;\n\t\texcessDomChildren = [oldDom];\n\t}\n\n\tif ((tmp = options._diff)) tmp(newVNode);\n\n\ttry {\n\t\touter: if (typeof newType == 'function') {\n\t\t\tlet c, isNew, oldProps, oldState, snapshot, clearProcessingException;\n\t\t\tlet newProps = newVNode.props;\n\n\t\t\t// Necessary for createContext api. Setting this property will pass\n\t\t\t// the context value as `this.context` just for this component.\n\t\t\ttmp = newType.contextType;\n\t\t\tlet provider = tmp && globalContext[tmp._id];\n\t\t\tlet componentContext = tmp\n\t\t\t\t? provider\n\t\t\t\t\t? provider.props.value\n\t\t\t\t\t: tmp._defaultValue\n\t\t\t\t: globalContext;\n\n\t\t\t// Get component and set it to `c`\n\t\t\tif (oldVNode._component) {\n\t\t\t\tc = newVNode._component = oldVNode._component;\n\t\t\t\tclearProcessingException = c._processingException = c._pendingError;\n\t\t\t} else {\n\t\t\t\t// Instantiate the new component\n\t\t\t\tif ('prototype' in newType && newType.prototype.render) {\n\t\t\t\t\t// @ts-ignore The check above verifies that newType is suppose to be constructed\n\t\t\t\t\tnewVNode._component = c = new newType(newProps, componentContext); // eslint-disable-line new-cap\n\t\t\t\t} else {\n\t\t\t\t\t// @ts-ignore Trust me, Component implements the interface we want\n\t\t\t\t\tnewVNode._component = c = new Component(newProps, componentContext);\n\t\t\t\t\tc.constructor = newType;\n\t\t\t\t\tc.render = doRender;\n\t\t\t\t}\n\t\t\t\tif (provider) provider.sub(c);\n\n\t\t\t\tc.props = newProps;\n\t\t\t\tif (!c.state) c.state = {};\n\t\t\t\tc.context = componentContext;\n\t\t\t\tc._globalContext = globalContext;\n\t\t\t\tisNew = c._dirty = true;\n\t\t\t\tc._renderCallbacks = [];\n\t\t\t\tc._stateCallbacks = [];\n\t\t\t}\n\n\t\t\t// Invoke getDerivedStateFromProps\n\t\t\tif (c._nextState == null) {\n\t\t\t\tc._nextState = c.state;\n\t\t\t}\n\n\t\t\tif (newType.getDerivedStateFromProps != null) {\n\t\t\t\tif (c._nextState == c.state) {\n\t\t\t\t\tc._nextState = assign({}, c._nextState);\n\t\t\t\t}\n\n\t\t\t\tassign(\n\t\t\t\t\tc._nextState,\n\t\t\t\t\tnewType.getDerivedStateFromProps(newProps, c._nextState)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\toldProps = c.props;\n\t\t\toldState = c.state;\n\n\t\t\t// Invoke pre-render lifecycle methods\n\t\t\tif (isNew) {\n\t\t\t\tif (\n\t\t\t\t\tnewType.getDerivedStateFromProps == null &&\n\t\t\t\t\tc.componentWillMount != null\n\t\t\t\t) {\n\t\t\t\t\tc.componentWillMount();\n\t\t\t\t}\n\n\t\t\t\tif (c.componentDidMount != null) {\n\t\t\t\t\tc._renderCallbacks.push(c.componentDidMount);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tnewType.getDerivedStateFromProps == null &&\n\t\t\t\t\tnewProps !== oldProps &&\n\t\t\t\t\tc.componentWillReceiveProps != null\n\t\t\t\t) {\n\t\t\t\t\tc.componentWillReceiveProps(newProps, componentContext);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t(!c._force &&\n\t\t\t\t\t\tc.shouldComponentUpdate != null &&\n\t\t\t\t\t\tc.shouldComponentUpdate(\n\t\t\t\t\t\t\tnewProps,\n\t\t\t\t\t\t\tc._nextState,\n\t\t\t\t\t\t\tcomponentContext\n\t\t\t\t\t\t) === false) ||\n\t\t\t\t\tnewVNode._original === oldVNode._original\n\t\t\t\t) {\n\t\t\t\t\tc.props = newProps;\n\t\t\t\t\tc.state = c._nextState;\n\t\t\t\t\t// More info about this here: https://gist.github.com/JoviDeCroock/bec5f2ce93544d2e6070ef8e0036e4e8\n\t\t\t\t\tif (newVNode._original !== oldVNode._original) c._dirty = false;\n\t\t\t\t\tc._vnode = newVNode;\n\t\t\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t\t\t\tnewVNode._children = oldVNode._children;\n\t\t\t\t\tnewVNode._children.forEach(vnode => {\n\t\t\t\t\t\tif (vnode) vnode._parent = newVNode;\n\t\t\t\t\t});\n\n\t\t\t\t\tfor (let i = 0; i < c._stateCallbacks.length; i++) {\n\t\t\t\t\t\tc._renderCallbacks.push(c._stateCallbacks[i]);\n\t\t\t\t\t}\n\t\t\t\t\tc._stateCallbacks = [];\n\n\t\t\t\t\tif (c._renderCallbacks.length) {\n\t\t\t\t\t\tcommitQueue.push(c);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\n\t\t\t\tif (c.componentWillUpdate != null) {\n\t\t\t\t\tc.componentWillUpdate(newProps, c._nextState, componentContext);\n\t\t\t\t}\n\n\t\t\t\tif (c.componentDidUpdate != null) {\n\t\t\t\t\tc._renderCallbacks.push(() => {\n\t\t\t\t\t\tc.componentDidUpdate(oldProps, oldState, snapshot);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tc.context = componentContext;\n\t\t\tc.props = newProps;\n\t\t\tc._vnode = newVNode;\n\t\t\tc._parentDom = parentDom;\n\n\t\t\tlet renderHook = options._render,\n\t\t\t\tcount = 0;\n\t\t\tif ('prototype' in newType && newType.prototype.render) {\n\t\t\t\tc.state = c._nextState;\n\t\t\t\tc._dirty = false;\n\n\t\t\t\tif (renderHook) renderHook(newVNode);\n\n\t\t\t\ttmp = c.render(c.props, c.state, c.context);\n\n\t\t\t\tfor (let i = 0; i < c._stateCallbacks.length; i++) {\n\t\t\t\t\tc._renderCallbacks.push(c._stateCallbacks[i]);\n\t\t\t\t}\n\t\t\t\tc._stateCallbacks = [];\n\t\t\t} else {\n\t\t\t\tdo {\n\t\t\t\t\tc._dirty = false;\n\t\t\t\t\tif (renderHook) renderHook(newVNode);\n\n\t\t\t\t\ttmp = c.render(c.props, c.state, c.context);\n\n\t\t\t\t\t// Handle setState called in render, see #2553\n\t\t\t\t\tc.state = c._nextState;\n\t\t\t\t} while (c._dirty && ++count < 25);\n\t\t\t}\n\n\t\t\t// Handle setState called in render, see #2553\n\t\t\tc.state = c._nextState;\n\n\t\t\tif (c.getChildContext != null) {\n\t\t\t\tglobalContext = assign(assign({}, globalContext), c.getChildContext());\n\t\t\t}\n\n\t\t\tif (!isNew && c.getSnapshotBeforeUpdate != null) {\n\t\t\t\tsnapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);\n\t\t\t}\n\n\t\t\tlet isTopLevelFragment =\n\t\t\t\ttmp != null && tmp.type === Fragment && tmp.key == null;\n\t\t\tlet renderResult = isTopLevelFragment ? tmp.props.children : tmp;\n\n\t\t\tdiffChildren(\n\t\t\t\tparentDom,\n\t\t\t\tArray.isArray(renderResult) ? renderResult : [renderResult],\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg,\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\toldDom,\n\t\t\t\tisHydrating\n\t\t\t);\n\n\t\t\tc.base = newVNode._dom;\n\n\t\t\t// We successfully rendered this VNode, unset any stored hydration/bailout state:\n\t\t\tnewVNode._hydrating = null;\n\n\t\t\tif (c._renderCallbacks.length) {\n\t\t\t\tcommitQueue.push(c);\n\t\t\t}\n\n\t\t\tif (clearProcessingException) {\n\t\t\t\tc._pendingError = c._processingException = null;\n\t\t\t}\n\n\t\t\tc._force = false;\n\t\t} else if (\n\t\t\texcessDomChildren == null &&\n\t\t\tnewVNode._original === oldVNode._original\n\t\t) {\n\t\t\tnewVNode._children = oldVNode._children;\n\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t} else {\n\t\t\tnewVNode._dom = diffElementNodes(\n\t\t\t\toldVNode._dom,\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg,\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\tisHydrating\n\t\t\t);\n\t\t}\n\n\t\tif ((tmp = options.diffed)) tmp(newVNode);\n\t} catch (e) {\n\t\tnewVNode._original = null;\n\t\t// if hydrating or creating initial tree, bailout preserves DOM:\n\t\tif (isHydrating || excessDomChildren != null) {\n\t\t\tnewVNode._dom = oldDom;\n\t\t\tnewVNode._hydrating = !!isHydrating;\n\t\t\texcessDomChildren[excessDomChildren.indexOf(oldDom)] = null;\n\t\t\t// ^ could possibly be simplified to:\n\t\t\t// excessDomChildren.length = 0;\n\t\t}\n\t\toptions._catchError(e, newVNode, oldVNode);\n\t}\n}\n\n/**\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').VNode} root\n */\nexport function commitRoot(commitQueue, root) {\n\tif (options._commit) options._commit(root, commitQueue);\n\n\tcommitQueue.some(c => {\n\t\ttry {\n\t\t\t// @ts-ignore Reuse the commitQueue variable here so the type changes\n\t\t\tcommitQueue = c._renderCallbacks;\n\t\t\tc._renderCallbacks = [];\n\t\t\tcommitQueue.some(cb => {\n\t\t\t\t// @ts-ignore See above ts-ignore on commitQueue\n\t\t\t\tcb.call(c);\n\t\t\t});\n\t\t} catch (e) {\n\t\t\toptions._catchError(e, c._vnode);\n\t\t}\n\t});\n}\n\n/**\n * Diff two virtual nodes representing DOM element\n * @param {import('../internal').PreactElement} dom The DOM element representing\n * the virtual nodes being diffed\n * @param {import('../internal').VNode} newVNode The new virtual node\n * @param {import('../internal').VNode} oldVNode The old virtual node\n * @param {object} globalContext The current context object\n * @param {boolean} isSvg Whether or not this DOM node is an SVG node\n * @param {*} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {boolean} isHydrating Whether or not we are in hydration\n * @returns {import('../internal').PreactElement}\n */\nfunction diffElementNodes(\n\tdom,\n\tnewVNode,\n\toldVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\tisHydrating\n) {\n\tlet oldProps = oldVNode.props;\n\tlet newProps = newVNode.props;\n\tlet nodeType = newVNode.type;\n\tlet i = 0;\n\n\t// Tracks entering and exiting SVG namespace when descending through the tree.\n\tif (nodeType === 'svg') isSvg = true;\n\n\tif (excessDomChildren != null) {\n\t\tfor (; i < excessDomChildren.length; i++) {\n\t\t\tconst child = excessDomChildren[i];\n\n\t\t\t// if newVNode matches an element in excessDomChildren or the `dom`\n\t\t\t// argument matches an element in excessDomChildren, remove it from\n\t\t\t// excessDomChildren so it isn't later removed in diffChildren\n\t\t\tif (\n\t\t\t\tchild &&\n\t\t\t\t'setAttribute' in child === !!nodeType &&\n\t\t\t\t(nodeType ? child.localName === nodeType : child.nodeType === 3)\n\t\t\t) {\n\t\t\t\tdom = child;\n\t\t\t\texcessDomChildren[i] = null;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (dom == null) {\n\t\tif (nodeType === null) {\n\t\t\t// @ts-ignore createTextNode returns Text, we expect PreactElement\n\t\t\treturn document.createTextNode(newProps);\n\t\t}\n\n\t\tif (isSvg) {\n\t\t\tdom = document.createElementNS(\n\t\t\t\t'http://www.w3.org/2000/svg',\n\t\t\t\t// @ts-ignore We know `newVNode.type` is a string\n\t\t\t\tnodeType\n\t\t\t);\n\t\t} else {\n\t\t\tdom = document.createElement(\n\t\t\t\t// @ts-ignore We know `newVNode.type` is a string\n\t\t\t\tnodeType,\n\t\t\t\tnewProps.is && newProps\n\t\t\t);\n\t\t}\n\n\t\t// we created a new parent, so none of the previously attached children can be reused:\n\t\texcessDomChildren = null;\n\t\t// we are creating a new node, so we can assume this is a new subtree (in case we are hydrating), this deopts the hydrate\n\t\tisHydrating = false;\n\t}\n\n\tif (nodeType === null) {\n\t\t// During hydration, we still have to split merged text from SSR'd HTML.\n\t\tif (oldProps !== newProps && (!isHydrating || dom.data !== newProps)) {\n\t\t\tdom.data = newProps;\n\t\t}\n\t} else {\n\t\t// If excessDomChildren was not null, repopulate it with the current element's children:\n\t\texcessDomChildren = excessDomChildren && slice.call(dom.childNodes);\n\n\t\toldProps = oldVNode.props || EMPTY_OBJ;\n\n\t\tlet oldHtml = oldProps.dangerouslySetInnerHTML;\n\t\tlet newHtml = newProps.dangerouslySetInnerHTML;\n\n\t\t// During hydration, props are not diffed at all (including dangerouslySetInnerHTML)\n\t\t// @TODO we should warn in debug mode when props don't match here.\n\t\tif (!isHydrating) {\n\t\t\t// But, if we are in a situation where we are using existing DOM (e.g. replaceNode)\n\t\t\t// we should read the existing DOM attributes to diff them\n\t\t\tif (excessDomChildren != null) {\n\t\t\t\toldProps = {};\n\t\t\t\tfor (i = 0; i < dom.attributes.length; i++) {\n\t\t\t\t\toldProps[dom.attributes[i].name] = dom.attributes[i].value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (newHtml || oldHtml) {\n\t\t\t\t// Avoid re-applying the same '__html' if it did not changed between re-render\n\t\t\t\tif (\n\t\t\t\t\t!newHtml ||\n\t\t\t\t\t((!oldHtml || newHtml.__html != oldHtml.__html) &&\n\t\t\t\t\t\tnewHtml.__html !== dom.innerHTML)\n\t\t\t\t) {\n\t\t\t\t\tdom.innerHTML = (newHtml && newHtml.__html) || '';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdiffProps(dom, newProps, oldProps, isSvg, isHydrating);\n\n\t\t// If the new vnode didn't have dangerouslySetInnerHTML, diff its children\n\t\tif (newHtml) {\n\t\t\tnewVNode._children = [];\n\t\t} else {\n\t\t\ti = newVNode.props.children;\n\t\t\tdiffChildren(\n\t\t\t\tdom,\n\t\t\t\tArray.isArray(i) ? i : [i],\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg && nodeType !== 'foreignObject',\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\texcessDomChildren\n\t\t\t\t\t? excessDomChildren[0]\n\t\t\t\t\t: oldVNode._children && getDomSibling(oldVNode, 0),\n\t\t\t\tisHydrating\n\t\t\t);\n\n\t\t\t// Remove children that are not part of any vnode.\n\t\t\tif (excessDomChildren != null) {\n\t\t\t\tfor (i = excessDomChildren.length; i--; ) {\n\t\t\t\t\tif (excessDomChildren[i] != null) removeNode(excessDomChildren[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// (as above, don't diff props during hydration)\n\t\tif (!isHydrating) {\n\t\t\tif (\n\t\t\t\t'value' in newProps &&\n\t\t\t\t(i = newProps.value) !== undefined &&\n\t\t\t\t// #2756 For the -element the initial value is 0,\n\t\t\t\t// despite the attribute not being present. When the attribute\n\t\t\t\t// is missing the progress bar is treated as indeterminate.\n\t\t\t\t// To fix that we'll always update it when it is 0 for progress elements\n\t\t\t\t(i !== dom.value ||\n\t\t\t\t\t(nodeType === 'progress' && !i) ||\n\t\t\t\t\t// This is only for IE 11 to fix \n\t\tif (\n\t\t\ttype == 'select' &&\n\t\t\tnormalizedProps.multiple &&\n\t\t\tArray.isArray(normalizedProps.value)\n\t\t) {\n\t\t\t// forEach() always returns undefined, which we abuse here to unset the value prop.\n\t\t\tnormalizedProps.value = toChildArray(props.children).forEach(child => {\n\t\t\t\tchild.props.selected =\n\t\t\t\t\tnormalizedProps.value.indexOf(child.props.value) != -1;\n\t\t\t});\n\t\t}\n\n\t\t// Adding support for defaultValue in select tag\n\t\tif (type == 'select' && normalizedProps.defaultValue != null) {\n\t\t\tnormalizedProps.value = toChildArray(props.children).forEach(child => {\n\t\t\t\tif (normalizedProps.multiple) {\n\t\t\t\t\tchild.props.selected =\n\t\t\t\t\t\tnormalizedProps.defaultValue.indexOf(child.props.value) != -1;\n\t\t\t\t} else {\n\t\t\t\t\tchild.props.selected =\n\t\t\t\t\t\tnormalizedProps.defaultValue == child.props.value;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvnode.props = normalizedProps;\n\n\t\tif (props.class != props.className) {\n\t\t\tclassNameDescriptor.enumerable = 'className' in props;\n\t\t\tif (props.className != null) normalizedProps.class = props.className;\n\t\t\tObject.defineProperty(normalizedProps, 'className', classNameDescriptor);\n\t\t}\n\t}\n\n\tvnode.$$typeof = REACT_ELEMENT_TYPE;\n\n\tif (oldVNodeHook) oldVNodeHook(vnode);\n};\n\n// Only needed for react-relay\nlet currentComponent;\nconst oldBeforeRender = options._render;\noptions._render = function(vnode) {\n\tif (oldBeforeRender) {\n\t\toldBeforeRender(vnode);\n\t}\n\tcurrentComponent = vnode._component;\n};\n\n// This is a very very private internal function for React it\n// is used to sort-of do runtime dependency injection. So far\n// only `react-relay` makes use of it. It uses it to read the\n// context value.\nexport const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {\n\tReactCurrentDispatcher: {\n\t\tcurrent: {\n\t\t\treadContext(context) {\n\t\t\t\treturn currentComponent._globalContext[context._id].props.value;\n\t\t\t}\n\t\t}\n\t}\n};\n", "import {\n\tcreateElement,\n\trender as preactRender,\n\tcloneElement as preactCloneElement,\n\tcreateRef,\n\tComponent,\n\tcreateContext,\n\tFragment\n} from 'preact';\nimport {\n\tuseState,\n\tuseId,\n\tuseReducer,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseCallback,\n\tuseContext,\n\tuseDebugValue\n} from 'preact/hooks';\nimport { PureComponent } from './PureComponent';\nimport { memo } from './memo';\nimport { forwardRef } from './forwardRef';\nimport { Children } from './Children';\nimport { Suspense, lazy } from './suspense';\nimport { SuspenseList } from './suspense-list';\nimport { createPortal } from './portals';\nimport { is } from './util';\nimport {\n\thydrate,\n\trender,\n\tREACT_ELEMENT_TYPE,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n} from './render';\n\nconst version = '17.0.2'; // trick libraries to think we are react\n\n/**\n * Legacy version of createElement.\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component constructor\n */\nfunction createFactory(type) {\n\treturn createElement.bind(null, type);\n}\n\n/**\n * Check if the passed element is a valid (p)react node.\n * @param {*} element The element to check\n * @returns {boolean}\n */\nfunction isValidElement(element) {\n\treturn !!element && element.$$typeof === REACT_ELEMENT_TYPE;\n}\n\n/**\n * Wrap `cloneElement` to abort if the passed element is not a valid element and apply\n * all vnode normalizations.\n * @param {import('./internal').VNode} element The vnode to clone\n * @param {object} props Props to add when cloning\n * @param {Array} rest Optional component children\n */\nfunction cloneElement(element) {\n\tif (!isValidElement(element)) return element;\n\treturn preactCloneElement.apply(null, arguments);\n}\n\n/**\n * Remove a component tree from the DOM, including state and event handlers.\n * @param {import('./internal').PreactElement} container\n * @returns {boolean}\n */\nfunction unmountComponentAtNode(container) {\n\tif (container._children) {\n\t\tpreactRender(null, container);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Get the matching DOM node for a component\n * @param {import('./internal').Component} component\n * @returns {import('./internal').PreactElement | null}\n */\nfunction findDOMNode(component) {\n\treturn (\n\t\t(component &&\n\t\t\t(component.base || (component.nodeType === 1 && component))) ||\n\t\tnull\n\t);\n}\n\n/**\n * Deprecated way to control batched rendering inside the reconciler, but we\n * already schedule in batches inside our rendering code\n * @template Arg\n * @param {(arg: Arg) => void} callback function that triggers the updated\n * @param {Arg} [arg] Optional argument that can be passed to the callback\n */\n// eslint-disable-next-line camelcase\nconst unstable_batchedUpdates = (callback, arg) => callback(arg);\n\n/**\n * In React, `flushSync` flushes the entire tree and forces a rerender. It's\n * implmented here as a no-op.\n * @template Arg\n * @template Result\n * @param {(arg: Arg) => Result} callback function that runs before the flush\n * @param {Arg} [arg] Optional arugment that can be passed to the callback\n * @returns\n */\nconst flushSync = (callback, arg) => callback(arg);\n\n/**\n * Strict Mode is not implemented in Preact, so we provide a stand-in for it\n * that just renders its children without imposing any restrictions.\n */\nconst StrictMode = Fragment;\n\nexport function startTransition(cb) {\n\tcb();\n}\n\nexport function useDeferredValue(val) {\n\treturn val;\n}\n\nexport function useTransition() {\n\treturn [false, startTransition];\n}\n\n// TODO: in theory this should be done after a VNode is diffed as we want to insert\n// styles/... before it attaches\nexport const useInsertionEffect = useLayoutEffect;\n\n/**\n * This is taken from https://github.com/facebook/react/blob/main/packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js#L84\n * on a high level this cuts out the warnings, ... and attempts a smaller implementation\n */\nexport function useSyncExternalStore(subscribe, getSnapshot) {\n\tconst value = getSnapshot();\n\n\tconst [{ _instance }, forceUpdate] = useState({\n\t\t_instance: { _value: value, _getSnapshot: getSnapshot }\n\t});\n\n\tuseLayoutEffect(() => {\n\t\t_instance._value = value;\n\t\t_instance._getSnapshot = getSnapshot;\n\n\t\tif (!is(_instance._value, getSnapshot())) {\n\t\t\tforceUpdate({ _instance });\n\t\t}\n\t}, [subscribe, value, getSnapshot]);\n\n\tuseEffect(() => {\n\t\tif (!is(_instance._value, _instance._getSnapshot())) {\n\t\t\tforceUpdate({ _instance });\n\t\t}\n\n\t\treturn subscribe(() => {\n\t\t\tif (!is(_instance._value, _instance._getSnapshot())) {\n\t\t\t\tforceUpdate({ _instance });\n\t\t\t}\n\t\t});\n\t}, [subscribe]);\n\n\treturn value;\n}\n\nexport * from 'preact/hooks';\nexport {\n\tversion,\n\tChildren,\n\trender,\n\thydrate,\n\tunmountComponentAtNode,\n\tcreatePortal,\n\tcreateElement,\n\tcreateContext,\n\tcreateFactory,\n\tcloneElement,\n\tcreateRef,\n\tFragment,\n\tisValidElement,\n\tfindDOMNode,\n\tComponent,\n\tPureComponent,\n\tmemo,\n\tforwardRef,\n\tflushSync,\n\t// eslint-disable-next-line camelcase\n\tunstable_batchedUpdates,\n\tStrictMode,\n\tSuspense,\n\tSuspenseList,\n\tlazy,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n};\n\n// React copies the named exports to the default one.\nexport default {\n\tuseState,\n\tuseId,\n\tuseReducer,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseInsertionEffect,\n\tuseTransition,\n\tuseDeferredValue,\n\tuseSyncExternalStore,\n\tstartTransition,\n\tuseRef,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseCallback,\n\tuseContext,\n\tuseDebugValue,\n\tversion,\n\tChildren,\n\trender,\n\thydrate,\n\tunmountComponentAtNode,\n\tcreatePortal,\n\tcreateElement,\n\tcreateContext,\n\tcreateFactory,\n\tcloneElement,\n\tcreateRef,\n\tFragment,\n\tisValidElement,\n\tfindDOMNode,\n\tComponent,\n\tPureComponent,\n\tmemo,\n\tforwardRef,\n\tflushSync,\n\tunstable_batchedUpdates,\n\tStrictMode,\n\tSuspense,\n\tSuspenseList,\n\tlazy,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n};\n", "/**\n * @license React\n * use-sync-external-store-shim.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var e=require(\"react\");function h(a,b){return a===b&&(0!==a||1/a===1/b)||a!==a&&b!==b}var k=\"function\"===typeof Object.is?Object.is:h,l=e.useState,m=e.useEffect,n=e.useLayoutEffect,p=e.useDebugValue;function q(a,b){var d=b(),f=l({inst:{value:d,getSnapshot:b}}),c=f[0].inst,g=f[1];n(function(){c.value=d;c.getSnapshot=b;r(c)&&g({inst:c})},[a,d,b]);m(function(){r(c)&&g({inst:c});return a(function(){r(c)&&g({inst:c})})},[a]);p(d);return d}\nfunction r(a){var b=a.getSnapshot;a=a.value;try{var d=b();return!k(a,d)}catch(f){return!0}}function t(a,b){return b()}var u=\"undefined\"===typeof window||\"undefined\"===typeof window.document||\"undefined\"===typeof window.document.createElement?t:q;exports.useSyncExternalStore=void 0!==e.useSyncExternalStore?e.useSyncExternalStore:u;\n", "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('../cjs/use-sync-external-store-shim.production.min.js');\n} else {\n module.exports = require('../cjs/use-sync-external-store-shim.development.js');\n}\n", "//---------------------------------------------------------------------\n//\n// QR Code Generator for JavaScript\n//\n// Copyright (c) 2009 Kazuhiko Arase\n//\n// URL: http://www.d-project.com/\n//\n// Licensed under the MIT license:\n// http://www.opensource.org/licenses/mit-license.php\n//\n// The word 'QR Code' is registered trademark of\n// DENSO WAVE INCORPORATED\n// http://www.denso-wave.com/qrcode/faqpatent-e.html\n//\n//---------------------------------------------------------------------\n\nvar qrcode = function() {\n\n //---------------------------------------------------------------------\n // qrcode\n //---------------------------------------------------------------------\n\n /**\n * qrcode\n * @param typeNumber 1 to 40\n * @param errorCorrectionLevel 'L','M','Q','H'\n */\n var qrcode = function(typeNumber, errorCorrectionLevel) {\n\n var PAD0 = 0xEC;\n var PAD1 = 0x11;\n\n var _typeNumber = typeNumber;\n var _errorCorrectionLevel = QRErrorCorrectionLevel[errorCorrectionLevel];\n var _modules = null;\n var _moduleCount = 0;\n var _dataCache = null;\n var _dataList = [];\n\n var _this = {};\n\n var makeImpl = function(test, maskPattern) {\n\n _moduleCount = _typeNumber * 4 + 17;\n _modules = function(moduleCount) {\n var modules = new Array(moduleCount);\n for (var row = 0; row < moduleCount; row += 1) {\n modules[row] = new Array(moduleCount);\n for (var col = 0; col < moduleCount; col += 1) {\n modules[row][col] = null;\n }\n }\n return modules;\n }(_moduleCount);\n\n setupPositionProbePattern(0, 0);\n setupPositionProbePattern(_moduleCount - 7, 0);\n setupPositionProbePattern(0, _moduleCount - 7);\n setupPositionAdjustPattern();\n setupTimingPattern();\n setupTypeInfo(test, maskPattern);\n\n if (_typeNumber >= 7) {\n setupTypeNumber(test);\n }\n\n if (_dataCache == null) {\n _dataCache = createData(_typeNumber, _errorCorrectionLevel, _dataList);\n }\n\n mapData(_dataCache, maskPattern);\n };\n\n var setupPositionProbePattern = function(row, col) {\n\n for (var r = -1; r <= 7; r += 1) {\n\n if (row + r <= -1 || _moduleCount <= row + r) continue;\n\n for (var c = -1; c <= 7; c += 1) {\n\n if (col + c <= -1 || _moduleCount <= col + c) continue;\n\n if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )\n || (0 <= c && c <= 6 && (r == 0 || r == 6) )\n || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {\n _modules[row + r][col + c] = true;\n } else {\n _modules[row + r][col + c] = false;\n }\n }\n }\n };\n\n var getBestMaskPattern = function() {\n\n var minLostPoint = 0;\n var pattern = 0;\n\n for (var i = 0; i < 8; i += 1) {\n\n makeImpl(true, i);\n\n var lostPoint = QRUtil.getLostPoint(_this);\n\n if (i == 0 || minLostPoint > lostPoint) {\n minLostPoint = lostPoint;\n pattern = i;\n }\n }\n\n return pattern;\n };\n\n var setupTimingPattern = function() {\n\n for (var r = 8; r < _moduleCount - 8; r += 1) {\n if (_modules[r][6] != null) {\n continue;\n }\n _modules[r][6] = (r % 2 == 0);\n }\n\n for (var c = 8; c < _moduleCount - 8; c += 1) {\n if (_modules[6][c] != null) {\n continue;\n }\n _modules[6][c] = (c % 2 == 0);\n }\n };\n\n var setupPositionAdjustPattern = function() {\n\n var pos = QRUtil.getPatternPosition(_typeNumber);\n\n for (var i = 0; i < pos.length; i += 1) {\n\n for (var j = 0; j < pos.length; j += 1) {\n\n var row = pos[i];\n var col = pos[j];\n\n if (_modules[row][col] != null) {\n continue;\n }\n\n for (var r = -2; r <= 2; r += 1) {\n\n for (var c = -2; c <= 2; c += 1) {\n\n if (r == -2 || r == 2 || c == -2 || c == 2\n || (r == 0 && c == 0) ) {\n _modules[row + r][col + c] = true;\n } else {\n _modules[row + r][col + c] = false;\n }\n }\n }\n }\n }\n };\n\n var setupTypeNumber = function(test) {\n\n var bits = QRUtil.getBCHTypeNumber(_typeNumber);\n\n for (var i = 0; i < 18; i += 1) {\n var mod = (!test && ( (bits >> i) & 1) == 1);\n _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;\n }\n\n for (var i = 0; i < 18; i += 1) {\n var mod = (!test && ( (bits >> i) & 1) == 1);\n _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n }\n };\n\n var setupTypeInfo = function(test, maskPattern) {\n\n var data = (_errorCorrectionLevel << 3) | maskPattern;\n var bits = QRUtil.getBCHTypeInfo(data);\n\n // vertical\n for (var i = 0; i < 15; i += 1) {\n\n var mod = (!test && ( (bits >> i) & 1) == 1);\n\n if (i < 6) {\n _modules[i][8] = mod;\n } else if (i < 8) {\n _modules[i + 1][8] = mod;\n } else {\n _modules[_moduleCount - 15 + i][8] = mod;\n }\n }\n\n // horizontal\n for (var i = 0; i < 15; i += 1) {\n\n var mod = (!test && ( (bits >> i) & 1) == 1);\n\n if (i < 8) {\n _modules[8][_moduleCount - i - 1] = mod;\n } else if (i < 9) {\n _modules[8][15 - i - 1 + 1] = mod;\n } else {\n _modules[8][15 - i - 1] = mod;\n }\n }\n\n // fixed module\n _modules[_moduleCount - 8][8] = (!test);\n };\n\n var mapData = function(data, maskPattern) {\n\n var inc = -1;\n var row = _moduleCount - 1;\n var bitIndex = 7;\n var byteIndex = 0;\n var maskFunc = QRUtil.getMaskFunction(maskPattern);\n\n for (var col = _moduleCount - 1; col > 0; col -= 2) {\n\n if (col == 6) col -= 1;\n\n while (true) {\n\n for (var c = 0; c < 2; c += 1) {\n\n if (_modules[row][col - c] == null) {\n\n var dark = false;\n\n if (byteIndex < data.length) {\n dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);\n }\n\n var mask = maskFunc(row, col - c);\n\n if (mask) {\n dark = !dark;\n }\n\n _modules[row][col - c] = dark;\n bitIndex -= 1;\n\n if (bitIndex == -1) {\n byteIndex += 1;\n bitIndex = 7;\n }\n }\n }\n\n row += inc;\n\n if (row < 0 || _moduleCount <= row) {\n row -= inc;\n inc = -inc;\n break;\n }\n }\n }\n };\n\n var createBytes = function(buffer, rsBlocks) {\n\n var offset = 0;\n\n var maxDcCount = 0;\n var maxEcCount = 0;\n\n var dcdata = new Array(rsBlocks.length);\n var ecdata = new Array(rsBlocks.length);\n\n for (var r = 0; r < rsBlocks.length; r += 1) {\n\n var dcCount = rsBlocks[r].dataCount;\n var ecCount = rsBlocks[r].totalCount - dcCount;\n\n maxDcCount = Math.max(maxDcCount, dcCount);\n maxEcCount = Math.max(maxEcCount, ecCount);\n\n dcdata[r] = new Array(dcCount);\n\n for (var i = 0; i < dcdata[r].length; i += 1) {\n dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];\n }\n offset += dcCount;\n\n var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);\n\n var modPoly = rawPoly.mod(rsPoly);\n ecdata[r] = new Array(rsPoly.getLength() - 1);\n for (var i = 0; i < ecdata[r].length; i += 1) {\n var modIndex = i + modPoly.getLength() - ecdata[r].length;\n ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;\n }\n }\n\n var totalCodeCount = 0;\n for (var i = 0; i < rsBlocks.length; i += 1) {\n totalCodeCount += rsBlocks[i].totalCount;\n }\n\n var data = new Array(totalCodeCount);\n var index = 0;\n\n for (var i = 0; i < maxDcCount; i += 1) {\n for (var r = 0; r < rsBlocks.length; r += 1) {\n if (i < dcdata[r].length) {\n data[index] = dcdata[r][i];\n index += 1;\n }\n }\n }\n\n for (var i = 0; i < maxEcCount; i += 1) {\n for (var r = 0; r < rsBlocks.length; r += 1) {\n if (i < ecdata[r].length) {\n data[index] = ecdata[r][i];\n index += 1;\n }\n }\n }\n\n return data;\n };\n\n var createData = function(typeNumber, errorCorrectionLevel, dataList) {\n\n var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectionLevel);\n\n var buffer = qrBitBuffer();\n\n for (var i = 0; i < dataList.length; i += 1) {\n var data = dataList[i];\n buffer.put(data.getMode(), 4);\n buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );\n data.write(buffer);\n }\n\n // calc num max data.\n var totalDataCount = 0;\n for (var i = 0; i < rsBlocks.length; i += 1) {\n totalDataCount += rsBlocks[i].dataCount;\n }\n\n if (buffer.getLengthInBits() > totalDataCount * 8) {\n throw 'code length overflow. ('\n + buffer.getLengthInBits()\n + '>'\n + totalDataCount * 8\n + ')';\n }\n\n // end code\n if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {\n buffer.put(0, 4);\n }\n\n // padding\n while (buffer.getLengthInBits() % 8 != 0) {\n buffer.putBit(false);\n }\n\n // padding\n while (true) {\n\n if (buffer.getLengthInBits() >= totalDataCount * 8) {\n break;\n }\n buffer.put(PAD0, 8);\n\n if (buffer.getLengthInBits() >= totalDataCount * 8) {\n break;\n }\n buffer.put(PAD1, 8);\n }\n\n return createBytes(buffer, rsBlocks);\n };\n\n _this.addData = function(data, mode) {\n\n mode = mode || 'Byte';\n\n var newData = null;\n\n switch(mode) {\n case 'Numeric' :\n newData = qrNumber(data);\n break;\n case 'Alphanumeric' :\n newData = qrAlphaNum(data);\n break;\n case 'Byte' :\n newData = qr8BitByte(data);\n break;\n case 'Kanji' :\n newData = qrKanji(data);\n break;\n default :\n throw 'mode:' + mode;\n }\n\n _dataList.push(newData);\n _dataCache = null;\n };\n\n _this.isDark = function(row, col) {\n if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {\n throw row + ',' + col;\n }\n return _modules[row][col];\n };\n\n _this.getModuleCount = function() {\n return _moduleCount;\n };\n\n _this.make = function() {\n if (_typeNumber < 1) {\n var typeNumber = 1;\n\n for (; typeNumber < 40; typeNumber++) {\n var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, _errorCorrectionLevel);\n var buffer = qrBitBuffer();\n\n for (var i = 0; i < _dataList.length; i++) {\n var data = _dataList[i];\n buffer.put(data.getMode(), 4);\n buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );\n data.write(buffer);\n }\n\n var totalDataCount = 0;\n for (var i = 0; i < rsBlocks.length; i++) {\n totalDataCount += rsBlocks[i].dataCount;\n }\n\n if (buffer.getLengthInBits() <= totalDataCount * 8) {\n break;\n }\n }\n\n _typeNumber = typeNumber;\n }\n\n makeImpl(false, getBestMaskPattern() );\n };\n\n _this.createTableTag = function(cellSize, margin) {\n\n cellSize = cellSize || 2;\n margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n var qrHtml = '';\n\n qrHtml += '' +\n escapeXml(title.text) + '' : '';\n qrSvg += (alt.text) ? '' +\n escapeXml(alt.text) + '' : '';\n qrSvg += '';\n qrSvg += '': escaped += '>'; break;\n case '&': escaped += '&'; break;\n case '\"': escaped += '"'; break;\n default : escaped += c; break;\n }\n }\n return escaped;\n };\n\n var _createHalfASCII = function(margin) {\n var cellSize = 1;\n margin = (typeof margin == 'undefined')? cellSize * 2 : margin;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n var min = margin;\n var max = size - margin;\n\n var y, x, r1, r2, p;\n\n var blocks = {\n '\u2588\u2588': '\u2588',\n '\u2588 ': '\u2580',\n ' \u2588': '\u2584',\n ' ': ' '\n };\n\n var blocksLastLineNoMargin = {\n '\u2588\u2588': '\u2580',\n '\u2588 ': '\u2580',\n ' \u2588': ' ',\n ' ': ' '\n };\n\n var ascii = '';\n for (y = 0; y < size; y += 2) {\n r1 = Math.floor((y - min) / cellSize);\n r2 = Math.floor((y + 1 - min) / cellSize);\n for (x = 0; x < size; x += 1) {\n p = '\u2588';\n\n if (min <= x && x < max && min <= y && y < max && _this.isDark(r1, Math.floor((x - min) / cellSize))) {\n p = ' ';\n }\n\n if (min <= x && x < max && min <= y+1 && y+1 < max && _this.isDark(r2, Math.floor((x - min) / cellSize))) {\n p += ' ';\n }\n else {\n p += '\u2588';\n }\n\n // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.\n ascii += (margin < 1 && y+1 >= max) ? blocksLastLineNoMargin[p] : blocks[p];\n }\n\n ascii += '\\n';\n }\n\n if (size % 2 && margin > 0) {\n return ascii.substring(0, ascii.length - size - 1) + Array(size+1).join('\u2580');\n }\n\n return ascii.substring(0, ascii.length-1);\n };\n\n _this.createASCII = function(cellSize, margin) {\n cellSize = cellSize || 1;\n\n if (cellSize < 2) {\n return _createHalfASCII(margin);\n }\n\n cellSize -= 1;\n margin = (typeof margin == 'undefined')? cellSize * 2 : margin;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n var min = margin;\n var max = size - margin;\n\n var y, x, r, p;\n\n var white = Array(cellSize+1).join('\u2588\u2588');\n var black = Array(cellSize+1).join(' ');\n\n var ascii = '';\n var line = '';\n for (y = 0; y < size; y += 1) {\n r = Math.floor( (y - min) / cellSize);\n line = '';\n for (x = 0; x < size; x += 1) {\n p = 1;\n\n if (min <= x && x < max && min <= y && y < max && _this.isDark(r, Math.floor((x - min) / cellSize))) {\n p = 0;\n }\n\n // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.\n line += p ? white : black;\n }\n\n for (r = 0; r < cellSize; r += 1) {\n ascii += line + '\\n';\n }\n }\n\n return ascii.substring(0, ascii.length-1);\n };\n\n _this.renderTo2dContext = function(context, cellSize) {\n cellSize = cellSize || 2;\n var length = _this.getModuleCount();\n for (var row = 0; row < length; row++) {\n for (var col = 0; col < length; col++) {\n context.fillStyle = _this.isDark(row, col) ? 'black' : 'white';\n context.fillRect(row * cellSize, col * cellSize, cellSize, cellSize);\n }\n }\n }\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrcode.stringToBytes\n //---------------------------------------------------------------------\n\n qrcode.stringToBytesFuncs = {\n 'default' : function(s) {\n var bytes = [];\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charCodeAt(i);\n bytes.push(c & 0xff);\n }\n return bytes;\n }\n };\n\n qrcode.stringToBytes = qrcode.stringToBytesFuncs['default'];\n\n //---------------------------------------------------------------------\n // qrcode.createStringToBytes\n //---------------------------------------------------------------------\n\n /**\n * @param unicodeData base64 string of byte array.\n * [16bit Unicode],[16bit Bytes], ...\n * @param numChars\n */\n qrcode.createStringToBytes = function(unicodeData, numChars) {\n\n // create conversion map.\n\n var unicodeMap = function() {\n\n var bin = base64DecodeInputStream(unicodeData);\n var read = function() {\n var b = bin.read();\n if (b == -1) throw 'eof';\n return b;\n };\n\n var count = 0;\n var unicodeMap = {};\n while (true) {\n var b0 = bin.read();\n if (b0 == -1) break;\n var b1 = read();\n var b2 = read();\n var b3 = read();\n var k = String.fromCharCode( (b0 << 8) | b1);\n var v = (b2 << 8) | b3;\n unicodeMap[k] = v;\n count += 1;\n }\n if (count != numChars) {\n throw count + ' != ' + numChars;\n }\n\n return unicodeMap;\n }();\n\n var unknownChar = '?'.charCodeAt(0);\n\n return function(s) {\n var bytes = [];\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charCodeAt(i);\n if (c < 128) {\n bytes.push(c);\n } else {\n var b = unicodeMap[s.charAt(i)];\n if (typeof b == 'number') {\n if ( (b & 0xff) == b) {\n // 1byte\n bytes.push(b);\n } else {\n // 2bytes\n bytes.push(b >>> 8);\n bytes.push(b & 0xff);\n }\n } else {\n bytes.push(unknownChar);\n }\n }\n }\n return bytes;\n };\n };\n\n //---------------------------------------------------------------------\n // QRMode\n //---------------------------------------------------------------------\n\n var QRMode = {\n MODE_NUMBER : 1 << 0,\n MODE_ALPHA_NUM : 1 << 1,\n MODE_8BIT_BYTE : 1 << 2,\n MODE_KANJI : 1 << 3\n };\n\n //---------------------------------------------------------------------\n // QRErrorCorrectionLevel\n //---------------------------------------------------------------------\n\n var QRErrorCorrectionLevel = {\n L : 1,\n M : 0,\n Q : 3,\n H : 2\n };\n\n //---------------------------------------------------------------------\n // QRMaskPattern\n //---------------------------------------------------------------------\n\n var QRMaskPattern = {\n PATTERN000 : 0,\n PATTERN001 : 1,\n PATTERN010 : 2,\n PATTERN011 : 3,\n PATTERN100 : 4,\n PATTERN101 : 5,\n PATTERN110 : 6,\n PATTERN111 : 7\n };\n\n //---------------------------------------------------------------------\n // QRUtil\n //---------------------------------------------------------------------\n\n var QRUtil = function() {\n\n var PATTERN_POSITION_TABLE = [\n [],\n [6, 18],\n [6, 22],\n [6, 26],\n [6, 30],\n [6, 34],\n [6, 22, 38],\n [6, 24, 42],\n [6, 26, 46],\n [6, 28, 50],\n [6, 30, 54],\n [6, 32, 58],\n [6, 34, 62],\n [6, 26, 46, 66],\n [6, 26, 48, 70],\n [6, 26, 50, 74],\n [6, 30, 54, 78],\n [6, 30, 56, 82],\n [6, 30, 58, 86],\n [6, 34, 62, 90],\n [6, 28, 50, 72, 94],\n [6, 26, 50, 74, 98],\n [6, 30, 54, 78, 102],\n [6, 28, 54, 80, 106],\n [6, 32, 58, 84, 110],\n [6, 30, 58, 86, 114],\n [6, 34, 62, 90, 118],\n [6, 26, 50, 74, 98, 122],\n [6, 30, 54, 78, 102, 126],\n [6, 26, 52, 78, 104, 130],\n [6, 30, 56, 82, 108, 134],\n [6, 34, 60, 86, 112, 138],\n [6, 30, 58, 86, 114, 142],\n [6, 34, 62, 90, 118, 146],\n [6, 30, 54, 78, 102, 126, 150],\n [6, 24, 50, 76, 102, 128, 154],\n [6, 28, 54, 80, 106, 132, 158],\n [6, 32, 58, 84, 110, 136, 162],\n [6, 26, 54, 82, 110, 138, 166],\n [6, 30, 58, 86, 114, 142, 170]\n ];\n var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);\n var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);\n var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);\n\n var _this = {};\n\n var getBCHDigit = function(data) {\n var digit = 0;\n while (data != 0) {\n digit += 1;\n data >>>= 1;\n }\n return digit;\n };\n\n _this.getBCHTypeInfo = function(data) {\n var d = data << 10;\n while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {\n d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );\n }\n return ( (data << 10) | d) ^ G15_MASK;\n };\n\n _this.getBCHTypeNumber = function(data) {\n var d = data << 12;\n while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {\n d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );\n }\n return (data << 12) | d;\n };\n\n _this.getPatternPosition = function(typeNumber) {\n return PATTERN_POSITION_TABLE[typeNumber - 1];\n };\n\n _this.getMaskFunction = function(maskPattern) {\n\n switch (maskPattern) {\n\n case QRMaskPattern.PATTERN000 :\n return function(i, j) { return (i + j) % 2 == 0; };\n case QRMaskPattern.PATTERN001 :\n return function(i, j) { return i % 2 == 0; };\n case QRMaskPattern.PATTERN010 :\n return function(i, j) { return j % 3 == 0; };\n case QRMaskPattern.PATTERN011 :\n return function(i, j) { return (i + j) % 3 == 0; };\n case QRMaskPattern.PATTERN100 :\n return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };\n case QRMaskPattern.PATTERN101 :\n return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };\n case QRMaskPattern.PATTERN110 :\n return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };\n case QRMaskPattern.PATTERN111 :\n return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };\n\n default :\n throw 'bad maskPattern:' + maskPattern;\n }\n };\n\n _this.getErrorCorrectPolynomial = function(errorCorrectLength) {\n var a = qrPolynomial([1], 0);\n for (var i = 0; i < errorCorrectLength; i += 1) {\n a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );\n }\n return a;\n };\n\n _this.getLengthInBits = function(mode, type) {\n\n if (1 <= type && type < 10) {\n\n // 1 - 9\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 10;\n case QRMode.MODE_ALPHA_NUM : return 9;\n case QRMode.MODE_8BIT_BYTE : return 8;\n case QRMode.MODE_KANJI : return 8;\n default :\n throw 'mode:' + mode;\n }\n\n } else if (type < 27) {\n\n // 10 - 26\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 12;\n case QRMode.MODE_ALPHA_NUM : return 11;\n case QRMode.MODE_8BIT_BYTE : return 16;\n case QRMode.MODE_KANJI : return 10;\n default :\n throw 'mode:' + mode;\n }\n\n } else if (type < 41) {\n\n // 27 - 40\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 14;\n case QRMode.MODE_ALPHA_NUM : return 13;\n case QRMode.MODE_8BIT_BYTE : return 16;\n case QRMode.MODE_KANJI : return 12;\n default :\n throw 'mode:' + mode;\n }\n\n } else {\n throw 'type:' + type;\n }\n };\n\n _this.getLostPoint = function(qrcode) {\n\n var moduleCount = qrcode.getModuleCount();\n\n var lostPoint = 0;\n\n // LEVEL1\n\n for (var row = 0; row < moduleCount; row += 1) {\n for (var col = 0; col < moduleCount; col += 1) {\n\n var sameCount = 0;\n var dark = qrcode.isDark(row, col);\n\n for (var r = -1; r <= 1; r += 1) {\n\n if (row + r < 0 || moduleCount <= row + r) {\n continue;\n }\n\n for (var c = -1; c <= 1; c += 1) {\n\n if (col + c < 0 || moduleCount <= col + c) {\n continue;\n }\n\n if (r == 0 && c == 0) {\n continue;\n }\n\n if (dark == qrcode.isDark(row + r, col + c) ) {\n sameCount += 1;\n }\n }\n }\n\n if (sameCount > 5) {\n lostPoint += (3 + sameCount - 5);\n }\n }\n };\n\n // LEVEL2\n\n for (var row = 0; row < moduleCount - 1; row += 1) {\n for (var col = 0; col < moduleCount - 1; col += 1) {\n var count = 0;\n if (qrcode.isDark(row, col) ) count += 1;\n if (qrcode.isDark(row + 1, col) ) count += 1;\n if (qrcode.isDark(row, col + 1) ) count += 1;\n if (qrcode.isDark(row + 1, col + 1) ) count += 1;\n if (count == 0 || count == 4) {\n lostPoint += 3;\n }\n }\n }\n\n // LEVEL3\n\n for (var row = 0; row < moduleCount; row += 1) {\n for (var col = 0; col < moduleCount - 6; col += 1) {\n if (qrcode.isDark(row, col)\n && !qrcode.isDark(row, col + 1)\n && qrcode.isDark(row, col + 2)\n && qrcode.isDark(row, col + 3)\n && qrcode.isDark(row, col + 4)\n && !qrcode.isDark(row, col + 5)\n && qrcode.isDark(row, col + 6) ) {\n lostPoint += 40;\n }\n }\n }\n\n for (var col = 0; col < moduleCount; col += 1) {\n for (var row = 0; row < moduleCount - 6; row += 1) {\n if (qrcode.isDark(row, col)\n && !qrcode.isDark(row + 1, col)\n && qrcode.isDark(row + 2, col)\n && qrcode.isDark(row + 3, col)\n && qrcode.isDark(row + 4, col)\n && !qrcode.isDark(row + 5, col)\n && qrcode.isDark(row + 6, col) ) {\n lostPoint += 40;\n }\n }\n }\n\n // LEVEL4\n\n var darkCount = 0;\n\n for (var col = 0; col < moduleCount; col += 1) {\n for (var row = 0; row < moduleCount; row += 1) {\n if (qrcode.isDark(row, col) ) {\n darkCount += 1;\n }\n }\n }\n\n var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n lostPoint += ratio * 10;\n\n return lostPoint;\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // QRMath\n //---------------------------------------------------------------------\n\n var QRMath = function() {\n\n var EXP_TABLE = new Array(256);\n var LOG_TABLE = new Array(256);\n\n // initialize tables\n for (var i = 0; i < 8; i += 1) {\n EXP_TABLE[i] = 1 << i;\n }\n for (var i = 8; i < 256; i += 1) {\n EXP_TABLE[i] = EXP_TABLE[i - 4]\n ^ EXP_TABLE[i - 5]\n ^ EXP_TABLE[i - 6]\n ^ EXP_TABLE[i - 8];\n }\n for (var i = 0; i < 255; i += 1) {\n LOG_TABLE[EXP_TABLE[i] ] = i;\n }\n\n var _this = {};\n\n _this.glog = function(n) {\n\n if (n < 1) {\n throw 'glog(' + n + ')';\n }\n\n return LOG_TABLE[n];\n };\n\n _this.gexp = function(n) {\n\n while (n < 0) {\n n += 255;\n }\n\n while (n >= 256) {\n n -= 255;\n }\n\n return EXP_TABLE[n];\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // qrPolynomial\n //---------------------------------------------------------------------\n\n function qrPolynomial(num, shift) {\n\n if (typeof num.length == 'undefined') {\n throw num.length + '/' + shift;\n }\n\n var _num = function() {\n var offset = 0;\n while (offset < num.length && num[offset] == 0) {\n offset += 1;\n }\n var _num = new Array(num.length - offset + shift);\n for (var i = 0; i < num.length - offset; i += 1) {\n _num[i] = num[i + offset];\n }\n return _num;\n }();\n\n var _this = {};\n\n _this.getAt = function(index) {\n return _num[index];\n };\n\n _this.getLength = function() {\n return _num.length;\n };\n\n _this.multiply = function(e) {\n\n var num = new Array(_this.getLength() + e.getLength() - 1);\n\n for (var i = 0; i < _this.getLength(); i += 1) {\n for (var j = 0; j < e.getLength(); j += 1) {\n num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );\n }\n }\n\n return qrPolynomial(num, 0);\n };\n\n _this.mod = function(e) {\n\n if (_this.getLength() - e.getLength() < 0) {\n return _this;\n }\n\n var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );\n\n var num = new Array(_this.getLength() );\n for (var i = 0; i < _this.getLength(); i += 1) {\n num[i] = _this.getAt(i);\n }\n\n for (var i = 0; i < e.getLength(); i += 1) {\n num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);\n }\n\n // recursive call\n return qrPolynomial(num, 0).mod(e);\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // QRRSBlock\n //---------------------------------------------------------------------\n\n var QRRSBlock = function() {\n\n var RS_BLOCK_TABLE = [\n\n // L\n // M\n // Q\n // H\n\n // 1\n [1, 26, 19],\n [1, 26, 16],\n [1, 26, 13],\n [1, 26, 9],\n\n // 2\n [1, 44, 34],\n [1, 44, 28],\n [1, 44, 22],\n [1, 44, 16],\n\n // 3\n [1, 70, 55],\n [1, 70, 44],\n [2, 35, 17],\n [2, 35, 13],\n\n // 4\n [1, 100, 80],\n [2, 50, 32],\n [2, 50, 24],\n [4, 25, 9],\n\n // 5\n [1, 134, 108],\n [2, 67, 43],\n [2, 33, 15, 2, 34, 16],\n [2, 33, 11, 2, 34, 12],\n\n // 6\n [2, 86, 68],\n [4, 43, 27],\n [4, 43, 19],\n [4, 43, 15],\n\n // 7\n [2, 98, 78],\n [4, 49, 31],\n [2, 32, 14, 4, 33, 15],\n [4, 39, 13, 1, 40, 14],\n\n // 8\n [2, 121, 97],\n [2, 60, 38, 2, 61, 39],\n [4, 40, 18, 2, 41, 19],\n [4, 40, 14, 2, 41, 15],\n\n // 9\n [2, 146, 116],\n [3, 58, 36, 2, 59, 37],\n [4, 36, 16, 4, 37, 17],\n [4, 36, 12, 4, 37, 13],\n\n // 10\n [2, 86, 68, 2, 87, 69],\n [4, 69, 43, 1, 70, 44],\n [6, 43, 19, 2, 44, 20],\n [6, 43, 15, 2, 44, 16],\n\n // 11\n [4, 101, 81],\n [1, 80, 50, 4, 81, 51],\n [4, 50, 22, 4, 51, 23],\n [3, 36, 12, 8, 37, 13],\n\n // 12\n [2, 116, 92, 2, 117, 93],\n [6, 58, 36, 2, 59, 37],\n [4, 46, 20, 6, 47, 21],\n [7, 42, 14, 4, 43, 15],\n\n // 13\n [4, 133, 107],\n [8, 59, 37, 1, 60, 38],\n [8, 44, 20, 4, 45, 21],\n [12, 33, 11, 4, 34, 12],\n\n // 14\n [3, 145, 115, 1, 146, 116],\n [4, 64, 40, 5, 65, 41],\n [11, 36, 16, 5, 37, 17],\n [11, 36, 12, 5, 37, 13],\n\n // 15\n [5, 109, 87, 1, 110, 88],\n [5, 65, 41, 5, 66, 42],\n [5, 54, 24, 7, 55, 25],\n [11, 36, 12, 7, 37, 13],\n\n // 16\n [5, 122, 98, 1, 123, 99],\n [7, 73, 45, 3, 74, 46],\n [15, 43, 19, 2, 44, 20],\n [3, 45, 15, 13, 46, 16],\n\n // 17\n [1, 135, 107, 5, 136, 108],\n [10, 74, 46, 1, 75, 47],\n [1, 50, 22, 15, 51, 23],\n [2, 42, 14, 17, 43, 15],\n\n // 18\n [5, 150, 120, 1, 151, 121],\n [9, 69, 43, 4, 70, 44],\n [17, 50, 22, 1, 51, 23],\n [2, 42, 14, 19, 43, 15],\n\n // 19\n [3, 141, 113, 4, 142, 114],\n [3, 70, 44, 11, 71, 45],\n [17, 47, 21, 4, 48, 22],\n [9, 39, 13, 16, 40, 14],\n\n // 20\n [3, 135, 107, 5, 136, 108],\n [3, 67, 41, 13, 68, 42],\n [15, 54, 24, 5, 55, 25],\n [15, 43, 15, 10, 44, 16],\n\n // 21\n [4, 144, 116, 4, 145, 117],\n [17, 68, 42],\n [17, 50, 22, 6, 51, 23],\n [19, 46, 16, 6, 47, 17],\n\n // 22\n [2, 139, 111, 7, 140, 112],\n [17, 74, 46],\n [7, 54, 24, 16, 55, 25],\n [34, 37, 13],\n\n // 23\n [4, 151, 121, 5, 152, 122],\n [4, 75, 47, 14, 76, 48],\n [11, 54, 24, 14, 55, 25],\n [16, 45, 15, 14, 46, 16],\n\n // 24\n [6, 147, 117, 4, 148, 118],\n [6, 73, 45, 14, 74, 46],\n [11, 54, 24, 16, 55, 25],\n [30, 46, 16, 2, 47, 17],\n\n // 25\n [8, 132, 106, 4, 133, 107],\n [8, 75, 47, 13, 76, 48],\n [7, 54, 24, 22, 55, 25],\n [22, 45, 15, 13, 46, 16],\n\n // 26\n [10, 142, 114, 2, 143, 115],\n [19, 74, 46, 4, 75, 47],\n [28, 50, 22, 6, 51, 23],\n [33, 46, 16, 4, 47, 17],\n\n // 27\n [8, 152, 122, 4, 153, 123],\n [22, 73, 45, 3, 74, 46],\n [8, 53, 23, 26, 54, 24],\n [12, 45, 15, 28, 46, 16],\n\n // 28\n [3, 147, 117, 10, 148, 118],\n [3, 73, 45, 23, 74, 46],\n [4, 54, 24, 31, 55, 25],\n [11, 45, 15, 31, 46, 16],\n\n // 29\n [7, 146, 116, 7, 147, 117],\n [21, 73, 45, 7, 74, 46],\n [1, 53, 23, 37, 54, 24],\n [19, 45, 15, 26, 46, 16],\n\n // 30\n [5, 145, 115, 10, 146, 116],\n [19, 75, 47, 10, 76, 48],\n [15, 54, 24, 25, 55, 25],\n [23, 45, 15, 25, 46, 16],\n\n // 31\n [13, 145, 115, 3, 146, 116],\n [2, 74, 46, 29, 75, 47],\n [42, 54, 24, 1, 55, 25],\n [23, 45, 15, 28, 46, 16],\n\n // 32\n [17, 145, 115],\n [10, 74, 46, 23, 75, 47],\n [10, 54, 24, 35, 55, 25],\n [19, 45, 15, 35, 46, 16],\n\n // 33\n [17, 145, 115, 1, 146, 116],\n [14, 74, 46, 21, 75, 47],\n [29, 54, 24, 19, 55, 25],\n [11, 45, 15, 46, 46, 16],\n\n // 34\n [13, 145, 115, 6, 146, 116],\n [14, 74, 46, 23, 75, 47],\n [44, 54, 24, 7, 55, 25],\n [59, 46, 16, 1, 47, 17],\n\n // 35\n [12, 151, 121, 7, 152, 122],\n [12, 75, 47, 26, 76, 48],\n [39, 54, 24, 14, 55, 25],\n [22, 45, 15, 41, 46, 16],\n\n // 36\n [6, 151, 121, 14, 152, 122],\n [6, 75, 47, 34, 76, 48],\n [46, 54, 24, 10, 55, 25],\n [2, 45, 15, 64, 46, 16],\n\n // 37\n [17, 152, 122, 4, 153, 123],\n [29, 74, 46, 14, 75, 47],\n [49, 54, 24, 10, 55, 25],\n [24, 45, 15, 46, 46, 16],\n\n // 38\n [4, 152, 122, 18, 153, 123],\n [13, 74, 46, 32, 75, 47],\n [48, 54, 24, 14, 55, 25],\n [42, 45, 15, 32, 46, 16],\n\n // 39\n [20, 147, 117, 4, 148, 118],\n [40, 75, 47, 7, 76, 48],\n [43, 54, 24, 22, 55, 25],\n [10, 45, 15, 67, 46, 16],\n\n // 40\n [19, 148, 118, 6, 149, 119],\n [18, 75, 47, 31, 76, 48],\n [34, 54, 24, 34, 55, 25],\n [20, 45, 15, 61, 46, 16]\n ];\n\n var qrRSBlock = function(totalCount, dataCount) {\n var _this = {};\n _this.totalCount = totalCount;\n _this.dataCount = dataCount;\n return _this;\n };\n\n var _this = {};\n\n var getRsBlockTable = function(typeNumber, errorCorrectionLevel) {\n\n switch(errorCorrectionLevel) {\n case QRErrorCorrectionLevel.L :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];\n case QRErrorCorrectionLevel.M :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];\n case QRErrorCorrectionLevel.Q :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];\n case QRErrorCorrectionLevel.H :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];\n default :\n return undefined;\n }\n };\n\n _this.getRSBlocks = function(typeNumber, errorCorrectionLevel) {\n\n var rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);\n\n if (typeof rsBlock == 'undefined') {\n throw 'bad rs block @ typeNumber:' + typeNumber +\n '/errorCorrectionLevel:' + errorCorrectionLevel;\n }\n\n var length = rsBlock.length / 3;\n\n var list = [];\n\n for (var i = 0; i < length; i += 1) {\n\n var count = rsBlock[i * 3 + 0];\n var totalCount = rsBlock[i * 3 + 1];\n var dataCount = rsBlock[i * 3 + 2];\n\n for (var j = 0; j < count; j += 1) {\n list.push(qrRSBlock(totalCount, dataCount) );\n }\n }\n\n return list;\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // qrBitBuffer\n //---------------------------------------------------------------------\n\n var qrBitBuffer = function() {\n\n var _buffer = [];\n var _length = 0;\n\n var _this = {};\n\n _this.getBuffer = function() {\n return _buffer;\n };\n\n _this.getAt = function(index) {\n var bufIndex = Math.floor(index / 8);\n return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;\n };\n\n _this.put = function(num, length) {\n for (var i = 0; i < length; i += 1) {\n _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);\n }\n };\n\n _this.getLengthInBits = function() {\n return _length;\n };\n\n _this.putBit = function(bit) {\n\n var bufIndex = Math.floor(_length / 8);\n if (_buffer.length <= bufIndex) {\n _buffer.push(0);\n }\n\n if (bit) {\n _buffer[bufIndex] |= (0x80 >>> (_length % 8) );\n }\n\n _length += 1;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrNumber\n //---------------------------------------------------------------------\n\n var qrNumber = function(data) {\n\n var _mode = QRMode.MODE_NUMBER;\n var _data = data;\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _data.length;\n };\n\n _this.write = function(buffer) {\n\n var data = _data;\n\n var i = 0;\n\n while (i + 2 < data.length) {\n buffer.put(strToNum(data.substring(i, i + 3) ), 10);\n i += 3;\n }\n\n if (i < data.length) {\n if (data.length - i == 1) {\n buffer.put(strToNum(data.substring(i, i + 1) ), 4);\n } else if (data.length - i == 2) {\n buffer.put(strToNum(data.substring(i, i + 2) ), 7);\n }\n }\n };\n\n var strToNum = function(s) {\n var num = 0;\n for (var i = 0; i < s.length; i += 1) {\n num = num * 10 + chatToNum(s.charAt(i) );\n }\n return num;\n };\n\n var chatToNum = function(c) {\n if ('0' <= c && c <= '9') {\n return c.charCodeAt(0) - '0'.charCodeAt(0);\n }\n throw 'illegal char :' + c;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrAlphaNum\n //---------------------------------------------------------------------\n\n var qrAlphaNum = function(data) {\n\n var _mode = QRMode.MODE_ALPHA_NUM;\n var _data = data;\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _data.length;\n };\n\n _this.write = function(buffer) {\n\n var s = _data;\n\n var i = 0;\n\n while (i + 1 < s.length) {\n buffer.put(\n getCode(s.charAt(i) ) * 45 +\n getCode(s.charAt(i + 1) ), 11);\n i += 2;\n }\n\n if (i < s.length) {\n buffer.put(getCode(s.charAt(i) ), 6);\n }\n };\n\n var getCode = function(c) {\n\n if ('0' <= c && c <= '9') {\n return c.charCodeAt(0) - '0'.charCodeAt(0);\n } else if ('A' <= c && c <= 'Z') {\n return c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;\n } else {\n switch (c) {\n case ' ' : return 36;\n case '$' : return 37;\n case '%' : return 38;\n case '*' : return 39;\n case '+' : return 40;\n case '-' : return 41;\n case '.' : return 42;\n case '/' : return 43;\n case ':' : return 44;\n default :\n throw 'illegal char :' + c;\n }\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qr8BitByte\n //---------------------------------------------------------------------\n\n var qr8BitByte = function(data) {\n\n var _mode = QRMode.MODE_8BIT_BYTE;\n var _data = data;\n var _bytes = qrcode.stringToBytes(data);\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _bytes.length;\n };\n\n _this.write = function(buffer) {\n for (var i = 0; i < _bytes.length; i += 1) {\n buffer.put(_bytes[i], 8);\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrKanji\n //---------------------------------------------------------------------\n\n var qrKanji = function(data) {\n\n var _mode = QRMode.MODE_KANJI;\n var _data = data;\n\n var stringToBytes = qrcode.stringToBytesFuncs['SJIS'];\n if (!stringToBytes) {\n throw 'sjis not supported.';\n }\n !function(c, code) {\n // self test for sjis support.\n var test = stringToBytes(c);\n if (test.length != 2 || ( (test[0] << 8) | test[1]) != code) {\n throw 'sjis not supported.';\n }\n }('\\u53cb', 0x9746);\n\n var _bytes = stringToBytes(data);\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return ~~(_bytes.length / 2);\n };\n\n _this.write = function(buffer) {\n\n var data = _bytes;\n\n var i = 0;\n\n while (i + 1 < data.length) {\n\n var c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);\n\n if (0x8140 <= c && c <= 0x9FFC) {\n c -= 0x8140;\n } else if (0xE040 <= c && c <= 0xEBBF) {\n c -= 0xC140;\n } else {\n throw 'illegal char at ' + (i + 1) + '/' + c;\n }\n\n c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);\n\n buffer.put(c, 13);\n\n i += 2;\n }\n\n if (i < data.length) {\n throw 'illegal char at ' + (i + 1);\n }\n };\n\n return _this;\n };\n\n //=====================================================================\n // GIF Support etc.\n //\n\n //---------------------------------------------------------------------\n // byteArrayOutputStream\n //---------------------------------------------------------------------\n\n var byteArrayOutputStream = function() {\n\n var _bytes = [];\n\n var _this = {};\n\n _this.writeByte = function(b) {\n _bytes.push(b & 0xff);\n };\n\n _this.writeShort = function(i) {\n _this.writeByte(i);\n _this.writeByte(i >>> 8);\n };\n\n _this.writeBytes = function(b, off, len) {\n off = off || 0;\n len = len || b.length;\n for (var i = 0; i < len; i += 1) {\n _this.writeByte(b[i + off]);\n }\n };\n\n _this.writeString = function(s) {\n for (var i = 0; i < s.length; i += 1) {\n _this.writeByte(s.charCodeAt(i) );\n }\n };\n\n _this.toByteArray = function() {\n return _bytes;\n };\n\n _this.toString = function() {\n var s = '';\n s += '[';\n for (var i = 0; i < _bytes.length; i += 1) {\n if (i > 0) {\n s += ',';\n }\n s += _bytes[i];\n }\n s += ']';\n return s;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // base64EncodeOutputStream\n //---------------------------------------------------------------------\n\n var base64EncodeOutputStream = function() {\n\n var _buffer = 0;\n var _buflen = 0;\n var _length = 0;\n var _base64 = '';\n\n var _this = {};\n\n var writeEncoded = function(b) {\n _base64 += String.fromCharCode(encode(b & 0x3f) );\n };\n\n var encode = function(n) {\n if (n < 0) {\n // error.\n } else if (n < 26) {\n return 0x41 + n;\n } else if (n < 52) {\n return 0x61 + (n - 26);\n } else if (n < 62) {\n return 0x30 + (n - 52);\n } else if (n == 62) {\n return 0x2b;\n } else if (n == 63) {\n return 0x2f;\n }\n throw 'n:' + n;\n };\n\n _this.writeByte = function(n) {\n\n _buffer = (_buffer << 8) | (n & 0xff);\n _buflen += 8;\n _length += 1;\n\n while (_buflen >= 6) {\n writeEncoded(_buffer >>> (_buflen - 6) );\n _buflen -= 6;\n }\n };\n\n _this.flush = function() {\n\n if (_buflen > 0) {\n writeEncoded(_buffer << (6 - _buflen) );\n _buffer = 0;\n _buflen = 0;\n }\n\n if (_length % 3 != 0) {\n // padding\n var padlen = 3 - _length % 3;\n for (var i = 0; i < padlen; i += 1) {\n _base64 += '=';\n }\n }\n };\n\n _this.toString = function() {\n return _base64;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // base64DecodeInputStream\n //---------------------------------------------------------------------\n\n var base64DecodeInputStream = function(str) {\n\n var _str = str;\n var _pos = 0;\n var _buffer = 0;\n var _buflen = 0;\n\n var _this = {};\n\n _this.read = function() {\n\n while (_buflen < 8) {\n\n if (_pos >= _str.length) {\n if (_buflen == 0) {\n return -1;\n }\n throw 'unexpected end of file./' + _buflen;\n }\n\n var c = _str.charAt(_pos);\n _pos += 1;\n\n if (c == '=') {\n _buflen = 0;\n return -1;\n } else if (c.match(/^\\s$/) ) {\n // ignore if whitespace.\n continue;\n }\n\n _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );\n _buflen += 6;\n }\n\n var n = (_buffer >>> (_buflen - 8) ) & 0xff;\n _buflen -= 8;\n return n;\n };\n\n var decode = function(c) {\n if (0x41 <= c && c <= 0x5a) {\n return c - 0x41;\n } else if (0x61 <= c && c <= 0x7a) {\n return c - 0x61 + 26;\n } else if (0x30 <= c && c <= 0x39) {\n return c - 0x30 + 52;\n } else if (c == 0x2b) {\n return 62;\n } else if (c == 0x2f) {\n return 63;\n } else {\n throw 'c:' + c;\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // gifImage (B/W)\n //---------------------------------------------------------------------\n\n var gifImage = function(width, height) {\n\n var _width = width;\n var _height = height;\n var _data = new Array(width * height);\n\n var _this = {};\n\n _this.setPixel = function(x, y, pixel) {\n _data[y * _width + x] = pixel;\n };\n\n _this.write = function(out) {\n\n //---------------------------------\n // GIF Signature\n\n out.writeString('GIF87a');\n\n //---------------------------------\n // Screen Descriptor\n\n out.writeShort(_width);\n out.writeShort(_height);\n\n out.writeByte(0x80); // 2bit\n out.writeByte(0);\n out.writeByte(0);\n\n //---------------------------------\n // Global Color Map\n\n // black\n out.writeByte(0x00);\n out.writeByte(0x00);\n out.writeByte(0x00);\n\n // white\n out.writeByte(0xff);\n out.writeByte(0xff);\n out.writeByte(0xff);\n\n //---------------------------------\n // Image Descriptor\n\n out.writeString(',');\n out.writeShort(0);\n out.writeShort(0);\n out.writeShort(_width);\n out.writeShort(_height);\n out.writeByte(0);\n\n //---------------------------------\n // Local Color Map\n\n //---------------------------------\n // Raster Data\n\n var lzwMinCodeSize = 2;\n var raster = getLZWRaster(lzwMinCodeSize);\n\n out.writeByte(lzwMinCodeSize);\n\n var offset = 0;\n\n while (raster.length - offset > 255) {\n out.writeByte(255);\n out.writeBytes(raster, offset, 255);\n offset += 255;\n }\n\n out.writeByte(raster.length - offset);\n out.writeBytes(raster, offset, raster.length - offset);\n out.writeByte(0x00);\n\n //---------------------------------\n // GIF Terminator\n out.writeString(';');\n };\n\n var bitOutputStream = function(out) {\n\n var _out = out;\n var _bitLength = 0;\n var _bitBuffer = 0;\n\n var _this = {};\n\n _this.write = function(data, length) {\n\n if ( (data >>> length) != 0) {\n throw 'length over';\n }\n\n while (_bitLength + length >= 8) {\n _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );\n length -= (8 - _bitLength);\n data >>>= (8 - _bitLength);\n _bitBuffer = 0;\n _bitLength = 0;\n }\n\n _bitBuffer = (data << _bitLength) | _bitBuffer;\n _bitLength = _bitLength + length;\n };\n\n _this.flush = function() {\n if (_bitLength > 0) {\n _out.writeByte(_bitBuffer);\n }\n };\n\n return _this;\n };\n\n var getLZWRaster = function(lzwMinCodeSize) {\n\n var clearCode = 1 << lzwMinCodeSize;\n var endCode = (1 << lzwMinCodeSize) + 1;\n var bitLength = lzwMinCodeSize + 1;\n\n // Setup LZWTable\n var table = lzwTable();\n\n for (var i = 0; i < clearCode; i += 1) {\n table.add(String.fromCharCode(i) );\n }\n table.add(String.fromCharCode(clearCode) );\n table.add(String.fromCharCode(endCode) );\n\n var byteOut = byteArrayOutputStream();\n var bitOut = bitOutputStream(byteOut);\n\n // clear code\n bitOut.write(clearCode, bitLength);\n\n var dataIndex = 0;\n\n var s = String.fromCharCode(_data[dataIndex]);\n dataIndex += 1;\n\n while (dataIndex < _data.length) {\n\n var c = String.fromCharCode(_data[dataIndex]);\n dataIndex += 1;\n\n if (table.contains(s + c) ) {\n\n s = s + c;\n\n } else {\n\n bitOut.write(table.indexOf(s), bitLength);\n\n if (table.size() < 0xfff) {\n\n if (table.size() == (1 << bitLength) ) {\n bitLength += 1;\n }\n\n table.add(s + c);\n }\n\n s = c;\n }\n }\n\n bitOut.write(table.indexOf(s), bitLength);\n\n // end code\n bitOut.write(endCode, bitLength);\n\n bitOut.flush();\n\n return byteOut.toByteArray();\n };\n\n var lzwTable = function() {\n\n var _map = {};\n var _size = 0;\n\n var _this = {};\n\n _this.add = function(key) {\n if (_this.contains(key) ) {\n throw 'dup key:' + key;\n }\n _map[key] = _size;\n _size += 1;\n };\n\n _this.size = function() {\n return _size;\n };\n\n _this.indexOf = function(key) {\n return _map[key];\n };\n\n _this.contains = function(key) {\n return typeof _map[key] != 'undefined';\n };\n\n return _this;\n };\n\n return _this;\n };\n\n var createDataURL = function(width, height, getPixel) {\n var gif = gifImage(width, height);\n for (var y = 0; y < height; y += 1) {\n for (var x = 0; x < width; x += 1) {\n gif.setPixel(x, y, getPixel(x, y) );\n }\n }\n\n var b = byteArrayOutputStream();\n gif.write(b);\n\n var base64 = base64EncodeOutputStream();\n var bytes = b.toByteArray();\n for (var i = 0; i < bytes.length; i += 1) {\n base64.writeByte(bytes[i]);\n }\n base64.flush();\n\n return 'data:image/gif;base64,' + base64;\n };\n\n //---------------------------------------------------------------------\n // returns qrcode function.\n\n return qrcode;\n}();\n\n// multibyte support\n!function() {\n\n qrcode.stringToBytesFuncs['UTF-8'] = function(s) {\n // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array\n function toUTF8Array(str) {\n var utf8 = [];\n for (var i=0; i < str.length; i++) {\n var charcode = str.charCodeAt(i);\n if (charcode < 0x80) utf8.push(charcode);\n else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6),\n 0x80 | (charcode & 0x3f));\n }\n else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(0xe0 | (charcode >> 12),\n 0x80 | ((charcode>>6) & 0x3f),\n 0x80 | (charcode & 0x3f));\n }\n // surrogate pair\n else {\n i++;\n // UTF-16 encodes 0x10000-0x10FFFF by\n // subtracting 0x10000 and splitting the\n // 20 bits of 0x0-0xFFFFF into two halves\n charcode = 0x10000 + (((charcode & 0x3ff)<<10)\n | (str.charCodeAt(i) & 0x3ff));\n utf8.push(0xf0 | (charcode >>18),\n 0x80 | ((charcode>>12) & 0x3f),\n 0x80 | ((charcode>>6) & 0x3f),\n 0x80 | (charcode & 0x3f));\n }\n }\n return utf8;\n }\n return toUTF8Array(s);\n };\n\n}();\n\n(function (factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n }\n}(function () {\n return qrcode;\n}));\n", "// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri.\n// TypeScript port in 2019 by Florian Dold.\n// Public domain.\n//\n// Implementation derived from TweetNaCl version 20140427.\n// See for details: http://tweetnacl.cr.yp.to/\n\nconst gf = function (init: number[] = []): Float64Array {\n const r = new Float64Array(16);\n if (init) for (let i = 0; i < init.length; i++) r[i] = init[i];\n return r;\n};\n\n// Pluggable, initialized in high-level API below.\nlet randombytes = function (x: Uint8Array, n: number): void {\n throw new Error(\"no PRNG\");\n};\n\nconst _9 = new Uint8Array(32);\n_9[0] = 9;\n\n// prettier-ignore\nconst gf0 = gf();\nconst gf1 = gf([1]);\nconst _121665 = gf([0xdb41, 1]);\nconst D = gf([\n 0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898,\n 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203,\n]);\nconst D2 = gf([\n 0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130,\n 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406,\n]);\nconst X = gf([\n 0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c,\n 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169,\n]);\nconst Y = gf([\n 0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,\n 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,\n]);\nconst I = gf([\n 0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7,\n 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83,\n]);\n\nfunction ts64(x: Uint8Array, i: number, h: number, l: number): void {\n x[i] = (h >> 24) & 0xff;\n x[i + 1] = (h >> 16) & 0xff;\n x[i + 2] = (h >> 8) & 0xff;\n x[i + 3] = h & 0xff;\n x[i + 4] = (l >> 24) & 0xff;\n x[i + 5] = (l >> 16) & 0xff;\n x[i + 6] = (l >> 8) & 0xff;\n x[i + 7] = l & 0xff;\n}\n\nfunction vn(\n x: Uint8Array,\n xi: number,\n y: Uint8Array,\n yi: number,\n n: number,\n): number {\n let i,\n d = 0;\n for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i];\n return (1 & ((d - 1) >>> 8)) - 1;\n}\n\nexport function crypto_verify_16(\n x: Uint8Array,\n xi: number,\n y: Uint8Array,\n yi: number,\n) {\n return vn(x, xi, y, yi, 16);\n}\n\nfunction crypto_verify_32(\n x: Uint8Array,\n xi: number,\n y: Uint8Array,\n yi: number,\n): number {\n return vn(x, xi, y, yi, 32);\n}\n\nfunction core_salsa20(\n o: Uint8Array,\n p: Uint8Array,\n k: Uint8Array,\n c: Uint8Array,\n) {\n var j0 =\n (c[0] & 0xff) |\n ((c[1] & 0xff) << 8) |\n ((c[2] & 0xff) << 16) |\n ((c[3] & 0xff) << 24),\n j1 =\n (k[0] & 0xff) |\n ((k[1] & 0xff) << 8) |\n ((k[2] & 0xff) << 16) |\n ((k[3] & 0xff) << 24),\n j2 =\n (k[4] & 0xff) |\n ((k[5] & 0xff) << 8) |\n ((k[6] & 0xff) << 16) |\n ((k[7] & 0xff) << 24),\n j3 =\n (k[8] & 0xff) |\n ((k[9] & 0xff) << 8) |\n ((k[10] & 0xff) << 16) |\n ((k[11] & 0xff) << 24),\n j4 =\n (k[12] & 0xff) |\n ((k[13] & 0xff) << 8) |\n ((k[14] & 0xff) << 16) |\n ((k[15] & 0xff) << 24),\n j5 =\n (c[4] & 0xff) |\n ((c[5] & 0xff) << 8) |\n ((c[6] & 0xff) << 16) |\n ((c[7] & 0xff) << 24),\n j6 =\n (p[0] & 0xff) |\n ((p[1] & 0xff) << 8) |\n ((p[2] & 0xff) << 16) |\n ((p[3] & 0xff) << 24),\n j7 =\n (p[4] & 0xff) |\n ((p[5] & 0xff) << 8) |\n ((p[6] & 0xff) << 16) |\n ((p[7] & 0xff) << 24),\n j8 =\n (p[8] & 0xff) |\n ((p[9] & 0xff) << 8) |\n ((p[10] & 0xff) << 16) |\n ((p[11] & 0xff) << 24),\n j9 =\n (p[12] & 0xff) |\n ((p[13] & 0xff) << 8) |\n ((p[14] & 0xff) << 16) |\n ((p[15] & 0xff) << 24),\n j10 =\n (c[8] & 0xff) |\n ((c[9] & 0xff) << 8) |\n ((c[10] & 0xff) << 16) |\n ((c[11] & 0xff) << 24),\n j11 =\n (k[16] & 0xff) |\n ((k[17] & 0xff) << 8) |\n ((k[18] & 0xff) << 16) |\n ((k[19] & 0xff) << 24),\n j12 =\n (k[20] & 0xff) |\n ((k[21] & 0xff) << 8) |\n ((k[22] & 0xff) << 16) |\n ((k[23] & 0xff) << 24),\n j13 =\n (k[24] & 0xff) |\n ((k[25] & 0xff) << 8) |\n ((k[26] & 0xff) << 16) |\n ((k[27] & 0xff) << 24),\n j14 =\n (k[28] & 0xff) |\n ((k[29] & 0xff) << 8) |\n ((k[30] & 0xff) << 16) |\n ((k[31] & 0xff) << 24),\n j15 =\n (c[12] & 0xff) |\n ((c[13] & 0xff) << 8) |\n ((c[14] & 0xff) << 16) |\n ((c[15] & 0xff) << 24);\n\n var x0 = j0,\n x1 = j1,\n x2 = j2,\n x3 = j3,\n x4 = j4,\n x5 = j5,\n x6 = j6,\n x7 = j7,\n x8 = j8,\n x9 = j9,\n x10 = j10,\n x11 = j11,\n x12 = j12,\n x13 = j13,\n x14 = j14,\n x15 = j15,\n u;\n\n for (var i = 0; i < 20; i += 2) {\n u = (x0 + x12) | 0;\n x4 ^= (u << 7) | (u >>> (32 - 7));\n u = (x4 + x0) | 0;\n x8 ^= (u << 9) | (u >>> (32 - 9));\n u = (x8 + x4) | 0;\n x12 ^= (u << 13) | (u >>> (32 - 13));\n u = (x12 + x8) | 0;\n x0 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x5 + x1) | 0;\n x9 ^= (u << 7) | (u >>> (32 - 7));\n u = (x9 + x5) | 0;\n x13 ^= (u << 9) | (u >>> (32 - 9));\n u = (x13 + x9) | 0;\n x1 ^= (u << 13) | (u >>> (32 - 13));\n u = (x1 + x13) | 0;\n x5 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x10 + x6) | 0;\n x14 ^= (u << 7) | (u >>> (32 - 7));\n u = (x14 + x10) | 0;\n x2 ^= (u << 9) | (u >>> (32 - 9));\n u = (x2 + x14) | 0;\n x6 ^= (u << 13) | (u >>> (32 - 13));\n u = (x6 + x2) | 0;\n x10 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x15 + x11) | 0;\n x3 ^= (u << 7) | (u >>> (32 - 7));\n u = (x3 + x15) | 0;\n x7 ^= (u << 9) | (u >>> (32 - 9));\n u = (x7 + x3) | 0;\n x11 ^= (u << 13) | (u >>> (32 - 13));\n u = (x11 + x7) | 0;\n x15 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x0 + x3) | 0;\n x1 ^= (u << 7) | (u >>> (32 - 7));\n u = (x1 + x0) | 0;\n x2 ^= (u << 9) | (u >>> (32 - 9));\n u = (x2 + x1) | 0;\n x3 ^= (u << 13) | (u >>> (32 - 13));\n u = (x3 + x2) | 0;\n x0 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x5 + x4) | 0;\n x6 ^= (u << 7) | (u >>> (32 - 7));\n u = (x6 + x5) | 0;\n x7 ^= (u << 9) | (u >>> (32 - 9));\n u = (x7 + x6) | 0;\n x4 ^= (u << 13) | (u >>> (32 - 13));\n u = (x4 + x7) | 0;\n x5 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x10 + x9) | 0;\n x11 ^= (u << 7) | (u >>> (32 - 7));\n u = (x11 + x10) | 0;\n x8 ^= (u << 9) | (u >>> (32 - 9));\n u = (x8 + x11) | 0;\n x9 ^= (u << 13) | (u >>> (32 - 13));\n u = (x9 + x8) | 0;\n x10 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x15 + x14) | 0;\n x12 ^= (u << 7) | (u >>> (32 - 7));\n u = (x12 + x15) | 0;\n x13 ^= (u << 9) | (u >>> (32 - 9));\n u = (x13 + x12) | 0;\n x14 ^= (u << 13) | (u >>> (32 - 13));\n u = (x14 + x13) | 0;\n x15 ^= (u << 18) | (u >>> (32 - 18));\n }\n x0 = (x0 + j0) | 0;\n x1 = (x1 + j1) | 0;\n x2 = (x2 + j2) | 0;\n x3 = (x3 + j3) | 0;\n x4 = (x4 + j4) | 0;\n x5 = (x5 + j5) | 0;\n x6 = (x6 + j6) | 0;\n x7 = (x7 + j7) | 0;\n x8 = (x8 + j8) | 0;\n x9 = (x9 + j9) | 0;\n x10 = (x10 + j10) | 0;\n x11 = (x11 + j11) | 0;\n x12 = (x12 + j12) | 0;\n x13 = (x13 + j13) | 0;\n x14 = (x14 + j14) | 0;\n x15 = (x15 + j15) | 0;\n\n o[0] = (x0 >>> 0) & 0xff;\n o[1] = (x0 >>> 8) & 0xff;\n o[2] = (x0 >>> 16) & 0xff;\n o[3] = (x0 >>> 24) & 0xff;\n\n o[4] = (x1 >>> 0) & 0xff;\n o[5] = (x1 >>> 8) & 0xff;\n o[6] = (x1 >>> 16) & 0xff;\n o[7] = (x1 >>> 24) & 0xff;\n\n o[8] = (x2 >>> 0) & 0xff;\n o[9] = (x2 >>> 8) & 0xff;\n o[10] = (x2 >>> 16) & 0xff;\n o[11] = (x2 >>> 24) & 0xff;\n\n o[12] = (x3 >>> 0) & 0xff;\n o[13] = (x3 >>> 8) & 0xff;\n o[14] = (x3 >>> 16) & 0xff;\n o[15] = (x3 >>> 24) & 0xff;\n\n o[16] = (x4 >>> 0) & 0xff;\n o[17] = (x4 >>> 8) & 0xff;\n o[18] = (x4 >>> 16) & 0xff;\n o[19] = (x4 >>> 24) & 0xff;\n\n o[20] = (x5 >>> 0) & 0xff;\n o[21] = (x5 >>> 8) & 0xff;\n o[22] = (x5 >>> 16) & 0xff;\n o[23] = (x5 >>> 24) & 0xff;\n\n o[24] = (x6 >>> 0) & 0xff;\n o[25] = (x6 >>> 8) & 0xff;\n o[26] = (x6 >>> 16) & 0xff;\n o[27] = (x6 >>> 24) & 0xff;\n\n o[28] = (x7 >>> 0) & 0xff;\n o[29] = (x7 >>> 8) & 0xff;\n o[30] = (x7 >>> 16) & 0xff;\n o[31] = (x7 >>> 24) & 0xff;\n\n o[32] = (x8 >>> 0) & 0xff;\n o[33] = (x8 >>> 8) & 0xff;\n o[34] = (x8 >>> 16) & 0xff;\n o[35] = (x8 >>> 24) & 0xff;\n\n o[36] = (x9 >>> 0) & 0xff;\n o[37] = (x9 >>> 8) & 0xff;\n o[38] = (x9 >>> 16) & 0xff;\n o[39] = (x9 >>> 24) & 0xff;\n\n o[40] = (x10 >>> 0) & 0xff;\n o[41] = (x10 >>> 8) & 0xff;\n o[42] = (x10 >>> 16) & 0xff;\n o[43] = (x10 >>> 24) & 0xff;\n\n o[44] = (x11 >>> 0) & 0xff;\n o[45] = (x11 >>> 8) & 0xff;\n o[46] = (x11 >>> 16) & 0xff;\n o[47] = (x11 >>> 24) & 0xff;\n\n o[48] = (x12 >>> 0) & 0xff;\n o[49] = (x12 >>> 8) & 0xff;\n o[50] = (x12 >>> 16) & 0xff;\n o[51] = (x12 >>> 24) & 0xff;\n\n o[52] = (x13 >>> 0) & 0xff;\n o[53] = (x13 >>> 8) & 0xff;\n o[54] = (x13 >>> 16) & 0xff;\n o[55] = (x13 >>> 24) & 0xff;\n\n o[56] = (x14 >>> 0) & 0xff;\n o[57] = (x14 >>> 8) & 0xff;\n o[58] = (x14 >>> 16) & 0xff;\n o[59] = (x14 >>> 24) & 0xff;\n\n o[60] = (x15 >>> 0) & 0xff;\n o[61] = (x15 >>> 8) & 0xff;\n o[62] = (x15 >>> 16) & 0xff;\n o[63] = (x15 >>> 24) & 0xff;\n}\n\nfunction core_hsalsa20(\n o: Uint8Array,\n p: Uint8Array,\n k: Uint8Array,\n c: Uint8Array,\n) {\n var j0 =\n (c[0] & 0xff) |\n ((c[1] & 0xff) << 8) |\n ((c[2] & 0xff) << 16) |\n ((c[3] & 0xff) << 24),\n j1 =\n (k[0] & 0xff) |\n ((k[1] & 0xff) << 8) |\n ((k[2] & 0xff) << 16) |\n ((k[3] & 0xff) << 24),\n j2 =\n (k[4] & 0xff) |\n ((k[5] & 0xff) << 8) |\n ((k[6] & 0xff) << 16) |\n ((k[7] & 0xff) << 24),\n j3 =\n (k[8] & 0xff) |\n ((k[9] & 0xff) << 8) |\n ((k[10] & 0xff) << 16) |\n ((k[11] & 0xff) << 24),\n j4 =\n (k[12] & 0xff) |\n ((k[13] & 0xff) << 8) |\n ((k[14] & 0xff) << 16) |\n ((k[15] & 0xff) << 24),\n j5 =\n (c[4] & 0xff) |\n ((c[5] & 0xff) << 8) |\n ((c[6] & 0xff) << 16) |\n ((c[7] & 0xff) << 24),\n j6 =\n (p[0] & 0xff) |\n ((p[1] & 0xff) << 8) |\n ((p[2] & 0xff) << 16) |\n ((p[3] & 0xff) << 24),\n j7 =\n (p[4] & 0xff) |\n ((p[5] & 0xff) << 8) |\n ((p[6] & 0xff) << 16) |\n ((p[7] & 0xff) << 24),\n j8 =\n (p[8] & 0xff) |\n ((p[9] & 0xff) << 8) |\n ((p[10] & 0xff) << 16) |\n ((p[11] & 0xff) << 24),\n j9 =\n (p[12] & 0xff) |\n ((p[13] & 0xff) << 8) |\n ((p[14] & 0xff) << 16) |\n ((p[15] & 0xff) << 24),\n j10 =\n (c[8] & 0xff) |\n ((c[9] & 0xff) << 8) |\n ((c[10] & 0xff) << 16) |\n ((c[11] & 0xff) << 24),\n j11 =\n (k[16] & 0xff) |\n ((k[17] & 0xff) << 8) |\n ((k[18] & 0xff) << 16) |\n ((k[19] & 0xff) << 24),\n j12 =\n (k[20] & 0xff) |\n ((k[21] & 0xff) << 8) |\n ((k[22] & 0xff) << 16) |\n ((k[23] & 0xff) << 24),\n j13 =\n (k[24] & 0xff) |\n ((k[25] & 0xff) << 8) |\n ((k[26] & 0xff) << 16) |\n ((k[27] & 0xff) << 24),\n j14 =\n (k[28] & 0xff) |\n ((k[29] & 0xff) << 8) |\n ((k[30] & 0xff) << 16) |\n ((k[31] & 0xff) << 24),\n j15 =\n (c[12] & 0xff) |\n ((c[13] & 0xff) << 8) |\n ((c[14] & 0xff) << 16) |\n ((c[15] & 0xff) << 24);\n\n var x0 = j0,\n x1 = j1,\n x2 = j2,\n x3 = j3,\n x4 = j4,\n x5 = j5,\n x6 = j6,\n x7 = j7,\n x8 = j8,\n x9 = j9,\n x10 = j10,\n x11 = j11,\n x12 = j12,\n x13 = j13,\n x14 = j14,\n x15 = j15,\n u;\n\n for (var i = 0; i < 20; i += 2) {\n u = (x0 + x12) | 0;\n x4 ^= (u << 7) | (u >>> (32 - 7));\n u = (x4 + x0) | 0;\n x8 ^= (u << 9) | (u >>> (32 - 9));\n u = (x8 + x4) | 0;\n x12 ^= (u << 13) | (u >>> (32 - 13));\n u = (x12 + x8) | 0;\n x0 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x5 + x1) | 0;\n x9 ^= (u << 7) | (u >>> (32 - 7));\n u = (x9 + x5) | 0;\n x13 ^= (u << 9) | (u >>> (32 - 9));\n u = (x13 + x9) | 0;\n x1 ^= (u << 13) | (u >>> (32 - 13));\n u = (x1 + x13) | 0;\n x5 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x10 + x6) | 0;\n x14 ^= (u << 7) | (u >>> (32 - 7));\n u = (x14 + x10) | 0;\n x2 ^= (u << 9) | (u >>> (32 - 9));\n u = (x2 + x14) | 0;\n x6 ^= (u << 13) | (u >>> (32 - 13));\n u = (x6 + x2) | 0;\n x10 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x15 + x11) | 0;\n x3 ^= (u << 7) | (u >>> (32 - 7));\n u = (x3 + x15) | 0;\n x7 ^= (u << 9) | (u >>> (32 - 9));\n u = (x7 + x3) | 0;\n x11 ^= (u << 13) | (u >>> (32 - 13));\n u = (x11 + x7) | 0;\n x15 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x0 + x3) | 0;\n x1 ^= (u << 7) | (u >>> (32 - 7));\n u = (x1 + x0) | 0;\n x2 ^= (u << 9) | (u >>> (32 - 9));\n u = (x2 + x1) | 0;\n x3 ^= (u << 13) | (u >>> (32 - 13));\n u = (x3 + x2) | 0;\n x0 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x5 + x4) | 0;\n x6 ^= (u << 7) | (u >>> (32 - 7));\n u = (x6 + x5) | 0;\n x7 ^= (u << 9) | (u >>> (32 - 9));\n u = (x7 + x6) | 0;\n x4 ^= (u << 13) | (u >>> (32 - 13));\n u = (x4 + x7) | 0;\n x5 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x10 + x9) | 0;\n x11 ^= (u << 7) | (u >>> (32 - 7));\n u = (x11 + x10) | 0;\n x8 ^= (u << 9) | (u >>> (32 - 9));\n u = (x8 + x11) | 0;\n x9 ^= (u << 13) | (u >>> (32 - 13));\n u = (x9 + x8) | 0;\n x10 ^= (u << 18) | (u >>> (32 - 18));\n\n u = (x15 + x14) | 0;\n x12 ^= (u << 7) | (u >>> (32 - 7));\n u = (x12 + x15) | 0;\n x13 ^= (u << 9) | (u >>> (32 - 9));\n u = (x13 + x12) | 0;\n x14 ^= (u << 13) | (u >>> (32 - 13));\n u = (x14 + x13) | 0;\n x15 ^= (u << 18) | (u >>> (32 - 18));\n }\n\n o[0] = (x0 >>> 0) & 0xff;\n o[1] = (x0 >>> 8) & 0xff;\n o[2] = (x0 >>> 16) & 0xff;\n o[3] = (x0 >>> 24) & 0xff;\n\n o[4] = (x5 >>> 0) & 0xff;\n o[5] = (x5 >>> 8) & 0xff;\n o[6] = (x5 >>> 16) & 0xff;\n o[7] = (x5 >>> 24) & 0xff;\n\n o[8] = (x10 >>> 0) & 0xff;\n o[9] = (x10 >>> 8) & 0xff;\n o[10] = (x10 >>> 16) & 0xff;\n o[11] = (x10 >>> 24) & 0xff;\n\n o[12] = (x15 >>> 0) & 0xff;\n o[13] = (x15 >>> 8) & 0xff;\n o[14] = (x15 >>> 16) & 0xff;\n o[15] = (x15 >>> 24) & 0xff;\n\n o[16] = (x6 >>> 0) & 0xff;\n o[17] = (x6 >>> 8) & 0xff;\n o[18] = (x6 >>> 16) & 0xff;\n o[19] = (x6 >>> 24) & 0xff;\n\n o[20] = (x7 >>> 0) & 0xff;\n o[21] = (x7 >>> 8) & 0xff;\n o[22] = (x7 >>> 16) & 0xff;\n o[23] = (x7 >>> 24) & 0xff;\n\n o[24] = (x8 >>> 0) & 0xff;\n o[25] = (x8 >>> 8) & 0xff;\n o[26] = (x8 >>> 16) & 0xff;\n o[27] = (x8 >>> 24) & 0xff;\n\n o[28] = (x9 >>> 0) & 0xff;\n o[29] = (x9 >>> 8) & 0xff;\n o[30] = (x9 >>> 16) & 0xff;\n o[31] = (x9 >>> 24) & 0xff;\n}\n\nvar sigma = new Uint8Array([\n 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107,\n]);\n// \"expand 32-byte k\"\n\nfunction crypto_stream_salsa20_xor(\n c: Uint8Array,\n cpos: number,\n m: Uint8Array,\n mpos: number,\n b: number,\n n: Uint8Array,\n k: Uint8Array,\n) {\n var z = new Uint8Array(16),\n x = new Uint8Array(64);\n var u, i;\n for (i = 0; i < 16; i++) z[i] = 0;\n for (i = 0; i < 8; i++) z[i] = n[i];\n while (b >= 64) {\n core_salsa20(x, z, k, sigma);\n for (i = 0; i < 64; i++) c[cpos + i] = m[mpos + i] ^ x[i];\n u = 1;\n for (i = 8; i < 16; i++) {\n u = (u + (z[i] & 0xff)) | 0;\n z[i] = u & 0xff;\n u >>>= 8;\n }\n b -= 64;\n cpos += 64;\n mpos += 64;\n }\n if (b > 0) {\n core_salsa20(x, z, k, sigma);\n for (i = 0; i < b; i++) c[cpos + i] = m[mpos + i] ^ x[i];\n }\n return 0;\n}\n\nfunction crypto_stream_salsa20(\n c: Uint8Array,\n cpos: number,\n b: number,\n n: Uint8Array,\n k: Uint8Array,\n) {\n var z = new Uint8Array(16),\n x = new Uint8Array(64);\n var u, i;\n for (i = 0; i < 16; i++) z[i] = 0;\n for (i = 0; i < 8; i++) z[i] = n[i];\n while (b >= 64) {\n core_salsa20(x, z, k, sigma);\n for (i = 0; i < 64; i++) c[cpos + i] = x[i];\n u = 1;\n for (i = 8; i < 16; i++) {\n u = (u + (z[i] & 0xff)) | 0;\n z[i] = u & 0xff;\n u >>>= 8;\n }\n b -= 64;\n cpos += 64;\n }\n if (b > 0) {\n core_salsa20(x, z, k, sigma);\n for (i = 0; i < b; i++) c[cpos + i] = x[i];\n }\n return 0;\n}\n\nfunction crypto_stream(\n c: Uint8Array,\n cpos: number,\n d: number,\n n: Uint8Array,\n k: Uint8Array,\n) {\n var s = new Uint8Array(32);\n core_hsalsa20(s, n, k, sigma);\n var sn = new Uint8Array(8);\n for (var i = 0; i < 8; i++) sn[i] = n[i + 16];\n return crypto_stream_salsa20(c, cpos, d, sn, s);\n}\n\nfunction crypto_stream_xor(\n c: Uint8Array,\n cpos: number,\n m: Uint8Array,\n mpos: number,\n d: number,\n n: Uint8Array,\n k: Uint8Array,\n) {\n var s = new Uint8Array(32);\n core_hsalsa20(s, n, k, sigma);\n var sn = new Uint8Array(8);\n for (var i = 0; i < 8; i++) sn[i] = n[i + 16];\n return crypto_stream_salsa20_xor(c, cpos, m, mpos, d, sn, s);\n}\n\n/*\n * Port of Andrew Moon's Poly1305-donna-16. Public domain.\n * https://github.com/floodyberry/poly1305-donna\n */\n\nexport class poly1305 {\n buffer = new Uint8Array(16);\n r = new Uint16Array(10);\n h = new Uint16Array(10);\n pad = new Uint16Array(8);\n leftover = 0;\n fin = 0;\n\n constructor(key: Uint8Array) {\n var t0, t1, t2, t3, t4, t5, t6, t7;\n\n t0 = (key[0] & 0xff) | ((key[1] & 0xff) << 8);\n this.r[0] = t0 & 0x1fff;\n t1 = (key[2] & 0xff) | ((key[3] & 0xff) << 8);\n this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;\n t2 = (key[4] & 0xff) | ((key[5] & 0xff) << 8);\n this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;\n t3 = (key[6] & 0xff) | ((key[7] & 0xff) << 8);\n this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;\n t4 = (key[8] & 0xff) | ((key[9] & 0xff) << 8);\n this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;\n this.r[5] = (t4 >>> 1) & 0x1ffe;\n t5 = (key[10] & 0xff) | ((key[11] & 0xff) << 8);\n this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;\n t6 = (key[12] & 0xff) | ((key[13] & 0xff) << 8);\n this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;\n t7 = (key[14] & 0xff) | ((key[15] & 0xff) << 8);\n this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;\n this.r[9] = (t7 >>> 5) & 0x007f;\n\n this.pad[0] = (key[16] & 0xff) | ((key[17] & 0xff) << 8);\n this.pad[1] = (key[18] & 0xff) | ((key[19] & 0xff) << 8);\n this.pad[2] = (key[20] & 0xff) | ((key[21] & 0xff) << 8);\n this.pad[3] = (key[22] & 0xff) | ((key[23] & 0xff) << 8);\n this.pad[4] = (key[24] & 0xff) | ((key[25] & 0xff) << 8);\n this.pad[5] = (key[26] & 0xff) | ((key[27] & 0xff) << 8);\n this.pad[6] = (key[28] & 0xff) | ((key[29] & 0xff) << 8);\n this.pad[7] = (key[30] & 0xff) | ((key[31] & 0xff) << 8);\n }\n\n blocks(m: Uint8Array, mpos: number, bytes: number) {\n var hibit = this.fin ? 0 : 1 << 11;\n var t0, t1, t2, t3, t4, t5, t6, t7, c;\n var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9;\n\n var h0 = this.h[0],\n h1 = this.h[1],\n h2 = this.h[2],\n h3 = this.h[3],\n h4 = this.h[4],\n h5 = this.h[5],\n h6 = this.h[6],\n h7 = this.h[7],\n h8 = this.h[8],\n h9 = this.h[9];\n\n var r0 = this.r[0],\n r1 = this.r[1],\n r2 = this.r[2],\n r3 = this.r[3],\n r4 = this.r[4],\n r5 = this.r[5],\n r6 = this.r[6],\n r7 = this.r[7],\n r8 = this.r[8],\n r9 = this.r[9];\n\n while (bytes >= 16) {\n t0 = (m[mpos + 0] & 0xff) | ((m[mpos + 1] & 0xff) << 8);\n h0 += t0 & 0x1fff;\n t1 = (m[mpos + 2] & 0xff) | ((m[mpos + 3] & 0xff) << 8);\n h1 += ((t0 >>> 13) | (t1 << 3)) & 0x1fff;\n t2 = (m[mpos + 4] & 0xff) | ((m[mpos + 5] & 0xff) << 8);\n h2 += ((t1 >>> 10) | (t2 << 6)) & 0x1fff;\n t3 = (m[mpos + 6] & 0xff) | ((m[mpos + 7] & 0xff) << 8);\n h3 += ((t2 >>> 7) | (t3 << 9)) & 0x1fff;\n t4 = (m[mpos + 8] & 0xff) | ((m[mpos + 9] & 0xff) << 8);\n h4 += ((t3 >>> 4) | (t4 << 12)) & 0x1fff;\n h5 += (t4 >>> 1) & 0x1fff;\n t5 = (m[mpos + 10] & 0xff) | ((m[mpos + 11] & 0xff) << 8);\n h6 += ((t4 >>> 14) | (t5 << 2)) & 0x1fff;\n t6 = (m[mpos + 12] & 0xff) | ((m[mpos + 13] & 0xff) << 8);\n h7 += ((t5 >>> 11) | (t6 << 5)) & 0x1fff;\n t7 = (m[mpos + 14] & 0xff) | ((m[mpos + 15] & 0xff) << 8);\n h8 += ((t6 >>> 8) | (t7 << 8)) & 0x1fff;\n h9 += (t7 >>> 5) | hibit;\n\n c = 0;\n\n d0 = c;\n d0 += h0 * r0;\n d0 += h1 * (5 * r9);\n d0 += h2 * (5 * r8);\n d0 += h3 * (5 * r7);\n d0 += h4 * (5 * r6);\n c = d0 >>> 13;\n d0 &= 0x1fff;\n d0 += h5 * (5 * r5);\n d0 += h6 * (5 * r4);\n d0 += h7 * (5 * r3);\n d0 += h8 * (5 * r2);\n d0 += h9 * (5 * r1);\n c += d0 >>> 13;\n d0 &= 0x1fff;\n\n d1 = c;\n d1 += h0 * r1;\n d1 += h1 * r0;\n d1 += h2 * (5 * r9);\n d1 += h3 * (5 * r8);\n d1 += h4 * (5 * r7);\n c = d1 >>> 13;\n d1 &= 0x1fff;\n d1 += h5 * (5 * r6);\n d1 += h6 * (5 * r5);\n d1 += h7 * (5 * r4);\n d1 += h8 * (5 * r3);\n d1 += h9 * (5 * r2);\n c += d1 >>> 13;\n d1 &= 0x1fff;\n\n d2 = c;\n d2 += h0 * r2;\n d2 += h1 * r1;\n d2 += h2 * r0;\n d2 += h3 * (5 * r9);\n d2 += h4 * (5 * r8);\n c = d2 >>> 13;\n d2 &= 0x1fff;\n d2 += h5 * (5 * r7);\n d2 += h6 * (5 * r6);\n d2 += h7 * (5 * r5);\n d2 += h8 * (5 * r4);\n d2 += h9 * (5 * r3);\n c += d2 >>> 13;\n d2 &= 0x1fff;\n\n d3 = c;\n d3 += h0 * r3;\n d3 += h1 * r2;\n d3 += h2 * r1;\n d3 += h3 * r0;\n d3 += h4 * (5 * r9);\n c = d3 >>> 13;\n d3 &= 0x1fff;\n d3 += h5 * (5 * r8);\n d3 += h6 * (5 * r7);\n d3 += h7 * (5 * r6);\n d3 += h8 * (5 * r5);\n d3 += h9 * (5 * r4);\n c += d3 >>> 13;\n d3 &= 0x1fff;\n\n d4 = c;\n d4 += h0 * r4;\n d4 += h1 * r3;\n d4 += h2 * r2;\n d4 += h3 * r1;\n d4 += h4 * r0;\n c = d4 >>> 13;\n d4 &= 0x1fff;\n d4 += h5 * (5 * r9);\n d4 += h6 * (5 * r8);\n d4 += h7 * (5 * r7);\n d4 += h8 * (5 * r6);\n d4 += h9 * (5 * r5);\n c += d4 >>> 13;\n d4 &= 0x1fff;\n\n d5 = c;\n d5 += h0 * r5;\n d5 += h1 * r4;\n d5 += h2 * r3;\n d5 += h3 * r2;\n d5 += h4 * r1;\n c = d5 >>> 13;\n d5 &= 0x1fff;\n d5 += h5 * r0;\n d5 += h6 * (5 * r9);\n d5 += h7 * (5 * r8);\n d5 += h8 * (5 * r7);\n d5 += h9 * (5 * r6);\n c += d5 >>> 13;\n d5 &= 0x1fff;\n\n d6 = c;\n d6 += h0 * r6;\n d6 += h1 * r5;\n d6 += h2 * r4;\n d6 += h3 * r3;\n d6 += h4 * r2;\n c = d6 >>> 13;\n d6 &= 0x1fff;\n d6 += h5 * r1;\n d6 += h6 * r0;\n d6 += h7 * (5 * r9);\n d6 += h8 * (5 * r8);\n d6 += h9 * (5 * r7);\n c += d6 >>> 13;\n d6 &= 0x1fff;\n\n d7 = c;\n d7 += h0 * r7;\n d7 += h1 * r6;\n d7 += h2 * r5;\n d7 += h3 * r4;\n d7 += h4 * r3;\n c = d7 >>> 13;\n d7 &= 0x1fff;\n d7 += h5 * r2;\n d7 += h6 * r1;\n d7 += h7 * r0;\n d7 += h8 * (5 * r9);\n d7 += h9 * (5 * r8);\n c += d7 >>> 13;\n d7 &= 0x1fff;\n\n d8 = c;\n d8 += h0 * r8;\n d8 += h1 * r7;\n d8 += h2 * r6;\n d8 += h3 * r5;\n d8 += h4 * r4;\n c = d8 >>> 13;\n d8 &= 0x1fff;\n d8 += h5 * r3;\n d8 += h6 * r2;\n d8 += h7 * r1;\n d8 += h8 * r0;\n d8 += h9 * (5 * r9);\n c += d8 >>> 13;\n d8 &= 0x1fff;\n\n d9 = c;\n d9 += h0 * r9;\n d9 += h1 * r8;\n d9 += h2 * r7;\n d9 += h3 * r6;\n d9 += h4 * r5;\n c = d9 >>> 13;\n d9 &= 0x1fff;\n d9 += h5 * r4;\n d9 += h6 * r3;\n d9 += h7 * r2;\n d9 += h8 * r1;\n d9 += h9 * r0;\n c += d9 >>> 13;\n d9 &= 0x1fff;\n\n c = ((c << 2) + c) | 0;\n c = (c + d0) | 0;\n d0 = c & 0x1fff;\n c = c >>> 13;\n d1 += c;\n\n h0 = d0;\n h1 = d1;\n h2 = d2;\n h3 = d3;\n h4 = d4;\n h5 = d5;\n h6 = d6;\n h7 = d7;\n h8 = d8;\n h9 = d9;\n\n mpos += 16;\n bytes -= 16;\n }\n this.h[0] = h0;\n this.h[1] = h1;\n this.h[2] = h2;\n this.h[3] = h3;\n this.h[4] = h4;\n this.h[5] = h5;\n this.h[6] = h6;\n this.h[7] = h7;\n this.h[8] = h8;\n this.h[9] = h9;\n }\n\n finish(mac: Uint8Array, macpos: number) {\n var g = new Uint16Array(10);\n var c, mask, f, i;\n\n if (this.leftover) {\n i = this.leftover;\n this.buffer[i++] = 1;\n for (; i < 16; i++) this.buffer[i] = 0;\n this.fin = 1;\n this.blocks(this.buffer, 0, 16);\n }\n\n c = this.h[1] >>> 13;\n this.h[1] &= 0x1fff;\n for (i = 2; i < 10; i++) {\n this.h[i] += c;\n c = this.h[i] >>> 13;\n this.h[i] &= 0x1fff;\n }\n this.h[0] += c * 5;\n c = this.h[0] >>> 13;\n this.h[0] &= 0x1fff;\n this.h[1] += c;\n c = this.h[1] >>> 13;\n this.h[1] &= 0x1fff;\n this.h[2] += c;\n\n g[0] = this.h[0] + 5;\n c = g[0] >>> 13;\n g[0] &= 0x1fff;\n for (i = 1; i < 10; i++) {\n g[i] = this.h[i] + c;\n c = g[i] >>> 13;\n g[i] &= 0x1fff;\n }\n g[9] -= 1 << 13;\n\n mask = (c ^ 1) - 1;\n for (i = 0; i < 10; i++) g[i] &= mask;\n mask = ~mask;\n for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i];\n\n this.h[0] = (this.h[0] | (this.h[1] << 13)) & 0xffff;\n this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10)) & 0xffff;\n this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7)) & 0xffff;\n this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4)) & 0xffff;\n this.h[4] =\n ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff;\n this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11)) & 0xffff;\n this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8)) & 0xffff;\n this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5)) & 0xffff;\n\n f = this.h[0] + this.pad[0];\n this.h[0] = f & 0xffff;\n for (i = 1; i < 8; i++) {\n f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0;\n this.h[i] = f & 0xffff;\n }\n\n mac[macpos + 0] = (this.h[0] >>> 0) & 0xff;\n mac[macpos + 1] = (this.h[0] >>> 8) & 0xff;\n mac[macpos + 2] = (this.h[1] >>> 0) & 0xff;\n mac[macpos + 3] = (this.h[1] >>> 8) & 0xff;\n mac[macpos + 4] = (this.h[2] >>> 0) & 0xff;\n mac[macpos + 5] = (this.h[2] >>> 8) & 0xff;\n mac[macpos + 6] = (this.h[3] >>> 0) & 0xff;\n mac[macpos + 7] = (this.h[3] >>> 8) & 0xff;\n mac[macpos + 8] = (this.h[4] >>> 0) & 0xff;\n mac[macpos + 9] = (this.h[4] >>> 8) & 0xff;\n mac[macpos + 10] = (this.h[5] >>> 0) & 0xff;\n mac[macpos + 11] = (this.h[5] >>> 8) & 0xff;\n mac[macpos + 12] = (this.h[6] >>> 0) & 0xff;\n mac[macpos + 13] = (this.h[6] >>> 8) & 0xff;\n mac[macpos + 14] = (this.h[7] >>> 0) & 0xff;\n mac[macpos + 15] = (this.h[7] >>> 8) & 0xff;\n }\n\n update(m: Uint8Array, mpos: number, bytes: number) {\n let i: number;\n let want: number;\n if (this.leftover) {\n want = 16 - this.leftover;\n if (want > bytes) want = bytes;\n for (i = 0; i < want; i++) this.buffer[this.leftover + i] = m[mpos + i];\n bytes -= want;\n mpos += want;\n this.leftover += want;\n if (this.leftover < 16) return;\n this.blocks(this.buffer, 0, 16);\n this.leftover = 0;\n }\n\n if (bytes >= 16) {\n want = bytes - (bytes % 16);\n this.blocks(m, mpos, want);\n mpos += want;\n bytes -= want;\n }\n\n if (bytes) {\n for (i = 0; i < bytes; i++) this.buffer[this.leftover + i] = m[mpos + i];\n this.leftover += bytes;\n }\n }\n}\n\nfunction crypto_onetimeauth(\n out: Uint8Array,\n outpos: number,\n m: any,\n mpos: number,\n n: number,\n k: Uint8Array,\n) {\n var s = new poly1305(k);\n s.update(m, mpos, n);\n s.finish(out, outpos);\n return 0;\n}\n\nfunction crypto_onetimeauth_verify(\n h: Uint8Array,\n hpos: number,\n m: any,\n mpos: number,\n n: number,\n k: Uint8Array,\n) {\n var x = new Uint8Array(16);\n crypto_onetimeauth(x, 0, m, mpos, n, k);\n return crypto_verify_16(h, hpos, x, 0);\n}\n\nfunction crypto_secretbox(\n c: Uint8Array,\n m: Uint8Array,\n d: number,\n n: Uint8Array,\n k: Uint8Array,\n): number {\n var i;\n if (d < 32) return -1;\n crypto_stream_xor(c, 0, m, 0, d, n, k);\n crypto_onetimeauth(c, 16, c, 32, d - 32, c);\n for (i = 0; i < 16; i++) c[i] = 0;\n return 0;\n}\n\nfunction crypto_secretbox_open(\n m: Uint8Array,\n c: Uint8Array,\n d: number,\n n: Uint8Array,\n k: Uint8Array,\n): number {\n var i;\n var x = new Uint8Array(32);\n if (d < 32) return -1;\n crypto_stream(x, 0, 32, n, k);\n if (crypto_onetimeauth_verify(c, 16, c, 32, d - 32, x) !== 0) return -1;\n crypto_stream_xor(m, 0, c, 0, d, n, k);\n for (i = 0; i < 32; i++) m[i] = 0;\n return 0;\n}\n\nfunction set25519(r: Float64Array, a: Float64Array): void {\n let i;\n for (i = 0; i < 16; i++) r[i] = a[i] | 0;\n}\n\nfunction car25519(o: Float64Array): void {\n let i,\n v,\n c = 1;\n for (i = 0; i < 16; i++) {\n v = o[i] + c + 65535;\n c = Math.floor(v / 65536);\n o[i] = v - c * 65536;\n }\n o[0] += c - 1 + 37 * (c - 1);\n}\n\nfunction sel25519(p: Float64Array, q: Float64Array, b: number): void {\n let t;\n const c = ~(b - 1);\n for (let i = 0; i < 16; i++) {\n t = c & (p[i] ^ q[i]);\n p[i] ^= t;\n q[i] ^= t;\n }\n}\n\nfunction pack25519(o: Uint8Array, n: Float64Array): void {\n let i, j, b;\n const m = gf(),\n t = gf();\n for (i = 0; i < 16; i++) t[i] = n[i];\n car25519(t);\n car25519(t);\n car25519(t);\n for (j = 0; j < 2; j++) {\n m[0] = t[0] - 0xffed;\n for (i = 1; i < 15; i++) {\n m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);\n m[i - 1] &= 0xffff;\n }\n m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);\n b = (m[15] >> 16) & 1;\n m[14] &= 0xffff;\n sel25519(t, m, 1 - b);\n }\n for (i = 0; i < 16; i++) {\n o[2 * i] = t[i] & 0xff;\n o[2 * i + 1] = t[i] >> 8;\n }\n}\n\nfunction neq25519(a: Float64Array, b: Float64Array): number {\n const c = new Uint8Array(32),\n d = new Uint8Array(32);\n pack25519(c, a);\n pack25519(d, b);\n return crypto_verify_32(c, 0, d, 0);\n}\n\nfunction par25519(a: Float64Array): number {\n const d = new Uint8Array(32);\n pack25519(d, a);\n return d[0] & 1;\n}\n\nfunction unpack25519(o: Float64Array, n: Uint8Array): void {\n let i;\n for (i = 0; i < 16; i++) o[i] = n[2 * i] + (n[2 * i + 1] << 8);\n o[15] &= 0x7fff;\n}\n\nfunction A(o: Float64Array, a: Float64Array, b: Float64Array): void {\n for (let i = 0; i < 16; i++) o[i] = a[i] + b[i];\n}\n\nfunction Z(o: Float64Array, a: Float64Array, b: Float64Array): void {\n for (let i = 0; i < 16; i++) o[i] = a[i] - b[i];\n}\n\nfunction M(o: Float64Array, a: Float64Array, b: Float64Array): void {\n let v,\n c,\n t0 = 0,\n t1 = 0,\n t2 = 0,\n t3 = 0,\n t4 = 0,\n t5 = 0,\n t6 = 0,\n t7 = 0,\n t8 = 0,\n t9 = 0,\n t10 = 0,\n t11 = 0,\n t12 = 0,\n t13 = 0,\n t14 = 0,\n t15 = 0,\n t16 = 0,\n t17 = 0,\n t18 = 0,\n t19 = 0,\n t20 = 0,\n t21 = 0,\n t22 = 0,\n t23 = 0,\n t24 = 0,\n t25 = 0,\n t26 = 0,\n t27 = 0,\n t28 = 0,\n t29 = 0,\n t30 = 0;\n const b0 = b[0],\n b1 = b[1],\n b2 = b[2],\n b3 = b[3],\n b4 = b[4],\n b5 = b[5],\n b6 = b[6],\n b7 = b[7],\n b8 = b[8],\n b9 = b[9],\n b10 = b[10],\n b11 = b[11],\n b12 = b[12],\n b13 = b[13],\n b14 = b[14],\n b15 = b[15];\n\n v = a[0];\n t0 += v * b0;\n t1 += v * b1;\n t2 += v * b2;\n t3 += v * b3;\n t4 += v * b4;\n t5 += v * b5;\n t6 += v * b6;\n t7 += v * b7;\n t8 += v * b8;\n t9 += v * b9;\n t10 += v * b10;\n t11 += v * b11;\n t12 += v * b12;\n t13 += v * b13;\n t14 += v * b14;\n t15 += v * b15;\n v = a[1];\n t1 += v * b0;\n t2 += v * b1;\n t3 += v * b2;\n t4 += v * b3;\n t5 += v * b4;\n t6 += v * b5;\n t7 += v * b6;\n t8 += v * b7;\n t9 += v * b8;\n t10 += v * b9;\n t11 += v * b10;\n t12 += v * b11;\n t13 += v * b12;\n t14 += v * b13;\n t15 += v * b14;\n t16 += v * b15;\n v = a[2];\n t2 += v * b0;\n t3 += v * b1;\n t4 += v * b2;\n t5 += v * b3;\n t6 += v * b4;\n t7 += v * b5;\n t8 += v * b6;\n t9 += v * b7;\n t10 += v * b8;\n t11 += v * b9;\n t12 += v * b10;\n t13 += v * b11;\n t14 += v * b12;\n t15 += v * b13;\n t16 += v * b14;\n t17 += v * b15;\n v = a[3];\n t3 += v * b0;\n t4 += v * b1;\n t5 += v * b2;\n t6 += v * b3;\n t7 += v * b4;\n t8 += v * b5;\n t9 += v * b6;\n t10 += v * b7;\n t11 += v * b8;\n t12 += v * b9;\n t13 += v * b10;\n t14 += v * b11;\n t15 += v * b12;\n t16 += v * b13;\n t17 += v * b14;\n t18 += v * b15;\n v = a[4];\n t4 += v * b0;\n t5 += v * b1;\n t6 += v * b2;\n t7 += v * b3;\n t8 += v * b4;\n t9 += v * b5;\n t10 += v * b6;\n t11 += v * b7;\n t12 += v * b8;\n t13 += v * b9;\n t14 += v * b10;\n t15 += v * b11;\n t16 += v * b12;\n t17 += v * b13;\n t18 += v * b14;\n t19 += v * b15;\n v = a[5];\n t5 += v * b0;\n t6 += v * b1;\n t7 += v * b2;\n t8 += v * b3;\n t9 += v * b4;\n t10 += v * b5;\n t11 += v * b6;\n t12 += v * b7;\n t13 += v * b8;\n t14 += v * b9;\n t15 += v * b10;\n t16 += v * b11;\n t17 += v * b12;\n t18 += v * b13;\n t19 += v * b14;\n t20 += v * b15;\n v = a[6];\n t6 += v * b0;\n t7 += v * b1;\n t8 += v * b2;\n t9 += v * b3;\n t10 += v * b4;\n t11 += v * b5;\n t12 += v * b6;\n t13 += v * b7;\n t14 += v * b8;\n t15 += v * b9;\n t16 += v * b10;\n t17 += v * b11;\n t18 += v * b12;\n t19 += v * b13;\n t20 += v * b14;\n t21 += v * b15;\n v = a[7];\n t7 += v * b0;\n t8 += v * b1;\n t9 += v * b2;\n t10 += v * b3;\n t11 += v * b4;\n t12 += v * b5;\n t13 += v * b6;\n t14 += v * b7;\n t15 += v * b8;\n t16 += v * b9;\n t17 += v * b10;\n t18 += v * b11;\n t19 += v * b12;\n t20 += v * b13;\n t21 += v * b14;\n t22 += v * b15;\n v = a[8];\n t8 += v * b0;\n t9 += v * b1;\n t10 += v * b2;\n t11 += v * b3;\n t12 += v * b4;\n t13 += v * b5;\n t14 += v * b6;\n t15 += v * b7;\n t16 += v * b8;\n t17 += v * b9;\n t18 += v * b10;\n t19 += v * b11;\n t20 += v * b12;\n t21 += v * b13;\n t22 += v * b14;\n t23 += v * b15;\n v = a[9];\n t9 += v * b0;\n t10 += v * b1;\n t11 += v * b2;\n t12 += v * b3;\n t13 += v * b4;\n t14 += v * b5;\n t15 += v * b6;\n t16 += v * b7;\n t17 += v * b8;\n t18 += v * b9;\n t19 += v * b10;\n t20 += v * b11;\n t21 += v * b12;\n t22 += v * b13;\n t23 += v * b14;\n t24 += v * b15;\n v = a[10];\n t10 += v * b0;\n t11 += v * b1;\n t12 += v * b2;\n t13 += v * b3;\n t14 += v * b4;\n t15 += v * b5;\n t16 += v * b6;\n t17 += v * b7;\n t18 += v * b8;\n t19 += v * b9;\n t20 += v * b10;\n t21 += v * b11;\n t22 += v * b12;\n t23 += v * b13;\n t24 += v * b14;\n t25 += v * b15;\n v = a[11];\n t11 += v * b0;\n t12 += v * b1;\n t13 += v * b2;\n t14 += v * b3;\n t15 += v * b4;\n t16 += v * b5;\n t17 += v * b6;\n t18 += v * b7;\n t19 += v * b8;\n t20 += v * b9;\n t21 += v * b10;\n t22 += v * b11;\n t23 += v * b12;\n t24 += v * b13;\n t25 += v * b14;\n t26 += v * b15;\n v = a[12];\n t12 += v * b0;\n t13 += v * b1;\n t14 += v * b2;\n t15 += v * b3;\n t16 += v * b4;\n t17 += v * b5;\n t18 += v * b6;\n t19 += v * b7;\n t20 += v * b8;\n t21 += v * b9;\n t22 += v * b10;\n t23 += v * b11;\n t24 += v * b12;\n t25 += v * b13;\n t26 += v * b14;\n t27 += v * b15;\n v = a[13];\n t13 += v * b0;\n t14 += v * b1;\n t15 += v * b2;\n t16 += v * b3;\n t17 += v * b4;\n t18 += v * b5;\n t19 += v * b6;\n t20 += v * b7;\n t21 += v * b8;\n t22 += v * b9;\n t23 += v * b10;\n t24 += v * b11;\n t25 += v * b12;\n t26 += v * b13;\n t27 += v * b14;\n t28 += v * b15;\n v = a[14];\n t14 += v * b0;\n t15 += v * b1;\n t16 += v * b2;\n t17 += v * b3;\n t18 += v * b4;\n t19 += v * b5;\n t20 += v * b6;\n t21 += v * b7;\n t22 += v * b8;\n t23 += v * b9;\n t24 += v * b10;\n t25 += v * b11;\n t26 += v * b12;\n t27 += v * b13;\n t28 += v * b14;\n t29 += v * b15;\n v = a[15];\n t15 += v * b0;\n t16 += v * b1;\n t17 += v * b2;\n t18 += v * b3;\n t19 += v * b4;\n t20 += v * b5;\n t21 += v * b6;\n t22 += v * b7;\n t23 += v * b8;\n t24 += v * b9;\n t25 += v * b10;\n t26 += v * b11;\n t27 += v * b12;\n t28 += v * b13;\n t29 += v * b14;\n t30 += v * b15;\n\n t0 += 38 * t16;\n t1 += 38 * t17;\n t2 += 38 * t18;\n t3 += 38 * t19;\n t4 += 38 * t20;\n t5 += 38 * t21;\n t6 += 38 * t22;\n t7 += 38 * t23;\n t8 += 38 * t24;\n t9 += 38 * t25;\n t10 += 38 * t26;\n t11 += 38 * t27;\n t12 += 38 * t28;\n t13 += 38 * t29;\n t14 += 38 * t30;\n // t15 left as is\n\n // first car\n c = 1;\n v = t0 + c + 65535;\n c = Math.floor(v / 65536);\n t0 = v - c * 65536;\n v = t1 + c + 65535;\n c = Math.floor(v / 65536);\n t1 = v - c * 65536;\n v = t2 + c + 65535;\n c = Math.floor(v / 65536);\n t2 = v - c * 65536;\n v = t3 + c + 65535;\n c = Math.floor(v / 65536);\n t3 = v - c * 65536;\n v = t4 + c + 65535;\n c = Math.floor(v / 65536);\n t4 = v - c * 65536;\n v = t5 + c + 65535;\n c = Math.floor(v / 65536);\n t5 = v - c * 65536;\n v = t6 + c + 65535;\n c = Math.floor(v / 65536);\n t6 = v - c * 65536;\n v = t7 + c + 65535;\n c = Math.floor(v / 65536);\n t7 = v - c * 65536;\n v = t8 + c + 65535;\n c = Math.floor(v / 65536);\n t8 = v - c * 65536;\n v = t9 + c + 65535;\n c = Math.floor(v / 65536);\n t9 = v - c * 65536;\n v = t10 + c + 65535;\n c = Math.floor(v / 65536);\n t10 = v - c * 65536;\n v = t11 + c + 65535;\n c = Math.floor(v / 65536);\n t11 = v - c * 65536;\n v = t12 + c + 65535;\n c = Math.floor(v / 65536);\n t12 = v - c * 65536;\n v = t13 + c + 65535;\n c = Math.floor(v / 65536);\n t13 = v - c * 65536;\n v = t14 + c + 65535;\n c = Math.floor(v / 65536);\n t14 = v - c * 65536;\n v = t15 + c + 65535;\n c = Math.floor(v / 65536);\n t15 = v - c * 65536;\n t0 += c - 1 + 37 * (c - 1);\n\n // second car\n c = 1;\n v = t0 + c + 65535;\n c = Math.floor(v / 65536);\n t0 = v - c * 65536;\n v = t1 + c + 65535;\n c = Math.floor(v / 65536);\n t1 = v - c * 65536;\n v = t2 + c + 65535;\n c = Math.floor(v / 65536);\n t2 = v - c * 65536;\n v = t3 + c + 65535;\n c = Math.floor(v / 65536);\n t3 = v - c * 65536;\n v = t4 + c + 65535;\n c = Math.floor(v / 65536);\n t4 = v - c * 65536;\n v = t5 + c + 65535;\n c = Math.floor(v / 65536);\n t5 = v - c * 65536;\n v = t6 + c + 65535;\n c = Math.floor(v / 65536);\n t6 = v - c * 65536;\n v = t7 + c + 65535;\n c = Math.floor(v / 65536);\n t7 = v - c * 65536;\n v = t8 + c + 65535;\n c = Math.floor(v / 65536);\n t8 = v - c * 65536;\n v = t9 + c + 65535;\n c = Math.floor(v / 65536);\n t9 = v - c * 65536;\n v = t10 + c + 65535;\n c = Math.floor(v / 65536);\n t10 = v - c * 65536;\n v = t11 + c + 65535;\n c = Math.floor(v / 65536);\n t11 = v - c * 65536;\n v = t12 + c + 65535;\n c = Math.floor(v / 65536);\n t12 = v - c * 65536;\n v = t13 + c + 65535;\n c = Math.floor(v / 65536);\n t13 = v - c * 65536;\n v = t14 + c + 65535;\n c = Math.floor(v / 65536);\n t14 = v - c * 65536;\n v = t15 + c + 65535;\n c = Math.floor(v / 65536);\n t15 = v - c * 65536;\n t0 += c - 1 + 37 * (c - 1);\n\n o[0] = t0;\n o[1] = t1;\n o[2] = t2;\n o[3] = t3;\n o[4] = t4;\n o[5] = t5;\n o[6] = t6;\n o[7] = t7;\n o[8] = t8;\n o[9] = t9;\n o[10] = t10;\n o[11] = t11;\n o[12] = t12;\n o[13] = t13;\n o[14] = t14;\n o[15] = t15;\n}\n\nfunction S(o: Float64Array, a: Float64Array): void {\n M(o, a, a);\n}\n\nfunction inv25519(o: Float64Array, i: Float64Array): void {\n const c = gf();\n let a;\n for (a = 0; a < 16; a++) c[a] = i[a];\n for (a = 253; a >= 0; a--) {\n S(c, c);\n if (a !== 2 && a !== 4) M(c, c, i);\n }\n for (a = 0; a < 16; a++) o[a] = c[a];\n}\n\nfunction pow2523(o: Float64Array, i: Float64Array): void {\n const c = gf();\n let a;\n for (a = 0; a < 16; a++) c[a] = i[a];\n for (a = 250; a >= 0; a--) {\n S(c, c);\n if (a !== 1) M(c, c, i);\n }\n for (a = 0; a < 16; a++) o[a] = c[a];\n}\n\nfunction crypto_scalarmult(\n q: Uint8Array,\n n: Uint8Array,\n p: Uint8Array,\n): number {\n const z = new Uint8Array(32);\n const x = new Float64Array(80);\n let r;\n let i;\n const a = gf(),\n b = gf(),\n c = gf(),\n d = gf(),\n e = gf(),\n f = gf();\n for (i = 0; i < 31; i++) z[i] = n[i];\n z[31] = (n[31] & 127) | 64;\n z[0] &= 248;\n unpack25519(x, p);\n for (i = 0; i < 16; i++) {\n b[i] = x[i];\n d[i] = a[i] = c[i] = 0;\n }\n a[0] = d[0] = 1;\n for (i = 254; i >= 0; --i) {\n r = (z[i >>> 3] >>> (i & 7)) & 1;\n sel25519(a, b, r);\n sel25519(c, d, r);\n A(e, a, c);\n Z(a, a, c);\n A(c, b, d);\n Z(b, b, d);\n S(d, e);\n S(f, a);\n M(a, c, a);\n M(c, b, e);\n A(e, a, c);\n Z(a, a, c);\n S(b, a);\n Z(c, d, f);\n M(a, c, _121665);\n A(a, a, d);\n M(c, c, a);\n M(a, d, f);\n M(d, b, x);\n S(b, e);\n sel25519(a, b, r);\n sel25519(c, d, r);\n }\n for (i = 0; i < 16; i++) {\n x[i + 16] = a[i];\n x[i + 32] = c[i];\n x[i + 48] = b[i];\n x[i + 64] = d[i];\n }\n const x32 = x.subarray(32);\n const x16 = x.subarray(16);\n inv25519(x32, x32);\n M(x16, x16, x32);\n pack25519(q, x16);\n return 0;\n}\n\nfunction crypto_scalarmult_base(q: Uint8Array, n: Uint8Array): number {\n return crypto_scalarmult(q, n, _9);\n}\n\nexport function crypto_scalarmult_noclamp(\n q: Uint8Array,\n n: Uint8Array,\n p: Uint8Array,\n): number {\n const z = new Uint8Array(32);\n const x = new Float64Array(80);\n let r;\n let i;\n const a = gf(),\n b = gf(),\n c = gf(),\n d = gf(),\n e = gf(),\n f = gf();\n for (i = 0; i < 31; i++) z[i] = n[i];\n unpack25519(x, p);\n for (i = 0; i < 16; i++) {\n b[i] = x[i];\n d[i] = a[i] = c[i] = 0;\n }\n a[0] = d[0] = 1;\n for (i = 254; i >= 0; --i) {\n r = (z[i >>> 3] >>> (i & 7)) & 1;\n sel25519(a, b, r);\n sel25519(c, d, r);\n A(e, a, c);\n Z(a, a, c);\n A(c, b, d);\n Z(b, b, d);\n S(d, e);\n S(f, a);\n M(a, c, a);\n M(c, b, e);\n A(e, a, c);\n Z(a, a, c);\n S(b, a);\n Z(c, d, f);\n M(a, c, _121665);\n A(a, a, d);\n M(c, c, a);\n M(a, d, f);\n M(d, b, x);\n S(b, e);\n sel25519(a, b, r);\n sel25519(c, d, r);\n }\n for (i = 0; i < 16; i++) {\n x[i + 16] = a[i];\n x[i + 32] = c[i];\n x[i + 48] = b[i];\n x[i + 64] = d[i];\n }\n const x32 = x.subarray(32);\n const x16 = x.subarray(16);\n inv25519(x32, x32);\n M(x16, x16, x32);\n pack25519(q, x16);\n return 0;\n}\n\nexport function crypto_scalarmult_base_noclamp(\n q: Uint8Array,\n n: Uint8Array,\n): number {\n return crypto_scalarmult_noclamp(q, n, _9);\n}\n\n// prettier-ignore\nconst K = [\n 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,\n 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,\n 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,\n 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,\n 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,\n 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,\n 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,\n 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,\n 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,\n 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,\n 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,\n 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,\n 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,\n 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,\n 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,\n 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,\n 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,\n 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,\n 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,\n 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,\n 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,\n 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,\n 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,\n 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,\n 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,\n 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,\n 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,\n 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,\n 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,\n 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,\n 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,\n 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,\n 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,\n 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,\n 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,\n 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,\n 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,\n 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,\n 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,\n 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817\n];\n\nfunction crypto_hashblocks_hl(\n hh: Int32Array,\n hl: Int32Array,\n m: Uint8Array,\n n: number,\n): number {\n const wh = new Int32Array(16),\n wl = new Int32Array(16);\n let bh0,\n bh1,\n bh2,\n bh3,\n bh4,\n bh5,\n bh6,\n bh7,\n bl0,\n bl1,\n bl2,\n bl3,\n bl4,\n bl5,\n bl6,\n bl7,\n th,\n tl,\n i,\n j,\n h,\n l,\n a,\n b,\n c,\n d;\n\n let ah0 = hh[0],\n ah1 = hh[1],\n ah2 = hh[2],\n ah3 = hh[3],\n ah4 = hh[4],\n ah5 = hh[5],\n ah6 = hh[6],\n ah7 = hh[7],\n al0 = hl[0],\n al1 = hl[1],\n al2 = hl[2],\n al3 = hl[3],\n al4 = hl[4],\n al5 = hl[5],\n al6 = hl[6],\n al7 = hl[7];\n\n let pos = 0;\n while (n >= 128) {\n for (i = 0; i < 16; i++) {\n j = 8 * i + pos;\n wh[i] = (m[j + 0] << 24) | (m[j + 1] << 16) | (m[j + 2] << 8) | m[j + 3];\n wl[i] = (m[j + 4] << 24) | (m[j + 5] << 16) | (m[j + 6] << 8) | m[j + 7];\n }\n for (i = 0; i < 80; i++) {\n bh0 = ah0;\n bh1 = ah1;\n bh2 = ah2;\n bh3 = ah3;\n bh4 = ah4;\n bh5 = ah5;\n bh6 = ah6;\n bh7 = ah7;\n\n bl0 = al0;\n bl1 = al1;\n bl2 = al2;\n bl3 = al3;\n bl4 = al4;\n bl5 = al5;\n bl6 = al6;\n bl7 = al7;\n\n // add\n h = ah7;\n l = al7;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n // Sigma1\n h =\n ((ah4 >>> 14) | (al4 << (32 - 14))) ^\n ((ah4 >>> 18) | (al4 << (32 - 18))) ^\n ((al4 >>> (41 - 32)) | (ah4 << (32 - (41 - 32))));\n l =\n ((al4 >>> 14) | (ah4 << (32 - 14))) ^\n ((al4 >>> 18) | (ah4 << (32 - 18))) ^\n ((ah4 >>> (41 - 32)) | (al4 << (32 - (41 - 32))));\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n // Ch\n h = (ah4 & ah5) ^ (~ah4 & ah6);\n l = (al4 & al5) ^ (~al4 & al6);\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n // K\n h = K[i * 2];\n l = K[i * 2 + 1];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n // w\n h = wh[i % 16];\n l = wl[i % 16];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n th = (c & 0xffff) | (d << 16);\n tl = (a & 0xffff) | (b << 16);\n\n // add\n h = th;\n l = tl;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n // Sigma0\n h =\n ((ah0 >>> 28) | (al0 << (32 - 28))) ^\n ((al0 >>> (34 - 32)) | (ah0 << (32 - (34 - 32)))) ^\n ((al0 >>> (39 - 32)) | (ah0 << (32 - (39 - 32))));\n l =\n ((al0 >>> 28) | (ah0 << (32 - 28))) ^\n ((ah0 >>> (34 - 32)) | (al0 << (32 - (34 - 32)))) ^\n ((ah0 >>> (39 - 32)) | (al0 << (32 - (39 - 32))));\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n // Maj\n h = (ah0 & ah1) ^ (ah0 & ah2) ^ (ah1 & ah2);\n l = (al0 & al1) ^ (al0 & al2) ^ (al1 & al2);\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n bh7 = (c & 0xffff) | (d << 16);\n bl7 = (a & 0xffff) | (b << 16);\n\n // add\n h = bh3;\n l = bl3;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = th;\n l = tl;\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n bh3 = (c & 0xffff) | (d << 16);\n bl3 = (a & 0xffff) | (b << 16);\n\n ah1 = bh0;\n ah2 = bh1;\n ah3 = bh2;\n ah4 = bh3;\n ah5 = bh4;\n ah6 = bh5;\n ah7 = bh6;\n ah0 = bh7;\n\n al1 = bl0;\n al2 = bl1;\n al3 = bl2;\n al4 = bl3;\n al5 = bl4;\n al6 = bl5;\n al7 = bl6;\n al0 = bl7;\n\n if (i % 16 === 15) {\n for (j = 0; j < 16; j++) {\n // add\n h = wh[j];\n l = wl[j];\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = wh[(j + 9) % 16];\n l = wl[(j + 9) % 16];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n // sigma0\n th = wh[(j + 1) % 16];\n tl = wl[(j + 1) % 16];\n h =\n ((th >>> 1) | (tl << (32 - 1))) ^\n ((th >>> 8) | (tl << (32 - 8))) ^\n (th >>> 7);\n l =\n ((tl >>> 1) | (th << (32 - 1))) ^\n ((tl >>> 8) | (th << (32 - 8))) ^\n ((tl >>> 7) | (th << (32 - 7)));\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n // sigma1\n th = wh[(j + 14) % 16];\n tl = wl[(j + 14) % 16];\n h =\n ((th >>> 19) | (tl << (32 - 19))) ^\n ((tl >>> (61 - 32)) | (th << (32 - (61 - 32)))) ^\n (th >>> 6);\n l =\n ((tl >>> 19) | (th << (32 - 19))) ^\n ((th >>> (61 - 32)) | (tl << (32 - (61 - 32)))) ^\n ((tl >>> 6) | (th << (32 - 6)));\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n wh[j] = (c & 0xffff) | (d << 16);\n wl[j] = (a & 0xffff) | (b << 16);\n }\n }\n }\n\n // add\n h = ah0;\n l = al0;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = hh[0];\n l = hl[0];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n hh[0] = ah0 = (c & 0xffff) | (d << 16);\n hl[0] = al0 = (a & 0xffff) | (b << 16);\n\n h = ah1;\n l = al1;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = hh[1];\n l = hl[1];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n hh[1] = ah1 = (c & 0xffff) | (d << 16);\n hl[1] = al1 = (a & 0xffff) | (b << 16);\n\n h = ah2;\n l = al2;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = hh[2];\n l = hl[2];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n hh[2] = ah2 = (c & 0xffff) | (d << 16);\n hl[2] = al2 = (a & 0xffff) | (b << 16);\n\n h = ah3;\n l = al3;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = hh[3];\n l = hl[3];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n hh[3] = ah3 = (c & 0xffff) | (d << 16);\n hl[3] = al3 = (a & 0xffff) | (b << 16);\n\n h = ah4;\n l = al4;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = hh[4];\n l = hl[4];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n hh[4] = ah4 = (c & 0xffff) | (d << 16);\n hl[4] = al4 = (a & 0xffff) | (b << 16);\n\n h = ah5;\n l = al5;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = hh[5];\n l = hl[5];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n hh[5] = ah5 = (c & 0xffff) | (d << 16);\n hl[5] = al5 = (a & 0xffff) | (b << 16);\n\n h = ah6;\n l = al6;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = hh[6];\n l = hl[6];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n hh[6] = ah6 = (c & 0xffff) | (d << 16);\n hl[6] = al6 = (a & 0xffff) | (b << 16);\n\n h = ah7;\n l = al7;\n\n a = l & 0xffff;\n b = l >>> 16;\n c = h & 0xffff;\n d = h >>> 16;\n\n h = hh[7];\n l = hl[7];\n\n a += l & 0xffff;\n b += l >>> 16;\n c += h & 0xffff;\n d += h >>> 16;\n\n b += a >>> 16;\n c += b >>> 16;\n d += c >>> 16;\n\n hh[7] = ah7 = (c & 0xffff) | (d << 16);\n hl[7] = al7 = (a & 0xffff) | (b << 16);\n\n pos += 128;\n n -= 128;\n }\n\n return n;\n}\n\nfunction crypto_hash(out: Uint8Array, m: Uint8Array, n: number): number {\n const hh = new Int32Array(8);\n const hl = new Int32Array(8);\n const x = new Uint8Array(256);\n const b = n;\n\n hh[0] = 0x6a09e667;\n hh[1] = 0xbb67ae85;\n hh[2] = 0x3c6ef372;\n hh[3] = 0xa54ff53a;\n hh[4] = 0x510e527f;\n hh[5] = 0x9b05688c;\n hh[6] = 0x1f83d9ab;\n hh[7] = 0x5be0cd19;\n\n hl[0] = 0xf3bcc908;\n hl[1] = 0x84caa73b;\n hl[2] = 0xfe94f82b;\n hl[3] = 0x5f1d36f1;\n hl[4] = 0xade682d1;\n hl[5] = 0x2b3e6c1f;\n hl[6] = 0xfb41bd6b;\n hl[7] = 0x137e2179;\n\n crypto_hashblocks_hl(hh, hl, m, n);\n n %= 128;\n\n for (let i = 0; i < n; i++) x[i] = m[b - n + i];\n x[n] = 128;\n\n n = 256 - 128 * (n < 112 ? 1 : 0);\n x[n - 9] = 0;\n ts64(x, n - 8, (b / 0x20000000) | 0, b << 3);\n crypto_hashblocks_hl(hh, hl, x, n);\n\n for (let i = 0; i < 8; i++) ts64(out, 8 * i, hh[i], hl[i]);\n\n return 0;\n}\n\n/**\n * Incremental version of crypto_hash.\n */\nexport class HashState {\n private hh = new Int32Array(8);\n private hl = new Int32Array(8);\n\n private next = new Uint8Array(128);\n private p = 0;\n private total = 0;\n\n constructor() {\n this.hh[0] = 0x6a09e667;\n this.hh[1] = 0xbb67ae85;\n this.hh[2] = 0x3c6ef372;\n this.hh[3] = 0xa54ff53a;\n this.hh[4] = 0x510e527f;\n this.hh[5] = 0x9b05688c;\n this.hh[6] = 0x1f83d9ab;\n this.hh[7] = 0x5be0cd19;\n\n this.hl[0] = 0xf3bcc908;\n this.hl[1] = 0x84caa73b;\n this.hl[2] = 0xfe94f82b;\n this.hl[3] = 0x5f1d36f1;\n this.hl[4] = 0xade682d1;\n this.hl[5] = 0x2b3e6c1f;\n this.hl[6] = 0xfb41bd6b;\n this.hl[7] = 0x137e2179;\n }\n\n update(data: Uint8Array): HashState {\n this.total += data.length;\n let i = 0;\n while (i < data.length) {\n const r = 128 - this.p;\n if (r > data.length - i) {\n for (let j = 0; i + j < data.length; j++) {\n this.next[this.p + j] = data[i + j];\n }\n this.p += data.length - i;\n break;\n } else {\n for (let j = 0; this.p + j < 128; j++) {\n this.next[this.p + j] = data[i + j];\n }\n crypto_hashblocks_hl(this.hh, this.hl, this.next, 128);\n i += 128 - this.p;\n this.p = 0;\n }\n }\n return this;\n }\n\n finish(): Uint8Array {\n const out = new Uint8Array(64);\n let n = this.p;\n const x = new Uint8Array(256);\n const b = this.total;\n for (let i = 0; i < n; i++) x[i] = this.next[i];\n x[n] = 128;\n\n n = 256 - 128 * (n < 112 ? 1 : 0);\n x[n - 9] = 0;\n ts64(x, n - 8, (b / 0x20000000) | 0, b << 3);\n crypto_hashblocks_hl(this.hh, this.hl, x, n);\n\n for (let i = 0; i < 8; i++) ts64(out, 8 * i, this.hh[i], this.hl[i]);\n return out;\n }\n}\n\nfunction add(p: Float64Array[], q: Float64Array[]): void {\n const a = gf(),\n b = gf(),\n c = gf(),\n d = gf(),\n e = gf(),\n f = gf(),\n g = gf(),\n h = gf(),\n t = gf();\n\n Z(a, p[1], p[0]);\n Z(t, q[1], q[0]);\n M(a, a, t);\n A(b, p[0], p[1]);\n A(t, q[0], q[1]);\n M(b, b, t);\n M(c, p[3], q[3]);\n M(c, c, D2);\n M(d, p[2], q[2]);\n A(d, d, d);\n Z(e, b, a);\n Z(f, d, c);\n A(g, d, c);\n A(h, b, a);\n\n M(p[0], e, f);\n M(p[1], h, g);\n M(p[2], g, f);\n M(p[3], e, h);\n}\n\nfunction cswap(p: Float64Array[], q: Float64Array[], b: number): void {\n let i;\n for (i = 0; i < 4; i++) {\n sel25519(p[i], q[i], b);\n }\n}\n\nfunction pack(r: Uint8Array, p: Float64Array[]): void {\n const tx = gf(),\n ty = gf(),\n zi = gf();\n inv25519(zi, p[2]);\n M(tx, p[0], zi);\n M(ty, p[1], zi);\n pack25519(r, ty);\n r[31] ^= par25519(tx) << 7;\n}\n\n/**\n * Ed25519 scalar multiplication\n */\nfunction scalarmult(p: Float64Array[], q: Float64Array[], s: Uint8Array): void {\n let b, i;\n set25519(p[0], gf0);\n set25519(p[1], gf1);\n set25519(p[2], gf1);\n set25519(p[3], gf0);\n for (i = 255; i >= 0; --i) {\n b = (s[(i / 8) | 0] >> (i & 7)) & 1;\n cswap(p, q, b);\n add(q, p);\n add(p, p);\n cswap(p, q, b);\n }\n}\n\nfunction scalarbase(p: Float64Array[], s: Uint8Array): void {\n const q = [gf(), gf(), gf(), gf()];\n set25519(q[0], X);\n set25519(q[1], Y);\n set25519(q[2], gf1);\n M(q[3], X, Y);\n scalarmult(p, q, s);\n}\n\nfunction crypto_sign_keypair(\n pk: Uint8Array,\n sk: Uint8Array,\n seeded: boolean,\n): number {\n const d = new Uint8Array(64);\n const p = [gf(), gf(), gf(), gf()];\n\n if (!seeded) randombytes(sk, 32);\n crypto_hash(d, sk, 32);\n d[0] &= 248;\n d[31] &= 127;\n d[31] |= 64;\n\n scalarbase(p, d);\n pack(pk, p);\n\n for (let i = 0; i < 32; i++) sk[i + 32] = pk[i];\n return 0;\n}\n\nexport const L = new Float64Array([\n 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde,\n 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10,\n]);\n\nfunction modL(r: Uint8Array, x: Float64Array): void {\n let carry, i, j, k;\n for (i = 63; i >= 32; --i) {\n carry = 0;\n for (j = i - 32, k = i - 12; j < k; ++j) {\n x[j] += carry - 16 * x[i] * L[j - (i - 32)];\n carry = Math.floor((x[j] + 128) / 256);\n x[j] -= carry * 256;\n }\n x[j] += carry;\n x[i] = 0;\n }\n carry = 0;\n for (j = 0; j < 32; j++) {\n x[j] += carry - (x[31] >> 4) * L[j];\n carry = x[j] >> 8;\n x[j] &= 255;\n }\n for (j = 0; j < 32; j++) x[j] -= carry * L[j];\n for (i = 0; i < 32; i++) {\n x[i + 1] += x[i] >> 8;\n r[i] = x[i] & 255;\n }\n}\n\nfunction reduce(r: Uint8Array): void {\n const x = new Float64Array(64);\n for (let i = 0; i < 64; i++) x[i] = r[i];\n for (let i = 0; i < 64; i++) r[i] = 0;\n modL(r, x);\n}\n\n// Note: difference from C - smlen returned, not passed as argument.\nfunction crypto_sign(\n sm: Uint8Array,\n m: Uint8Array,\n n: number,\n sk: Uint8Array,\n): number {\n const d = new Uint8Array(64),\n h = new Uint8Array(64),\n r = new Uint8Array(64);\n let i, j;\n const x = new Float64Array(64);\n const p = [gf(), gf(), gf(), gf()];\n\n crypto_hash(d, sk, 32);\n d[0] &= 248;\n d[31] &= 127;\n d[31] |= 64;\n\n const smlen = n + 64;\n for (i = 0; i < n; i++) sm[64 + i] = m[i];\n for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i];\n\n crypto_hash(r, sm.subarray(32), n + 32);\n reduce(r);\n scalarbase(p, r);\n pack(sm, p);\n\n for (i = 32; i < 64; i++) sm[i] = sk[i];\n crypto_hash(h, sm, n + 64);\n reduce(h);\n\n for (i = 0; i < 64; i++) x[i] = 0;\n for (i = 0; i < 32; i++) x[i] = r[i];\n for (i = 0; i < 32; i++) {\n for (j = 0; j < 32; j++) {\n x[i + j] += h[i] * d[j];\n }\n }\n\n modL(sm.subarray(32), x);\n return smlen;\n}\n\nfunction unpackpos(r: Float64Array[], p: Uint8Array): number {\n // FIXME: implement directly\n const q = [gf(), gf(), gf(), gf()];\n if (unpackneg(q, p)) return -1;\n const scalar0 = new Uint8Array(32);\n const scalar1 = new Uint8Array(32);\n scalar1[0] = 1;\n const scalarNeg1 = crypto_core_ed25519_scalar_sub(scalar0, scalar1);\n scalarmult(r, q, scalarNeg1);\n return 0;\n}\n\nfunction unpackneg(r: Float64Array[], p: Uint8Array): number {\n const t = gf();\n const chk = gf();\n const num = gf();\n const den = gf();\n const den2 = gf();\n const den4 = gf();\n const den6 = gf();\n\n set25519(r[2], gf1);\n unpack25519(r[1], p);\n S(num, r[1]);\n M(den, num, D);\n Z(num, num, r[2]);\n A(den, r[2], den);\n\n S(den2, den);\n S(den4, den2);\n M(den6, den4, den2);\n M(t, den6, num);\n M(t, t, den);\n\n pow2523(t, t);\n M(t, t, num);\n M(t, t, den);\n M(t, t, den);\n M(r[0], t, den);\n\n S(chk, r[0]);\n M(chk, chk, den);\n if (neq25519(chk, num)) M(r[0], r[0], I);\n\n S(chk, r[0]);\n M(chk, chk, den);\n if (neq25519(chk, num)) return -1;\n\n if (par25519(r[0]) === p[31] >> 7) Z(r[0], gf0, r[0]);\n\n M(r[3], r[0], r[1]);\n return 0;\n}\n\nexport function crypto_scalarmult_ed25519_base_noclamp(\n s: Uint8Array,\n): Uint8Array {\n const r = new Uint8Array(32);\n const p = [gf(), gf(), gf(), gf()];\n\n scalarbase(p, s);\n pack(r, p);\n return r;\n}\n\nexport function crypto_scalarmult_ed25519_noclamp(\n s: Uint8Array,\n q: Uint8Array,\n): Uint8Array {\n const r = new Uint8Array(32);\n const p = [gf(), gf(), gf(), gf()];\n const ql = [gf(), gf(), gf(), gf()];\n\n if (unpackpos(ql, q)) throw new Error();\n scalarmult(p, ql, s);\n pack(r, p);\n return r;\n}\n\nexport function crypto_core_ed25519_add(\n p1: Uint8Array,\n p2: Uint8Array,\n): Uint8Array {\n const q1 = [gf(), gf(), gf(), gf()];\n const q2 = [gf(), gf(), gf(), gf()];\n const res = new Uint8Array(32);\n if (unpackpos(q1, p1)) throw new Error();\n if (unpackpos(q2, p2)) throw new Error();\n add(q1, q2);\n pack(res, q1);\n return res;\n}\n\nfunction crypto_sign_open(\n m: Uint8Array,\n sm: Uint8Array,\n n: number,\n pk: Uint8Array,\n): number {\n let i, mlen;\n const t = new Uint8Array(32),\n h = new Uint8Array(64);\n const p = [gf(), gf(), gf(), gf()],\n q = [gf(), gf(), gf(), gf()];\n\n mlen = -1;\n if (n < 64) return -1;\n\n if (unpackneg(q, pk)) return -1;\n\n for (i = 0; i < n; i++) m[i] = sm[i];\n for (i = 0; i < 32; i++) m[i + 32] = pk[i];\n crypto_hash(h, m, n);\n reduce(h);\n scalarmult(p, q, h);\n\n scalarbase(q, sm.subarray(32));\n add(p, q);\n pack(t, p);\n\n n -= 64;\n if (crypto_verify_32(sm, 0, t, 0)) {\n for (i = 0; i < n; i++) m[i] = 0;\n return -1;\n }\n\n for (i = 0; i < n; i++) m[i] = sm[i + 64];\n mlen = n;\n return mlen;\n}\n\nconst crypto_secretbox_KEYBYTES = 32;\nconst crypto_secretbox_NONCEBYTES = 24;\nconst crypto_secretbox_ZEROBYTES = 32;\nconst crypto_secretbox_BOXZEROBYTES = 16;\nconst crypto_scalarmult_BYTES = 32;\nconst crypto_scalarmult_SCALARBYTES = 32;\nconst crypto_sign_BYTES = 64;\nconst crypto_sign_PUBLICKEYBYTES = 32;\nconst crypto_sign_SECRETKEYBYTES = 64;\nconst crypto_sign_SEEDBYTES = 32;\nconst crypto_hash_BYTES = 64;\n\n/* High-level API */\n\nfunction checkLengths(k: Uint8Array, n: Uint8Array) {\n if (k.length !== crypto_secretbox_KEYBYTES) throw new Error(\"bad key size\");\n if (n.length !== crypto_secretbox_NONCEBYTES)\n throw new Error(\"bad nonce size\");\n}\n\nfunction checkArrayTypes(...args: Uint8Array[]): void {\n for (let i = 0; i < args.length; i++) {\n if (!(args[i] instanceof Uint8Array))\n throw new TypeError(\"unexpected type, use Uint8Array\");\n }\n}\n\nexport function randomBytes(n: number): Uint8Array {\n const b = new Uint8Array(n);\n randombytes(b, n);\n return b;\n}\n\nexport function scalarMult(n: Uint8Array, p: Uint8Array): Uint8Array {\n checkArrayTypes(n, p);\n if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error(\"bad n size\");\n if (p.length !== crypto_scalarmult_BYTES) throw new Error(\"bad p size\");\n const q = new Uint8Array(crypto_scalarmult_BYTES);\n crypto_scalarmult(q, n, p);\n return q;\n}\n\nexport function scalarMult_base(n: Uint8Array): Uint8Array {\n checkArrayTypes(n);\n if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error(\"bad n size\");\n const q = new Uint8Array(crypto_scalarmult_BYTES);\n crypto_scalarmult_base(q, n);\n return q;\n}\n\nexport const scalarMult_scalarLength = crypto_scalarmult_SCALARBYTES;\nexport const scalarMult_groupElementLength = crypto_scalarmult_BYTES;\n\nexport function sign(msg: Uint8Array, secretKey: Uint8Array): Uint8Array {\n checkArrayTypes(msg, secretKey);\n if (secretKey.length !== crypto_sign_SECRETKEYBYTES)\n throw new Error(\"bad secret key size\");\n const signedMsg = new Uint8Array(crypto_sign_BYTES + msg.length);\n crypto_sign(signedMsg, msg, msg.length, secretKey);\n return signedMsg;\n}\n\nexport function sign_open(\n signedMsg: Uint8Array,\n publicKey: Uint8Array,\n): Uint8Array | null {\n checkArrayTypes(signedMsg, publicKey);\n if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)\n throw new Error(\"bad public key size\");\n const tmp = new Uint8Array(signedMsg.length);\n const mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey);\n if (mlen < 0) return null;\n const m = new Uint8Array(mlen);\n for (let i = 0; i < m.length; i++) m[i] = tmp[i];\n return m;\n}\n\nexport function sign_detached(\n msg: Uint8Array,\n secretKey: Uint8Array,\n): Uint8Array {\n const signedMsg = sign(msg, secretKey);\n const sig = new Uint8Array(crypto_sign_BYTES);\n for (let i = 0; i < sig.length; i++) sig[i] = signedMsg[i];\n return sig;\n}\n\nexport function sign_detached_verify(\n msg: Uint8Array,\n sig: Uint8Array,\n publicKey: Uint8Array,\n): boolean {\n checkArrayTypes(msg, sig, publicKey);\n if (sig.length !== crypto_sign_BYTES) throw new Error(\"bad signature size\");\n if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)\n throw new Error(\"bad public key size\");\n const sm = new Uint8Array(crypto_sign_BYTES + msg.length);\n const m = new Uint8Array(crypto_sign_BYTES + msg.length);\n let i;\n for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i];\n for (i = 0; i < msg.length; i++) sm[i + crypto_sign_BYTES] = msg[i];\n return crypto_sign_open(m, sm, sm.length, publicKey) >= 0;\n}\n\nexport function sign_keyPair(): {\n publicKey: Uint8Array;\n secretKey: Uint8Array;\n} {\n const pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);\n const sk = new Uint8Array(crypto_sign_SECRETKEYBYTES);\n crypto_sign_keypair(pk, sk, false);\n return { publicKey: pk, secretKey: sk };\n}\n\nexport function x25519_edwards_keyPair_fromSecretKey(\n secretKey: Uint8Array,\n): Uint8Array {\n const p = [gf(), gf(), gf(), gf()];\n const pk = new Uint8Array(32);\n\n const d = new Uint8Array(64);\n if (secretKey.length != 32) {\n throw new Error(\"bad secret key size\");\n }\n d.set(secretKey, 0);\n\n d[0] &= 248;\n d[31] &= 127;\n d[31] |= 64;\n\n scalarbase(p, d);\n pack(pk, p);\n\n return pk;\n}\n\nexport function crypto_sign_keyPair_fromSecretKey(secretKey: Uint8Array): {\n publicKey: Uint8Array;\n secretKey: Uint8Array;\n} {\n checkArrayTypes(secretKey);\n if (secretKey.length !== crypto_sign_SECRETKEYBYTES)\n throw new Error(\"bad secret key size\");\n const pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);\n for (let i = 0; i < pk.length; i++) pk[i] = secretKey[32 + i];\n return { publicKey: pk, secretKey: new Uint8Array(secretKey) };\n}\n\nexport function crypto_sign_keyPair_fromSeed(seed: Uint8Array): {\n publicKey: Uint8Array;\n secretKey: Uint8Array;\n} {\n checkArrayTypes(seed);\n if (seed.length !== crypto_sign_SEEDBYTES)\n throw new Error(`bad seed size: ${seed.length}`);\n const pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES);\n const sk = new Uint8Array(crypto_sign_SECRETKEYBYTES);\n for (let i = 0; i < 32; i++) sk[i] = seed[i];\n crypto_sign_keypair(pk, sk, true);\n return { publicKey: pk, secretKey: sk };\n}\n\nexport const sign_publicKeyLength = crypto_sign_PUBLICKEYBYTES;\nexport const sign_secretKeyLength = crypto_sign_SECRETKEYBYTES;\nexport const sign_seedLength = crypto_sign_SEEDBYTES;\nexport const sign_signatureLength = crypto_sign_BYTES;\n\nexport function hash(msg: Uint8Array): Uint8Array {\n checkArrayTypes(msg);\n const h = new Uint8Array(crypto_hash_BYTES);\n crypto_hash(h, msg, msg.length);\n return h;\n}\n\nexport const hash_hashLength = crypto_hash_BYTES;\n\nexport function verify(x: Uint8Array, y: Uint8Array): boolean {\n checkArrayTypes(x, y);\n // Zero length arguments are considered not equal.\n if (x.length === 0 || y.length === 0) return false;\n if (x.length !== y.length) return false;\n return vn(x, 0, y, 0, x.length) === 0 ? true : false;\n}\n\nexport function setPRNG(fn: (x: Uint8Array, n: number) => void): void {\n randombytes = fn;\n}\n\nexport function sign_ed25519_pk_to_curve25519(\n ed25519_pk: Uint8Array,\n): Uint8Array {\n const ge_a = [gf(), gf(), gf(), gf()];\n const x = gf();\n const one_minus_y = gf();\n const x25519_pk = new Uint8Array(32);\n\n if (unpackneg(ge_a, ed25519_pk)) {\n throw Error(\"invalid public key\");\n }\n\n set25519(one_minus_y, gf1);\n Z(one_minus_y, one_minus_y, ge_a[1]);\n\n set25519(x, gf1);\n A(x, x, ge_a[1]);\n\n inv25519(one_minus_y, one_minus_y);\n M(x, x, one_minus_y);\n pack25519(x25519_pk, x);\n\n return x25519_pk;\n}\n\nexport function secretbox(\n msg: Uint8Array,\n nonce: Uint8Array,\n key: Uint8Array,\n): Uint8Array {\n checkArrayTypes(msg, nonce, key);\n checkLengths(key, nonce);\n var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length);\n var c = new Uint8Array(m.length);\n for (var i = 0; i < msg.length; i++)\n m[i + crypto_secretbox_ZEROBYTES] = msg[i];\n crypto_secretbox(c, m, m.length, nonce, key);\n return c.subarray(crypto_secretbox_BOXZEROBYTES);\n}\n\nexport function secretbox_open(\n box: Uint8Array,\n nonce: Uint8Array,\n key: Uint8Array,\n): Uint8Array | undefined {\n checkArrayTypes(box, nonce, key);\n checkLengths(key, nonce);\n var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length);\n var m = new Uint8Array(c.length);\n for (var i = 0; i < box.length; i++)\n c[i + crypto_secretbox_BOXZEROBYTES] = box[i];\n if (c.length < 32) return undefined;\n if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return undefined;\n return m.subarray(crypto_secretbox_ZEROBYTES);\n}\n\nexport function crypto_core_ed25519_scalar_add(\n x: Uint8Array,\n y: Uint8Array,\n): Uint8Array {\n const z = new Float64Array(64);\n for (let i = 0; i < 32; i++) {\n z[i] = x[i] + y[i];\n }\n const o = new Uint8Array(32);\n modL(o, z);\n return o;\n}\n\n/**\n * Reduce a scalar \"s\" to \"s mod L\". The input can be up to 64 bytes long.\n */\nexport function crypto_core_ed25519_scalar_reduce(x: Uint8Array): Uint8Array {\n const len = x.length;\n const z = new Float64Array(64);\n for (let i = 0; i < len; i++) z[i] = x[i];\n const o = new Uint8Array(32);\n modL(o, z);\n return o;\n}\n\nexport function crypto_core_ed25519_scalar_sub(\n x: Uint8Array,\n y: Uint8Array,\n): Uint8Array {\n const z = new Float64Array(64);\n for (let i = 0; i < 32; i++) {\n z[i] = x[i] - y[i];\n }\n const o = new Uint8Array(32);\n modL(o, z);\n return o;\n}\n\nexport function crypto_edx25519_private_key_create(): Uint8Array {\n const seed = new Uint8Array(32);\n randombytes(seed, 32);\n return crypto_edx25519_private_key_create_from_seed(seed);\n}\n\nexport function crypto_edx25519_private_key_create_from_seed(\n seed: Uint8Array,\n): Uint8Array {\n const pk = hash(seed);\n pk[0] &= 248;\n pk[31] &= 127;\n pk[31] |= 64;\n return pk;\n}\n\nexport function crypto_edx25519_get_public(priv: Uint8Array): Uint8Array {\n return crypto_scalarmult_ed25519_base_noclamp(priv.subarray(0, 32));\n}\n\nexport function crypto_edx25519_sign_detached(\n m: Uint8Array,\n skx: Uint8Array,\n pkx: Uint8Array,\n): Uint8Array {\n const n: number = m.length;\n const h = new Uint8Array(64);\n const r = new Uint8Array(64);\n let i, j;\n const x = new Float64Array(64);\n const p = [gf(), gf(), gf(), gf()];\n\n const sm = new Uint8Array(n + 64);\n\n for (i = 0; i < n; i++) sm[64 + i] = m[i];\n for (i = 0; i < 32; i++) sm[32 + i] = skx[32 + i];\n\n crypto_hash(r, sm.subarray(32), n + 32);\n reduce(r);\n scalarbase(p, r);\n pack(sm, p);\n\n for (i = 32; i < 64; i++) sm[i] = pkx[i - 32];\n crypto_hash(h, sm, n + 64);\n reduce(h);\n\n for (i = 0; i < 64; i++) x[i] = 0;\n for (i = 0; i < 32; i++) x[i] = r[i];\n for (i = 0; i < 32; i++) {\n for (j = 0; j < 32; j++) {\n x[i + j] += h[i] * skx[j];\n }\n }\n\n modL(sm.subarray(32), x);\n return sm.subarray(0, 64);\n}\n\nexport function crypto_edx25519_sign_detached_verify(\n msg: Uint8Array,\n sig: Uint8Array,\n publicKey: Uint8Array,\n): boolean {\n checkArrayTypes(msg, sig, publicKey);\n if (sig.length !== crypto_sign_BYTES) throw new Error(\"bad signature size\");\n if (publicKey.length !== crypto_sign_PUBLICKEYBYTES)\n throw new Error(\"bad public key size\");\n const sm = new Uint8Array(crypto_sign_BYTES + msg.length);\n const m = new Uint8Array(crypto_sign_BYTES + msg.length);\n let i;\n for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i];\n for (i = 0; i < msg.length; i++) sm[i + crypto_sign_BYTES] = msg[i];\n return crypto_sign_open(m, sm, sm.length, publicKey) >= 0;\n}\n", "import { setPRNG } from \"./nacl-fast.js\";\n\n/**\n * This only be used when taler util is packaged to run in browser\n * but run in non-browser environment which is common for\n * unit testing. Under this conditions no random is ok.\n */\nconst nullRandom = {\n getRandomValues: (c: Uint8Array) => c,\n};\n\nexport function loadBrowserPrng() {\n // Initialize PRNG if environment provides CSPRNG.\n // If not, methods calling randombytes will throw.\n const cr =\n // @ts-expect-error self is not defined\n typeof self !== \"undefined\" ? self.crypto || self.msCrypto : nullRandom;\n\n const QUOTA = 65536;\n setPRNG(function (x: Uint8Array, n: number) {\n let i;\n const v = new Uint8Array(n);\n for (i = 0; i < n; i += QUOTA) {\n cr.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA)));\n }\n for (i = 0; i < n; i++) x[i] = v[i];\n for (i = 0; i < v.length; i++) v[i] = 0;\n });\n}\n", "/*\nCopyright Mathias Bynens \nCopyright (c) 2022 Taler Systems S.A.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n\n/** Highest positive signed 32-bit float value */\nconst maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1\n\n/** Bootstring parameters */\nconst base = 36;\nconst tMin = 1;\nconst tMax = 26;\nconst skew = 38;\nconst damp = 700;\nconst initialBias = 72;\nconst initialN = 128; // 0x80\nconst delimiter = \"-\"; // '\\x2D'\n\n/** Regular expressions */\nconst regexPunycode = /^xn--/;\nconst regexNonASCII = /[^\\0-\\x7E]/; // non-ASCII chars\nconst regexSeparators = /[\\x2E\\u3002\\uFF0E\\uFF61]/g; // RFC 3490 separators\n\n/** Error messages */\nconst errors = {\n overflow: \"Overflow: input needs wider integers to process\",\n \"not-basic\": \"Illegal input >= 0x80 (not a basic code point)\",\n \"invalid-input\": \"Invalid input\",\n} as { [x: string]: string };\n\n/** Convenience shortcuts */\nconst baseMinusTMin = base - tMin;\nconst floor = Math.floor;\nconst stringFromCharCode = String.fromCharCode;\n\n/*--------------------------------------------------------------------------*/\n\n/**\n * A generic error utility function.\n * @private\n * @param {String} type The error type.\n * @returns {Error} Throws a `RangeError` with the applicable error message.\n */\nfunction error(type: string) {\n throw new RangeError(errors[type]);\n}\n\n/**\n * A generic `Array#map` utility function.\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} callback The function that gets called for every array\n * item.\n * @returns {Array} A new array of values returned by the callback function.\n */\nfunction map(array: any[], fn: (arg0: any) => any) {\n const result = [];\n let length = array.length;\n while (length--) {\n result[length] = fn(array[length]);\n }\n return result;\n}\n\n/**\n * A simple `Array#map`-like wrapper to work with domain name strings or email\n * addresses.\n * @private\n * @param {String} domain The domain name or email address.\n * @param {Function} callback The function that gets called for every\n * character.\n * @returns {Array} A new string of characters returned by the callback\n * function.\n */\nfunction mapDomain(\n string: string,\n fn: { (string: any): any; (string: any): any; (arg0: any): any },\n) {\n const parts = string.split(\"@\");\n let result = \"\";\n if (parts.length > 1) {\n // In email addresses, only the domain name should be punycoded. Leave\n // the local part (i.e. everything up to `@`) intact.\n result = parts[0] + \"@\";\n string = parts[1];\n }\n // Avoid `split(regex)` for IE8 compatibility. See #17.\n string = string.replace(regexSeparators, \"\\x2E\");\n const labels = string.split(\".\");\n const encoded = map(labels, fn).join(\".\");\n return result + encoded;\n}\n\n/**\n * Creates an array containing the numeric code points of each Unicode\n * character in the string. While JavaScript uses UCS-2 internally,\n * this function will convert a pair of surrogate halves (each of which\n * UCS-2 exposes as separate characters) into a single code point,\n * matching UTF-16.\n * @see `punycode.ucs2.encode`\n * @see \n * @memberOf punycode.ucs2\n * @name decode\n * @param {String} string The Unicode input string (UCS-2).\n * @returns {Array} The new array of code points.\n */\nfunction ucs2decode(string: string) {\n const output = [];\n let counter = 0;\n const length = string.length;\n while (counter < length) {\n const value = string.charCodeAt(counter++);\n if (value >= 0xd800 && value <= 0xdbff && counter < length) {\n // It's a high surrogate, and there is a next character.\n const extra = string.charCodeAt(counter++);\n if ((extra & 0xfc00) == 0xdc00) {\n // Low surrogate.\n output.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);\n } else {\n // It's an unmatched surrogate; only append this code unit, in case the\n // next code unit is the high surrogate of a surrogate pair.\n output.push(value);\n counter--;\n }\n } else {\n output.push(value);\n }\n }\n return output;\n}\n\n/**\n * Creates a string based on an array of numeric code points.\n * @see `punycode.ucs2.decode`\n * @memberOf punycode.ucs2\n * @name encode\n * @param {Array} codePoints The array of numeric code points.\n * @returns {String} The new Unicode string (UCS-2).\n */\nconst ucs2encode = (array: any): string => String.fromCodePoint(...array);\n\n/**\n * Converts a basic code point into a digit/integer.\n * @see `digitToBasic()`\n * @private\n * @param {Number} codePoint The basic numeric code point value.\n * @returns {Number} The numeric value of a basic code point (for use in\n * representing integers) in the range `0` to `base - 1`, or `base` if\n * the code point does not represent a value.\n */\nconst basicToDigit = function (codePoint: number) {\n if (codePoint - 0x30 < 0x0a) {\n return codePoint - 0x16;\n }\n if (codePoint - 0x41 < 0x1a) {\n return codePoint - 0x41;\n }\n if (codePoint - 0x61 < 0x1a) {\n return codePoint - 0x61;\n }\n return base;\n};\n\n/**\n * Converts a digit/integer into a basic code point.\n * @see `basicToDigit()`\n * @private\n * @param {Number} digit The numeric value of a basic code point.\n * @returns {Number} The basic code point whose value (when used for\n * representing integers) is `digit`, which needs to be in the range\n * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is\n * used; else, the lowercase form is used. The behavior is undefined\n * if `flag` is non-zero and `digit` has no uppercase form.\n */\nconst digitToBasic = function (digit: number, flag: number) {\n // 0..25 map to ASCII a..z or A..Z\n // 26..35 map to ASCII 0..9\n return digit + 22 + 75 * Number(digit < 26) - (Number(flag != 0) << 5);\n};\n\n/**\n * Bias adaptation function as per section 3.4 of RFC 3492.\n * https://tools.ietf.org/html/rfc3492#section-3.4\n * @private\n */\nconst adapt = function (delta: number, numPoints: number, firstTime: boolean) {\n let k = 0;\n delta = firstTime ? floor(delta / damp) : delta >> 1;\n delta += floor(delta / numPoints);\n for (\n ;\n /* no initialization */ delta > (baseMinusTMin * tMax) >> 1;\n k += base\n ) {\n delta = floor(delta / baseMinusTMin);\n }\n return floor(k + ((baseMinusTMin + 1) * delta) / (delta + skew));\n};\n\n/**\n * Converts a Punycode string of ASCII-only symbols to a string of Unicode\n * symbols.\n * @memberOf punycode\n * @param {String} input The Punycode string of ASCII-only symbols.\n * @returns {String} The resulting string of Unicode symbols.\n */\nconst decode = function (input: string) {\n // Don't use UCS-2.\n const output = [];\n const inputLength = input.length;\n let i = 0;\n let n = initialN;\n let bias = initialBias;\n\n // Handle the basic code points: let `basic` be the number of input code\n // points before the last delimiter, or `0` if there is none, then copy\n // the first basic code points to the output.\n\n let basic = input.lastIndexOf(delimiter);\n if (basic < 0) {\n basic = 0;\n }\n\n for (let j = 0; j < basic; ++j) {\n // if it's not a basic code point\n if (input.charCodeAt(j) >= 0x80) {\n error(\"not-basic\");\n }\n output.push(input.charCodeAt(j));\n }\n\n // Main decoding loop: start just after the last delimiter if any basic code\n // points were copied; start at the beginning otherwise.\n\n for (\n let index = basic > 0 ? basic + 1 : 0;\n index < inputLength /* no final expression */;\n ) {\n // `index` is the index of the next character to be consumed.\n // Decode a generalized variable-length integer into `delta`,\n // which gets added to `i`. The overflow checking is easier\n // if we increase `i` as we go, then subtract off its starting\n // value at the end to obtain `delta`.\n let oldi = i;\n for (let w = 1, k = base /* no condition */; ; k += base) {\n if (index >= inputLength) {\n error(\"invalid-input\");\n }\n\n const digit = basicToDigit(input.charCodeAt(index++));\n\n if (digit >= base || digit > floor((maxInt - i) / w)) {\n error(\"overflow\");\n }\n\n i += digit * w;\n const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;\n\n if (digit < t) {\n break;\n }\n\n const baseMinusT = base - t;\n if (w > floor(maxInt / baseMinusT)) {\n error(\"overflow\");\n }\n\n w *= baseMinusT;\n }\n\n const out = output.length + 1;\n bias = adapt(i - oldi, out, oldi == 0);\n\n // `i` was supposed to wrap around from `out` to `0`,\n // incrementing `n` each time, so we'll fix that now:\n if (floor(i / out) > maxInt - n) {\n error(\"overflow\");\n }\n\n n += floor(i / out);\n i %= out;\n\n // Insert `n` at position `i` of the output.\n output.splice(i++, 0, n);\n }\n\n return String.fromCodePoint(...output);\n};\n\n/**\n * Converts a string of Unicode symbols (e.g. a domain name label) to a\n * Punycode string of ASCII-only symbols.\n * @memberOf punycode\n * @param {String} input The string of Unicode symbols.\n * @returns {String} The resulting Punycode string of ASCII-only symbols.\n */\nconst encode = function (inputArg: string) {\n const output = [];\n\n // Convert the input in UCS-2 to an array of Unicode code points.\n let input = ucs2decode(inputArg);\n\n // Cache the length.\n let inputLength = input.length;\n\n // Initialize the state.\n let n = initialN;\n let delta = 0;\n let bias = initialBias;\n\n // Handle the basic code points.\n for (const currentValue of input) {\n if (currentValue < 0x80) {\n output.push(stringFromCharCode(currentValue));\n }\n }\n\n let basicLength = output.length;\n let handledCPCount = basicLength;\n\n // `handledCPCount` is the number of code points that have been handled;\n // `basicLength` is the number of basic code points.\n\n // Finish the basic string with a delimiter unless it's empty.\n if (basicLength) {\n output.push(delimiter);\n }\n\n // Main encoding loop:\n while (handledCPCount < inputLength) {\n // All non-basic code points < n have been handled already. Find the next\n // larger one:\n let m = maxInt;\n for (const currentValue of input) {\n if (currentValue >= n && currentValue < m) {\n m = currentValue;\n }\n }\n\n // Increase `delta` enough to advance the decoder's state to ,\n // but guard against overflow.\n const handledCPCountPlusOne = handledCPCount + 1;\n if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {\n error(\"overflow\");\n }\n\n delta += (m - n) * handledCPCountPlusOne;\n n = m;\n\n for (const currentValue of input) {\n if (currentValue < n && ++delta > maxInt) {\n error(\"overflow\");\n }\n if (currentValue == n) {\n // Represent delta as a generalized variable-length integer.\n let q = delta;\n for (let k = base /* no condition */; ; k += base) {\n const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;\n if (q < t) {\n break;\n }\n const qMinusT = q - t;\n const baseMinusT = base - t;\n output.push(\n stringFromCharCode(digitToBasic(t + (qMinusT % baseMinusT), 0)),\n );\n q = floor(qMinusT / baseMinusT);\n }\n\n output.push(stringFromCharCode(digitToBasic(q, 0)));\n bias = adapt(\n delta,\n handledCPCountPlusOne,\n handledCPCount == basicLength,\n );\n delta = 0;\n ++handledCPCount;\n }\n }\n\n ++delta;\n ++n;\n }\n return output.join(\"\");\n};\n\n/**\n * Converts a Punycode string representing a domain name or an email address\n * to Unicode. Only the Punycoded parts of the input will be converted, i.e.\n * it doesn't matter if you call it on a string that has already been\n * converted to Unicode.\n * @memberOf punycode\n * @param {String} input The Punycoded domain name or email address to\n * convert to Unicode.\n * @returns {String} The Unicode representation of the given Punycode\n * string.\n */\nconst toUnicode = function (input: string) {\n return mapDomain(input, function (string) {\n return regexPunycode.test(string)\n ? decode(string.slice(4).toLowerCase())\n : string;\n });\n};\n\n/**\n * Converts a Unicode string representing a domain name or an email address to\n * Punycode. Only the non-ASCII parts of the domain name will be converted,\n * i.e. it doesn't matter if you call it with a domain that's already in\n * ASCII.\n * @memberOf punycode\n * @param {String} input The domain name or email address to convert, as a\n * Unicode string.\n * @returns {String} The Punycode representation of the given domain name or\n * email address.\n */\nconst toASCII = function (input: string) {\n return mapDomain(input, function (string) {\n return regexNonASCII.test(string) ? \"xn--\" + encode(string) : string;\n });\n};\n\n/*--------------------------------------------------------------------------*/\n\n/** Define the public API */\nexport const punycode = {\n /**\n * A string representing the current Punycode.js version number.\n * @memberOf punycode\n * @type String\n */\n version: \"2.1.0\",\n /**\n * An object of methods to convert from JavaScript's internal character\n * representation (UCS-2) to Unicode code points, and back.\n * @see \n * @memberOf punycode\n * @type Object\n */\n ucs2: {\n decode: ucs2decode,\n encode: ucs2encode,\n },\n decode: decode,\n encode: encode,\n toASCII: toASCII,\n toUnicode: toUnicode,\n};\n", "/*\nThe MIT License (MIT)\n\nCopyright (c) Sebastian Mayr\nCopyright (c) 2022 Taler Systems S.A.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\n// Vendored with modifications (TypeScript etc.) from https://github.com/jsdom/whatwg-url\n\nconst utf8Encoder = new TextEncoder();\nconst utf8Decoder = new TextDecoder(\"utf-8\", { ignoreBOM: true });\n\nfunction utf8Encode(string: string | undefined) {\n return utf8Encoder.encode(string);\n}\n\nfunction utf8DecodeWithoutBOM(bytes: Uint8Array) {\n return utf8Decoder.decode(bytes);\n}\n\n// https://url.spec.whatwg.org/#concept-urlencoded-parser\nfunction parseUrlencoded(input: Uint8Array) {\n const sequences = strictlySplitByteSequence(input, p(\"&\"));\n const output = [];\n for (const bytes of sequences) {\n if (bytes.length === 0) {\n continue;\n }\n\n let name, value;\n const indexOfEqual = bytes.indexOf(p(\"=\")!);\n\n if (indexOfEqual >= 0) {\n name = bytes.slice(0, indexOfEqual);\n value = bytes.slice(indexOfEqual + 1);\n } else {\n name = bytes;\n value = new Uint8Array(0);\n }\n\n name = replaceByteInByteSequence(name, 0x2b, 0x20);\n value = replaceByteInByteSequence(value, 0x2b, 0x20);\n\n const nameString = utf8DecodeWithoutBOM(percentDecodeBytes(name));\n const valueString = utf8DecodeWithoutBOM(percentDecodeBytes(value));\n\n output.push([nameString, valueString]);\n }\n return output;\n}\n\n// https://url.spec.whatwg.org/#concept-urlencoded-string-parser\nfunction parseUrlencodedString(input: string | undefined) {\n return parseUrlencoded(utf8Encode(input));\n}\n\n// https://url.spec.whatwg.org/#concept-urlencoded-serializer\nfunction serializeUrlencoded(tuples: any[], encodingOverride = undefined) {\n let encoding = \"utf-8\";\n if (encodingOverride !== undefined) {\n // TODO \"get the output encoding\", i.e. handle encoding labels vs. names.\n encoding = encodingOverride;\n }\n\n let output = \"\";\n for (const [i, tuple] of tuples.entries()) {\n // TODO: handle encoding override\n\n const name = utf8PercentEncodeString(\n tuple[0],\n isURLEncodedPercentEncode,\n true,\n );\n\n let value = tuple[1];\n if (tuple.length > 2 && tuple[2] !== undefined) {\n if (tuple[2] === \"hidden\" && name === \"_charset_\") {\n value = encoding;\n } else if (tuple[2] === \"file\") {\n // value is a File object\n value = value.name;\n }\n }\n\n value = utf8PercentEncodeString(value, isURLEncodedPercentEncode, true);\n\n if (i !== 0) {\n output += \"&\";\n }\n output += `${name}=${value}`;\n }\n return output;\n}\n\nfunction strictlySplitByteSequence(buf: Uint8Array, cp: any) {\n const list = [];\n let last = 0;\n let i = buf.indexOf(cp);\n while (i >= 0) {\n list.push(buf.slice(last, i));\n last = i + 1;\n i = buf.indexOf(cp, last);\n }\n if (last !== buf.length) {\n list.push(buf.slice(last));\n }\n return list;\n}\n\nfunction replaceByteInByteSequence(buf: Uint8Array, from: number, to: number) {\n let i = buf.indexOf(from);\n while (i >= 0) {\n buf[i] = to;\n i = buf.indexOf(from, i + 1);\n }\n return buf;\n}\n\nfunction p(char: string) {\n return char.codePointAt(0);\n}\n\n// https://url.spec.whatwg.org/#percent-encode\nfunction percentEncode(c: number) {\n let hex = c.toString(16).toUpperCase();\n if (hex.length === 1) {\n hex = `0${hex}`;\n }\n\n return `%${hex}`;\n}\n\n// https://url.spec.whatwg.org/#percent-decode\nfunction percentDecodeBytes(input: Uint8Array): Uint8Array {\n const output = new Uint8Array(input.byteLength);\n let outputIndex = 0;\n for (let i = 0; i < input.byteLength; ++i) {\n const byte = input[i];\n if (byte !== 0x25) {\n output[outputIndex++] = byte;\n } else if (\n byte === 0x25 &&\n (!isASCIIHex(input[i + 1]) || !isASCIIHex(input[i + 2]))\n ) {\n output[outputIndex++] = byte;\n } else {\n const bytePoint = parseInt(\n String.fromCodePoint(input[i + 1], input[i + 2]),\n 16,\n );\n output[outputIndex++] = bytePoint;\n i += 2;\n }\n }\n\n return output.slice(0, outputIndex);\n}\n\n// https://url.spec.whatwg.org/#string-percent-decode\nfunction percentDecodeString(input: string) {\n const bytes = utf8Encode(input);\n return percentDecodeBytes(bytes);\n}\n\n// https://url.spec.whatwg.org/#c0-control-percent-encode-set\nfunction isC0ControlPercentEncode(c: number) {\n return c <= 0x1f || c > 0x7e;\n}\n\n// https://url.spec.whatwg.org/#fragment-percent-encode-set\nconst extraFragmentPercentEncodeSet = new Set([\n p(\" \"),\n p('\"'),\n p(\"<\"),\n p(\">\"),\n p(\"`\"),\n]);\n\nfunction isFragmentPercentEncode(c: number) {\n return isC0ControlPercentEncode(c) || extraFragmentPercentEncodeSet.has(c);\n}\n\n// https://url.spec.whatwg.org/#query-percent-encode-set\nconst extraQueryPercentEncodeSet = new Set([\n p(\" \"),\n p('\"'),\n p(\"#\"),\n p(\"<\"),\n p(\">\"),\n]);\n\nfunction isQueryPercentEncode(c: number) {\n return isC0ControlPercentEncode(c) || extraQueryPercentEncodeSet.has(c);\n}\n\n// https://url.spec.whatwg.org/#special-query-percent-encode-set\nfunction isSpecialQueryPercentEncode(c: number) {\n return isQueryPercentEncode(c) || c === p(\"'\");\n}\n\n// https://url.spec.whatwg.org/#path-percent-encode-set\nconst extraPathPercentEncodeSet = new Set([p(\"?\"), p(\"`\"), p(\"{\"), p(\"}\")]);\nfunction isPathPercentEncode(c: number) {\n return isQueryPercentEncode(c) || extraPathPercentEncodeSet.has(c);\n}\n\n// https://url.spec.whatwg.org/#userinfo-percent-encode-set\nconst extraUserinfoPercentEncodeSet = new Set([\n p(\"/\"),\n p(\":\"),\n p(\";\"),\n p(\"=\"),\n p(\"@\"),\n p(\"[\"),\n p(\"\\\\\"),\n p(\"]\"),\n p(\"^\"),\n p(\"|\"),\n]);\nfunction isUserinfoPercentEncode(c: number) {\n return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c);\n}\n\n// https://url.spec.whatwg.org/#component-percent-encode-set\nconst extraComponentPercentEncodeSet = new Set([\n p(\"$\"),\n p(\"%\"),\n p(\"&\"),\n p(\"+\"),\n p(\",\"),\n]);\nfunction isComponentPercentEncode(c: number) {\n return isUserinfoPercentEncode(c) || extraComponentPercentEncodeSet.has(c);\n}\n\n// https://url.spec.whatwg.org/#application-x-www-form-urlencoded-percent-encode-set\nconst extraURLEncodedPercentEncodeSet = new Set([\n p(\"!\"),\n p(\"'\"),\n p(\"(\"),\n p(\")\"),\n p(\"~\"),\n]);\n\nfunction isURLEncodedPercentEncode(c: number) {\n return isComponentPercentEncode(c) || extraURLEncodedPercentEncodeSet.has(c);\n}\n\n// https://url.spec.whatwg.org/#code-point-percent-encode-after-encoding\n// https://url.spec.whatwg.org/#utf-8-percent-encode\n// Assuming encoding is always utf-8 allows us to trim one of the logic branches. TODO: support encoding.\n// The \"-Internal\" variant here has code points as JS strings. The external version used by other files has code points\n// as JS numbers, like the rest of the codebase.\nfunction utf8PercentEncodeCodePointInternal(\n codePoint: string,\n percentEncodePredicate: (arg0: number) => any,\n) {\n const bytes = utf8Encode(codePoint);\n let output = \"\";\n for (const byte of bytes) {\n // Our percentEncodePredicate operates on bytes, not code points, so this is slightly different from the spec.\n if (!percentEncodePredicate(byte)) {\n output += String.fromCharCode(byte);\n } else {\n output += percentEncode(byte);\n }\n }\n\n return output;\n}\n\nfunction utf8PercentEncodeCodePoint(\n codePoint: number,\n percentEncodePredicate: (arg0: number) => any,\n) {\n return utf8PercentEncodeCodePointInternal(\n String.fromCodePoint(codePoint),\n percentEncodePredicate,\n );\n}\n\n// https://url.spec.whatwg.org/#string-percent-encode-after-encoding\n// https://url.spec.whatwg.org/#string-utf-8-percent-encode\nfunction utf8PercentEncodeString(\n input: string,\n percentEncodePredicate: {\n (c: number): boolean;\n (c: number): boolean;\n (arg0: number): any;\n },\n spaceAsPlus = false,\n) {\n let output = \"\";\n for (const codePoint of input) {\n if (spaceAsPlus && codePoint === \" \") {\n output += \"+\";\n } else {\n output += utf8PercentEncodeCodePointInternal(\n codePoint,\n percentEncodePredicate,\n );\n }\n }\n return output;\n}\n\n// Note that we take code points as JS numbers, not JS strings.\n\nfunction isASCIIDigit(c: number) {\n return c >= 0x30 && c <= 0x39;\n}\n\nfunction isASCIIAlpha(c: number) {\n return (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a);\n}\n\nfunction isASCIIAlphanumeric(c: number) {\n return isASCIIAlpha(c) || isASCIIDigit(c);\n}\n\nfunction isASCIIHex(c: number) {\n return (\n isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66)\n );\n}\n\nexport class URLSearchParamsImpl {\n _list: any[];\n _url: any;\n constructor(init: any, { doNotStripQMark = false }: any = {}) {\n this._list = [];\n this._url = null;\n\n if (!doNotStripQMark && typeof init === \"string\" && init[0] === \"?\") {\n init = init.slice(1);\n }\n\n if (Array.isArray(init)) {\n for (const pair of init) {\n if (pair.length !== 2) {\n throw new TypeError(\n \"Failed to construct 'URLSearchParams': parameter 1 sequence's element does not \" +\n \"contain exactly two elements.\",\n );\n }\n this._list.push([pair[0], pair[1]]);\n }\n } else if (\n typeof init === \"object\" &&\n Object.getPrototypeOf(init) === null\n ) {\n for (const name of Object.keys(init)) {\n const value = init[name];\n this._list.push([name, value]);\n }\n } else {\n this._list = parseUrlencodedString(init);\n }\n }\n\n _updateSteps() {\n if (this._url !== null) {\n let query: string | null = serializeUrlencoded(this._list);\n if (query === \"\") {\n query = null;\n }\n this._url._url.query = query;\n }\n }\n\n append(name: string, value: string) {\n this._list.push([name, value]);\n this._updateSteps();\n }\n\n delete(name: string) {\n let i = 0;\n while (i < this._list.length) {\n if (this._list[i][0] === name) {\n this._list.splice(i, 1);\n } else {\n i++;\n }\n }\n this._updateSteps();\n }\n\n get(name: string) {\n for (const tuple of this._list) {\n if (tuple[0] === name) {\n return tuple[1];\n }\n }\n return null;\n }\n\n getAll(name: string) {\n const output = [];\n for (const tuple of this._list) {\n if (tuple[0] === name) {\n output.push(tuple[1]);\n }\n }\n return output;\n }\n\n get size(): number {\n return this._list.length;\n }\n\n entries() {\n return [...this._list.map((x) => [x[0], x[1]])];\n }\n\n forEach(\n callbackfn: (\n value: string,\n key: string,\n parent: URLSearchParamsImpl,\n ) => void,\n thisArg?: any,\n ): void {\n for (const tuple of this._list) {\n callbackfn.call(thisArg, tuple[1], tuple[0], this);\n }\n }\n\n has(name: string) {\n for (const tuple of this._list) {\n if (tuple[0] === name) {\n return true;\n }\n }\n return false;\n }\n\n set(name: string, value: string) {\n let found = false;\n let i = 0;\n while (i < this._list.length) {\n if (this._list[i][0] === name) {\n if (found) {\n this._list.splice(i, 1);\n } else {\n found = true;\n this._list[i][1] = value;\n i++;\n }\n } else {\n i++;\n }\n }\n if (!found) {\n this._list.push([name, value]);\n }\n this._updateSteps();\n }\n\n sort() {\n this._list.sort((a, b) => {\n if (a[0] < b[0]) {\n return -1;\n }\n if (a[0] > b[0]) {\n return 1;\n }\n return 0;\n });\n\n this._updateSteps();\n }\n\n [Symbol.iterator]() {\n return this._list[Symbol.iterator]();\n }\n\n toString() {\n return serializeUrlencoded(this._list);\n }\n}\n\nconst specialSchemes = {\n ftp: 21,\n file: null,\n http: 80,\n https: 443,\n ws: 80,\n wss: 443,\n} as { [x: string]: number | null };\n\nconst failure = Symbol(\"failure\");\n\nfunction countSymbols(str: any) {\n return [...str].length;\n}\n\nfunction at(input: any, idx: any) {\n const c = input[idx];\n return isNaN(c) ? undefined : String.fromCodePoint(c);\n}\n\nfunction isSingleDot(buffer: string) {\n return buffer === \".\" || buffer.toLowerCase() === \"%2e\";\n}\n\nfunction isDoubleDot(buffer: string) {\n buffer = buffer.toLowerCase();\n return (\n buffer === \"..\" ||\n buffer === \"%2e.\" ||\n buffer === \".%2e\" ||\n buffer === \"%2e%2e\"\n );\n}\n\nfunction isWindowsDriveLetterCodePoints(cp1: number, cp2: number) {\n return isASCIIAlpha(cp1) && (cp2 === p(\":\") || cp2 === p(\"|\"));\n}\n\nfunction isWindowsDriveLetterString(string: string) {\n return (\n string.length === 2 &&\n isASCIIAlpha(string.codePointAt(0)!) &&\n (string[1] === \":\" || string[1] === \"|\")\n );\n}\n\nfunction isNormalizedWindowsDriveLetterString(string: string) {\n return (\n string.length === 2 &&\n isASCIIAlpha(string.codePointAt(0)!) &&\n string[1] === \":\"\n );\n}\n\nfunction containsForbiddenHostCodePoint(string: string) {\n return (\n string.search(\n /\\u0000|\\u0009|\\u000A|\\u000D|\\u0020|#|\\/|:|<|>|\\?|@|\\[|\\\\|\\]|\\^|\\|/u,\n ) !== -1\n );\n}\n\nfunction containsForbiddenDomainCodePoint(string: string) {\n return (\n containsForbiddenHostCodePoint(string) ||\n string.search(/[\\u0000-\\u001F]|%|\\u007F/u) !== -1\n );\n}\n\nfunction isSpecialScheme(scheme: string) {\n return specialSchemes[scheme] !== undefined;\n}\n\nfunction isSpecial(url: any) {\n return isSpecialScheme(url.scheme);\n}\n\nfunction isNotSpecial(url: UrlObj) {\n return !isSpecialScheme(url.scheme);\n}\n\nfunction defaultPort(scheme: string) {\n return specialSchemes[scheme];\n}\n\nfunction parseIPv4Number(input: string) {\n if (input === \"\") {\n return failure;\n }\n\n let R = 10;\n\n if (\n input.length >= 2 &&\n input.charAt(0) === \"0\" &&\n input.charAt(1).toLowerCase() === \"x\"\n ) {\n input = input.substring(2);\n R = 16;\n } else if (input.length >= 2 && input.charAt(0) === \"0\") {\n input = input.substring(1);\n R = 8;\n }\n\n if (input === \"\") {\n return 0;\n }\n\n let regex = /[^0-7]/u;\n if (R === 10) {\n regex = /[^0-9]/u;\n }\n if (R === 16) {\n regex = /[^0-9A-Fa-f]/u;\n }\n\n if (regex.test(input)) {\n return failure;\n }\n\n return parseInt(input, R);\n}\n\nfunction parseIPv4(input: string) {\n const parts = input.split(\".\");\n if (parts[parts.length - 1] === \"\") {\n if (parts.length > 1) {\n parts.pop();\n }\n }\n\n if (parts.length > 4) {\n return failure;\n }\n\n const numbers = [];\n for (const part of parts) {\n const n = parseIPv4Number(part);\n if (n === failure) {\n return failure;\n }\n\n numbers.push(n);\n }\n\n for (let i = 0; i < numbers.length - 1; ++i) {\n if (numbers[i] > 255) {\n return failure;\n }\n }\n if (numbers[numbers.length - 1] >= 256 ** (5 - numbers.length)) {\n return failure;\n }\n\n let ipv4 = numbers.pop();\n let counter = 0;\n\n for (const n of numbers) {\n ipv4! += n * 256 ** (3 - counter);\n ++counter;\n }\n\n return ipv4;\n}\n\nfunction serializeIPv4(address: number) {\n let output = \"\";\n let n = address;\n\n for (let i = 1; i <= 4; ++i) {\n output = String(n % 256) + output;\n if (i !== 4) {\n output = `.${output}`;\n }\n n = Math.floor(n / 256);\n }\n\n return output;\n}\n\nfunction parseIPv6(inputArg: string) {\n const address = [0, 0, 0, 0, 0, 0, 0, 0];\n let pieceIndex = 0;\n let compress = null;\n let pointer = 0;\n\n const input = Array.from(inputArg, (c) => c.codePointAt(0));\n\n if (input[pointer] === p(\":\")) {\n if (input[pointer + 1] !== p(\":\")) {\n return failure;\n }\n\n pointer += 2;\n ++pieceIndex;\n compress = pieceIndex;\n }\n\n while (pointer < input.length) {\n if (pieceIndex === 8) {\n return failure;\n }\n\n if (input[pointer] === p(\":\")) {\n if (compress !== null) {\n return failure;\n }\n ++pointer;\n ++pieceIndex;\n compress = pieceIndex;\n continue;\n }\n\n let value = 0;\n let length = 0;\n\n while (length < 4 && isASCIIHex(input[pointer]!)) {\n value = value * 0x10 + parseInt(at(input, pointer)!, 16);\n ++pointer;\n ++length;\n }\n\n if (input[pointer] === p(\".\")) {\n if (length === 0) {\n return failure;\n }\n\n pointer -= length;\n\n if (pieceIndex > 6) {\n return failure;\n }\n\n let numbersSeen = 0;\n\n while (input[pointer] !== undefined) {\n let ipv4Piece = null;\n\n if (numbersSeen > 0) {\n if (input[pointer] === p(\".\") && numbersSeen < 4) {\n ++pointer;\n } else {\n return failure;\n }\n }\n\n if (!isASCIIDigit(input[pointer]!)) {\n return failure;\n }\n\n while (isASCIIDigit(input[pointer]!)) {\n const number = parseInt(at(input, pointer)!);\n if (ipv4Piece === null) {\n ipv4Piece = number;\n } else if (ipv4Piece === 0) {\n return failure;\n } else {\n ipv4Piece = ipv4Piece * 10 + number;\n }\n if (ipv4Piece > 255) {\n return failure;\n }\n ++pointer;\n }\n\n address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece!;\n\n ++numbersSeen;\n\n if (numbersSeen === 2 || numbersSeen === 4) {\n ++pieceIndex;\n }\n }\n\n if (numbersSeen !== 4) {\n return failure;\n }\n\n break;\n } else if (input[pointer] === p(\":\")) {\n ++pointer;\n if (input[pointer] === undefined) {\n return failure;\n }\n } else if (input[pointer] !== undefined) {\n return failure;\n }\n\n address[pieceIndex] = value;\n ++pieceIndex;\n }\n\n if (compress !== null) {\n let swaps = pieceIndex - compress;\n pieceIndex = 7;\n while (pieceIndex !== 0 && swaps > 0) {\n const temp = address[compress + swaps - 1];\n address[compress + swaps - 1] = address[pieceIndex];\n address[pieceIndex] = temp;\n --pieceIndex;\n --swaps;\n }\n } else if (compress === null && pieceIndex !== 8) {\n return failure;\n }\n\n return address;\n}\n\nfunction serializeIPv6(address: any[]) {\n let output = \"\";\n const compress = findLongestZeroSequence(address);\n let ignore0 = false;\n\n for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) {\n if (ignore0 && address[pieceIndex] === 0) {\n continue;\n } else if (ignore0) {\n ignore0 = false;\n }\n\n if (compress === pieceIndex) {\n const separator = pieceIndex === 0 ? \"::\" : \":\";\n output += separator;\n ignore0 = true;\n continue;\n }\n\n output += address[pieceIndex].toString(16);\n\n if (pieceIndex !== 7) {\n output += \":\";\n }\n }\n\n return output;\n}\n\nfunction parseHost(input: string, isNotSpecialArg = false) {\n if (input[0] === \"[\") {\n if (input[input.length - 1] !== \"]\") {\n return failure;\n }\n\n return parseIPv6(input.substring(1, input.length - 1));\n }\n\n if (isNotSpecialArg) {\n return parseOpaqueHost(input);\n }\n\n const domain = utf8DecodeWithoutBOM(percentDecodeString(input));\n const asciiDomain = domainToASCII(domain);\n if (asciiDomain === failure) {\n return failure;\n }\n\n if (containsForbiddenDomainCodePoint(asciiDomain)) {\n return failure;\n }\n\n if (endsInANumber(asciiDomain)) {\n return parseIPv4(asciiDomain);\n }\n\n return asciiDomain;\n}\n\nfunction endsInANumber(input: string) {\n const parts = input.split(\".\");\n if (parts[parts.length - 1] === \"\") {\n if (parts.length === 1) {\n return false;\n }\n parts.pop();\n }\n\n const last = parts[parts.length - 1];\n if (parseIPv4Number(last) !== failure) {\n return true;\n }\n\n if (/^[0-9]+$/u.test(last)) {\n return true;\n }\n\n return false;\n}\n\nfunction parseOpaqueHost(input: string) {\n if (containsForbiddenHostCodePoint(input)) {\n return failure;\n }\n\n return utf8PercentEncodeString(input, isC0ControlPercentEncode);\n}\n\nfunction findLongestZeroSequence(arr: number[]) {\n let maxIdx = null;\n let maxLen = 1; // only find elements > 1\n let currStart = null;\n let currLen = 0;\n\n for (let i = 0; i < arr.length; ++i) {\n if (arr[i] !== 0) {\n if (currLen > maxLen) {\n maxIdx = currStart;\n maxLen = currLen;\n }\n\n currStart = null;\n currLen = 0;\n } else {\n if (currStart === null) {\n currStart = i;\n }\n ++currLen;\n }\n }\n\n // if trailing zeros\n if (currLen > maxLen) {\n return currStart;\n }\n\n return maxIdx;\n}\n\nfunction serializeHost(host: number | number[] | string) {\n if (typeof host === \"number\") {\n return serializeIPv4(host);\n }\n\n // IPv6 serializer\n if (host instanceof Array) {\n return `[${serializeIPv6(host)}]`;\n }\n\n return host;\n}\n\nimport { punycode } from \"./punycode.js\";\n\nfunction domainToASCII(domain: string, beStrict = false) {\n // const result = tr46.toASCII(domain, {\n // checkBidi: true,\n // checkHyphens: false,\n // checkJoiners: true,\n // useSTD3ASCIIRules: beStrict,\n // verifyDNSLength: beStrict,\n // });\n let result;\n try {\n result = punycode.toASCII(domain);\n } catch (e) {\n return failure;\n }\n if (result === null || result === \"\") {\n return failure;\n }\n return result;\n}\n\nfunction trimControlChars(url: string) {\n return url.replace(/^[\\u0000-\\u001F\\u0020]+|[\\u0000-\\u001F\\u0020]+$/gu, \"\");\n}\n\nfunction trimTabAndNewline(url: string) {\n return url.replace(/\\u0009|\\u000A|\\u000D/gu, \"\");\n}\n\nfunction shortenPath(url: UrlObj) {\n const { path } = url;\n if (path.length === 0) {\n return;\n }\n if (\n url.scheme === \"file\" &&\n path.length === 1 &&\n isNormalizedWindowsDriveLetter(path[0])\n ) {\n return;\n }\n\n path.pop();\n}\n\nfunction includesCredentials(url: UrlObj) {\n return url.username !== \"\" || url.password !== \"\";\n}\n\nfunction cannotHaveAUsernamePasswordPort(url: UrlObj) {\n return url.host === null || url.host === \"\" || url.scheme === \"file\";\n}\n\nfunction hasAnOpaquePath(url: UrlObj) {\n return typeof url.path === \"string\";\n}\n\nfunction isNormalizedWindowsDriveLetter(string: string) {\n return /^[A-Za-z]:$/u.test(string);\n}\n\nexport interface UrlObj {\n scheme: string;\n username: string;\n password: string;\n host: string | number[] | number | null | undefined;\n port: number | null;\n path: string[];\n query: any;\n fragment: any;\n}\n\nclass URLStateMachine {\n pointer: number;\n input: number[];\n base: any;\n encodingOverride: string;\n url: UrlObj;\n state: string;\n stateOverride: string;\n failure: boolean;\n parseError: boolean;\n buffer: string;\n atFlag: boolean;\n arrFlag: boolean;\n passwordTokenSeenFlag: boolean;\n\n constructor(\n input: string,\n base: any,\n encodingOverride: string,\n url: UrlObj,\n stateOverride: string,\n ) {\n this.pointer = 0;\n this.base = base || null;\n this.encodingOverride = encodingOverride || \"utf-8\";\n this.url = url;\n this.failure = false;\n this.parseError = false;\n\n if (!this.url) {\n this.url = {\n scheme: \"\",\n username: \"\",\n password: \"\",\n host: null,\n port: null,\n path: [],\n query: null,\n fragment: null,\n };\n\n const res = trimControlChars(input);\n if (res !== input) {\n this.parseError = true;\n }\n input = res;\n }\n\n const res = trimTabAndNewline(input);\n if (res !== input) {\n this.parseError = true;\n }\n input = res;\n\n this.state = stateOverride || \"scheme start\";\n\n this.buffer = \"\";\n this.atFlag = false;\n this.arrFlag = false;\n this.passwordTokenSeenFlag = false;\n\n this.input = Array.from(input, (c) => c.codePointAt(0)!);\n\n for (; this.pointer <= this.input.length; ++this.pointer) {\n const c = this.input[this.pointer];\n const cStr = isNaN(c) ? undefined : String.fromCodePoint(c);\n\n // exec state machine\n const ret = this.table[`parse ${this.state}`].call(this, c, cStr!);\n if (!ret) {\n break; // terminate algorithm\n } else if (ret === failure) {\n this.failure = true;\n break;\n }\n }\n }\n\n table = {\n \"parse scheme start\": this.parseSchemeStart,\n \"parse scheme\": this.parseScheme,\n \"parse no scheme\": this.parseNoScheme,\n \"parse special relative or authority\": this.parseSpecialRelativeOrAuthority,\n \"parse path or authority\": this.parsePathOrAuthority,\n \"parse relative\": this.parseRelative,\n \"parse relative slash\": this.parseRelativeSlash,\n \"parse special authority slashes\": this.parseSpecialAuthoritySlashes,\n \"parse special authority ignore slashes\":\n this.parseSpecialAuthorityIgnoreSlashes,\n \"parse authority\": this.parseAuthority,\n \"parse host\": this.parseHostName,\n \"parse hostname\": this.parseHostName /* intentional duplication */,\n \"parse port\": this.parsePort,\n \"parse file\": this.parseFile,\n \"parse file slash\": this.parseFileSlash,\n \"parse file host\": this.parseFileHost,\n \"parse path start\": this.parsePathStart,\n \"parse path\": this.parsePath,\n \"parse opaque path\": this.parseOpaquePath,\n \"parse query\": this.parseQuery,\n \"parse fragment\": this.parseFragment,\n } as { [x: string]: (c: number, cStr: string) => any };\n\n parseSchemeStart(c: number, cStr: string) {\n if (isASCIIAlpha(c)) {\n this.buffer += cStr.toLowerCase();\n this.state = \"scheme\";\n } else if (!this.stateOverride) {\n this.state = \"no scheme\";\n --this.pointer;\n } else {\n this.parseError = true;\n return failure;\n }\n\n return true;\n }\n\n parseScheme(c: number, cStr: string) {\n if (\n isASCIIAlphanumeric(c) ||\n c === p(\"+\") ||\n c === p(\"-\") ||\n c === p(\".\")\n ) {\n this.buffer += cStr.toLowerCase();\n } else if (c === p(\":\")) {\n if (this.stateOverride) {\n if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) {\n return false;\n }\n\n if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) {\n return false;\n }\n\n if (\n (includesCredentials(this.url) || this.url.port !== null) &&\n this.buffer === \"file\"\n ) {\n return false;\n }\n\n if (this.url.scheme === \"file\" && this.url.host === \"\") {\n return false;\n }\n }\n this.url.scheme = this.buffer;\n if (this.stateOverride) {\n if (this.url.port === defaultPort(this.url.scheme)) {\n this.url.port = null;\n }\n return false;\n }\n this.buffer = \"\";\n if (this.url.scheme === \"file\") {\n if (\n this.input[this.pointer + 1] !== p(\"/\") ||\n this.input[this.pointer + 2] !== p(\"/\")\n ) {\n this.parseError = true;\n }\n this.state = \"file\";\n } else if (\n isSpecial(this.url) &&\n this.base !== null &&\n this.base.scheme === this.url.scheme\n ) {\n this.state = \"special relative or authority\";\n } else if (isSpecial(this.url)) {\n this.state = \"special authority slashes\";\n } else if (this.input[this.pointer + 1] === p(\"/\")) {\n this.state = \"path or authority\";\n ++this.pointer;\n } else {\n this.url.path = [\"\"];\n this.state = \"opaque path\";\n }\n } else if (!this.stateOverride) {\n this.buffer = \"\";\n this.state = \"no scheme\";\n this.pointer = -1;\n } else {\n this.parseError = true;\n return failure;\n }\n\n return true;\n }\n\n parseNoScheme(c: number) {\n if (this.base === null || (hasAnOpaquePath(this.base) && c !== p(\"#\"))) {\n return failure;\n } else if (hasAnOpaquePath(this.base) && c === p(\"#\")) {\n this.url.scheme = this.base.scheme;\n this.url.path = this.base.path;\n this.url.query = this.base.query;\n this.url.fragment = \"\";\n this.state = \"fragment\";\n } else if (this.base.scheme === \"file\") {\n this.state = \"file\";\n --this.pointer;\n } else {\n this.state = \"relative\";\n --this.pointer;\n }\n\n return true;\n }\n\n parseSpecialRelativeOrAuthority(c: number) {\n if (c === p(\"/\") && this.input[this.pointer + 1] === p(\"/\")) {\n this.state = \"special authority ignore slashes\";\n ++this.pointer;\n } else {\n this.parseError = true;\n this.state = \"relative\";\n --this.pointer;\n }\n\n return true;\n }\n\n parsePathOrAuthority(c: number) {\n if (c === p(\"/\")) {\n this.state = \"authority\";\n } else {\n this.state = \"path\";\n --this.pointer;\n }\n\n return true;\n }\n\n parseRelative(c: number) {\n this.url.scheme = this.base.scheme;\n if (c === p(\"/\")) {\n this.state = \"relative slash\";\n } else if (isSpecial(this.url) && c === p(\"\\\\\")) {\n this.parseError = true;\n this.state = \"relative slash\";\n } else {\n this.url.username = this.base.username;\n this.url.password = this.base.password;\n this.url.host = this.base.host;\n this.url.port = this.base.port;\n this.url.path = this.base.path.slice();\n this.url.query = this.base.query;\n if (c === p(\"?\")) {\n this.url.query = \"\";\n this.state = \"query\";\n } else if (c === p(\"#\")) {\n this.url.fragment = \"\";\n this.state = \"fragment\";\n } else if (!isNaN(c)) {\n this.url.query = null;\n this.url.path.pop();\n this.state = \"path\";\n --this.pointer;\n }\n }\n\n return true;\n }\n\n parseRelativeSlash(c: number) {\n if (isSpecial(this.url) && (c === p(\"/\") || c === p(\"\\\\\"))) {\n if (c === p(\"\\\\\")) {\n this.parseError = true;\n }\n this.state = \"special authority ignore slashes\";\n } else if (c === p(\"/\")) {\n this.state = \"authority\";\n } else {\n this.url.username = this.base.username;\n this.url.password = this.base.password;\n this.url.host = this.base.host;\n this.url.port = this.base.port;\n this.state = \"path\";\n --this.pointer;\n }\n\n return true;\n }\n\n parseSpecialAuthoritySlashes(c: number) {\n if (c === p(\"/\") && this.input[this.pointer + 1] === p(\"/\")) {\n this.state = \"special authority ignore slashes\";\n ++this.pointer;\n } else {\n this.parseError = true;\n this.state = \"special authority ignore slashes\";\n --this.pointer;\n }\n\n return true;\n }\n\n parseSpecialAuthorityIgnoreSlashes(c: number) {\n if (c !== p(\"/\") && c !== p(\"\\\\\")) {\n this.state = \"authority\";\n --this.pointer;\n } else {\n this.parseError = true;\n }\n\n return true;\n }\n\n parseAuthority(c: number, cStr: string) {\n if (c === p(\"@\")) {\n this.parseError = true;\n if (this.atFlag) {\n this.buffer = `%40${this.buffer}`;\n }\n this.atFlag = true;\n\n // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars\n const len = countSymbols(this.buffer);\n for (let pointer = 0; pointer < len; ++pointer) {\n const codePoint = this.buffer.codePointAt(pointer);\n\n if (codePoint === p(\":\") && !this.passwordTokenSeenFlag) {\n this.passwordTokenSeenFlag = true;\n continue;\n }\n const encodedCodePoints = utf8PercentEncodeCodePoint(\n codePoint!,\n isUserinfoPercentEncode,\n );\n if (this.passwordTokenSeenFlag) {\n this.url.password += encodedCodePoints;\n } else {\n this.url.username += encodedCodePoints;\n }\n }\n this.buffer = \"\";\n } else if (\n isNaN(c) ||\n c === p(\"/\") ||\n c === p(\"?\") ||\n c === p(\"#\") ||\n (isSpecial(this.url) && c === p(\"\\\\\"))\n ) {\n if (this.atFlag && this.buffer === \"\") {\n this.parseError = true;\n return failure;\n }\n this.pointer -= countSymbols(this.buffer) + 1;\n this.buffer = \"\";\n this.state = \"host\";\n } else {\n this.buffer += cStr;\n }\n\n return true;\n }\n\n parseHostName(c: number, cStr: string) {\n if (this.stateOverride && this.url.scheme === \"file\") {\n --this.pointer;\n this.state = \"file host\";\n } else if (c === p(\":\") && !this.arrFlag) {\n if (this.buffer === \"\") {\n this.parseError = true;\n return failure;\n }\n\n if (this.stateOverride === \"hostname\") {\n return false;\n }\n\n const host = parseHost(this.buffer, isNotSpecial(this.url));\n if (host === failure) {\n return failure;\n }\n\n this.url.host = host;\n this.buffer = \"\";\n this.state = \"port\";\n } else if (\n isNaN(c) ||\n c === p(\"/\") ||\n c === p(\"?\") ||\n c === p(\"#\") ||\n (isSpecial(this.url) && c === p(\"\\\\\"))\n ) {\n --this.pointer;\n if (isSpecial(this.url) && this.buffer === \"\") {\n this.parseError = true;\n return failure;\n } else if (\n this.stateOverride &&\n this.buffer === \"\" &&\n (includesCredentials(this.url) || this.url.port !== null)\n ) {\n this.parseError = true;\n return false;\n }\n\n const host = parseHost(this.buffer, isNotSpecial(this.url));\n if (host === failure) {\n return failure;\n }\n\n this.url.host = host;\n this.buffer = \"\";\n this.state = \"path start\";\n if (this.stateOverride) {\n return false;\n }\n } else {\n if (c === p(\"[\")) {\n this.arrFlag = true;\n } else if (c === p(\"]\")) {\n this.arrFlag = false;\n }\n this.buffer += cStr;\n }\n\n return true;\n }\n\n parsePort(c: number, cStr: any) {\n if (isASCIIDigit(c)) {\n this.buffer += cStr;\n } else if (\n isNaN(c) ||\n c === p(\"/\") ||\n c === p(\"?\") ||\n c === p(\"#\") ||\n (isSpecial(this.url) && c === p(\"\\\\\")) ||\n this.stateOverride\n ) {\n if (this.buffer !== \"\") {\n const port = parseInt(this.buffer);\n if (port > 2 ** 16 - 1) {\n this.parseError = true;\n return failure;\n }\n this.url.port = port === defaultPort(this.url.scheme) ? null : port;\n this.buffer = \"\";\n }\n if (this.stateOverride) {\n return false;\n }\n this.state = \"path start\";\n --this.pointer;\n } else {\n this.parseError = true;\n return failure;\n }\n\n return true;\n }\n\n parseFile(c: number) {\n this.url.scheme = \"file\";\n this.url.host = \"\";\n\n if (c === p(\"/\") || c === p(\"\\\\\")) {\n if (c === p(\"\\\\\")) {\n this.parseError = true;\n }\n this.state = \"file slash\";\n } else if (this.base !== null && this.base.scheme === \"file\") {\n this.url.host = this.base.host;\n this.url.path = this.base.path.slice();\n this.url.query = this.base.query;\n if (c === p(\"?\")) {\n this.url.query = \"\";\n this.state = \"query\";\n } else if (c === p(\"#\")) {\n this.url.fragment = \"\";\n this.state = \"fragment\";\n } else if (!isNaN(c)) {\n this.url.query = null;\n if (!startsWithWindowsDriveLetter(this.input, this.pointer)) {\n shortenPath(this.url);\n } else {\n this.parseError = true;\n this.url.path = [];\n }\n\n this.state = \"path\";\n --this.pointer;\n }\n } else {\n this.state = \"path\";\n --this.pointer;\n }\n\n return true;\n }\n\n parseFileSlash(c: number) {\n if (c === p(\"/\") || c === p(\"\\\\\")) {\n if (c === p(\"\\\\\")) {\n this.parseError = true;\n }\n this.state = \"file host\";\n } else {\n if (this.base !== null && this.base.scheme === \"file\") {\n if (\n !startsWithWindowsDriveLetter(this.input, this.pointer) &&\n isNormalizedWindowsDriveLetterString(this.base.path[0])\n ) {\n this.url.path.push(this.base.path[0]);\n }\n this.url.host = this.base.host;\n }\n this.state = \"path\";\n --this.pointer;\n }\n\n return true;\n }\n\n parseFileHost(c: number, cStr: string) {\n if (\n isNaN(c) ||\n c === p(\"/\") ||\n c === p(\"\\\\\") ||\n c === p(\"?\") ||\n c === p(\"#\")\n ) {\n --this.pointer;\n if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) {\n this.parseError = true;\n this.state = \"path\";\n } else if (this.buffer === \"\") {\n this.url.host = \"\";\n if (this.stateOverride) {\n return false;\n }\n this.state = \"path start\";\n } else {\n let host = parseHost(this.buffer, isNotSpecial(this.url));\n if (host === failure) {\n return failure;\n }\n if (host === \"localhost\") {\n host = \"\";\n }\n this.url.host = host as any;\n\n if (this.stateOverride) {\n return false;\n }\n\n this.buffer = \"\";\n this.state = \"path start\";\n }\n } else {\n this.buffer += cStr;\n }\n\n return true;\n }\n\n parsePathStart(c: number) {\n if (isSpecial(this.url)) {\n if (c === p(\"\\\\\")) {\n this.parseError = true;\n }\n this.state = \"path\";\n\n if (c !== p(\"/\") && c !== p(\"\\\\\")) {\n --this.pointer;\n }\n } else if (!this.stateOverride && c === p(\"?\")) {\n this.url.query = \"\";\n this.state = \"query\";\n } else if (!this.stateOverride && c === p(\"#\")) {\n this.url.fragment = \"\";\n this.state = \"fragment\";\n } else if (c !== undefined) {\n this.state = \"path\";\n if (c !== p(\"/\")) {\n --this.pointer;\n }\n } else if (this.stateOverride && this.url.host === null) {\n this.url.path.push(\"\");\n }\n\n return true;\n }\n\n parsePath(c: number) {\n if (\n isNaN(c) ||\n c === p(\"/\") ||\n (isSpecial(this.url) && c === p(\"\\\\\")) ||\n (!this.stateOverride && (c === p(\"?\") || c === p(\"#\")))\n ) {\n if (isSpecial(this.url) && c === p(\"\\\\\")) {\n this.parseError = true;\n }\n\n if (isDoubleDot(this.buffer)) {\n shortenPath(this.url);\n if (c !== p(\"/\") && !(isSpecial(this.url) && c === p(\"\\\\\"))) {\n this.url.path.push(\"\");\n }\n } else if (\n isSingleDot(this.buffer) &&\n c !== p(\"/\") &&\n !(isSpecial(this.url) && c === p(\"\\\\\"))\n ) {\n this.url.path.push(\"\");\n } else if (!isSingleDot(this.buffer)) {\n if (\n this.url.scheme === \"file\" &&\n this.url.path.length === 0 &&\n isWindowsDriveLetterString(this.buffer)\n ) {\n this.buffer = `${this.buffer[0]}:`;\n }\n this.url.path.push(this.buffer);\n }\n this.buffer = \"\";\n if (c === p(\"?\")) {\n this.url.query = \"\";\n this.state = \"query\";\n }\n if (c === p(\"#\")) {\n this.url.fragment = \"\";\n this.state = \"fragment\";\n }\n } else {\n // TODO: If c is not a URL code point and not \"%\", parse error.\n\n if (\n c === p(\"%\") &&\n (!isASCIIHex(this.input[this.pointer + 1]) ||\n !isASCIIHex(this.input[this.pointer + 2]))\n ) {\n this.parseError = true;\n }\n\n this.buffer += utf8PercentEncodeCodePoint(c, isPathPercentEncode);\n }\n\n return true;\n }\n\n parseOpaquePath(c: number) {\n if (c === p(\"?\")) {\n this.url.query = \"\";\n this.state = \"query\";\n } else if (c === p(\"#\")) {\n this.url.fragment = \"\";\n this.state = \"fragment\";\n } else {\n // TODO: Add: not a URL code point\n if (!isNaN(c) && c !== p(\"%\")) {\n this.parseError = true;\n }\n\n if (\n c === p(\"%\") &&\n (!isASCIIHex(this.input[this.pointer + 1]) ||\n !isASCIIHex(this.input[this.pointer + 2]))\n ) {\n this.parseError = true;\n }\n\n if (!isNaN(c)) {\n // @ts-ignore\n this.url.path += utf8PercentEncodeCodePoint(\n c,\n isC0ControlPercentEncode,\n );\n }\n }\n\n return true;\n }\n\n parseQuery(c: number, cStr: string) {\n if (\n !isSpecial(this.url) ||\n this.url.scheme === \"ws\" ||\n this.url.scheme === \"wss\"\n ) {\n this.encodingOverride = \"utf-8\";\n }\n\n if ((!this.stateOverride && c === p(\"#\")) || isNaN(c)) {\n const queryPercentEncodePredicate = isSpecial(this.url)\n ? isSpecialQueryPercentEncode\n : isQueryPercentEncode;\n this.url.query += utf8PercentEncodeString(\n this.buffer,\n queryPercentEncodePredicate,\n );\n\n this.buffer = \"\";\n\n if (c === p(\"#\")) {\n this.url.fragment = \"\";\n this.state = \"fragment\";\n }\n } else if (!isNaN(c)) {\n // TODO: If c is not a URL code point and not \"%\", parse error.\n\n if (\n c === p(\"%\") &&\n (!isASCIIHex(this.input[this.pointer + 1]) ||\n !isASCIIHex(this.input[this.pointer + 2]))\n ) {\n this.parseError = true;\n }\n\n this.buffer += cStr;\n }\n\n return true;\n }\n\n parseFragment(c: number) {\n if (!isNaN(c)) {\n // TODO: If c is not a URL code point and not \"%\", parse error.\n if (\n c === p(\"%\") &&\n (!isASCIIHex(this.input[this.pointer + 1]) ||\n !isASCIIHex(this.input[this.pointer + 2]))\n ) {\n this.parseError = true;\n }\n\n this.url.fragment += utf8PercentEncodeCodePoint(\n c,\n isFragmentPercentEncode,\n );\n }\n\n return true;\n }\n}\n\nconst fileOtherwiseCodePoints = new Set([p(\"/\"), p(\"\\\\\"), p(\"?\"), p(\"#\")]);\n\nfunction startsWithWindowsDriveLetter(input: number[], pointer: number) {\n const length = input.length - pointer;\n return (\n length >= 2 &&\n isWindowsDriveLetterCodePoints(input[pointer], input[pointer + 1]) &&\n (length === 2 || fileOtherwiseCodePoints.has(input[pointer + 2]))\n );\n}\n\nfunction serializeURL(url: any, excludeFragment?: boolean) {\n let output = `${url.scheme}:`;\n if (url.host !== null) {\n output += \"//\";\n\n if (url.username !== \"\" || url.password !== \"\") {\n output += url.username;\n if (url.password !== \"\") {\n output += `:${url.password}`;\n }\n output += \"@\";\n }\n\n output += serializeHost(url.host);\n\n if (url.port !== null) {\n output += `:${url.port}`;\n }\n }\n\n if (\n url.host === null &&\n !hasAnOpaquePath(url) &&\n url.path.length > 1 &&\n url.path[0] === \"\"\n ) {\n output += \"/.\";\n }\n output += serializePath(url);\n\n if (url.query !== null) {\n output += `?${url.query}`;\n }\n\n if (!excludeFragment && url.fragment !== null) {\n output += `#${url.fragment}`;\n }\n\n return output;\n}\n\nfunction serializeOrigin(tuple: {\n scheme: string;\n port: number;\n host: number | number[] | string;\n}) {\n let result = `${tuple.scheme}://`;\n result += serializeHost(tuple.host);\n\n if (tuple.port !== null) {\n result += `:${tuple.port}`;\n }\n\n return result;\n}\n\nfunction serializePath(url: UrlObj): string {\n if (typeof url.path === \"string\") {\n return url.path;\n }\n\n let output = \"\";\n for (const segment of url.path) {\n output += `/${segment}`;\n }\n return output;\n}\n\nfunction serializeURLOrigin(url: any): any {\n // https://url.spec.whatwg.org/#concept-url-origin\n switch (url.scheme) {\n case \"blob\":\n try {\n return serializeURLOrigin(parseURL(serializePath(url)));\n } catch (e) {\n // serializing an opaque origin returns \"null\"\n return \"null\";\n }\n case \"ftp\":\n case \"http\":\n case \"https\":\n case \"ws\":\n case \"wss\":\n return serializeOrigin({\n scheme: url.scheme,\n host: url.host,\n port: url.port,\n });\n case \"file\":\n // The spec says:\n // > Unfortunate as it is, this is left as an exercise to the reader. When in doubt, return a new opaque origin.\n // Browsers tested so far:\n // - Chrome says \"file://\", but treats file: URLs as cross-origin for most (all?) purposes; see e.g.\n // https://bugs.chromium.org/p/chromium/issues/detail?id=37586\n // - Firefox says \"null\", but treats file: URLs as same-origin sometimes based on directory stuff; see\n // https://developer.mozilla.org/en-US/docs/Archive/Misc_top_level/Same-origin_policy_for_file:_URIs\n return \"null\";\n default:\n // serializing an opaque origin returns \"null\"\n return \"null\";\n }\n}\n\nexport function basicURLParse(input: string, options?: any) {\n if (options === undefined) {\n options = {};\n }\n\n const usm = new URLStateMachine(\n input,\n options.baseURL,\n options.encodingOverride,\n options.url,\n options.stateOverride,\n );\n\n if (usm.failure) {\n return null;\n }\n\n return usm.url;\n}\n\nfunction setTheUsername(url: UrlObj, username: string) {\n url.username = utf8PercentEncodeString(username, isUserinfoPercentEncode);\n}\n\nfunction setThePassword(url: UrlObj, password: string) {\n url.password = utf8PercentEncodeString(password, isUserinfoPercentEncode);\n}\n\nfunction serializeInteger(integer: number) {\n return String(integer);\n}\n\nfunction parseURL(\n input: any,\n options?: { baseURL?: any; encodingOverride?: any },\n) {\n if (options === undefined) {\n options = {};\n }\n\n // We don't handle blobs, so this just delegates:\n return basicURLParse(input, {\n baseURL: options.baseURL,\n encodingOverride: options.encodingOverride,\n });\n}\n\nconst NativeURL = typeof URL !== \"undefined\" ? URL : undefined;\nexport class URLImpl {\n //Include URL type for \"url\" and \"base\" params.\n constructor(url: string | URL, base?: string | URL) {\n let parsedBase = null;\n if (base !== undefined) {\n if (base instanceof URL) {\n base = base.href;\n }\n parsedBase = basicURLParse(base);\n if (parsedBase === null) {\n throw new TypeError(`Invalid base URL: ${base}`);\n }\n }\n\n if (url instanceof URL) {\n url = url.href;\n }\n const parsedURL = basicURLParse(url, { baseURL: parsedBase });\n if (parsedURL === null) {\n throw new TypeError(`Invalid URL: ${url}`);\n }\n\n const query = parsedURL.query !== null ? parsedURL.query : \"\";\n\n this._url = parsedURL;\n\n // We cannot invoke the \"new URLSearchParams object\" algorithm without going through the constructor, which strips\n // question mark by default. Therefore the doNotStripQMark hack is used.\n this._query = new URLSearchParamsImpl(query, {\n doNotStripQMark: true,\n });\n this._query._url = this;\n }\n\n get href() {\n return serializeURL(this._url);\n }\n\n set href(v) {\n const parsedURL = basicURLParse(v);\n if (parsedURL === null) {\n throw new TypeError(`Invalid URL: ${v}`);\n }\n\n this._url = parsedURL;\n\n this._query._list.splice(0);\n const { query } = parsedURL;\n if (query !== null) {\n this._query._list = parseUrlencodedString(query);\n }\n }\n\n get origin() {\n return serializeURLOrigin(this._url);\n }\n\n get protocol() {\n return `${this._url.scheme}:`;\n }\n\n set protocol(v) {\n basicURLParse(`${v}:`, {\n url: this._url,\n stateOverride: \"scheme start\",\n });\n }\n\n get username() {\n return this._url.username;\n }\n\n set username(v) {\n if (cannotHaveAUsernamePasswordPort(this._url)) {\n return;\n }\n\n setTheUsername(this._url, v);\n }\n\n get password() {\n return this._url.password;\n }\n\n set password(v) {\n if (cannotHaveAUsernamePasswordPort(this._url)) {\n return;\n }\n\n setThePassword(this._url, v);\n }\n\n get host() {\n const url = this._url;\n\n if (url.host === null) {\n return \"\";\n }\n\n if (url.port === null) {\n return serializeHost(url.host);\n }\n\n return `${serializeHost(url.host)}:${serializeInteger(url.port)}`;\n }\n\n set host(v) {\n if (hasAnOpaquePath(this._url)) {\n return;\n }\n\n basicURLParse(v, { url: this._url, stateOverride: \"host\" });\n }\n\n get hostname() {\n if (this._url.host === null) {\n return \"\";\n }\n\n return serializeHost(this._url.host);\n }\n\n set hostname(v) {\n if (hasAnOpaquePath(this._url)) {\n return;\n }\n\n basicURLParse(v, { url: this._url, stateOverride: \"hostname\" });\n }\n\n get port() {\n if (this._url.port === null) {\n return \"\";\n }\n\n return serializeInteger(this._url.port);\n }\n\n set port(v) {\n if (cannotHaveAUsernamePasswordPort(this._url)) {\n return;\n }\n\n if (v === \"\") {\n this._url.port = null;\n } else {\n basicURLParse(v, { url: this._url, stateOverride: \"port\" });\n }\n }\n\n get pathname() {\n return serializePath(this._url);\n }\n\n set pathname(v: string) {\n if (hasAnOpaquePath(this._url)) {\n return;\n }\n\n this._url.path = [];\n basicURLParse(v, { url: this._url, stateOverride: \"path start\" });\n }\n\n get search() {\n if (this._url.query === null || this._url.query === \"\") {\n return \"\";\n }\n\n return `?${this._url.query}`;\n }\n\n set search(v) {\n const url = this._url;\n\n if (v === \"\") {\n url.query = null;\n this._query._list = [];\n return;\n }\n\n const input = v[0] === \"?\" ? v.substring(1) : v;\n url.query = \"\";\n basicURLParse(input, { url, stateOverride: \"query\" });\n this._query._list = parseUrlencodedString(input);\n }\n\n get searchParams() {\n return this._query;\n }\n\n get hash() {\n if (this._url.fragment === null || this._url.fragment === \"\") {\n return \"\";\n }\n\n return `#${this._url.fragment}`;\n }\n\n set hash(v) {\n if (v === \"\") {\n this._url.fragment = null;\n return;\n }\n\n const input = v[0] === \"#\" ? v.substring(1) : v;\n this._url.fragment = \"\";\n basicURLParse(input, { url: this._url, stateOverride: \"fragment\" });\n }\n\n toJSON() {\n return this.href;\n }\n\n static createObjectURL(blob: Blob) {\n if (!NativeURL)\n throw new Error(\n \"This method requires a native implementation, which does not exist\",\n );\n return NativeURL.createObjectURL(blob);\n }\n static revokeObjectURL(url: string) {\n if (!NativeURL)\n throw new Error(\n \"This method requires a native implementation, which does not exist\",\n );\n return NativeURL.revokeObjectURL(url);\n }\n\n // FIXME: type!\n _url: any;\n _query: any;\n}\n", "/*\n This file is part of GNU Taler\n (C) 2020 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { URLImpl, URLSearchParamsImpl } from \"./whatwg-url.js\";\n\ninterface URL {\n hash: string;\n host: string;\n hostname: string;\n href: string;\n toString(): string;\n readonly origin: string;\n password: string;\n pathname: string;\n port: string;\n protocol: string;\n search: string;\n readonly searchParams: URLSearchParams;\n username: string;\n toJSON(): string;\n}\n\ninterface URLSearchParams {\n readonly size: number;\n append(name: string, value: string): void;\n delete(name: string): void;\n get(name: string): string | null;\n getAll(name: string): string[];\n has(name: string): boolean;\n set(name: string, value: string): void;\n sort(): void;\n toString(): string;\n forEach(\n callbackfn: (value: string, key: string, parent: URLSearchParams) => void,\n thisArg?: any,\n ): void;\n entries(): IterableIterator<[string, string]>;\n keys(): IterableIterator;\n values(): IterableIterator;\n [Symbol.iterator](): IterableIterator<[string, string]>;\n}\n\nexport interface URLSearchParamsCtor {\n new (\n init?:\n | URLSearchParams\n | string\n | Record>\n | Iterable<[string, string]>\n | ReadonlyArray<[string, string]>,\n ): URLSearchParams;\n}\n\nexport interface URLCtor {\n new (url: string, base?: string | URL): URL;\n}\n\n// globalThis polyfill, see https://mathiasbynens.be/notes/globalthis\n(function () {\n if (typeof globalThis === \"object\") return;\n Object.defineProperty(Object.prototype, \"__magic__\", {\n get: function () {\n return this;\n },\n configurable: true, // This makes it possible to `delete` the getter later.\n });\n // @ts-ignore: polyfill magic\n __magic__.globalThis = __magic__; // lolwat\n // @ts-ignore: polyfill magic\n delete Object.prototype.__magic__;\n})();\n\n// Use native or pure JS URL implementation?\nconst useOwnUrlImp = true;\n\n// @ts-ignore\nlet _URL = globalThis.URL;\nif (useOwnUrlImp || !_URL) {\n // @ts-ignore\n globalThis.URL = _URL = URLImpl;\n // @ts-ignore\n _URL = URLImpl;\n}\n\nexport const URL: URLCtor = _URL;\n\n// @ts-ignore\nlet _URLSearchParams = globalThis.URLSearchParams;\n\nif (useOwnUrlImp || !_URLSearchParams) {\n // @ts-ignore\n globalThis.URLSearchParams = URLSearchParamsImpl;\n // @ts-ignore\n _URLSearchParams = URLSearchParamsImpl;\n}\n\nexport const URLSearchParams: URLSearchParamsCtor = _URLSearchParams;\n", "/*\n This file is part of TALER\n (C) 2016 GNUnet e.V.\n\n TALER is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n TALER is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n TALER; see the file COPYING. If not, see \n */\n\n/**\n * Small helper functions that don't fit anywhere else.\n */\n\n/**\n * Imports.\n */\nimport { URL } from \"./url.js\";\n\n/**\n * Canonicalize a base url, typically for the exchange.\n *\n * See http://api.taler.net/wallet.html#general\n */\nexport function canonicalizeBaseUrl(url: string): string {\n if (!url.startsWith(\"http\") && !url.startsWith(\"https\")) {\n url = \"https://\" + url;\n }\n const x = new URL(url);\n if (!x.pathname.endsWith(\"/\")) {\n x.pathname = x.pathname + \"/\";\n }\n x.search = \"\";\n x.hash = \"\";\n return x.href;\n}\n\n/**\n * Convert object to JSON with canonical ordering of keys\n * and whitespace omitted.\n *\n * See RFC 4885 (https://tools.ietf.org/html/rfc8785).\n */\nexport function canonicalJson(obj: any): string {\n // Check for cycles, etc.\n obj = JSON.parse(JSON.stringify(obj));\n if (typeof obj === \"string\") {\n return JSON.stringify(obj);\n }\n if (typeof obj === \"number\" || typeof obj === \"boolean\" || obj === null) {\n return JSON.stringify(obj);\n }\n if (Array.isArray(obj)) {\n const objs: string[] = obj.map((e) => canonicalJson(e));\n return `[${objs.join(\",\")}]`;\n }\n const keys: string[] = [];\n for (const key in obj) {\n keys.push(key);\n }\n keys.sort();\n let s = \"{\";\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n s += JSON.stringify(key) + \":\" + canonicalJson(obj[key]);\n if (i !== keys.length - 1) {\n s += \",\";\n }\n }\n return s + \"}\";\n}\n\n/**\n * Lexically compare two strings.\n */\nexport function strcmp(s1: string, s2: string): -1 | 0 | 1 {\n if (s1 < s2) {\n return -1;\n }\n if (s1 > s2) {\n return 1;\n }\n return 0;\n}\n\n/**\n * Shorthand function for formatted JSON stringification.\n */\nexport function j2s(x: any): string {\n return JSON.stringify(x, undefined, 2);\n}\n\n/**\n * Use this to filter null or undefined from an array in a type-safe fashion\n *\n * example:\n * const array: Array = [undefined, null]\n * const filtered: Array = array.filter(notEmpty)\n *\n * @param value\n * @returns\n */\nexport function notEmpty(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\n/**\n * Safe function to stringify errors.\n */\nexport function stringifyError(x: any): string {\n if (typeof x === \"undefined\") {\n return \"\";\n }\n if (x === null) {\n return ``;\n }\n if (typeof x === \"object\") {\n return x.toString();\n }\n return ``;\n}\n", "/*\n This file is part of TALER\n (C) 2019 GNUnet e.V.\n\n TALER is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n TALER is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n TALER; see the file COPYING. If not, see \n */\n\n/**\n * Check if we are running under nodejs.\n */\n\nconst isNode =\n typeof process !== \"undefined\" &&\n typeof process.release !== \"undefined\" &&\n process.release.name === \"node\";\n\nexport enum LogLevel {\n Trace = \"trace\",\n Message = \"message\",\n Info = \"info\",\n Warn = \"warn\",\n Error = \"error\",\n None = \"none\",\n}\n\nlet globalLogLevel = LogLevel.Info;\nconst byTagLogLevel: Record = {};\n\nlet nativeLogging: boolean = false;\n\n// from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString\nError.prototype.toString = function () {\n if (\n this === null ||\n (typeof this !== \"object\" && typeof this !== \"function\")\n ) {\n throw new TypeError();\n }\n let name = this.name;\n name = name === undefined ? \"Error\" : `${name}`;\n let msg = this.message;\n msg = msg === undefined ? \"\" : `${msg}`;\n\n let cause = \"\";\n if (\"cause\" in this) {\n cause = `\\n Caused by: ${this.cause}`;\n }\n return `${name}: ${msg}${cause}`;\n};\n\nexport function getGlobalLogLevel(): string {\n return globalLogLevel;\n}\n\nexport function setGlobalLogLevelFromString(logLevelStr: string): void {\n globalLogLevel = getLevelForString(logLevelStr);\n}\n\nexport function setLogLevelFromString(tag: string, logLevelStr: string): void {\n byTagLogLevel[tag] = getLevelForString(logLevelStr);\n}\n\nexport function enableNativeLogging() {\n nativeLogging = true;\n}\n\nfunction getLevelForString(logLevelStr: string): LogLevel {\n switch (logLevelStr.toLowerCase()) {\n case \"trace\":\n return LogLevel.Trace;\n case \"info\":\n return LogLevel.Info;\n case \"warn\":\n case \"warning\":\n return LogLevel.Warn;\n case \"error\":\n return LogLevel.Error;\n case \"none\":\n return LogLevel.None;\n default:\n if (isNode) {\n process.stderr.write(`Invalid log level, defaulting to WARNING\\n`);\n } else {\n console.warn(`Invalid log level, defaulting to WARNING`);\n }\n return LogLevel.Warn;\n }\n}\n\nfunction writeNativeLog(\n message: any,\n tag: string,\n level: number,\n args: any[],\n): void {\n const logFn = (globalThis as any).__nativeLog;\n if (logFn) {\n let m: string;\n if (args.length == 0) {\n m = message;\n } else {\n m = message + \" \" + args.toString();\n }\n logFn(level, tag, message);\n }\n}\n\nfunction writeNodeLog(\n message: any,\n tag: string,\n level: string,\n args: any[],\n): void {\n try {\n let msg = `${new Date().toISOString()} ${tag} ${level} ${message}`;\n if (args.length != 0) {\n msg += ` ${JSON.stringify(args, undefined, 2)}\\n`;\n } else {\n msg += `\\n`;\n }\n process.stderr.write(msg);\n } catch (e) {\n // This can happen when we're trying to log something that doesn't want to be\n // converted to a string.\n let msg = `${new Date().toISOString()} (logger) FATAL `;\n if (e instanceof Error) {\n msg += `failed to write log: ${e.message}\\n`;\n } else {\n msg += \"failed to write log\\n\";\n }\n process.stderr.write(msg);\n }\n}\n\n/**\n * Logger that writes to stderr when running under node,\n * and uses the corresponding console.* method to log in the browser.\n */\nexport class Logger {\n constructor(private tag: string) {}\n\n getGlobalLogLevel(): string {\n return globalLogLevel;\n }\n\n shouldLogTrace(): boolean {\n const level = byTagLogLevel[this.tag] ?? globalLogLevel;\n switch (level) {\n case LogLevel.Trace:\n return true;\n case LogLevel.Message:\n case LogLevel.Info:\n case LogLevel.Warn:\n case LogLevel.Error:\n case LogLevel.None:\n return false;\n }\n }\n\n shouldLogInfo(): boolean {\n const level = byTagLogLevel[this.tag] ?? globalLogLevel;\n switch (level) {\n case LogLevel.Trace:\n case LogLevel.Message:\n case LogLevel.Info:\n return true;\n case LogLevel.Warn:\n case LogLevel.Error:\n case LogLevel.None:\n return false;\n }\n }\n\n shouldLogWarn(): boolean {\n const level = byTagLogLevel[this.tag] ?? globalLogLevel;\n switch (level) {\n case LogLevel.Trace:\n case LogLevel.Message:\n case LogLevel.Info:\n case LogLevel.Warn:\n return true;\n case LogLevel.Error:\n case LogLevel.None:\n return false;\n }\n }\n\n shouldLogError(): boolean {\n const level = byTagLogLevel[this.tag] ?? globalLogLevel;\n switch (level) {\n case LogLevel.Trace:\n case LogLevel.Message:\n case LogLevel.Info:\n case LogLevel.Warn:\n case LogLevel.Error:\n return true;\n case LogLevel.None:\n return false;\n }\n }\n\n info(message: string, ...args: any[]): void {\n if (!this.shouldLogInfo()) {\n return;\n }\n if (nativeLogging) {\n writeNativeLog(message, this.tag, 2, args);\n return;\n }\n if (isNode) {\n writeNodeLog(message, this.tag, \"INFO\", args);\n } else {\n console.info(\n `${new Date().toISOString()} ${this.tag} INFO ` + message,\n ...args,\n );\n }\n }\n\n warn(message: string, ...args: any[]): void {\n if (!this.shouldLogWarn()) {\n return;\n }\n if (nativeLogging) {\n writeNativeLog(message, this.tag, 3, args);\n return;\n }\n if (isNode) {\n writeNodeLog(message, this.tag, \"WARN\", args);\n } else {\n console.warn(\n `${new Date().toISOString()} ${this.tag} INFO ` + message,\n ...args,\n );\n }\n }\n\n error(message: string, ...args: any[]): void {\n if (!this.shouldLogError()) {\n return;\n }\n if (nativeLogging) {\n writeNativeLog(message, this.tag, 4, args);\n return;\n }\n if (isNode) {\n writeNodeLog(message, this.tag, \"ERROR\", args);\n } else {\n console.info(\n `${new Date().toISOString()} ${this.tag} ERROR ` + message,\n ...args,\n );\n }\n }\n\n trace(message: string, ...args: any[]): void {\n if (!this.shouldLogTrace()) {\n return;\n }\n if (nativeLogging) {\n writeNativeLog(message, this.tag, 1, args);\n return;\n }\n if (isNode) {\n writeNodeLog(message, this.tag, \"TRACE\", args);\n } else {\n console.info(\n `${new Date().toISOString()} ${this.tag} TRACE ` + message,\n ...args,\n );\n }\n }\n\n reportBreak(): void {\n if (!this.shouldLogError()) {\n return;\n }\n const location = new Error(\"programming error\");\n this.error(`assertion failed: ${location.stack}`);\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2018-2019 GNUnet e.V.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { j2s } from \"./helpers.js\";\nimport { Logger } from \"./logging.js\";\n\n/**\n * Type-safe codecs for converting from/to JSON.\n */\n\n/* eslint-disable @typescript-eslint/ban-types */\n\nconst logger = new Logger(\"codec.ts\");\n\n/**\n * Error thrown when decoding fails.\n */\nexport class DecodingError extends Error {\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, DecodingError.prototype);\n this.name = \"DecodingError\";\n }\n}\n\n/**\n * Context information to show nicer error messages when decoding fails.\n */\nexport interface Context {\n readonly path?: string[];\n}\n\nexport function renderContext(c?: Context): string {\n const p = c?.path;\n if (p) {\n return p.join(\".\");\n } else {\n return \"(unknown)\";\n }\n}\n\nfunction joinContext(c: Context | undefined, part: string): Context {\n const path = c?.path ?? [];\n return {\n path: path.concat([part]),\n };\n}\n\n/**\n * A codec converts untyped JSON to a typed object.\n */\nexport interface Codec {\n /**\n * Decode untyped JSON to an object of type [[V]].\n */\n readonly decode: (x: any, c?: Context) => V;\n}\n\n/**\n * A codec built from an ObjectCodecBuilder object.\n */\nexport interface ObjectCodec extends Codec {\n /**\n * Get properties from builder. This method is only supported for codecs\n * built from ObjectCodecBuilder.\n */\n readonly getProps: () => Prop[];\n}\n\ntype SingletonRecord = { [Y in K]: V };\n\ninterface Prop {\n name: string;\n codec: Codec;\n deprecated?: boolean;\n}\n\ninterface Alternative {\n tagValue: any;\n codec: Codec;\n}\n\nclass ObjectCodecBuilder {\n private propList: Prop[] = [];\n private deprecatedProps: Set = new Set();\n private _allowExtra: boolean = false;\n\n /**\n * Define a property for the object.\n */\n property(\n x: K,\n codec: Codec,\n ): ObjectCodecBuilder<\n OutputType,\n PartialOutputType & SingletonRecord\n > {\n if (!codec) {\n throw Error(\"inner codec must be defined\");\n }\n this.propList.push({ name: x, codec: codec });\n return this as any;\n }\n\n /**\n * Define a property for the object.\n */\n propertyStrict(\n x: K,\n codec: Codec,\n ): ObjectCodecBuilder<\n OutputType,\n PartialOutputType & SingletonRecord\n > {\n if (!codec) {\n throw Error(\"inner codec must be defined\");\n }\n this.propList.push({ name: x, codec: codec });\n return this as any;\n }\n\n /**\n * Concatenate properties from @a codec.\n *\n * @param other codec to concat properties from\n *\n * FIXME: do proper union of all `other' props.\n */\n mixin(\n other: ObjectCodec,\n ): ObjectCodecBuilder {\n this.propList.push(...other.getProps());\n return this as any;\n }\n\n /**\n * Define a deprecated property for the object.\n *\n * Deprecated properties won't be validated, their presence will\n * be validated in TRACE mode.\n */\n deprecatedProperty(\n x: string,\n ): ObjectCodecBuilder {\n this.deprecatedProps.add(x);\n return this as any;\n }\n\n /**\n * Do not log warnings if the object has extra properties.\n */\n allowExtra(): ObjectCodecBuilder {\n this._allowExtra = true;\n return this;\n }\n\n /**\n * Return the built codec.\n *\n * @param objectDisplayName name of the object that this codec operates on,\n * used in error messages.\n */\n build(objectDisplayName: string): ObjectCodec {\n const propList = this.propList;\n const allowExtra = this._allowExtra;\n const deprecatedPros = this.deprecatedProps;\n return {\n decode(x: any, c?: Context): PartialOutputType {\n if (!c) {\n c = {\n path: [`(${objectDisplayName})`],\n };\n }\n if (typeof x !== \"object\") {\n throw new DecodingError(\n `expected object for ${objectDisplayName} at ${renderContext(\n c,\n )} but got ${typeof x}`,\n );\n }\n const obj: any = {};\n for (const prop of propList) {\n const propRawVal = x[prop.name];\n const propVal = prop.codec.decode(\n propRawVal,\n joinContext(c, prop.name),\n );\n obj[prop.name] = propVal;\n }\n for (const prop in x) {\n if (prop in obj) {\n continue;\n }\n if (allowExtra) {\n obj[prop] = x[prop];\n } else if (deprecatedPros.has(prop)) {\n logger.trace(\n `Deprecated property ${prop} for ${objectDisplayName} at ${renderContext(\n c,\n )}`,\n );\n } else {\n logger.warn(\n `Extra property ${prop} for ${objectDisplayName} at ${renderContext(\n c,\n )}`,\n );\n }\n }\n return obj as PartialOutputType;\n },\n\n getProps(): Prop[] {\n return propList;\n },\n };\n }\n}\n\nclass UnionCodecBuilder<\n TargetType,\n TagPropertyLabel extends keyof TargetType,\n CommonBaseType,\n PartialTargetType,\n> {\n private alternatives = new Map();\n\n constructor(\n private discriminator: TagPropertyLabel,\n private baseCodec?: Codec,\n ) {}\n\n /**\n * Define a property for the object.\n */\n alternativeOnMissing(\n tagValue: TargetType[TagPropertyLabel],\n codec: Codec,\n ): UnionCodecBuilder<\n TargetType,\n TagPropertyLabel,\n CommonBaseType,\n PartialTargetType | V\n > {\n if (!codec) {\n throw Error(\"inner codec must be defined\");\n }\n this.alternatives.set(undefined, { codec, tagValue });\n return this as any;\n }\n\n /**\n * Define a property for the object.\n */\n alternative(\n tagValue: TargetType[TagPropertyLabel],\n codec: Codec,\n ): UnionCodecBuilder<\n TargetType,\n TagPropertyLabel,\n CommonBaseType,\n PartialTargetType | V\n > {\n if (!codec) {\n throw Error(\"inner codec must be defined\");\n }\n this.alternatives.set(tagValue, { codec, tagValue });\n return this as any;\n }\n\n /**\n * Return the built codec.\n *\n * @param objectDisplayName name of the object that this codec operates on,\n * used in error messages.\n */\n build(\n objectDisplayName: string,\n ): Codec {\n const alternatives = this.alternatives;\n const discriminator = this.discriminator;\n const baseCodec = this.baseCodec;\n return {\n decode(x: any, c?: Context): R {\n if (!c) {\n c = {\n path: [`(${objectDisplayName})`],\n };\n }\n const d = x[discriminator];\n if (d === undefined && !alternatives.has(d)) {\n throw new DecodingError(\n `expected tag for ${objectDisplayName} at ${renderContext(\n c,\n )}.${String(discriminator)}`,\n );\n }\n const alt = alternatives.get(d);\n if (!alt) {\n throw new DecodingError(\n `unknown tag for ${objectDisplayName} ${d} at ${renderContext(\n c,\n )}.${String(discriminator)}`,\n );\n }\n const altDecoded = alt.codec.decode(x);\n if (baseCodec) {\n const baseDecoded = baseCodec.decode(x, c);\n return { ...baseDecoded, ...altDecoded };\n } else {\n return altDecoded;\n }\n },\n };\n }\n}\n\nexport class UnionCodecPreBuilder {\n discriminateOn(\n discriminator: D,\n baseCodec?: Codec,\n ): UnionCodecBuilder {\n return new UnionCodecBuilder(discriminator, baseCodec);\n }\n}\n\n/**\n * Return a builder for a codec that decodes an object with properties.\n */\nexport function buildCodecForObject(): ObjectCodecBuilder {\n return new ObjectCodecBuilder();\n}\n\nexport function buildCodecForUnion(): UnionCodecPreBuilder {\n return new UnionCodecPreBuilder();\n}\n\n/**\n * Return a codec for a mapping from a string to values described by the inner codec.\n */\nexport function codecForMap(\n innerCodec: Codec,\n): Codec<{ [x: string]: T }> {\n if (!innerCodec) {\n throw Error(\"inner codec must be defined\");\n }\n return {\n decode(x: any, c?: Context): { [x: string]: T } {\n const map: { [x: string]: T } = {};\n if (typeof x !== \"object\") {\n throw new DecodingError(`expected object at ${renderContext(c)}`);\n }\n for (const i in x) {\n map[i] = innerCodec.decode(x[i], joinContext(c, `[${i}]`));\n }\n return map;\n },\n };\n}\n\n/**\n * Return a codec for a list, containing values described by the inner codec.\n */\nexport function codecForList(innerCodec: Codec): Codec {\n if (!innerCodec) {\n throw Error(\"inner codec must be defined\");\n }\n return {\n decode(x: any, c?: Context): T[] {\n const arr: T[] = [];\n if (!Array.isArray(x)) {\n throw new DecodingError(`expected array at ${renderContext(c)}`);\n }\n for (const i in x) {\n arr.push(innerCodec.decode(x[i], joinContext(c, `[${i}]`)));\n }\n return arr;\n },\n };\n}\n\n/**\n * Return a codec for a value that must be a number.\n */\nexport function codecForNumber(): Codec {\n return {\n decode(x: any, c?: Context): number {\n if (typeof x === \"number\") {\n return x;\n }\n throw new DecodingError(\n `expected number at ${renderContext(c)} but got ${typeof x}`,\n );\n },\n };\n}\n\n/**\n * Return a codec for a value that must be a number.\n */\nexport function codecForBoolean(): Codec {\n return {\n decode(x: any, c?: Context): boolean {\n if (typeof x === \"boolean\") {\n return x;\n }\n throw new DecodingError(\n `expected boolean at ${renderContext(c)} but got ${typeof x}`,\n );\n },\n };\n}\n\n/**\n * Return a codec for a value that must be a string.\n */\nexport function codecForString(): Codec {\n return {\n decode(x: any, c?: Context): string {\n if (typeof x === \"string\") {\n return x;\n }\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n },\n };\n}\n\nexport function codecForStringUnion>(\n ...vals: [...T]\n): Codec {\n return {\n decode(x: any, c?: Context): T[number] {\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n if (!vals.includes(x)) {\n throw new DecodingError(\n `expected constant of ${JSON.stringify(vals)} at ${renderContext(\n c,\n )} but got ${x}`,\n );\n }\n return x;\n },\n };\n}\n\n/**\n * Return a codec for a value that must be a string.\n */\nexport function codecForStringURL(shouldEndWithSlash?: boolean): Codec {\n return {\n decode(x: any, c?: Context): string {\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n if (shouldEndWithSlash && !x.endsWith(\"/\")) {\n throw new DecodingError(\n `expected URL string that ends with slash at ${renderContext(\n c,\n )} but got ${x}`,\n );\n }\n try {\n const url = new URL(x);\n return x;\n } catch (e) {\n if (e instanceof Error) {\n throw new DecodingError(e.message);\n } else {\n throw new DecodingError(\n `expected an URL string at ${renderContext(c)} but got \"${x}\"`,\n );\n }\n }\n },\n };\n}\n\n/**\n * Return a codec for a value that must be a string.\n */\nexport function codecForURL(shouldEndWithSlash?: boolean): Codec {\n return {\n decode(x: any, c?: Context): URL {\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n if (shouldEndWithSlash && !x.endsWith(\"/\")) {\n throw new DecodingError(\n `expected URL string that ends with slash at ${renderContext(\n c,\n )} but got ${x}`,\n );\n }\n try {\n const url = new URL(x);\n return url;\n } catch (e) {\n if (e instanceof Error) {\n throw new DecodingError(e.message);\n } else {\n throw new DecodingError(\n `expected an URL string at ${renderContext(c)} but got \"${x}\"`,\n );\n }\n }\n },\n };\n}\n\n/**\n * Codec that allows any value.\n */\nexport function codecForAny(): Codec {\n return {\n decode(x: any, c?: Context): any {\n return x;\n },\n };\n}\n\n/**\n * Return a codec for a value that must be a string.\n */\nexport function codecForConstString(s: V): Codec {\n return {\n decode(x: any, c?: Context): V {\n if (x === s) {\n return x;\n }\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string constant \"${s}\" at ${renderContext(\n c,\n )} but got ${typeof x}`,\n );\n }\n throw new DecodingError(\n `expected string constant \"${s}\" at ${renderContext(\n c,\n )} but got string value \"${x}\"`,\n );\n },\n };\n}\n\n/**\n * Return a codec for a boolean true constant.\n */\nexport function codecForConstTrue(): Codec {\n return {\n decode(x: any, c?: Context): true {\n if (x === true) {\n return x;\n }\n throw new DecodingError(\n `expected boolean true at ${renderContext(c)} but got ${typeof x}`,\n );\n },\n };\n}\n\n/**\n * Return a codec for a boolean true constant.\n */\nexport function codecForConstFalse(): Codec {\n return {\n decode(x: any, c?: Context): false {\n if (x === false) {\n return x;\n }\n throw new DecodingError(\n `expected boolean false at ${renderContext(c)} but got ${typeof x}`,\n );\n },\n };\n}\n\n/**\n * Return a codec for a value that must be a constant number.\n */\nexport function codecForConstNumber(n: V): Codec {\n return {\n decode(x: any, c?: Context): V {\n if (x === n) {\n return x;\n }\n throw new DecodingError(\n `expected number constant \"${n}\" at ${renderContext(\n c,\n )} but got ${typeof x}`,\n );\n },\n };\n}\n\nexport function codecOptional(innerCodec: Codec): Codec {\n return {\n decode(x: any, c?: Context): V | undefined {\n if (x === undefined || x === null) {\n return undefined;\n }\n return innerCodec.decode(x, c);\n },\n };\n}\n\nexport function codecOptionalDefault(\n innerCodec: Codec,\n def: V,\n): Codec {\n return {\n decode(x: any, c?: Context): V {\n if (x === undefined || x === null) {\n return def;\n }\n return innerCodec.decode(x, c);\n },\n };\n}\n\nexport function codecForLazy(innerCodec: () => Codec): Codec {\n let instance: Codec | undefined = undefined;\n return {\n decode(x: any, c?: Context): V {\n if (instance === undefined) {\n instance = innerCodec();\n }\n return instance.decode(x, c);\n },\n };\n}\n\nexport type CodecType = T extends Codec ? X : any;\n\nexport function codecForEither>>(\n ...alts: [...T]\n): Codec> {\n return {\n decode(x: any, c?: Context): any {\n for (const alt of alts) {\n try {\n return alt.decode(x, c);\n } catch (e) {\n continue;\n }\n }\n if (logger.shouldLogTrace()) {\n logger.trace(`offending value: ${j2s(x)}`);\n }\n throw new DecodingError(`No alternative matched at ${renderContext(c)}`);\n },\n };\n}\n", "/*\nMIT License\n\nCopyright (c) 2017 Conrad Reuter\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\nconst NOOP = () => {};\n\n/**\n * A token that can be passed around to inform consumers of the token that a\n * certain operation has been cancelled.\n */\nclass CancellationToken {\n private _reason: any;\n private _callbacks?: Set<(reason?: any) => void> = new Set();\n\n /**\n * A cancellation token that is already cancelled.\n */\n public static readonly CANCELLED: CancellationToken = new CancellationToken(\n true,\n true,\n );\n\n /**\n * A cancellation token that is never cancelled.\n */\n public static readonly CONTINUE: CancellationToken = new CancellationToken(\n false,\n false,\n );\n\n /**\n * Whether the token has been cancelled.\n */\n public get isCancelled(): boolean {\n return this._isCancelled;\n }\n\n /**\n * Whether the token can be cancelled.\n */\n public get canBeCancelled(): boolean {\n return this._canBeCancelled;\n }\n\n /**\n * Why this token has been cancelled.\n */\n public get reason(): any {\n if (this.isCancelled) {\n return this._reason;\n } else {\n throw new Error(\"This token is not cancelled.\");\n }\n }\n\n /**\n * Make a promise that resolves when the async operation resolves,\n * or rejects when the operation is rejected or this token is cancelled.\n */\n public racePromise(asyncOperation: Promise): Promise {\n if (!this.canBeCancelled) {\n return asyncOperation;\n }\n return new Promise((resolve, reject) => {\n // we could use Promise.finally here as soon as it's implemented in the major browsers\n const unregister = this.onCancelled((reason) =>\n reject(new CancellationToken.CancellationError(reason)),\n );\n asyncOperation.then(\n (value) => {\n resolve(value);\n unregister();\n },\n (err) => {\n reject(err);\n unregister();\n },\n );\n });\n }\n\n /**\n * Throw a {CancellationToken.CancellationError} if this token is cancelled.\n */\n public throwIfCancelled(): void {\n if (this._isCancelled) {\n throw new CancellationToken.CancellationError(this._reason);\n }\n }\n\n /**\n * Invoke the callback when this token is cancelled.\n * If this token is already cancelled, the callback is invoked immediately.\n * Returns a function that unregisters the cancellation callback.\n */\n public onCancelled(cb: (reason?: any) => void): () => void {\n if (!this.canBeCancelled) {\n return NOOP;\n }\n if (this.isCancelled) {\n cb(this.reason);\n return NOOP;\n }\n\n /* istanbul ignore next */\n this._callbacks?.add(cb);\n return () => this._callbacks?.delete(cb);\n }\n\n private constructor(\n /**\n * Whether the token is already cancelled.\n */\n private _isCancelled: boolean,\n /**\n * Whether the token can be cancelled.\n */\n private _canBeCancelled: boolean,\n ) {}\n\n /**\n * Create a {CancellationTokenSource}.\n */\n public static create(): CancellationToken.Source {\n const token = new CancellationToken(false, true);\n\n const cancel = (reason?: any) => {\n if (token._isCancelled) return;\n token._isCancelled = true;\n token._reason = reason;\n token._callbacks?.forEach((cb) => cb(reason));\n dispose();\n };\n\n const dispose = () => {\n token._canBeCancelled = token.isCancelled;\n delete token._callbacks; // release memory\n };\n\n return { token, cancel, dispose };\n }\n\n /**\n * Create a {CancellationTokenSource}.\n * The token will be cancelled automatically after the specified timeout in milliseconds.\n */\n public static timeout(ms: number): CancellationToken.Source {\n const {\n token,\n cancel: originalCancel,\n dispose: originalDispose,\n } = CancellationToken.create();\n\n let timer: NodeJS.Timeout | null;\n timer = setTimeout(\n () => originalCancel(`CancellationToken.timeout ${ms}`),\n ms,\n );\n const disposeTimer = () => {\n if (timer == null) return;\n clearTimeout(timer);\n timer = null;\n };\n\n const cancel = (reason?: any) => {\n disposeTimer();\n originalCancel(reason);\n };\n\n /* istanbul ignore next */\n const dispose = () => {\n disposeTimer();\n originalDispose();\n };\n\n return { token, cancel, dispose };\n }\n\n /**\n * Create a {CancellationToken} that is cancelled when all of the given tokens are cancelled.\n *\n * This is like {Promise.all} for {CancellationToken}s.\n */\n public static all(...tokens: CancellationToken[]): CancellationToken {\n // If *any* of the tokens cannot be cancelled, then the token we return can never be.\n if (tokens.some((token) => !token.canBeCancelled)) {\n return CancellationToken.CONTINUE;\n }\n\n const combined = CancellationToken.create();\n let countdown = tokens.length;\n const handleNextTokenCancelled = () => {\n if (--countdown === 0) {\n const reasons = tokens.map((token) => token._reason);\n combined.cancel(reasons);\n }\n };\n tokens.forEach((token) => token.onCancelled(handleNextTokenCancelled));\n return combined.token;\n }\n\n /**\n * Create a {CancellationToken} that is cancelled when at least one of the given tokens is cancelled.\n *\n * This is like {Promise.race} for {CancellationToken}s.\n */\n public static race(...tokens: CancellationToken[]): CancellationToken {\n // If *any* of the tokens is already cancelled, immediately return that token.\n for (const token of tokens) {\n if (token._isCancelled) {\n return token;\n }\n }\n\n const combined = CancellationToken.create();\n let unregistrations: (() => void)[];\n const handleAnyTokenCancelled = (reason?: any) => {\n unregistrations.forEach((unregister) => unregister()); // release memory\n combined.cancel(reason);\n };\n unregistrations = tokens.map((token) =>\n token.onCancelled(handleAnyTokenCancelled),\n );\n return combined.token;\n }\n}\n\n/* istanbul ignore next */\nnamespace CancellationToken {\n /**\n * Provides a {CancellationToken}, along with some methods to operate on it.\n */\n export interface Source {\n /**\n * The token provided by this source.\n */\n token: CancellationToken;\n\n /**\n * Cancel the provided token with the given reason.\n * Do nothing if the provided token cannot be cancelled or is already cancelled.\n */\n cancel(reason?: any): void;\n\n /**\n * Dispose of the token and this source and release memory.\n */\n dispose(): void;\n }\n\n /**\n * The error that is thrown when a {CancellationToken} has been cancelled and a\n * consumer of the token calls {CancellationToken.throwIfCancelled} on it.\n */\n export class CancellationError extends Error {\n public constructor(\n /**\n * The reason why the token was cancelled.\n */\n public readonly reason: any,\n ) {\n super(\"Operation cancelled\");\n Object.setPrototypeOf(this, CancellationError.prototype);\n }\n }\n}\n\nexport { CancellationToken };\n", "/*\n This file is part of GNU Taler\n Copyright (C) 2012-2026 Taler Systems SA\n\n GNU Taler is free software: you can redistribute it and/or modify it\n under the terms of the GNU Lesser General Public License as published\n by the Free Software Foundation, either version 3 of the License,\n or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but\n WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see .\n\n SPDX-License-Identifier: LGPL3.0-or-later\n\n Note: the LGPL does not apply to all components of GNU Taler,\n but it does apply to this file.\n */\n\nexport enum TalerErrorCode {\n\n\n /**\n * Special code to indicate success (no error).\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n NONE = 0,\n\n\n /**\n * An error response did not include an error code in the format expected by the client. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n INVALID = 1,\n\n\n /**\n * An internal failure happened on the client side. Details should be in the local logs. Check if you are using the latest available version or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_CLIENT_INTERNAL_ERROR = 2,\n\n\n /**\n * The client does not support the protocol version advertised by the server.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_CLIENT_UNSUPPORTED_PROTOCOL_VERSION = 3,\n\n\n /**\n * The response we got from the server was not in the expected format. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_INVALID_RESPONSE = 10,\n\n\n /**\n * The operation timed out. Trying again might help. Check the network connection.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_TIMEOUT = 11,\n\n\n /**\n * The protocol version given by the server does not follow the required format. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_VERSION_MALFORMED = 12,\n\n\n /**\n * The service responded with a reply that was in the right data format, but the content did not satisfy the protocol. Please file a bug report.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_REPLY_MALFORMED = 13,\n\n\n /**\n * There is an error in the client-side configuration, for example an option is set to an invalid value. Check the logs and fix the local configuration.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_CONFIGURATION_INVALID = 14,\n\n\n /**\n * The client made a request to a service, but received an error response it does not know how to handle. Please file a bug report.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_UNEXPECTED_REQUEST_ERROR = 15,\n\n\n /**\n * The token used by the client to authorize the request does not grant the required permissions for the request. Check the requirements and obtain a suitable authorization token to proceed.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_TOKEN_PERMISSION_INSUFFICIENT = 16,\n\n\n /**\n * The HTTP method used is invalid for this endpoint. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_METHOD_NOT_ALLOWED (405).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_METHOD_INVALID = 20,\n\n\n /**\n * There is no endpoint defined for the URL provided by the client. Check if you used the correct URL and/or file a report with the developers of the client software.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_ENDPOINT_UNKNOWN = 21,\n\n\n /**\n * The JSON in the client's request was malformed. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_JSON_INVALID = 22,\n\n\n /**\n * Some of the HTTP headers provided by the client were malformed and caused the server to not be able to handle the request. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_HTTP_HEADERS_MALFORMED = 23,\n\n\n /**\n * The payto:// URI provided by the client is malformed. Check that you are using the correct syntax as of RFC 8905 and/or that you entered the bank account number correctly.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_PAYTO_URI_MALFORMED = 24,\n\n\n /**\n * A required parameter in the request was missing. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_PARAMETER_MISSING = 25,\n\n\n /**\n * A parameter in the request was malformed. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_PARAMETER_MALFORMED = 26,\n\n\n /**\n * The reserve public key was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_RESERVE_PUB_MALFORMED = 27,\n\n\n /**\n * The body in the request could not be decompressed by the server. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_COMPRESSION_INVALID = 28,\n\n\n /**\n * A segment in the path of the URL provided by the client is malformed. Check that you are using the correct encoding for the URL.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_PATH_SEGMENT_MALFORMED = 29,\n\n\n /**\n * The currency involved in the operation is not acceptable for this server. Check your configuration and make sure the currency specified for a given service provider is one of the currencies supported by that provider.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_CURRENCY_MISMATCH = 30,\n\n\n /**\n * The URI is longer than the longest URI the HTTP server is willing to parse. If you believe this was a legitimate request, contact the server administrators and/or the software developers to increase the limit.\n * Returned with an HTTP status code of #MHD_HTTP_URI_TOO_LONG (414).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_URI_TOO_LONG = 31,\n\n\n /**\n * The body is too large to be permissible for the endpoint. If you believe this was a legitimate request, contact the server administrators and/or the software developers to increase the limit.\n * Returned with an HTTP status code of #MHD_HTTP_CONTENT_TOO_LARGE (413).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_UPLOAD_EXCEEDS_LIMIT = 32,\n\n\n /**\n * A parameter in the request was given that must not be present. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_PARAMETER_EXTRA = 33,\n\n\n /**\n * The service refused the request due to lack of proper authorization. Accessing this endpoint requires an access token from the account owner.\n * Returned with an HTTP status code of #MHD_HTTP_UNAUTHORIZED (401).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_UNAUTHORIZED = 40,\n\n\n /**\n * The service refused the request as the given authorization token is unknown. You should request a valid access token from the account owner.\n * Returned with an HTTP status code of #MHD_HTTP_UNAUTHORIZED (401).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_TOKEN_UNKNOWN = 41,\n\n\n /**\n * The service refused the request as the given authorization token expired. You should request a fresh authorization token from the account owner.\n * Returned with an HTTP status code of #MHD_HTTP_UNAUTHORIZED (401).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_TOKEN_EXPIRED = 42,\n\n\n /**\n * The service refused the request as the given authorization token is invalid or malformed. You should check that you have the right credentials.\n * Returned with an HTTP status code of #MHD_HTTP_UNAUTHORIZED (401).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_TOKEN_MALFORMED = 43,\n\n\n /**\n * The service refused the request due to lack of proper rights on the resource. You may need different credentials to be allowed to perform this operation.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_FORBIDDEN = 44,\n\n\n /**\n * The service failed initialize its connection to the database. The system administrator should check that the service has permissions to access the database and that the database is running.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_DB_SETUP_FAILED = 50,\n\n\n /**\n * The service encountered an error event to just start the database transaction. The system administrator should check that the database is running.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_DB_START_FAILED = 51,\n\n\n /**\n * The service failed to store information in its database. The system administrator should check that the database is running and review the service logs.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_DB_STORE_FAILED = 52,\n\n\n /**\n * The service failed to fetch information from its database. The system administrator should check that the database is running and review the service logs.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_DB_FETCH_FAILED = 53,\n\n\n /**\n * The service encountered an unrecoverable error trying to commit a transaction to the database. The system administrator should check that the database is running and review the service logs.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_DB_COMMIT_FAILED = 54,\n\n\n /**\n * The service encountered an error event to commit the database transaction, even after repeatedly retrying it there was always a conflicting transaction. This indicates a repeated serialization error; it should only happen if some client maliciously tries to create conflicting concurrent transactions. It could also be a sign of a missing index. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_DB_SOFT_FAILURE = 55,\n\n\n /**\n * The service's database is inconsistent and violates service-internal invariants. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_DB_INVARIANT_FAILURE = 56,\n\n\n /**\n * The HTTP server experienced an internal invariant failure (bug). Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_INTERNAL_INVARIANT_FAILURE = 60,\n\n\n /**\n * The service could not compute a cryptographic hash over some JSON value. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_FAILED_COMPUTE_JSON_HASH = 61,\n\n\n /**\n * The service could not compute an amount. Check if you are using the latest available version and/or file a report with the developers.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_FAILED_COMPUTE_AMOUNT = 62,\n\n\n /**\n * The HTTP server had insufficient memory to parse the request. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_PARSER_OUT_OF_MEMORY = 70,\n\n\n /**\n * The HTTP server failed to allocate memory. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_ALLOCATION_FAILURE = 71,\n\n\n /**\n * The HTTP server failed to allocate memory for building JSON reply. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_JSON_ALLOCATION_FAILURE = 72,\n\n\n /**\n * The HTTP server failed to allocate memory for making a CURL request. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_CURL_ALLOCATION_FAILURE = 73,\n\n\n /**\n * The backend could not locate a required template to generate an HTML reply. The system administrator should check if the resource files are installed in the correct location and are readable to the service.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_ACCEPTABLE (406).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_FAILED_TO_LOAD_TEMPLATE = 74,\n\n\n /**\n * The backend could not expand the template to generate an HTML reply. The system administrator should investigate the logs and check if the templates are well-formed.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_FAILED_TO_EXPAND_TEMPLATE = 75,\n\n\n /**\n * The requested feature is not implemented by the server. The system administrator of the server may try to update the software or build it with other options to enable the feature.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_FEATURE_NOT_IMPLEMENTED = 76,\n\n\n /**\n * The operating system failed to allocate required resources. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_OS_RESOURCE_ALLOCATION_FAILURE = 77,\n\n\n /**\n * The requested content type is not supported by the server. The client should try requesting a different format.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_ACCEPTABLE (406).\n * (A value of 0 indicates that the error is generated client-side).\n */\n GENERIC_REQUESTED_FORMAT_UNSUPPORTED = 78,\n\n\n /**\n * Exchange is badly configured and thus cannot operate.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_BAD_CONFIGURATION = 1000,\n\n\n /**\n * Operation specified unknown for this endpoint.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_OPERATION_UNKNOWN = 1001,\n\n\n /**\n * The number of segments included in the URI does not match the number of segments expected by the endpoint.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS = 1002,\n\n\n /**\n * The same coin was already used with a different denomination previously.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY = 1003,\n\n\n /**\n * The public key of given to a \"/coins/\" endpoint of the exchange was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB = 1004,\n\n\n /**\n * The exchange is not aware of the denomination key the wallet requested for the operation.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN = 1005,\n\n\n /**\n * The signature of the denomination key over the coin is not valid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DENOMINATION_SIGNATURE_INVALID = 1006,\n\n\n /**\n * The exchange failed to perform the operation as it could not find the private keys. This is a problem with the exchange setup, not with the client's request.\n * Returned with an HTTP status code of #MHD_HTTP_SERVICE_UNAVAILABLE (503).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_KEYS_MISSING = 1007,\n\n\n /**\n * Validity period of the denomination lies in the future.\n * Returned with an HTTP status code of #MHD_HTTP_PRECONDITION_FAILED (412).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE = 1008,\n\n\n /**\n * Denomination key of the coin is past its expiration time for the requested operation.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_DENOMINATION_EXPIRED = 1009,\n\n\n /**\n * Denomination key of the coin has been revoked.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_DENOMINATION_REVOKED = 1010,\n\n\n /**\n * An operation where the exchange interacted with a security module timed out.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_SECMOD_TIMEOUT = 1011,\n\n\n /**\n * The respective coin did not have sufficient residual value for the operation. The \"history\" in this response provides the \"residual_value\" of the coin, which may be less than its \"original_value\".\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_INSUFFICIENT_FUNDS = 1012,\n\n\n /**\n * The exchange had an internal error reconstructing the transaction history of the coin that was being processed.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_COIN_HISTORY_COMPUTATION_FAILED = 1013,\n\n\n /**\n * The exchange failed to obtain the transaction history of the given coin from the database while generating an insufficient funds errors.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS = 1014,\n\n\n /**\n * The same coin was already used with a different age hash previously.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH = 1015,\n\n\n /**\n * The requested operation is not valid for the cipher used by the selected denomination.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION = 1016,\n\n\n /**\n * The provided arguments for the operation use inconsistent ciphers.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_CIPHER_MISMATCH = 1017,\n\n\n /**\n * The number of denominations specified in the request exceeds the limit of the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE = 1018,\n\n\n /**\n * The coin is not known to the exchange (yet).\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_COIN_UNKNOWN = 1019,\n\n\n /**\n * The time at the server is too far off from the time specified in the request. Most likely the client system time is wrong.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_CLOCK_SKEW = 1020,\n\n\n /**\n * The specified amount for the coin is higher than the value of the denomination of the coin.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_AMOUNT_EXCEEDS_DENOMINATION_VALUE = 1021,\n\n\n /**\n * The exchange was not properly configured with global fees.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_GLOBAL_FEES_MISSING = 1022,\n\n\n /**\n * The exchange was not properly configured with wire fees.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_WIRE_FEES_MISSING = 1023,\n\n\n /**\n * The purse public key was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_PURSE_PUB_MALFORMED = 1024,\n\n\n /**\n * The purse is unknown.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_PURSE_UNKNOWN = 1025,\n\n\n /**\n * The purse has expired.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_PURSE_EXPIRED = 1026,\n\n\n /**\n * The exchange has no information about the \"reserve_pub\" that was given.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_RESERVE_UNKNOWN = 1027,\n\n\n /**\n * The exchange is not allowed to proceed with the operation until the client has satisfied a KYC check.\n * Returned with an HTTP status code of #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS (451).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_KYC_REQUIRED = 1028,\n\n\n /**\n * Inconsistency between provided age commitment and attest: either none or both must be provided\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_DEPOSIT_COIN_CONFLICTING_ATTEST_VS_AGE_COMMITMENT = 1029,\n\n\n /**\n * The provided attestation for the minimum age couldn't be verified by the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_DEPOSIT_COIN_AGE_ATTESTATION_FAILURE = 1030,\n\n\n /**\n * The purse was deleted.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_PURSE_DELETED = 1031,\n\n\n /**\n * The public key of the AML officer in the URL was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_AML_OFFICER_PUB_MALFORMED = 1032,\n\n\n /**\n * The signature affirming the GET request of the AML officer is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID = 1033,\n\n\n /**\n * The specified AML officer does not have access at this time.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED = 1034,\n\n\n /**\n * The requested operation is denied pending the resolution of an anti-money laundering investigation by the exchange operator. This is a manual process, please wait and retry later.\n * Returned with an HTTP status code of #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS (451).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_AML_PENDING = 1035,\n\n\n /**\n * The requested operation is denied as the account was frozen on suspicion of money laundering. Please contact the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS (451).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_AML_FROZEN = 1036,\n\n\n /**\n * The exchange failed to start a KYC attribute conversion helper process. It is likely configured incorrectly.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_KYC_CONVERTER_FAILED = 1037,\n\n\n /**\n * The KYC operation failed. This could be because the KYC provider rejected the KYC data provided, or because the user aborted the KYC process.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_KYC_FAILED = 1038,\n\n\n /**\n * A fallback measure for a KYC operation failed. This is a bug. Users should contact the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_KYC_FALLBACK_FAILED = 1039,\n\n\n /**\n * The specified fallback measure for a KYC operation is unknown. This is a bug. Users should contact the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_KYC_FALLBACK_UNKNOWN = 1040,\n\n\n /**\n * The exchange is not aware of the bank account (payto URI or hash thereof) specified in the request and thus cannot perform the requested operation. The client should check that the select account is correct.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_BANK_ACCOUNT_UNKNOWN = 1041,\n\n\n /**\n * The AML processing at the exchange did not terminate in an adequate timeframe. This is likely a configuration problem at the payment service provider. Users should contact the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_AML_PROGRAM_RECURSION_DETECTED = 1042,\n\n\n /**\n * A check against sanction lists failed. This is indicative of an internal error in the sanction list processing logic. This needs to be investigated by the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_KYC_SANCTION_LIST_CHECK_FAILED = 1043,\n\n\n /**\n * The process to generate a PDF from a template failed. A likely cause is a syntactic error in the template. This needs to be investigated by the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_TYPST_TEMPLATE_FAILURE = 1044,\n\n\n /**\n * A process to combine multiple PDFs into one larger document failed. A likely cause is a resource exhaustion problem on the server. This needs to be investigated by the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_PDFTK_FAILURE = 1045,\n\n\n /**\n * The process to generate a PDF from a template crashed. A likely cause is a bug in the Typst software. This needs to be investigated by the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_TYPST_CRASH = 1046,\n\n\n /**\n * The process to combine multiple PDFs into a larger document crashed. A likely cause is a bug in the pdftk software. This needs to be investigated by the exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_PDFTK_CRASH = 1047,\n\n\n /**\n * One of the binaries needed to generate the PDF is not installed. If this feature is required, the system administrator should make sure Typst and pdftk are both installed.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_NO_TYPST_OR_PDFTK = 1048,\n\n\n /**\n * The exchange is not aware of the given target account. The specified account is not a customer of this service.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_TARGET_ACCOUNT_UNKNOWN = 1049,\n\n\n /**\n * The specified AML officer does not have write access at this time.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GENERIC_AML_OFFICER_READ_ONLY = 1050,\n\n\n /**\n * The exchange did not find information about the specified transaction in the database.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSITS_GET_NOT_FOUND = 1100,\n\n\n /**\n * The wire hash of given to a \"/deposits/\" handler was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE = 1101,\n\n\n /**\n * The merchant key of given to a \"/deposits/\" handler was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB = 1102,\n\n\n /**\n * The hash of the contract terms given to a \"/deposits/\" handler was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS = 1103,\n\n\n /**\n * The coin public key of given to a \"/deposits/\" handler was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB = 1104,\n\n\n /**\n * The signature returned by the exchange in a /deposits/ request was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSITS_GET_INVALID_SIGNATURE_BY_EXCHANGE = 1105,\n\n\n /**\n * The signature of the merchant is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID = 1106,\n\n\n /**\n * The provided policy data was not accepted\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSITS_POLICY_NOT_ACCEPTED = 1107,\n\n\n /**\n * The given reserve does not have sufficient funds to admit the requested withdraw operation at this time. The response includes the current \"balance\" of the reserve as well as the transaction \"history\" that lead to this balance.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS = 1150,\n\n\n /**\n * The given reserve does not have sufficient funds to admit the requested age-withdraw operation at this time. The response includes the current \"balance\" of the reserve as well as the transaction \"history\" that lead to this balance.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AGE_WITHDRAW_INSUFFICIENT_FUNDS = 1151,\n\n\n /**\n * The amount to withdraw together with the fee exceeds the numeric range for Taler amounts. This is not a client failure, as the coin value and fees come from the exchange's configuration.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW = 1152,\n\n\n /**\n * The exchange failed to create the signature using the denomination key.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_SIGNATURE_FAILED = 1153,\n\n\n /**\n * The signature of the reserve is not valid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID = 1154,\n\n\n /**\n * When computing the reserve history, we ended up with a negative overall balance, which should be impossible.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVE_HISTORY_ERROR_INSUFFICIENT_FUNDS = 1155,\n\n\n /**\n * The reserve did not have sufficient funds in it to pay for a full reserve history statement.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_GET_RESERVE_HISTORY_ERROR_INSUFFICIENT_BALANCE = 1156,\n\n\n /**\n * Withdraw period of the coin to be withdrawn is in the past.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_DENOMINATION_KEY_LOST = 1158,\n\n\n /**\n * The client failed to unblind the blind signature.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_UNBLIND_FAILURE = 1159,\n\n\n /**\n * The client reused a withdraw nonce, which is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_NONCE_REUSE = 1160,\n\n\n /**\n * The client provided an unknown commitment for an age-withdraw request.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_COMMITMENT_UNKNOWN = 1161,\n\n\n /**\n * The total sum of amounts from the denominations did overflow.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_AMOUNT_OVERFLOW = 1162,\n\n\n /**\n * The total sum of value and fees from the denominations differs from the committed amount with fees.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AGE_WITHDRAW_AMOUNT_INCORRECT = 1163,\n\n\n /**\n * The original commitment differs from the calculated hash\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_REVEAL_INVALID_HASH = 1164,\n\n\n /**\n * The maximum age in the commitment is too large for the reserve\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_MAXIMUM_AGE_TOO_LARGE = 1165,\n\n\n /**\n * The withdraw operation included the same planchet more than once. This is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WITHDRAW_IDEMPOTENT_PLANCHET = 1175,\n\n\n /**\n * The signature made by the coin over the deposit permission is not valid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID = 1205,\n\n\n /**\n * The same coin was already deposited for the same merchant and contract with other details.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT = 1206,\n\n\n /**\n * The stated value of the coin after the deposit fee is subtracted would be negative.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE = 1207,\n\n\n /**\n * The stated refund deadline is after the wire deadline.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE = 1208,\n\n\n /**\n * The stated wire deadline is \"never\", which makes no sense.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_WIRE_DEADLINE_IS_NEVER = 1209,\n\n\n /**\n * The exchange failed to canonicalize and hash the given wire format. For example, the merchant failed to provide the \"salt\" or a valid payto:// URI in the wire details. Note that while the exchange will do some basic sanity checking on the wire details, it cannot warrant that the banking system will ultimately be able to route to the specified address, even if this check passed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_JSON = 1210,\n\n\n /**\n * The hash of the given wire address does not match the wire hash specified in the proposal data.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT = 1211,\n\n\n /**\n * The signature provided by the exchange is not valid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE = 1221,\n\n\n /**\n * The deposited amount is smaller than the deposit fee, which would result in a negative contribution.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT = 1222,\n\n\n /**\n * The proof of policy fulfillment was invalid.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_EXTENSIONS_INVALID_FULFILLMENT = 1240,\n\n\n /**\n * The coin history was requested with a bad signature.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_COIN_HISTORY_BAD_SIGNATURE = 1251,\n\n\n /**\n * The reserve history was requested with a bad signature.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVE_HISTORY_BAD_SIGNATURE = 1252,\n\n\n /**\n * The exchange encountered melt fees exceeding the melted coin's contribution.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MELT_FEES_EXCEED_CONTRIBUTION = 1302,\n\n\n /**\n * The signature made with the coin to be melted is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MELT_COIN_SIGNATURE_INVALID = 1303,\n\n\n /**\n * The denomination of the given coin has past its expiration date and it is also not a valid zombie (that is, was not refreshed with the fresh coin being subjected to recoup).\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MELT_COIN_EXPIRED_NO_ZOMBIE = 1305,\n\n\n /**\n * The signature returned by the exchange in a melt request was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MELT_INVALID_SIGNATURE_BY_EXCHANGE = 1306,\n\n\n /**\n * The provided transfer keys do not match up with the original commitment. Information about the original commitment is included in the response.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_COMMITMENT_VIOLATION = 1353,\n\n\n /**\n * Failed to produce the blinded signatures over the coins to be returned.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_SIGNING_ERROR = 1354,\n\n\n /**\n * The exchange is unaware of the refresh session specified in the request.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_SESSION_UNKNOWN = 1355,\n\n\n /**\n * The size of the cut-and-choose dimension of the private transfer keys request does not match #TALER_CNC_KAPPA - 1.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID = 1356,\n\n\n /**\n * The number of envelopes given does not match the number of denomination keys given.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISMATCH = 1358,\n\n\n /**\n * The exchange encountered a numeric overflow totaling up the cost for the refresh operation.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_COST_CALCULATION_OVERFLOW = 1359,\n\n\n /**\n * The exchange's cost calculation shows that the melt amount is below the costs of the transaction.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_AMOUNT_INSUFFICIENT = 1360,\n\n\n /**\n * The signature made with the coin over the link data is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_LINK_SIGNATURE_INVALID = 1361,\n\n\n /**\n * The refresh session hash given to a /refreshes/ handler was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_INVALID_RCH = 1362,\n\n\n /**\n * Operation specified invalid for this endpoint.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_OPERATION_INVALID = 1363,\n\n\n /**\n * The client provided age commitment data, but age restriction is not supported on this server.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_NOT_SUPPORTED = 1364,\n\n\n /**\n * The client provided invalid age commitment data: missing, not an array, or array of invalid size.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_COMMITMENT_INVALID = 1365,\n\n\n /**\n * The coin specified in the link request is unknown to the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_LINK_COIN_UNKNOWN = 1400,\n\n\n /**\n * The public key of given to a /transfers/ handler was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_TRANSFERS_GET_WTID_MALFORMED = 1450,\n\n\n /**\n * The exchange did not find information about the specified wire transfer identifier in the database.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_TRANSFERS_GET_WTID_NOT_FOUND = 1451,\n\n\n /**\n * The exchange did not find information about the wire transfer fees it charged.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_TRANSFERS_GET_WIRE_FEE_NOT_FOUND = 1452,\n\n\n /**\n * The exchange found a wire fee that was above the total transfer value (and thus could not have been charged).\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_TRANSFERS_GET_WIRE_FEE_INCONSISTENT = 1453,\n\n\n /**\n * The wait target of the URL was not in the set of expected values.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSES_INVALID_WAIT_TARGET = 1475,\n\n\n /**\n * The signature on the purse status returned by the exchange was invalid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSES_GET_INVALID_SIGNATURE_BY_EXCHANGE = 1476,\n\n\n /**\n * The exchange knows literally nothing about the coin we were asked to refund. But without a transaction history, we cannot issue a refund. This is kind-of OK, the owner should just refresh it directly without executing the refund.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_COIN_NOT_FOUND = 1500,\n\n\n /**\n * We could not process the refund request as the coin's transaction history does not permit the requested refund because then refunds would exceed the deposit amount. The \"history\" in the response proves this.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_CONFLICT_DEPOSIT_INSUFFICIENT = 1501,\n\n\n /**\n * The exchange knows about the coin we were asked to refund, but not about the specific /deposit operation. Hence, we cannot issue a refund (as we do not know if this merchant public key is authorized to do a refund).\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_DEPOSIT_NOT_FOUND = 1502,\n\n\n /**\n * The exchange can no longer refund the customer/coin as the money was already transferred (paid out) to the merchant. (It should be past the refund deadline.)\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_MERCHANT_ALREADY_PAID = 1503,\n\n\n /**\n * The refund fee specified for the request is lower than the refund fee charged by the exchange for the given denomination key of the refunded coin.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_FEE_TOO_LOW = 1504,\n\n\n /**\n * The refunded amount is smaller than the refund fee, which would result in a negative refund.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_FEE_ABOVE_AMOUNT = 1505,\n\n\n /**\n * The signature of the merchant is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_MERCHANT_SIGNATURE_INVALID = 1506,\n\n\n /**\n * Merchant backend failed to create the refund confirmation signature.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_MERCHANT_SIGNING_FAILED = 1507,\n\n\n /**\n * The signature returned by the exchange in a refund request was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE = 1508,\n\n\n /**\n * The failure proof returned by the exchange is incorrect.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE = 1509,\n\n\n /**\n * Conflicting refund granted before with different amount but same refund transaction ID.\n * Returned with an HTTP status code of #MHD_HTTP_FAILED_DEPENDENCY (424).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_REFUND_INCONSISTENT_AMOUNT = 1510,\n\n\n /**\n * The given coin signature is invalid for the request.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_SIGNATURE_INVALID = 1550,\n\n\n /**\n * The exchange could not find the corresponding withdraw operation. The request is denied.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_WITHDRAW_NOT_FOUND = 1551,\n\n\n /**\n * The coin's remaining balance is zero. The request is denied.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_COIN_BALANCE_ZERO = 1552,\n\n\n /**\n * The exchange failed to reproduce the coin's blinding.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_BLINDING_FAILED = 1553,\n\n\n /**\n * The coin's remaining balance is zero. The request is denied.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_COIN_BALANCE_NEGATIVE = 1554,\n\n\n /**\n * The coin's denomination has not been revoked yet.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_NOT_ELIGIBLE = 1555,\n\n\n /**\n * The given coin signature is invalid for the request.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_REFRESH_SIGNATURE_INVALID = 1575,\n\n\n /**\n * The exchange could not find the corresponding melt operation. The request is denied.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_REFRESH_MELT_NOT_FOUND = 1576,\n\n\n /**\n * The exchange failed to reproduce the coin's blinding.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED = 1578,\n\n\n /**\n * The coin's denomination has not been revoked yet.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RECOUP_REFRESH_NOT_ELIGIBLE = 1580,\n\n\n /**\n * This exchange does not allow clients to request /keys for times other than the current (exchange) time.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KEYS_TIMETRAVEL_FORBIDDEN = 1600,\n\n\n /**\n * A signature in the server's response was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WIRE_SIGNATURE_INVALID = 1650,\n\n\n /**\n * No bank accounts are enabled for the exchange. The administrator should enable-account using the taler-exchange-offline tool.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WIRE_NO_ACCOUNTS_CONFIGURED = 1651,\n\n\n /**\n * The payto:// URI stored in the exchange database for its bank account is malformed.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WIRE_INVALID_PAYTO_CONFIGURED = 1652,\n\n\n /**\n * No wire fees are configured for an enabled wire method of the exchange. The administrator must set the wire-fee using the taler-exchange-offline tool.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_WIRE_FEES_NOT_CONFIGURED = 1653,\n\n\n /**\n * This purse was previously created with different meta data.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_PURSE_CREATE_CONFLICTING_META_DATA = 1675,\n\n\n /**\n * This purse was previously merged with different meta data.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_PURSE_MERGE_CONFLICTING_META_DATA = 1676,\n\n\n /**\n * The reserve has insufficient funds to create another purse.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_PURSE_CREATE_INSUFFICIENT_FUNDS = 1677,\n\n\n /**\n * The purse fee specified for the request is lower than the purse fee charged by the exchange at this time.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_PURSE_FEE_TOO_LOW = 1678,\n\n\n /**\n * The payment request cannot be deleted anymore, as it either already completed or timed out.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_DELETE_ALREADY_DECIDED = 1679,\n\n\n /**\n * The signature affirming the purse deletion is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_DELETE_SIGNATURE_INVALID = 1680,\n\n\n /**\n * Withdrawal from the reserve requires age restriction to be set.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED = 1681,\n\n\n /**\n * The exchange failed to talk to the process responsible for its private denomination keys or the helpers had no denominations (properly) configured.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE = 1700,\n\n\n /**\n * The response from the denomination key helper process was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DENOMINATION_HELPER_BUG = 1701,\n\n\n /**\n * The helper refuses to sign with the key, because it is too early: the validity period has not yet started.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_DENOMINATION_HELPER_TOO_EARLY = 1702,\n\n\n /**\n * The signature of the exchange on the reply was invalid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_DEPOSIT_EXCHANGE_SIGNATURE_INVALID = 1725,\n\n\n /**\n * The exchange failed to talk to the process responsible for its private signing keys.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE = 1750,\n\n\n /**\n * The response from the online signing key helper process was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_SIGNKEY_HELPER_BUG = 1751,\n\n\n /**\n * The helper refuses to sign with the key, because it is too early: the validity period has not yet started.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_SIGNKEY_HELPER_TOO_EARLY = 1752,\n\n\n /**\n * The signatures from the master exchange public key are missing, thus the exchange cannot currently sign its API responses. The exchange operator must use taler-exchange-offline to sign the current key material.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_SIGNKEY_HELPER_OFFLINE_MISSING = 1753,\n\n\n /**\n * The purse expiration time is in the past at the time of its creation.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW = 1775,\n\n\n /**\n * The purse expiration time is set to never, which is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_PURSE_EXPIRATION_IS_NEVER = 1776,\n\n\n /**\n * The signature affirming the merge of the purse is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_PURSE_MERGE_SIGNATURE_INVALID = 1777,\n\n\n /**\n * The signature by the reserve affirming the merge is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_RESERVE_MERGE_SIGNATURE_INVALID = 1778,\n\n\n /**\n * The signature by the reserve affirming the open operation is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_OPEN_BAD_SIGNATURE = 1785,\n\n\n /**\n * The signature by the reserve affirming the close operation is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_CLOSE_BAD_SIGNATURE = 1786,\n\n\n /**\n * The signature by the reserve affirming the attestion request is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_ATTEST_BAD_SIGNATURE = 1787,\n\n\n /**\n * The exchange does not know an origin account to which the remaining reserve balance could be wired to, and the wallet failed to provide one.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_CLOSE_NO_TARGET_ACCOUNT = 1788,\n\n\n /**\n * The reserve balance is insufficient to pay for the open operation.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_RESERVES_OPEN_INSUFFICIENT_FUNDS = 1789,\n\n\n /**\n * The auditor that was supposed to be disabled is unknown to this exchange.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_AUDITOR_NOT_FOUND = 1800,\n\n\n /**\n * The exchange has a more recently signed conflicting instruction and is thus refusing the current change (replay detected).\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_AUDITOR_MORE_RECENT_PRESENT = 1801,\n\n\n /**\n * The signature to add or enable the auditor does not validate.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_AUDITOR_ADD_SIGNATURE_INVALID = 1802,\n\n\n /**\n * The signature to disable the auditor does not validate.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_AUDITOR_DEL_SIGNATURE_INVALID = 1803,\n\n\n /**\n * The signature to revoke the denomination does not validate.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_DENOMINATION_REVOKE_SIGNATURE_INVALID = 1804,\n\n\n /**\n * The signature to revoke the online signing key does not validate.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_SIGNKEY_REVOKE_SIGNATURE_INVALID = 1805,\n\n\n /**\n * The exchange has a more recently signed conflicting instruction and is thus refusing the current change (replay detected).\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_WIRE_MORE_RECENT_PRESENT = 1806,\n\n\n /**\n * The signingkey specified is unknown to the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_UNKNOWN = 1807,\n\n\n /**\n * The signature to publish wire account does not validate.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_WIRE_DETAILS_SIGNATURE_INVALID = 1808,\n\n\n /**\n * The signature to add the wire account does not validate.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_WIRE_ADD_SIGNATURE_INVALID = 1809,\n\n\n /**\n * The signature to disable the wire account does not validate.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_WIRE_DEL_SIGNATURE_INVALID = 1810,\n\n\n /**\n * The wire account to be disabled is unknown to the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_WIRE_NOT_FOUND = 1811,\n\n\n /**\n * The signature to affirm wire fees does not validate.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_WIRE_FEE_SIGNATURE_INVALID = 1812,\n\n\n /**\n * The signature conflicts with a previous signature affirming different fees.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_WIRE_FEE_MISMATCH = 1813,\n\n\n /**\n * The signature affirming the denomination key is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID = 1814,\n\n\n /**\n * The signature affirming the signing key is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID = 1815,\n\n\n /**\n * The signature conflicts with a previous signature affirming different fees.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_GLOBAL_FEE_MISMATCH = 1816,\n\n\n /**\n * The signature affirming the fee structure is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_GLOBAL_FEE_SIGNATURE_INVALID = 1817,\n\n\n /**\n * The signature affirming the profit drain is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_DRAIN_PROFITS_SIGNATURE_INVALID = 1818,\n\n\n /**\n * The signature affirming the AML decision is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AML_DECISION_ADD_SIGNATURE_INVALID = 1825,\n\n\n /**\n * The AML officer specified is not allowed to make AML decisions right now.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AML_DECISION_INVALID_OFFICER = 1826,\n\n\n /**\n * There is a more recent AML decision on file. The decision was rejected as timestamps of AML decisions must be monotonically increasing.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AML_DECISION_MORE_RECENT_PRESENT = 1827,\n\n\n /**\n * There AML decision would impose an AML check of a type that is not provided by any KYC provider known to the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AML_DECISION_UNKNOWN_CHECK = 1828,\n\n\n /**\n * The signature affirming the change in the AML officer status is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_UPDATE_AML_OFFICER_SIGNATURE_INVALID = 1830,\n\n\n /**\n * A more recent decision about the AML officer status is known to the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_AML_OFFICERS_MORE_RECENT_PRESENT = 1831,\n\n\n /**\n * The exchange already has this denomination key configured, but with different meta data. This should not be possible, contact the developers for support.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_CONFLICTING_DENOMINATION_META_DATA = 1832,\n\n\n /**\n * The exchange already has this signing key configured, but with different meta data. This should not be possible, contact the developers for support.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_CONFLICTING_SIGNKEY_META_DATA = 1833,\n\n\n /**\n * The purse was previously created with different meta data.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA = 1850,\n\n\n /**\n * The purse was previously created with a different contract.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_CREATE_CONFLICTING_CONTRACT_STORED = 1851,\n\n\n /**\n * A coin signature for a deposit into the purse is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID = 1852,\n\n\n /**\n * The purse expiration time is in the past.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_CREATE_EXPIRATION_BEFORE_NOW = 1853,\n\n\n /**\n * The purse expiration time is \"never\".\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_CREATE_EXPIRATION_IS_NEVER = 1854,\n\n\n /**\n * The purse signature over the purse meta data is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_CREATE_SIGNATURE_INVALID = 1855,\n\n\n /**\n * The signature over the encrypted contract is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_ECONTRACT_SIGNATURE_INVALID = 1856,\n\n\n /**\n * The signature from the exchange over the confirmation is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_CREATE_EXCHANGE_SIGNATURE_INVALID = 1857,\n\n\n /**\n * The coin was previously deposited with different meta data.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA = 1858,\n\n\n /**\n * The encrypted contract was previously uploaded with different meta data.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA = 1859,\n\n\n /**\n * The deposited amount is less than the purse fee.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_CREATE_PURSE_NEGATIVE_VALUE_AFTER_FEE = 1860,\n\n\n /**\n * The signature using the merge key is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_MERGE_INVALID_MERGE_SIGNATURE = 1876,\n\n\n /**\n * The signature using the reserve key is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_MERGE_INVALID_RESERVE_SIGNATURE = 1877,\n\n\n /**\n * The targeted purse is not yet full and thus cannot be merged. Retrying the request later may succeed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_NOT_FULL = 1878,\n\n\n /**\n * The signature from the exchange over the confirmation is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_MERGE_EXCHANGE_SIGNATURE_INVALID = 1879,\n\n\n /**\n * The exchange of the target account is not a partner of this exchange.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MERGE_PURSE_PARTNER_UNKNOWN = 1880,\n\n\n /**\n * The signature affirming the new partner is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_ADD_PARTNER_SIGNATURE_INVALID = 1890,\n\n\n /**\n * Conflicting data for the partner already exists with the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_MANAGEMENT_ADD_PARTNER_DATA_CONFLICT = 1891,\n\n\n /**\n * The auditor signature over the denomination meta data is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AUDITORS_AUDITOR_SIGNATURE_INVALID = 1900,\n\n\n /**\n * The auditor that was specified is unknown to this exchange.\n * Returned with an HTTP status code of #MHD_HTTP_PRECONDITION_FAILED (412).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AUDITORS_AUDITOR_UNKNOWN = 1901,\n\n\n /**\n * The auditor that was specified is no longer used by this exchange.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_AUDITORS_AUDITOR_INACTIVE = 1902,\n\n\n /**\n * The exchange tried to run an AML program, but that program did not terminate on time. Contact the exchange operator to address the AML program bug or performance issue. If it is not a performance issue, the timeout might have to be increased (requires changes to the source code).\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT = 1918,\n\n\n /**\n * The KYC info access token is not recognized. Hence the request was denied.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_INFO_AUTHORIZATION_FAILED = 1919,\n\n\n /**\n * The exchange got stuck in a long series of (likely recursive) KYC rules without user-inputs that did not result in a timely conclusion. This is a configuration failure. Please contact the administrator.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_RECURSIVE_RULE_DETECTED = 1920,\n\n\n /**\n * The submitted KYC data lacks an attribute that is required by the KYC form. Please submit the complete form.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_AML_FORM_INCOMPLETE = 1921,\n\n\n /**\n * The request requires an AML program which is no longer configured at the exchange. Contact the exchange operator to address the configuration issue.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_AML_PROGRAM_GONE = 1922,\n\n\n /**\n * The given check is not of type 'form' and thus using this handler for form submission is incorrect.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_NOT_A_FORM = 1923,\n\n\n /**\n * The request requires a check which is no longer configured at the exchange. Contact the exchange operator to address the configuration issue.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_CHECK_GONE = 1924,\n\n\n /**\n * The signature affirming the wallet's KYC request was invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_WALLET_SIGNATURE_INVALID = 1925,\n\n\n /**\n * The exchange received an unexpected malformed response from its KYC backend.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE = 1926,\n\n\n /**\n * The backend signaled an unexpected failure.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_PROOF_BACKEND_ERROR = 1927,\n\n\n /**\n * The backend signaled an authorization failure.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_PROOF_BACKEND_AUTHORIZATION_FAILED = 1928,\n\n\n /**\n * The exchange is unaware of having made an the authorization request.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN = 1929,\n\n\n /**\n * The KYC authorization signature was invalid. Hence the request was denied.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED = 1930,\n\n\n /**\n * The request used a logic specifier that is not known to the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN = 1931,\n\n\n /**\n * The request requires a logic which is no longer configured at the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_LOGIC_GONE = 1932,\n\n\n /**\n * The logic plugin had a bug in its interaction with the KYC provider.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_LOGIC_BUG = 1933,\n\n\n /**\n * The exchange could not process the request with its KYC provider because the provider refused access to the service. This indicates some configuration issue at the Taler exchange operator.\n * Returned with an HTTP status code of #MHD_HTTP_NETWORK_AUTHENTICATION_REQUIRED (511).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_PROVIDER_ACCESS_REFUSED = 1934,\n\n\n /**\n * There was a timeout in the interaction between the exchange and the KYC provider. The most likely cause is some networking problem. Trying again later might succeed.\n * Returned with an HTTP status code of #MHD_HTTP_GATEWAY_TIMEOUT (504).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_PROVIDER_TIMEOUT = 1935,\n\n\n /**\n * The KYC provider responded with a status that was completely unexpected by the KYC logic of the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY = 1936,\n\n\n /**\n * The rate limit of the exchange at the KYC provider has been exceeded. Trying much later might work.\n * Returned with an HTTP status code of #MHD_HTTP_SERVICE_UNAVAILABLE (503).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_PROVIDER_RATE_LIMIT_EXCEEDED = 1937,\n\n\n /**\n * The request to the webhook lacked proper authorization or authentication data.\n * Returned with an HTTP status code of #MHD_HTTP_UNAUTHORIZED (401).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_WEBHOOK_UNAUTHORIZED = 1938,\n\n\n /**\n * The exchange is unaware of the requested payto URI with respect to the KYC status.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_CHECK_REQUEST_UNKNOWN = 1939,\n\n\n /**\n * The exchange has no account public key to check the KYC authorization signature against. Hence the request was denied. The user should do a wire transfer to the exchange with the KYC authorization key in the subject.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_CHECK_AUTHORIZATION_KEY_UNKNOWN = 1940,\n\n\n /**\n * The form has been previously uploaded, and may only be filed once. The user should be redirected to their main KYC page and see if any other steps need to be taken.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_FORM_ALREADY_UPLOADED = 1941,\n\n\n /**\n * The internal state of the exchange specifying KYC measures is malformed. Please contact technical support.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_MEASURES_MALFORMED = 1942,\n\n\n /**\n * The specified index does not refer to a valid KYC measure. Please check the URL.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_MEASURE_INDEX_INVALID = 1943,\n\n\n /**\n * The operation is not supported by the selected KYC logic. This is either caused by a configuration change or some invalid use of the API. Please contact technical support.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_INVALID_LOGIC_TO_CHECK = 1944,\n\n\n /**\n * The AML program failed. This is either caused by a configuration change or a bug. Please contact technical support.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_AML_PROGRAM_FAILURE = 1945,\n\n\n /**\n * The AML program returned a malformed result. This is a bug. Please contact technical support.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT = 1946,\n\n\n /**\n * The response from the KYC provider lacked required attributes. Please contact technical support.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_REPLY = 1947,\n\n\n /**\n * The context of the KYC check lacked required fields. This is a bug. Please contact technical support.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_CONTEXT = 1948,\n\n\n /**\n * The logic plugin had a bug in its AML processing. This is a bug. Please contact technical support.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_GENERIC_AML_LOGIC_BUG = 1949,\n\n\n /**\n * The exchange does not know a contract under the given contract public key.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_CONTRACTS_UNKNOWN = 1950,\n\n\n /**\n * The URL does not encode a valid exchange public key in its path.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_CONTRACTS_INVALID_CONTRACT_PUB = 1951,\n\n\n /**\n * The returned encrypted contract did not decrypt.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_CONTRACTS_DECRYPTION_FAILED = 1952,\n\n\n /**\n * The signature on the encrypted contract did not validate.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_CONTRACTS_SIGNATURE_INVALID = 1953,\n\n\n /**\n * The decrypted contract was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_CONTRACTS_DECODING_FAILED = 1954,\n\n\n /**\n * A coin signature for a deposit into the purse is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_DEPOSIT_COIN_SIGNATURE_INVALID = 1975,\n\n\n /**\n * It is too late to deposit coins into the purse.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_PURSE_DEPOSIT_DECIDED_ALREADY = 1976,\n\n\n /**\n * The exchange is currently processing the KYC status and is not able to return a response yet.\n * Returned with an HTTP status code of #MHD_HTTP_ACCEPTED (202).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_KYC_INFO_BUSY = 1977,\n\n\n /**\n * TOTP key is not valid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n EXCHANGE_TOTP_KEY_INVALID = 1980,\n\n\n /**\n * The backend could not find the merchant instance specified in the request.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_INSTANCE_UNKNOWN = 2000,\n\n\n /**\n * The start and end-times in the wire fee structure leave a hole. This is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_HOLE_IN_WIRE_FEE_STRUCTURE = 2001,\n\n\n /**\n * The master key of the exchange does not match the one configured for this merchant. As a result, we refuse to do business with this exchange. The administrator should check if they configured the exchange correctly in the merchant backend.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_EXCHANGE_MASTER_KEY_MISMATCH = 2002,\n\n\n /**\n * The product category is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_CATEGORY_UNKNOWN = 2003,\n\n\n /**\n * The unit referenced in the request is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_UNIT_UNKNOWN = 2004,\n\n\n /**\n * The proposal is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_ORDER_UNKNOWN = 2005,\n\n\n /**\n * The order provided to the backend could not be completed, because a product to be completed via inventory data is not actually in our inventory.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_PRODUCT_UNKNOWN = 2006,\n\n\n /**\n * The reward ID is unknown. This could happen if the reward has expired.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_REWARD_ID_UNKNOWN = 2007,\n\n\n /**\n * The contract obtained from the merchant backend was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID = 2008,\n\n\n /**\n * The order we found does not match the provided contract hash.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_CONTRACT_HASH_DOES_NOT_MATCH_ORDER = 2009,\n\n\n /**\n * The exchange failed to provide a valid response to the merchant's /keys request.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE = 2010,\n\n\n /**\n * The exchange failed to respond to the merchant on time.\n * Returned with an HTTP status code of #MHD_HTTP_GATEWAY_TIMEOUT (504).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_EXCHANGE_TIMEOUT = 2011,\n\n\n /**\n * The merchant failed to talk to the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE = 2012,\n\n\n /**\n * The exchange returned a maformed response.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED = 2013,\n\n\n /**\n * The exchange returned an unexpected response status.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS = 2014,\n\n\n /**\n * The merchant refused the request due to lack of authorization.\n * Returned with an HTTP status code of #MHD_HTTP_UNAUTHORIZED (401).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_UNAUTHORIZED = 2015,\n\n\n /**\n * The merchant instance specified in the request was deleted.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_INSTANCE_DELETED = 2016,\n\n\n /**\n * The backend could not find the inbound wire transfer specified in the request.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_TRANSFER_UNKNOWN = 2017,\n\n\n /**\n * The backend could not find the template(id) because it is not exist.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_TEMPLATE_UNKNOWN = 2018,\n\n\n /**\n * The backend could not find the webhook(id) because it is not exist.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_WEBHOOK_UNKNOWN = 2019,\n\n\n /**\n * The backend could not find the webhook(serial) because it is not exist.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_PENDING_WEBHOOK_UNKNOWN = 2020,\n\n\n /**\n * The backend could not find the OTP device(id) because it is not exist.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN = 2021,\n\n\n /**\n * The account is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_ACCOUNT_UNKNOWN = 2022,\n\n\n /**\n * The wire hash was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_H_WIRE_MALFORMED = 2023,\n\n\n /**\n * The currency specified in the operation does not work with the current state of the given resource.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_CURRENCY_MISMATCH = 2024,\n\n\n /**\n * The exchange specified in the operation is not trusted by this exchange. The client should limit its operation to exchanges enabled by the merchant, or ask the merchant to enable additional exchanges in the configuration.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_EXCHANGE_UNTRUSTED = 2025,\n\n\n /**\n * The token family is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_TOKEN_FAMILY_UNKNOWN = 2026,\n\n\n /**\n * The token family key is not known to the backend. Check the local system time on the client, maybe an expired (or not yet valid) token was used.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN = 2027,\n\n\n /**\n * The merchant backend is not configured to support the DONAU protocol.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_DONAU_NOT_CONFIGURED = 2028,\n\n\n /**\n * The public signing key given in the exchange response is not in the current keys response. It is possible that the operation will succeed later after the merchant has downloaded an updated keys response.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_SIGN_PUB_UNKNOWN = 2029,\n\n\n /**\n * The merchant backend does not support the requested feature.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE = 2030,\n\n\n /**\n * This operation requires multi-factor authorization and the respective instance does not have a sufficient number of factors that could be validated configured. You need to ask the system administrator to perform this operation.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_MFA_MISSING = 2031,\n\n\n /**\n * A donation authority (Donau) provided an invalid response. This should be analyzed by the administrator. Trying again later may help.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_DONAU_INVALID_RESPONSE = 2032,\n\n\n /**\n * The unit referenced in the request is builtin and cannot be modified or deleted.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_UNIT_BUILTIN = 2033,\n\n\n /**\n * The report ID provided to the backend is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_REPORT_UNKNOWN = 2034,\n\n\n /**\n * The report ID provided to the backend is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_REPORT_GENERATOR_UNCONFIGURED = 2035,\n\n\n /**\n * The product group ID provided to the backend is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_PRODUCT_GROUP_UNKNOWN = 2036,\n\n\n /**\n * The money pod ID provided to the backend is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_MONEY_POT_UNKNOWN = 2037,\n\n\n /**\n * The session ID provided to the backend is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_SESSION_UNKNOWN = 2038,\n\n\n /**\n * The merchant does not have a charity associated with the selected Donau. As a result, it cannot generate the requested donation receipt. This could happen if the charity was removed from the backend between order creation and payment.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN = 2039,\n\n\n /**\n * The merchant does not expect any transfer with the given ID and can thus not return any details about it.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_EXPECTED_TRANSFER_UNKNOWN = 2040,\n\n\n /**\n * The Donau is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_DONAU_UNKNOWN = 2041,\n\n\n /**\n * The access token is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_ACCESS_TOKEN_UNKNOWN = 2042,\n\n\n /**\n * One of the binaries needed to generate the PDF is not installed. If this feature is required, the system administrator should make sure Typst and pdftk are both installed.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GENERIC_NO_TYPST_OR_PDFTK = 2048,\n\n\n /**\n * The exchange failed to provide a valid answer to the tracking request, thus those details are not in the response.\n * Returned with an HTTP status code of #MHD_HTTP_OK (200).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GET_ORDERS_EXCHANGE_TRACKING_FAILURE = 2100,\n\n\n /**\n * The merchant backend failed to construct the request for tracking to the exchange, thus tracking details are not in the response.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GET_ORDERS_ID_EXCHANGE_REQUEST_FAILURE = 2103,\n\n\n /**\n * The merchant backend failed trying to contact the exchange for tracking details, thus those details are not in the response.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GET_ORDERS_ID_EXCHANGE_LOOKUP_START_FAILURE = 2104,\n\n\n /**\n * The claim token used to authenticate the client is invalid for this order.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GET_ORDERS_ID_INVALID_TOKEN = 2105,\n\n\n /**\n * The contract terms hash used to authenticate the client is invalid for this order.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GET_ORDERS_ID_INVALID_CONTRACT_HASH = 2106,\n\n\n /**\n * The contract terms version is not understood by the merchant backend. Most likely the merchant backend was downgraded to a version incompatible with the content of the database.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_GET_ORDERS_ID_INVALID_CONTRACT_VERSION = 2107,\n\n\n /**\n * The provided TAN code is invalid for this challenge.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_TAN_CHALLENGE_FAILED = 2125,\n\n\n /**\n * The backend is not aware of the specified MFA challenge.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_TAN_CHALLENGE_UNKNOWN = 2126,\n\n\n /**\n * There have been too many attempts to solve the challenge. A new TAN must be requested.\n * Returned with an HTTP status code of #MHD_HTTP_TOO_MANY_REQUESTS (429).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_TAN_TOO_MANY_ATTEMPTS = 2127,\n\n\n /**\n * The backend failed to launch a helper process required for the multi-factor authentication step. The backend operator should check the logs and fix the Taler merchant backend configuration.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_TAN_MFA_HELPER_EXEC_FAILED = 2128,\n\n\n /**\n * The challenge was already solved. Thus, we refuse to send it again.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_TAN_CHALLENGE_SOLVED = 2129,\n\n\n /**\n * It is too early to request another transmission of the challenge. The client should wait and see if they received the previous challenge.\n * Returned with an HTTP status code of #MHD_HTTP_TOO_MANY_REQUESTS (429).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_TAN_TOO_EARLY = 2130,\n\n\n /**\n * There have been too many attempts to solve MFA. The client may attempt again in the future.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_MFA_FORBIDDEN = 2131,\n\n\n /**\n * The exchange responded saying that funds were insufficient (for example, due to double-spending).\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS = 2150,\n\n\n /**\n * The denomination key used for payment is not listed among the denomination keys of the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND = 2151,\n\n\n /**\n * The denomination key used for payment is not audited by an auditor approved by the merchant.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_AUDITOR_FAILURE = 2152,\n\n\n /**\n * There was an integer overflow totaling up the amounts or deposit fees in the payment.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW = 2153,\n\n\n /**\n * The deposit fees exceed the total value of the payment.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT = 2154,\n\n\n /**\n * After considering deposit and wire fees, the payment is insufficient to satisfy the required amount for the contract. The client should revisit the logic used to calculate fees it must cover.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES = 2155,\n\n\n /**\n * Even if we do not consider deposit and wire fees, the payment is insufficient to satisfy the required amount for the contract.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT = 2156,\n\n\n /**\n * The signature over the contract of one of the coins was invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_COIN_SIGNATURE_INVALID = 2157,\n\n\n /**\n * When we tried to find information about the exchange to issue the deposit, we failed. This usually only happens if the merchant backend is somehow unable to get its own HTTP client logic to work.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LOOKUP_FAILED = 2158,\n\n\n /**\n * The refund deadline in the contract is after the transfer deadline.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE = 2159,\n\n\n /**\n * The order was already paid (maybe by another wallet).\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID = 2160,\n\n\n /**\n * The payment is too late, the offer has expired.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED = 2161,\n\n\n /**\n * The \"merchant\" field is missing in the proposal data. This is an internal error as the proposal is from the merchant's own database at this point.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_MERCHANT_FIELD_MISSING = 2162,\n\n\n /**\n * Failed to locate merchant's account information matching the wire hash given in the proposal.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN = 2163,\n\n\n /**\n * The deposit time for the denomination has expired.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED = 2165,\n\n\n /**\n * The exchange of the deposited coin charges a wire fee that could not be added to the total (total amount too high).\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED = 2166,\n\n\n /**\n * The contract was not fully paid because of refunds. Note that clients MAY treat this as paid if, for example, contracts must be executed despite of refunds.\n * Returned with an HTTP status code of #MHD_HTTP_PAYMENT_REQUIRED (402).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_REFUNDED = 2167,\n\n\n /**\n * According to our database, we have refunded more than we were paid (which should not be possible).\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS = 2168,\n\n\n /**\n * The refund request is too late because it is past the wire transfer deadline of the order. The merchant must find a different way to pay back the money to the customer.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_REFUND_AFTER_WIRE_DEADLINE = 2169,\n\n\n /**\n * The payment failed at the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_FAILED = 2170,\n\n\n /**\n * The payment required a minimum age but one of the coins (of a denomination with support for age restriction) did not provide any age_commitment.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING = 2171,\n\n\n /**\n * The payment required a minimum age but one of the coins provided an age_commitment that contained a wrong number of public keys compared to the number of age groups defined in the denomination of the coin.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH = 2172,\n\n\n /**\n * The payment required a minimum age but one of the coins provided a minimum_age_sig that couldn't be verified with the given age_commitment for that particular minimum age.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED = 2173,\n\n\n /**\n * The payment required no minimum age but one of the coins (of a denomination with support for age restriction) did not provide the required h_age_commitment.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING = 2174,\n\n\n /**\n * The exchange does not support the selected bank account of the merchant. Likely the merchant had stale data on the bank accounts of the exchange and thus selected an inappropriate exchange when making the offer.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED = 2175,\n\n\n /**\n * The payment requires the wallet to select a choice from the choices array and pass it in the 'choice_index' field of the request.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING = 2176,\n\n\n /**\n * The 'choice_index' field is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS = 2177,\n\n\n /**\n * The provided 'tokens' array does not match with the required input tokens of the order.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_INPUT_TOKENS_MISMATCH = 2178,\n\n\n /**\n * Invalid token issue signature (blindly signed by merchant) for provided token.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID = 2179,\n\n\n /**\n * Invalid token use signature (EdDSA, signed by wallet) for provided token.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID = 2180,\n\n\n /**\n * The provided number of tokens does not match the required number.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH = 2181,\n\n\n /**\n * The provided number of token envelopes does not match the specified number.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH = 2182,\n\n\n /**\n * Invalid token because it was already used, is expired or not yet valid.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID = 2183,\n\n\n /**\n * The payment violates a transaction limit configured at the given exchange. The wallet has a bug in that it failed to check exchange limits during coin selection. Please report the bug to your wallet developer.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION = 2184,\n\n\n /**\n * The donation amount provided in the BKPS does not match the amount of the order choice.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH = 2185,\n\n\n /**\n * Some of the exchanges involved refused the request for reasons related to legitimization. The wallet should try with coins of different exchanges. The merchant should check if they have some legitimization process pending at the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS (451).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED = 2186,\n\n\n /**\n * The contract hash does not match the given order ID.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAID_CONTRACT_HASH_MISMATCH = 2200,\n\n\n /**\n * The signature of the merchant is not valid for the given contract hash.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_PAID_COIN_SIGNATURE_INVALID = 2201,\n\n\n /**\n * A token family with this ID but conflicting data exists.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_TOKEN_FAMILY_CONFLICT = 2225,\n\n\n /**\n * The backend is unaware of a token family with the given ID.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PATCH_TOKEN_FAMILY_NOT_FOUND = 2226,\n\n\n /**\n * The merchant failed to send the exchange the refund request.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_ABORT_EXCHANGE_REFUND_FAILED = 2251,\n\n\n /**\n * The merchant failed to find the exchange to process the lookup.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_ABORT_EXCHANGE_LOOKUP_FAILED = 2252,\n\n\n /**\n * The merchant could not find the contract.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_NOT_FOUND = 2253,\n\n\n /**\n * The payment was already completed and thus cannot be aborted anymore.\n * Returned with an HTTP status code of #MHD_HTTP_PRECONDITION_FAILED (412).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE = 2254,\n\n\n /**\n * The hash provided by the wallet does not match the order.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_HASH_MISSMATCH = 2255,\n\n\n /**\n * The array of coins cannot be empty.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_ABORT_COINS_ARRAY_EMPTY = 2256,\n\n\n /**\n * We are waiting for the exchange to provide us with key material before checking the wire transfer.\n * Returned with an HTTP status code of #MHD_HTTP_ACCEPTED (202).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_AWAITING_KEYS = 2258,\n\n\n /**\n * We are waiting for the exchange to provide us with the list of aggregated transactions.\n * Returned with an HTTP status code of #MHD_HTTP_ACCEPTED (202).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_AWAITING_LIST = 2259,\n\n\n /**\n * The endpoint indicated in the wire transfer does not belong to a GNU Taler exchange.\n * Returned with an HTTP status code of #MHD_HTTP_OK (200).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_FATAL_NO_EXCHANGE = 2260,\n\n\n /**\n * The exchange indicated in the wire transfer claims to know nothing about the wire transfer.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_FATAL_NOT_FOUND = 2261,\n\n\n /**\n * The interaction with the exchange is delayed due to rate limiting.\n * Returned with an HTTP status code of #MHD_HTTP_ACCEPTED (202).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_RATE_LIMITED = 2262,\n\n\n /**\n * We experienced a transient failure in our interaction with the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_ACCEPTED (202).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_TRANSIENT_FAILURE = 2263,\n\n\n /**\n * The response from the exchange was unacceptable and should be reviewed with an auditor.\n * Returned with an HTTP status code of #MHD_HTTP_OK (200).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_HARD_FAILURE = 2264,\n\n\n /**\n * The merchant backend failed to reach the banking gateway to shorten the wire transfer subject. This probably means that the banking gateway of the exchange is currently down. Contact the exchange operator or simply retry again later.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ACCOUNTS_KYCAUTH_BANK_GATEWAY_UNREACHABLE = 2275,\n\n\n /**\n * The merchant backend failed to reach the banking gateway to shorten the wire transfer subject. This probably means that the banking gateway of the exchange is currently down. Contact the exchange operator or simply retry again later.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ACCOUNTS_EXCHANGE_TOO_OLD = 2276,\n\n\n /**\n * The merchant backend failed to reach the specified exchange. This probably means that the exchange is currently down. Contact the exchange operator or simply retry again later.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ACCOUNTS_KYCAUTH_EXCHANGE_UNREACHABLE = 2277,\n\n\n /**\n * We could not claim the order because the backend is unaware of it.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_CLAIM_NOT_FOUND = 2300,\n\n\n /**\n * We could not claim the order because someone else claimed it first.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_CLAIM_ALREADY_CLAIMED = 2301,\n\n\n /**\n * The client-side experienced an internal failure.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_CLAIM_CLIENT_INTERNAL_FAILURE = 2302,\n\n\n /**\n * The unclaim signature of the wallet is not valid for the given contract hash.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_UNCLAIM_SIGNATURE_INVALID = 2303,\n\n\n /**\n * The backend failed to sign the refund request.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_REFUND_SIGNATURE_FAILED = 2350,\n\n\n /**\n * The client failed to unblind the signature returned by the merchant.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_REWARD_PICKUP_UNBLIND_FAILURE = 2400,\n\n\n /**\n * The exchange returned a failure code for the withdraw operation.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_REWARD_PICKUP_EXCHANGE_ERROR = 2403,\n\n\n /**\n * The merchant failed to add up the amounts to compute the pick up value.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_REWARD_PICKUP_SUMMATION_FAILED = 2404,\n\n\n /**\n * The reward expired.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_REWARD_PICKUP_HAS_EXPIRED = 2405,\n\n\n /**\n * The requested withdraw amount exceeds the amount remaining to be picked up.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_REWARD_PICKUP_AMOUNT_EXCEEDS_REWARD_REMAINING = 2406,\n\n\n /**\n * The merchant did not find the specified denomination key in the exchange's key set.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_REWARD_PICKUP_DENOMINATION_UNKNOWN = 2407,\n\n\n /**\n * The merchant instance has no active bank accounts configured. However, at least one bank account must be available to create new orders.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE = 2500,\n\n\n /**\n * The proposal had no timestamp and the merchant backend failed to obtain the current local time.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_NO_LOCALTIME = 2501,\n\n\n /**\n * The order provided to the backend could not be parsed; likely some required fields were missing or ill-formed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_PROPOSAL_PARSE_ERROR = 2502,\n\n\n /**\n * A conflicting order (sharing the same order identifier) already exists at this merchant backend instance.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS = 2503,\n\n\n /**\n * The order creation request is invalid because the given wire deadline is before the refund deadline.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_REFUND_AFTER_WIRE_DEADLINE = 2504,\n\n\n /**\n * The order creation request is invalid because the delivery date given is in the past.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_DELIVERY_DATE_IN_PAST = 2505,\n\n\n /**\n * The order creation request is invalid because a wire deadline of \"never\" is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_WIRE_DEADLINE_IS_NEVER = 2506,\n\n\n /**\n * The order creation request is invalid because the given payment deadline is in the past.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_PAY_DEADLINE_IN_PAST = 2507,\n\n\n /**\n * The order creation request is invalid because the given refund deadline is in the past.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_REFUND_DEADLINE_IN_PAST = 2508,\n\n\n /**\n * The backend does not trust any exchange that would allow funds to be wired to any bank account of this instance using the wire method specified with the order. (Note that right now, we do not support the use of exchange bank accounts with mandatory currency conversion.) One likely cause for this is that the taler-merchant-exchangekeyupdate process is not running.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGES_FOR_WIRE_METHOD = 2509,\n\n\n /**\n * One of the paths to forget is malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_PATCH_ORDERS_ID_FORGET_PATH_SYNTAX_INCORRECT = 2510,\n\n\n /**\n * One of the paths to forget was not marked as forgettable.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_PATCH_ORDERS_ID_FORGET_PATH_NOT_FORGETTABLE = 2511,\n\n\n /**\n * The refund amount would violate a refund transaction limit configured at the given exchange. Please find another way to refund the customer, and inquire with your legislator why they make strange banking regulations.\n * Returned with an HTTP status code of #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS (451).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_ORDERS_ID_REFUND_EXCHANGE_TRANSACTION_LIMIT_VIOLATION = 2512,\n\n\n /**\n * The total order amount exceeds hard legal transaction limits from the available exchanges, thus a customer could never legally make this payment. You may try to increase your limits by passing legitimization checks with exchange operators. You could also inquire with your legislator why the limits are prohibitively low for your business.\n * Returned with an HTTP status code of #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS (451).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_AMOUNT_EXCEEDS_LEGAL_LIMITS = 2513,\n\n\n /**\n * A currency specified to be paid in the contract is not supported by any exchange that this instance can currently use. Possible solutions include (1) specifying a different currency, (2) adding additional suitable exchange operators to the merchant backend configuration, or (3) satisfying compliance rules of an configured exchange to begin using the service of that provider.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGE_FOR_CURRENCY = 2514,\n\n\n /**\n * The order provided to the backend could not be deleted, our offer is still valid and awaiting payment. Deletion may work later after the offer has expired if it remains unpaid.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_DELETE_ORDERS_AWAITING_PAYMENT = 2520,\n\n\n /**\n * The order provided to the backend could not be deleted as the order was already paid.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_DELETE_ORDERS_ALREADY_PAID = 2521,\n\n\n /**\n * The client requested a report granularity that is not available at the backend. Possible solutions include extending the backend code and/or the database statistic triggers to support the desired data granularity. Alternatively, the client could request a different granularity.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_GET_STATISTICS_REPORT_GRANULARITY_UNAVAILABLE = 2525,\n\n\n /**\n * The amount to be refunded is inconsistent: either is lower than the previous amount being awarded, or it exceeds the original price paid by the customer.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_INCONSISTENT_AMOUNT = 2530,\n\n\n /**\n * Only paid orders can be refunded, and the frontend specified an unpaid order to issue a refund for.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_ORDER_UNPAID = 2531,\n\n\n /**\n * The refund delay was set to 0 and thus no refunds are ever allowed for this order.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_NOT_ALLOWED_BY_CONTRACT = 2532,\n\n\n /**\n * The token family slug provided in this order could not be found in the merchant database.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_SLUG_UNKNOWN = 2533,\n\n\n /**\n * A token family referenced in this order is either expired or not valid yet.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_NOT_VALID = 2534,\n\n\n /**\n * The exchange says it does not know this transfer.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_TRANSFERS_EXCHANGE_UNKNOWN = 2550,\n\n\n /**\n * We internally failed to execute the /track/transfer request.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_TRANSFERS_REQUEST_ERROR = 2551,\n\n\n /**\n * The amount transferred differs between what was submitted and what the exchange claimed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_TRANSFERS = 2552,\n\n\n /**\n * The exchange gave conflicting information about a coin which has been wire transferred.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_REPORTS = 2553,\n\n\n /**\n * The exchange charged a different wire fee than what it originally advertised, and it is higher.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_TRANSFERS_BAD_WIRE_FEE = 2554,\n\n\n /**\n * We did not find the account that the transfer was made to.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_TRANSFERS_ACCOUNT_NOT_FOUND = 2555,\n\n\n /**\n * The backend could not delete the transfer as the echange already replied to our inquiry about it and we have integrated the result.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_DELETE_TRANSFERS_ALREADY_CONFIRMED = 2556,\n\n\n /**\n * The backend could not persist the wire transfer due to the state of the backend. This usually means that a wire transfer with the same wire transfer subject but a different amount was previously submitted to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_SUBMISSION = 2557,\n\n\n /**\n * The target bank account given by the exchange is not (or no longer) known at the merchant instance.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_TARGET_ACCOUNT_UNKNOWN = 2558,\n\n\n /**\n * The amount transferred differs between what was submitted and what the exchange claimed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_EXCHANGE_TRANSFERS_CONFLICTING_TRANSFERS = 2563,\n\n\n /**\n * The report ID provided to the backend is not known to the backend.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_REPORT_GENERATOR_FAILED = 2570,\n\n\n /**\n * Failed to fetch the data for the report from the backend.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_REPORT_FETCH_FAILED = 2571,\n\n\n /**\n * The merchant backend cannot create an instance under the given identifier as one already exists. Use PATCH to modify the existing entry.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS = 2600,\n\n\n /**\n * The merchant backend cannot create an instance because the authentication configuration field is malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_INSTANCES_BAD_AUTH = 2601,\n\n\n /**\n * The merchant backend cannot update an instance's authentication settings because the provided authentication settings are malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_INSTANCE_AUTH_BAD_AUTH = 2602,\n\n\n /**\n * The merchant backend cannot create an instance under the given identifier, the previous one was deleted but must be purged first.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_INSTANCES_PURGE_REQUIRED = 2603,\n\n\n /**\n * The merchant backend cannot update an instance under the given identifier, the previous one was deleted but must be purged first.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_PATCH_INSTANCES_PURGE_REQUIRED = 2625,\n\n\n /**\n * The bank account referenced in the requested operation was not found.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_ACCOUNT_DELETE_UNKNOWN_ACCOUNT = 2626,\n\n\n /**\n * The bank account specified in the request already exists at the merchant.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_ACCOUNT_EXISTS = 2627,\n\n\n /**\n * The bank account specified is not acceptable for this exchange. The exchange either does not support the wire method or something else about the specific account. Consult the exchange account constraints and specify a different bank account if you want to use this exchange.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_ACCOUNT_NOT_ELIGIBLE_FOR_EXCHANGE = 2628,\n\n\n /**\n * The product ID exists.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_PRODUCTS_CONFLICT_PRODUCT_EXISTS = 2650,\n\n\n /**\n * A category with the same name exists already.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_CATEGORIES_CONFLICT_CATEGORY_EXISTS = 2651,\n\n\n /**\n * The update would have reduced the total amount of product lost, which is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_REDUCED = 2660,\n\n\n /**\n * The update would have mean that more stocks were lost than what remains from total inventory after sales, which is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_EXCEEDS_STOCKS = 2661,\n\n\n /**\n * The update would have reduced the total amount of product in stock, which is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_STOCKED_REDUCED = 2662,\n\n\n /**\n * The update would have reduced the total amount of product sold, which is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_SOLD_REDUCED = 2663,\n\n\n /**\n * The lock request is for more products than we have left (unlocked) in stock.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_PRODUCTS_LOCK_INSUFFICIENT_STOCKS = 2670,\n\n\n /**\n * The deletion request is for a product that is locked. The product cannot be deleted until the existing offer to expires.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_DELETE_PRODUCTS_CONFLICTING_LOCK = 2680,\n\n\n /**\n * The proposed name for the product group is already in use. You should select a different name.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_PRODUCT_GROUP_CONFLICTING_NAME = 2690,\n\n\n /**\n * The proposed name for the money pot is already in use. You should select a different name.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_MONEY_POT_CONFLICTING_NAME = 2691,\n\n\n /**\n * The total amount in the money pot is different from the amount required by the request. The client should fetch the current pot total and retry with the latest amount to succeed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_MONEY_POT_CONFLICTING_TOTAL = 2692,\n\n\n /**\n * The requested wire method is not supported by the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_RESERVES_UNSUPPORTED_WIRE_METHOD = 2700,\n\n\n /**\n * The requested exchange does not allow rewards.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_RESERVES_REWARDS_NOT_ALLOWED = 2701,\n\n\n /**\n * The reserve could not be deleted because it is unknown.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_DELETE_RESERVES_NO_SUCH_RESERVE = 2710,\n\n\n /**\n * The reserve that was used to fund the rewards has expired.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_EXPIRED = 2750,\n\n\n /**\n * The reserve that was used to fund the rewards was not found in the DB.\n * Returned with an HTTP status code of #MHD_HTTP_SERVICE_UNAVAILABLE (503).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_UNKNOWN = 2751,\n\n\n /**\n * The backend knows the instance that was supposed to support the reward, and it was configured for rewardping. However, the funds remaining are insufficient to cover the reward, and the merchant should top up the reserve.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_INSUFFICIENT_FUNDS = 2752,\n\n\n /**\n * The backend failed to find a reserve needed to authorize the reward.\n * Returned with an HTTP status code of #MHD_HTTP_SERVICE_UNAVAILABLE (503).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_NOT_FOUND = 2753,\n\n\n /**\n * The merchant backend encountered a failure in computing the deposit total.\n * Returned with an HTTP status code of #MHD_HTTP_OK (200).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_GET_ORDERS_ID_AMOUNT_ARITHMETIC_FAILURE = 2800,\n\n\n /**\n * The template ID already exists.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_TEMPLATES_CONFLICT_TEMPLATE_EXISTS = 2850,\n\n\n /**\n * The OTP device ID already exists.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_OTP_DEVICES_CONFLICT_OTP_DEVICE_EXISTS = 2851,\n\n\n /**\n * Amount given in the using template and in the template contract. There is a conflict.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT = 2860,\n\n\n /**\n * Subject given in the using template and in the template contract. There is a conflict.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_USING_TEMPLATES_SUMMARY_CONFLICT_TEMPLATES_CONTRACT_SUBJECT = 2861,\n\n\n /**\n * Amount not given in the using template and in the template contract. There is a conflict.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_USING_TEMPLATES_NO_AMOUNT = 2862,\n\n\n /**\n * Subject not given in the using template and in the template contract. There is a conflict.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY = 2863,\n\n\n /**\n * The selected template has a different type than the one specified in the request of the client. This may happen if the template was updated since the last time the client fetched it. The client should re-fetch the current template and send a request of the correct type.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_USING_TEMPLATES_WRONG_TYPE = 2864,\n\n\n /**\n * The selected template does not allow one of the specified products to be included in the order. This may happen if the template was updated since the last time the client fetched it. The client should re-fetch the current template and send a request of the correct type.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_USING_TEMPLATES_WRONG_PRODUCT = 2865,\n\n\n /**\n * The selected combination of products does not allow the backend to compute a price for the order in any of the supported currencies. This may happen if the template was updated since the last time the client fetched it or if the wallet assembled an unsupported combination of products. The site administrator might want to specify additional prices for products, while the client should re-fetch the current template and send a request with a combination of products for which prices exist in the same currency.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_POST_USING_TEMPLATES_NO_CURRENCY = 2866,\n\n\n /**\n * The webhook ID elready exists.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_WEBHOOKS_CONFLICT_WEBHOOK_EXISTS = 2900,\n\n\n /**\n * The webhook serial elready exists.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n MERCHANT_PRIVATE_POST_PENDING_WEBHOOKS_CONFLICT_PENDING_WEBHOOK_EXISTS = 2910,\n\n\n /**\n * The auditor refused the connection due to a lack of authorization.\n * Returned with an HTTP status code of #MHD_HTTP_UNAUTHORIZED (401).\n * (A value of 0 indicates that the error is generated client-side).\n */\n AUDITOR_GENERIC_UNAUTHORIZED = 3001,\n\n\n /**\n * This method is not allowed here.\n * Returned with an HTTP status code of #MHD_HTTP_METHOD_NOT_ALLOWED (405).\n * (A value of 0 indicates that the error is generated client-side).\n */\n AUDITOR_GENERIC_METHOD_NOT_ALLOWED = 3002,\n\n\n /**\n * The signature from the exchange on the deposit confirmation is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n AUDITOR_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID = 3100,\n\n\n /**\n * The exchange key used for the signature on the deposit confirmation was revoked.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n AUDITOR_EXCHANGE_SIGNING_KEY_REVOKED = 3101,\n\n\n /**\n * The requested resource could not be found.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n AUDITOR_RESOURCE_NOT_FOUND = 3102,\n\n\n /**\n * The URI is missing a path component.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n AUDITOR_URI_MISSING_PATH_COMPONENT = 3103,\n\n\n /**\n * Wire transfer attempted with credit and debit party being the same bank account.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_SAME_ACCOUNT = 5101,\n\n\n /**\n * Wire transfer impossible, due to financial limitation of the party that attempted the payment.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_UNALLOWED_DEBIT = 5102,\n\n\n /**\n * Negative numbers are not allowed (as value and/or fraction) to instantiate an amount object.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NEGATIVE_NUMBER_AMOUNT = 5103,\n\n\n /**\n * A too big number was used (as value and/or fraction) to instantiate an amount object.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NUMBER_TOO_BIG = 5104,\n\n\n /**\n * The bank account referenced in the requested operation was not found.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_UNKNOWN_ACCOUNT = 5106,\n\n\n /**\n * The transaction referenced in the requested operation (typically a reject operation), was not found.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TRANSACTION_NOT_FOUND = 5107,\n\n\n /**\n * Bank received a malformed amount string.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_BAD_FORMAT_AMOUNT = 5108,\n\n\n /**\n * The client does not own the account credited by the transaction which is to be rejected, so it has no rights do reject it.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_REJECT_NO_RIGHTS = 5109,\n\n\n /**\n * This error code is returned when no known exception types captured the exception.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_UNMANAGED_EXCEPTION = 5110,\n\n\n /**\n * This error code is used for all those exceptions that do not really need a specific error code to return to the client. Used for example when a client is trying to register with a unavailable username.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_SOFT_EXCEPTION = 5111,\n\n\n /**\n * The request UID for a request to transfer funds has already been used, but with different details for the transfer.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TRANSFER_REQUEST_UID_REUSED = 5112,\n\n\n /**\n * The withdrawal operation already has a reserve selected. The current request conflicts with the existing selection.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT = 5113,\n\n\n /**\n * The wire transfer subject duplicates an existing reserve public key. But wire transfer subjects must be unique.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_DUPLICATE_RESERVE_PUB_SUBJECT = 5114,\n\n\n /**\n * The client requested a transaction that is so far in the past, that it has been forgotten by the bank.\n * Returned with an HTTP status code of #MHD_HTTP_GONE (410).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_ANCIENT_TRANSACTION_GONE = 5115,\n\n\n /**\n * The client attempted to abort a transaction that was already confirmed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_ABORT_CONFIRM_CONFLICT = 5116,\n\n\n /**\n * The client attempted to confirm a transaction that was already aborted.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_CONFIRM_ABORT_CONFLICT = 5117,\n\n\n /**\n * The client attempted to register an account with the same name.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_REGISTER_CONFLICT = 5118,\n\n\n /**\n * The client attempted to confirm a withdrawal operation before the wallet posted the required details.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_POST_WITHDRAWAL_OPERATION_REQUIRED = 5119,\n\n\n /**\n * The client tried to register a new account under a reserved username (like 'admin' for example).\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_RESERVED_USERNAME_CONFLICT = 5120,\n\n\n /**\n * The client tried to register a new account with an username already in use.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_REGISTER_USERNAME_REUSE = 5121,\n\n\n /**\n * The client tried to register a new account with a payto:// URI already in use.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_REGISTER_PAYTO_URI_REUSE = 5122,\n\n\n /**\n * The client tried to delete an account with a non null balance.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_ACCOUNT_BALANCE_NOT_ZERO = 5123,\n\n\n /**\n * The client tried to create a transaction or an operation that credit an unknown account.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_UNKNOWN_CREDITOR = 5124,\n\n\n /**\n * The client tried to create a transaction or an operation that debit an unknown account.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_UNKNOWN_DEBTOR = 5125,\n\n\n /**\n * The client tried to perform an action prohibited for exchange accounts.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_ACCOUNT_IS_EXCHANGE = 5126,\n\n\n /**\n * The client tried to perform an action reserved for exchange accounts.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_ACCOUNT_IS_NOT_EXCHANGE = 5127,\n\n\n /**\n * Received currency conversion is wrong.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_BAD_CONVERSION = 5128,\n\n\n /**\n * The account referenced in this operation is missing tan info for the chosen channel.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_MISSING_TAN_INFO = 5129,\n\n\n /**\n * The client attempted to confirm a transaction with incomplete info.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_CONFIRM_INCOMPLETE = 5130,\n\n\n /**\n * The request rate is too high. The server is refusing requests to guard against brute-force attacks.\n * Returned with an HTTP status code of #MHD_HTTP_TOO_MANY_REQUESTS (429).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TAN_RATE_LIMITED = 5131,\n\n\n /**\n * This TAN channel is not supported.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TAN_CHANNEL_NOT_SUPPORTED = 5132,\n\n\n /**\n * Failed to send TAN using the helper script. Either script is not found, or script timeout, or script terminated with a non-successful result.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TAN_CHANNEL_SCRIPT_FAILED = 5133,\n\n\n /**\n * The client's response to the challenge was invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TAN_CHALLENGE_FAILED = 5134,\n\n\n /**\n * A non-admin user has tried to change their legal name.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NON_ADMIN_PATCH_LEGAL_NAME = 5135,\n\n\n /**\n * A non-admin user has tried to change their debt limit.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NON_ADMIN_PATCH_DEBT_LIMIT = 5136,\n\n\n /**\n * A non-admin user has tried to change their password whihout providing the current one.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD = 5137,\n\n\n /**\n * Provided old password does not match current password.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_PATCH_BAD_OLD_PASSWORD = 5138,\n\n\n /**\n * An admin user has tried to become an exchange.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_PATCH_ADMIN_EXCHANGE = 5139,\n\n\n /**\n * A non-admin user has tried to change their cashout account.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NON_ADMIN_PATCH_CASHOUT = 5140,\n\n\n /**\n * A non-admin user has tried to change their contact info.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NON_ADMIN_PATCH_CONTACT = 5141,\n\n\n /**\n * The client tried to create a transaction that credit the admin account.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_ADMIN_CREDITOR = 5142,\n\n\n /**\n * The referenced challenge was not found.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_CHALLENGE_NOT_FOUND = 5143,\n\n\n /**\n * The referenced challenge has expired.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TAN_CHALLENGE_EXPIRED = 5144,\n\n\n /**\n * A non-admin user has tried to create an account with 2fa.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NON_ADMIN_SET_TAN_CHANNEL = 5145,\n\n\n /**\n * A non-admin user has tried to set their minimum cashout amount.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NON_ADMIN_SET_MIN_CASHOUT = 5146,\n\n\n /**\n * Amount of currency conversion it less than the minimum allowed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_CONVERSION_AMOUNT_TO_SMALL = 5147,\n\n\n /**\n * Specified amount will not work for this withdrawal.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_AMOUNT_DIFFERS = 5148,\n\n\n /**\n * The backend requires an amount to be specified.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_AMOUNT_REQUIRED = 5149,\n\n\n /**\n * Provided password is too short.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_PASSWORD_TOO_SHORT = 5150,\n\n\n /**\n * Provided password is too long.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_PASSWORD_TOO_LONG = 5151,\n\n\n /**\n * Bank account is locked and cannot authenticate using his password.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_ACCOUNT_LOCKED = 5152,\n\n\n /**\n * The client attempted to update a transaction' details that was already aborted.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_UPDATE_ABORT_CONFLICT = 5153,\n\n\n /**\n * The wtid for a request to transfer funds has already been used, but with a different request unpaid.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TRANSFER_WTID_REUSED = 5154,\n\n\n /**\n * A non-admin user has tried to set their conversion rate class\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS = 5155,\n\n\n /**\n * The referenced conversion rate class was not found\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_CONVERSION_RATE_CLASS_UNKNOWN = 5156,\n\n\n /**\n * The client tried to use an already taken name.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_NAME_REUSE = 5157,\n\n\n /**\n * This subject format is not supported.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_UNSUPPORTED_SUBJECT_FORMAT = 5158,\n\n\n /**\n * The derived subject is already used.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_DERIVATION_REUSE = 5159,\n\n\n /**\n * The provided signature is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_BAD_SIGNATURE = 5160,\n\n\n /**\n * The provided timestamp is too old.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_OLD_TIMESTAMP = 5161,\n\n\n /**\n * The authorization_pub for a request to transfer funds has already been used for another non recurrent transfer.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TRANSFER_MAPPING_REUSED = 5162,\n\n\n /**\n * The authorization_pub for a request to transfer funds is not currently registered.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n BANK_TRANSFER_MAPPING_UNKNOWN = 5163,\n\n\n /**\n * The sync service failed find the account in its database.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_ACCOUNT_UNKNOWN = 6100,\n\n\n /**\n * The SHA-512 hash provided in the If-None-Match header is malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_BAD_IF_NONE_MATCH = 6101,\n\n\n /**\n * The SHA-512 hash provided in the If-Match header is malformed or missing.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_BAD_IF_MATCH = 6102,\n\n\n /**\n * The signature provided in the \"Sync-Signature\" header is malformed or missing.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_BAD_SYNC_SIGNATURE = 6103,\n\n\n /**\n * The signature provided in the \"Sync-Signature\" header does not match the account, old or new Etags.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_INVALID_SIGNATURE = 6104,\n\n\n /**\n * The \"Content-length\" field for the upload is not a number.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_MALFORMED_CONTENT_LENGTH = 6105,\n\n\n /**\n * The \"Content-length\" field for the upload is too big based on the server's terms of service.\n * Returned with an HTTP status code of #MHD_HTTP_CONTENT_TOO_LARGE (413).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_EXCESSIVE_CONTENT_LENGTH = 6106,\n\n\n /**\n * The server is out of memory to handle the upload. Trying again later may succeed.\n * Returned with an HTTP status code of #MHD_HTTP_CONTENT_TOO_LARGE (413).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_OUT_OF_MEMORY_ON_CONTENT_LENGTH = 6107,\n\n\n /**\n * The uploaded data does not match the Etag.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_INVALID_UPLOAD = 6108,\n\n\n /**\n * HTTP server experienced a timeout while awaiting promised payment.\n * Returned with an HTTP status code of #MHD_HTTP_REQUEST_TIMEOUT (408).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_PAYMENT_GENERIC_TIMEOUT = 6109,\n\n\n /**\n * Sync could not setup the payment request with its own backend.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_PAYMENT_CREATE_BACKEND_ERROR = 6110,\n\n\n /**\n * The sync service failed find the backup to be updated in its database.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_PREVIOUS_BACKUP_UNKNOWN = 6111,\n\n\n /**\n * The \"Content-length\" field for the upload is missing.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_MISSING_CONTENT_LENGTH = 6112,\n\n\n /**\n * Sync had problems communicating with its payment backend.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_GENERIC_BACKEND_ERROR = 6113,\n\n\n /**\n * Sync experienced a timeout communicating with its payment backend.\n * Returned with an HTTP status code of #MHD_HTTP_GATEWAY_TIMEOUT (504).\n * (A value of 0 indicates that the error is generated client-side).\n */\n SYNC_GENERIC_BACKEND_TIMEOUT = 6114,\n\n\n /**\n * The wallet does not implement a version of the exchange protocol that is compatible with the protocol version of the exchange.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_IMPLEMENTED (501).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE = 7000,\n\n\n /**\n * The wallet encountered an unexpected exception. This is likely a bug in the wallet implementation.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_UNEXPECTED_EXCEPTION = 7001,\n\n\n /**\n * The wallet received a response from a server, but the response can't be parsed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_RECEIVED_MALFORMED_RESPONSE = 7002,\n\n\n /**\n * The wallet tried to make a network request, but it received no response.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_NETWORK_ERROR = 7003,\n\n\n /**\n * The wallet tried to make a network request, but it was throttled.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_HTTP_REQUEST_THROTTLED = 7004,\n\n\n /**\n * The wallet made a request to a service, but received an error response it does not know how to handle.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_UNEXPECTED_REQUEST_ERROR = 7005,\n\n\n /**\n * The denominations offered by the exchange are insufficient. Likely the exchange is badly configured or not maintained.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_DENOMINATIONS_INSUFFICIENT = 7006,\n\n\n /**\n * The wallet does not support the operation requested by a client.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CORE_API_OPERATION_UNKNOWN = 7007,\n\n\n /**\n * The given taler://pay URI is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_INVALID_TALER_PAY_URI = 7008,\n\n\n /**\n * The signature on a coin by the exchange's denomination key is invalid after unblinding it.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_COIN_SIGNATURE_INVALID = 7009,\n\n\n /**\n * The wallet core service is not available.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CORE_NOT_AVAILABLE = 7011,\n\n\n /**\n * The bank has aborted a withdrawal operation, and thus a withdrawal can't complete.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK = 7012,\n\n\n /**\n * An HTTP request made by the wallet timed out.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_HTTP_REQUEST_GENERIC_TIMEOUT = 7013,\n\n\n /**\n * The order has already been claimed by another wallet.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_ORDER_ALREADY_CLAIMED = 7014,\n\n\n /**\n * A group of withdrawal operations (typically for the same reserve at the same exchange) has errors and will be tried again later.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_WITHDRAWAL_GROUP_INCOMPLETE = 7015,\n\n\n /**\n * The signature on a coin by the exchange's denomination key (obtained through the merchant via a reward) is invalid after unblinding it.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_REWARD_COIN_SIGNATURE_INVALID = 7016,\n\n\n /**\n * The wallet does not implement a version of the bank integration API that is compatible with the version offered by the bank.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_BANK_INTEGRATION_PROTOCOL_VERSION_INCOMPATIBLE = 7017,\n\n\n /**\n * The wallet processed a taler://pay URI, but the merchant base URL in the downloaded contract terms does not match the merchant base URL derived from the URI.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CONTRACT_TERMS_BASE_URL_MISMATCH = 7018,\n\n\n /**\n * The merchant's signature on the contract terms is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CONTRACT_TERMS_SIGNATURE_INVALID = 7019,\n\n\n /**\n * The contract terms given by the merchant are malformed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CONTRACT_TERMS_MALFORMED = 7020,\n\n\n /**\n * A pending operation failed, and thus the request can't be completed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_PENDING_OPERATION_FAILED = 7021,\n\n\n /**\n * A payment was attempted, but the merchant had an internal server error (5xx).\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_PAY_MERCHANT_SERVER_ERROR = 7022,\n\n\n /**\n * The crypto worker failed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CRYPTO_WORKER_ERROR = 7023,\n\n\n /**\n * The crypto worker received a bad request.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CRYPTO_WORKER_BAD_REQUEST = 7024,\n\n\n /**\n * A KYC step is required before withdrawal can proceed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_WITHDRAWAL_KYC_REQUIRED = 7025,\n\n\n /**\n * The wallet does not have sufficient balance to create a deposit group.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE = 7026,\n\n\n /**\n * The wallet does not have sufficient balance to create a peer push payment.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE = 7027,\n\n\n /**\n * The wallet does not have sufficient balance to pay for an invoice.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_PEER_PULL_PAYMENT_INSUFFICIENT_BALANCE = 7028,\n\n\n /**\n * A group of refresh operations has errors and will be tried again later.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_REFRESH_GROUP_INCOMPLETE = 7029,\n\n\n /**\n * The exchange's self-reported base URL does not match the one that the wallet is using.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_BASE_URL_MISMATCH = 7030,\n\n\n /**\n * The order has already been paid by another wallet.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_ORDER_ALREADY_PAID = 7031,\n\n\n /**\n * An exchange that is required for some request is currently not available.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_UNAVAILABLE = 7032,\n\n\n /**\n * An exchange entry is still used by the exchange, thus it can't be deleted without purging.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_ENTRY_USED = 7033,\n\n\n /**\n * The wallet database is unavailable and the wallet thus is not operational.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_DB_UNAVAILABLE = 7034,\n\n\n /**\n * A taler:// URI is malformed and can't be parsed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_TALER_URI_MALFORMED = 7035,\n\n\n /**\n * A wallet-core request was cancelled and thus can't provide a response.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CORE_REQUEST_CANCELLED = 7036,\n\n\n /**\n * A wallet-core request failed because the user needs to first accept the exchange's terms of service.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_TOS_NOT_ACCEPTED = 7037,\n\n\n /**\n * An exchange entry could not be updated, as the exchange's new details conflict with the new details.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_ENTRY_UPDATE_CONFLICT = 7038,\n\n\n /**\n * The wallet's information about the exchange is outdated.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_ENTRY_OUTDATED = 7039,\n\n\n /**\n * The merchant needs to do KYC first, the payment could not be completed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_PAY_MERCHANT_KYC_MISSING = 7040,\n\n\n /**\n * A peer-pull-debit transaction was aborted because the exchange reported the purse as gone.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_PEER_PULL_DEBIT_PURSE_GONE = 7041,\n\n\n /**\n * A transaction was aborted on explicit request by the user.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_TRANSACTION_ABORTED_BY_USER = 7042,\n\n\n /**\n * A transaction was abandoned on explicit request by the user.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_TRANSACTION_ABANDONED_BY_USER = 7043,\n\n\n /**\n * A payment was attempted, but the merchant claims the order is gone (likely expired).\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_PAY_MERCHANT_ORDER_GONE = 7044,\n\n\n /**\n * The wallet does not have an entry for the requested exchange.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_EXCHANGE_ENTRY_NOT_FOUND = 7045,\n\n\n /**\n * The wallet is not able to process the request due to the transaction's state.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_REQUEST_TRANSACTION_STATE_UNSUPPORTED = 7046,\n\n\n /**\n * A transaction could not be processed due to an unrecoverable protocol violation.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_TRANSACTION_PROTOCOL_VIOLATION = 7047,\n\n\n /**\n * A parameter in the request is malformed or missing.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_CORE_API_BAD_REQUEST = 7048,\n\n\n /**\n * The order could not be found. Maybe the merchant deleted it.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n WALLET_MERCHANT_ORDER_NOT_FOUND = 7049,\n\n\n /**\n * We encountered a timeout with our payment backend.\n * Returned with an HTTP status code of #MHD_HTTP_GATEWAY_TIMEOUT (504).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_BACKEND_TIMEOUT = 8000,\n\n\n /**\n * The backend requested payment, but the request is malformed.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_INVALID_PAYMENT_REQUEST = 8001,\n\n\n /**\n * The backend got an unexpected reply from the payment processor.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_BACKEND_ERROR = 8002,\n\n\n /**\n * The \"Content-length\" field for the upload is missing.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_MISSING_CONTENT_LENGTH = 8003,\n\n\n /**\n * The \"Content-length\" field for the upload is malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_MALFORMED_CONTENT_LENGTH = 8004,\n\n\n /**\n * The backend failed to setup an order with the payment processor.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_ORDER_CREATE_BACKEND_ERROR = 8005,\n\n\n /**\n * The backend was not authorized to check for payment with the payment processor.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_PAYMENT_CHECK_UNAUTHORIZED = 8006,\n\n\n /**\n * The backend could not check payment status with the payment processor.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_PAYMENT_CHECK_START_FAILED = 8007,\n\n\n /**\n * The Anastasis provider could not be reached.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_GENERIC_PROVIDER_UNREACHABLE = 8008,\n\n\n /**\n * HTTP server experienced a timeout while awaiting promised payment.\n * Returned with an HTTP status code of #MHD_HTTP_REQUEST_TIMEOUT (408).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_PAYMENT_GENERIC_TIMEOUT = 8009,\n\n\n /**\n * The key share is unknown to the provider.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_UNKNOWN = 8108,\n\n\n /**\n * The authorization method used for the key share is no longer supported by the provider.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_AUTHORIZATION_METHOD_NO_LONGER_SUPPORTED = 8109,\n\n\n /**\n * The client needs to respond to the challenge.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_CHALLENGE_RESPONSE_REQUIRED = 8110,\n\n\n /**\n * The client's response to the challenge was invalid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_CHALLENGE_FAILED = 8111,\n\n\n /**\n * The backend is not aware of having issued the provided challenge code. Either this is the wrong code, or it has expired.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_CHALLENGE_UNKNOWN = 8112,\n\n\n /**\n * The backend failed to initiate the authorization process.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_AUTHORIZATION_START_FAILED = 8114,\n\n\n /**\n * The authorization succeeded, but the key share is no longer available.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_KEY_SHARE_GONE = 8115,\n\n\n /**\n * The backend forgot the order we asked the client to pay for\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_ORDER_DISAPPEARED = 8116,\n\n\n /**\n * The backend itself reported a bad exchange interaction.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_BACKEND_EXCHANGE_BAD = 8117,\n\n\n /**\n * The backend reported a payment status we did not expect.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_UNEXPECTED_PAYMENT_STATUS = 8118,\n\n\n /**\n * The backend failed to setup the order for payment.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_PAYMENT_CREATE_BACKEND_ERROR = 8119,\n\n\n /**\n * The decryption of the key share failed with the provided key.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_DECRYPTION_FAILED = 8120,\n\n\n /**\n * The request rate is too high. The server is refusing requests to guard against brute-force attacks.\n * Returned with an HTTP status code of #MHD_HTTP_TOO_MANY_REQUESTS (429).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_RATE_LIMITED = 8121,\n\n\n /**\n * A request to issue a challenge is not valid for this authentication method.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_CHALLENGE_WRONG_METHOD = 8123,\n\n\n /**\n * The backend failed to store the key share because the UUID is already in use.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_UPLOAD_UUID_EXISTS = 8150,\n\n\n /**\n * The backend failed to store the key share because the authorization method is not supported.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TRUTH_UPLOAD_METHOD_NOT_SUPPORTED = 8151,\n\n\n /**\n * The provided phone number is not an acceptable number.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_SMS_PHONE_INVALID = 8200,\n\n\n /**\n * Failed to run the SMS transmission helper process.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_SMS_HELPER_EXEC_FAILED = 8201,\n\n\n /**\n * Provider failed to send SMS. Helper terminated with a non-successful result.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_SMS_HELPER_COMMAND_FAILED = 8202,\n\n\n /**\n * The provided email address is not an acceptable address.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_EMAIL_INVALID = 8210,\n\n\n /**\n * Failed to run the E-mail transmission helper process.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_EMAIL_HELPER_EXEC_FAILED = 8211,\n\n\n /**\n * Provider failed to send E-mail. Helper terminated with a non-successful result.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_EMAIL_HELPER_COMMAND_FAILED = 8212,\n\n\n /**\n * The provided postal address is not an acceptable address.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POST_INVALID = 8220,\n\n\n /**\n * Failed to run the mail transmission helper process.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POST_HELPER_EXEC_FAILED = 8221,\n\n\n /**\n * Provider failed to send mail. Helper terminated with a non-successful result.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POST_HELPER_COMMAND_FAILED = 8222,\n\n\n /**\n * The provided IBAN address is not an acceptable IBAN.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_IBAN_INVALID = 8230,\n\n\n /**\n * The provider has not yet received the IBAN wire transfer authorizing the disclosure of the key share.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_IBAN_MISSING_TRANSFER = 8231,\n\n\n /**\n * The backend did not find a TOTP key in the data provided.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TOTP_KEY_MISSING = 8240,\n\n\n /**\n * The key provided does not satisfy the format restrictions for an Anastasis TOTP key.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_TOTP_KEY_INVALID = 8241,\n\n\n /**\n * The given if-none-match header is malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POLICY_BAD_IF_NONE_MATCH = 8301,\n\n\n /**\n * The server is out of memory to handle the upload. Trying again later may succeed.\n * Returned with an HTTP status code of #MHD_HTTP_CONTENT_TOO_LARGE (413).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POLICY_OUT_OF_MEMORY_ON_CONTENT_LENGTH = 8304,\n\n\n /**\n * The signature provided in the \"Anastasis-Policy-Signature\" header is malformed or missing.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POLICY_BAD_SIGNATURE = 8305,\n\n\n /**\n * The given if-match header is malformed.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POLICY_BAD_IF_MATCH = 8306,\n\n\n /**\n * The uploaded data does not match the Etag.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POLICY_INVALID_UPLOAD = 8307,\n\n\n /**\n * The provider is unaware of the requested policy.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_POLICY_NOT_FOUND = 8350,\n\n\n /**\n * The given action is invalid for the current state of the reducer.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_ACTION_INVALID = 8400,\n\n\n /**\n * The given state of the reducer is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_STATE_INVALID = 8401,\n\n\n /**\n * The given input to the reducer is invalid.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_INPUT_INVALID = 8402,\n\n\n /**\n * The selected authentication method does not work for the Anastasis provider.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_AUTHENTICATION_METHOD_NOT_SUPPORTED = 8403,\n\n\n /**\n * The given input and action do not work for the current state.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE = 8404,\n\n\n /**\n * We experienced an unexpected failure interacting with the backend.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_BACKEND_FAILURE = 8405,\n\n\n /**\n * The contents of a resource file did not match our expectations.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_RESOURCE_MALFORMED = 8406,\n\n\n /**\n * A required resource file is missing.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_RESOURCE_MISSING = 8407,\n\n\n /**\n * An input did not match the regular expression.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_INPUT_REGEX_FAILED = 8408,\n\n\n /**\n * An input did not match the custom validation logic.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_INPUT_VALIDATION_FAILED = 8409,\n\n\n /**\n * Our attempts to download the recovery document failed with all providers. Most likely the personal information you entered differs from the information you provided during the backup process and you should go back to the previous step. Alternatively, if you used a backup provider that is unknown to this application, you should add that provider manually.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_POLICY_LOOKUP_FAILED = 8410,\n\n\n /**\n * Anastasis provider reported a fatal failure.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_BACKUP_PROVIDER_FAILED = 8411,\n\n\n /**\n * Anastasis provider failed to respond to the configuration request.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_PROVIDER_CONFIG_FAILED = 8412,\n\n\n /**\n * The policy we downloaded is malformed. Must have been a client error while creating the backup.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_POLICY_MALFORMED = 8413,\n\n\n /**\n * We failed to obtain the policy, likely due to a network issue.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_NETWORK_FAILED = 8414,\n\n\n /**\n * The recovered secret did not match the required syntax.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_SECRET_MALFORMED = 8415,\n\n\n /**\n * The challenge data provided is too large for the available providers.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_CHALLENGE_DATA_TOO_BIG = 8416,\n\n\n /**\n * The provided core secret is too large for some of the providers.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_SECRET_TOO_BIG = 8417,\n\n\n /**\n * The provider returned in invalid configuration.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_PROVIDER_INVALID_CONFIG = 8418,\n\n\n /**\n * The reducer encountered an internal error, likely a bug that needs to be reported.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_INTERNAL_ERROR = 8419,\n\n\n /**\n * The reducer already synchronized with all providers.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n ANASTASIS_REDUCER_PROVIDERS_ALREADY_SYNCED = 8420,\n\n\n /**\n * The requested operation is not valid for the cipher used by the selected denomination.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION = 8606,\n\n\n /**\n * The Donau failed to perform the operation as it could not find the private keys. This is a problem with the Donau setup, not with the client's request.\n * Returned with an HTTP status code of #MHD_HTTP_SERVICE_UNAVAILABLE (503).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_GENERIC_KEYS_MISSING = 8607,\n\n\n /**\n * The signature of the charity key is not valid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_CHARITY_SIGNATURE_INVALID = 8608,\n\n\n /**\n * The charity is unknown.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_CHARITY_NOT_FOUND = 8609,\n\n\n /**\n * The donation amount specified in the request exceeds the limit of the charity.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_EXCEEDING_DONATION_LIMIT = 8610,\n\n\n /**\n * The Donau is not aware of the donation unit requested for the operation.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_GENERIC_DONATION_UNIT_UNKNOWN = 8611,\n\n\n /**\n * The Donau failed to talk to the process responsible for its private donation unit keys or the helpers had no donation units (properly) configured.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_DONATION_UNIT_HELPER_UNAVAILABLE = 8612,\n\n\n /**\n * The Donau failed to talk to the process responsible for its private signing keys.\n * Returned with an HTTP status code of #MHD_HTTP_BAD_GATEWAY (502).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_SIGNKEY_HELPER_UNAVAILABLE = 8613,\n\n\n /**\n * The response from the online signing key helper process was malformed.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_SIGNKEY_HELPER_BUG = 8614,\n\n\n /**\n * The number of segments included in the URI does not match the number of segments expected by the endpoint.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_GENERIC_WRONG_NUMBER_OF_SEGMENTS = 8615,\n\n\n /**\n * The signature of the donation receipt is not valid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_DONATION_RECEIPT_SIGNATURE_INVALID = 8616,\n\n\n /**\n * The client reused a unique donor identifier nonce, which is not allowed.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_DONOR_IDENTIFIER_NONCE_REUSE = 8617,\n\n\n /**\n * A charity with the same public key is already registered.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n DONAU_CHARITY_PUB_EXISTS = 8618,\n\n\n /**\n * A generic error happened in the LibEuFin nexus. See the enclose details JSON for more information.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n LIBEUFIN_NEXUS_GENERIC_ERROR = 9000,\n\n\n /**\n * An uncaught exception happened in the LibEuFin nexus service.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n LIBEUFIN_NEXUS_UNCAUGHT_EXCEPTION = 9001,\n\n\n /**\n * A generic error happened in the LibEuFin sandbox. See the enclose details JSON for more information.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n LIBEUFIN_SANDBOX_GENERIC_ERROR = 9500,\n\n\n /**\n * An uncaught exception happened in the LibEuFin sandbox service.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n LIBEUFIN_SANDBOX_UNCAUGHT_EXCEPTION = 9501,\n\n\n /**\n * This validation method is not supported by the service.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n TALDIR_METHOD_NOT_SUPPORTED = 9600,\n\n\n /**\n * Number of allowed attempts for initiating a challenge exceeded.\n * Returned with an HTTP status code of #MHD_HTTP_TOO_MANY_REQUESTS (429).\n * (A value of 0 indicates that the error is generated client-side).\n */\n TALDIR_REGISTER_RATE_LIMITED = 9601,\n\n\n /**\n * The client is unknown or unauthorized.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_GENERIC_CLIENT_UNKNOWN = 9750,\n\n\n /**\n * The client is not authorized to use the given redirect URI.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_GENERIC_CLIENT_FORBIDDEN_BAD_REDIRECT_URI = 9751,\n\n\n /**\n * The service failed to execute its helper process to send the challenge.\n * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR (500).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_HELPER_EXEC_FAILED = 9752,\n\n\n /**\n * The grant is unknown to the service (it could also have expired).\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_GRANT_UNKNOWN = 9753,\n\n\n /**\n * The code given is not even well-formed.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE = 9754,\n\n\n /**\n * The service is not aware of the referenced validation process.\n * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_GENERIC_VALIDATION_UNKNOWN = 9755,\n\n\n /**\n * The code given is not valid.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_CLIENT_FORBIDDEN_INVALID_CODE = 9756,\n\n\n /**\n * Too many attempts have been made, validation is temporarily disabled for this address.\n * Returned with an HTTP status code of #MHD_HTTP_TOO_MANY_REQUESTS (429).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_TOO_MANY_ATTEMPTS = 9757,\n\n\n /**\n * The PIN code provided is incorrect.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_INVALID_PIN = 9758,\n\n\n /**\n * The token cannot be valid as no address was ever provided by the client.\n * Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_MISSING_ADDRESS = 9759,\n\n\n /**\n * The client is not allowed to change the address being validated.\n * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).\n * (A value of 0 indicates that the error is generated client-side).\n */\n CHALLENGER_CLIENT_FORBIDDEN_READ_ONLY = 9760,\n\n\n /**\n * End of error code range.\n * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).\n * (A value of 0 indicates that the error is generated client-side).\n */\n END = 9999,\n\n\n}\n", "/*\n This file is part of GNU Taler\n (C) 2017-2019 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Helpers for relative and absolute time.\n */\n\n/**\n * Imports.\n */\nimport { Codec, Context, renderContext } from \"./codec.js\";\n\ndeclare const flavor_AbsoluteTime: unique symbol;\ndeclare const flavor_TalerProtocolTimestamp: unique symbol;\ndeclare const flavor_TalerPreciseTimestamp: unique symbol;\n\nconst opaque_AbsoluteTime: unique symbol = Symbol(\"opaque_AbsoluteTime\");\n\n// FIXME: Make this opaque!\nexport interface AbsoluteTime {\n /**\n * Timestamp in milliseconds.\n */\n readonly t_ms: number | \"never\";\n\n readonly _flavor?: typeof flavor_AbsoluteTime;\n\n // Make the type opaque, we only want our constructors\n // to able to create an AbsoluteTime value.\n [opaque_AbsoluteTime]: true;\n}\n\nexport interface TalerProtocolTimestamp {\n /**\n * Seconds (as integer) since epoch.\n */\n readonly t_s: number | \"never\";\n\n readonly _flavor?: typeof flavor_TalerProtocolTimestamp;\n}\n\n/**\n * Precise timestamp, typically used in the wallet-core\n * API but not in other Taler APIs so far.\n */\nexport interface TalerPreciseTimestamp {\n /**\n * Seconds (as integer) since epoch.\n */\n readonly t_s: number | \"never\";\n\n /**\n * Optional microsecond offset (non-negative integer).\n */\n readonly off_us?: number;\n\n readonly _flavor?: typeof flavor_TalerPreciseTimestamp;\n}\n\nexport namespace TalerPreciseTimestamp {\n export function now(): TalerPreciseTimestamp {\n const absNow = AbsoluteTime.now();\n return AbsoluteTime.toPreciseTimestamp(absNow);\n }\n\n export function round(t: TalerPreciseTimestamp): TalerProtocolTimestamp {\n return {\n t_s: t.t_s,\n };\n }\n\n export function fromSeconds(s: number): TalerPreciseTimestamp {\n return {\n t_s: Math.floor(s),\n off_us: Math.floor((s - Math.floor(s)) / 1000 / 1000),\n };\n }\n\n export function fromMilliseconds(ms: number): TalerPreciseTimestamp {\n return {\n t_s: Math.floor(ms / 1000),\n off_us: Math.floor((ms - Math.floor(ms / 1000) * 1000) * 1000),\n };\n }\n}\n\nexport namespace TalerProtocolDuration {\n export function fromSpec(d: DurationUnitSpec) {\n return Duration.toTalerProtocolDuration(Duration.fromSpec(d));\n }\n\n export function forever(): TalerProtocolDuration {\n return {\n d_us: \"forever\",\n };\n }\n}\n\nexport namespace TalerProtocolTimestamp {\n export function isTimestamp(x: unknown): x is TalerProtocolTimestamp {\n return (\n typeof x === \"object\" &&\n x !== null &&\n \"t_s\" in x &&\n (typeof x.t_s === \"number\" || x.t_s === \"never\")\n );\n }\n export function now(): TalerProtocolTimestamp {\n return AbsoluteTime.toProtocolTimestamp(AbsoluteTime.now());\n }\n\n export function zero(): TalerProtocolTimestamp {\n return {\n t_s: 0,\n };\n }\n\n export function never(): TalerProtocolTimestamp {\n return {\n t_s: \"never\",\n };\n }\n\n export function isNever(t: TalerProtocolTimestamp): boolean {\n return t.t_s === \"never\";\n }\n\n export function fromSeconds(s: number): TalerProtocolTimestamp {\n return {\n t_s: s,\n };\n }\n\n export function min(\n t1: TalerProtocolTimestamp,\n t2: TalerProtocolTimestamp,\n ): TalerProtocolTimestamp {\n if (t1.t_s === \"never\") {\n return { t_s: t2.t_s };\n }\n if (t2.t_s === \"never\") {\n return { t_s: t1.t_s };\n }\n return { t_s: Math.min(t1.t_s, t2.t_s) };\n }\n\n export function max(\n t1: TalerProtocolTimestamp,\n t2: TalerProtocolTimestamp,\n ): TalerProtocolTimestamp {\n if (t1.t_s === \"never\" || t2.t_s === \"never\") {\n return { t_s: \"never\" };\n }\n return { t_s: Math.max(t1.t_s, t2.t_s) };\n }\n}\n\nexport interface Duration {\n /**\n * Duration in milliseconds.\n */\n readonly d_ms: number | \"forever\";\n}\n\nexport interface TalerProtocolDuration {\n readonly d_us: number | \"forever\";\n}\n\n/**\n * Timeshift in milliseconds.\n */\nlet timeshift = 0;\n\n/**\n * Set timetravel offset in milliseconds.\n *\n * Use carefully and only for testing.\n */\nexport function setDangerousTimetravel(dt: number): void {\n timeshift = dt;\n}\n\nexport interface DurationUnitSpec {\n seconds?: number;\n minutes?: number;\n hours?: number;\n days?: number;\n months?: number;\n years?: number;\n}\n\nexport namespace Duration {\n export function toMilliseconds(d: Duration): number {\n if (d.d_ms === \"forever\") {\n return Number.MAX_VALUE;\n }\n return d.d_ms;\n }\n export function getRemaining(\n deadline: AbsoluteTime,\n now = AbsoluteTime.now(),\n ): Duration {\n if (deadline.t_ms === \"never\") {\n return { d_ms: \"forever\" };\n }\n if (now.t_ms === \"never\") {\n throw Error(\"invalid argument for 'now'\");\n }\n if (deadline.t_ms < now.t_ms) {\n return { d_ms: 0 };\n }\n return { d_ms: deadline.t_ms - now.t_ms };\n }\n\n export function fromPrettyString(s: string): Duration {\n let dMs = 0;\n let currentNum = \"\";\n let parsingNum = true;\n for (let i = 0; i < s.length; i++) {\n const cc = s.charCodeAt(i);\n if (cc >= \"0\".charCodeAt(0) && cc <= \"9\".charCodeAt(0)) {\n if (!parsingNum) {\n throw Error(\"invalid duration, unexpected number\");\n }\n currentNum += s[i];\n continue;\n }\n if (s[i] == \" \") {\n if (currentNum != \"\") {\n parsingNum = false;\n }\n continue;\n }\n\n if (currentNum == \"\") {\n throw Error(\"invalid duration, missing number\");\n }\n\n if (s[i] === \"s\") {\n if (s.startsWith(\"seconds\", i)) {\n i += \"seconds\".length - 1;\n }\n dMs += 1000 * Number.parseInt(currentNum, 10);\n } else if (s[i] === \"m\") {\n if (s.startsWith(\"minutes\", i)) {\n i += \"minutes\".length - 1;\n }\n dMs += 60 * 1000 * Number.parseInt(currentNum, 10);\n } else if (s[i] === \"h\") {\n if (s.startsWith(\"hours\", i)) {\n i += \"hours\".length - 1;\n }\n dMs += 60 * 60 * 1000 * Number.parseInt(currentNum, 10);\n } else if (s[i] === \"d\") {\n if (s.startsWith(\"days\", i)) {\n i += \"days\".length - 1;\n }\n dMs += 24 * 60 * 60 * 1000 * Number.parseInt(currentNum, 10);\n } else {\n throw Error(\"invalid duration, unsupported unit\");\n }\n currentNum = \"\";\n parsingNum = true;\n }\n return {\n d_ms: dMs,\n };\n }\n\n /**\n * Compare two durations. Returns 0 when equal, -1 when a < b\n * and +1 when a > b.\n */\n export function cmp(d1: Duration, d2: Duration): 1 | 0 | -1 {\n if (d1.d_ms === \"forever\") {\n if (d2.d_ms === \"forever\") {\n return 0;\n }\n return 1;\n }\n if (d2.d_ms === \"forever\") {\n return -1;\n }\n if (d1.d_ms == d2.d_ms) {\n return 0;\n }\n if (d1.d_ms > d2.d_ms) {\n return 1;\n }\n return -1;\n }\n\n export function add(d1: Duration, d2: Duration): Duration {\n if (d1.d_ms === \"forever\") {\n return Duration.getForever();\n }\n if (d2.d_ms === \"forever\") {\n return Duration.getForever();\n }\n return Duration.fromMilliseconds(d1.d_ms + d2.d_ms);\n }\n\n export function max(d1: Duration, d2: Duration): Duration {\n return durationMax(d1, d2);\n }\n\n export function min(d1: Duration, d2: Duration): Duration {\n return durationMin(d1, d2);\n }\n\n export function multiply(d1: Duration, n: number): Duration {\n return durationMul(d1, n);\n }\n\n export function toIntegerYears(d: Duration): number {\n if (typeof d.d_ms !== \"number\") {\n throw Error(\"infinite duration\");\n }\n return Math.ceil(d.d_ms / 1000 / 60 / 60 / 24 / 365);\n }\n\n /**\n * Construct a duration from a specification of the individual units.\n *\n * Returns a zero duration if none of the units were specified.\n */\n export function fromSpec(spec: DurationUnitSpec): Duration {\n let d_ms = 0;\n d_ms += (spec.seconds ?? 0) * SECONDS;\n d_ms += (spec.minutes ?? 0) * MINUTES;\n d_ms += (spec.hours ?? 0) * HOURS;\n d_ms += (spec.days ?? 0) * DAYS;\n d_ms += (spec.months ?? 0) * MONTHS;\n d_ms += (spec.years ?? 0) * YEARS;\n return { d_ms };\n }\n\n export function fromSpecOrUndefined(\n spec: DurationUnitSpec,\n ): Duration | undefined {\n if (\n spec.seconds == undefined &&\n spec.minutes == undefined &&\n spec.hours == undefined &&\n spec.days == undefined &&\n spec.months == undefined &&\n spec.years == undefined\n ) {\n return undefined;\n }\n\n return Duration.fromSpec(spec);\n }\n\n export function toSpec({ d_ms }: Duration):\n | {\n seconds: number;\n minutes: number;\n hours: number;\n days: number;\n month: number;\n years: number;\n }\n | undefined {\n if (d_ms === \"forever\") return undefined;\n const ms = d_ms > 0 ? d_ms : 0;\n const Y_rest = ms % YEARS;\n const M_rest = Y_rest % MONTHS;\n const D_rest = M_rest % DAYS;\n const h_rest = D_rest % HOURS;\n const m_rest = h_rest % MINUTES;\n const millis = m_rest % SECONDS;\n\n return {\n years: (ms - Y_rest) / YEARS,\n month: (Y_rest - M_rest) / MONTHS,\n days: (M_rest - D_rest) / DAYS,\n hours: (D_rest - h_rest) / HOURS,\n minutes: (h_rest - m_rest) / MINUTES,\n seconds: (m_rest - millis) / SECONDS,\n };\n }\n\n export function getForever(): Duration {\n return { d_ms: \"forever\" };\n }\n\n export function isForever(d: Duration): boolean {\n return d.d_ms === \"forever\";\n }\n\n export function getZero(): Duration {\n return { d_ms: 0 };\n }\n\n export function fromTalerProtocolDuration(\n d: TalerProtocolDuration,\n ): Duration {\n if (d.d_us === \"forever\") {\n return {\n d_ms: \"forever\",\n };\n }\n return {\n d_ms: Math.floor(d.d_us / 1000),\n };\n }\n\n export function toTalerProtocolDuration(d: Duration): TalerProtocolDuration {\n if (d.d_ms === \"forever\") {\n return {\n d_us: \"forever\",\n };\n }\n return {\n d_us: d.d_ms * 1000,\n };\n }\n\n export function fromMilliseconds(ms: number): Duration {\n return {\n d_ms: ms,\n };\n }\n\n export function clamp(args: {\n lower: Duration;\n upper: Duration;\n value: Duration;\n }): Duration {\n return durationMax(durationMin(args.value, args.upper), args.lower);\n }\n}\n\nexport namespace AbsoluteTime {\n export function getStampMsNow(): number {\n return new Date().getTime();\n }\n\n export function getStampMsNever(): number {\n return Number.MAX_SAFE_INTEGER;\n }\n\n export function now(): AbsoluteTime {\n return {\n t_ms: new Date().getTime() + timeshift,\n [opaque_AbsoluteTime]: true,\n };\n }\n\n export function zero(): AbsoluteTime {\n return {\n t_ms: 0,\n [opaque_AbsoluteTime]: true,\n };\n }\n\n export function never(): AbsoluteTime {\n return {\n t_ms: \"never\",\n [opaque_AbsoluteTime]: true,\n };\n }\n\n export function fromMilliseconds(ms: number): AbsoluteTime {\n return {\n t_ms: ms,\n [opaque_AbsoluteTime]: true,\n };\n }\n\n export function cmp(t1: AbsoluteTime, t2: AbsoluteTime): number {\n if (t1.t_ms === \"never\") {\n if (t2.t_ms === \"never\") {\n return 0;\n }\n return 1;\n }\n if (t2.t_ms === \"never\") {\n return -1;\n }\n if (t1.t_ms == t2.t_ms) {\n return 0;\n }\n if (t1.t_ms > t2.t_ms) {\n return 1;\n }\n return -1;\n }\n\n export function min(t1: AbsoluteTime, t2: AbsoluteTime): AbsoluteTime {\n if (t1.t_ms === \"never\") {\n return { t_ms: t2.t_ms, [opaque_AbsoluteTime]: true };\n }\n if (t2.t_ms === \"never\") {\n return { t_ms: t2.t_ms, [opaque_AbsoluteTime]: true };\n }\n return { t_ms: Math.min(t1.t_ms, t2.t_ms), [opaque_AbsoluteTime]: true };\n }\n\n export function max(t1: AbsoluteTime, t2: AbsoluteTime): AbsoluteTime {\n if (t1.t_ms === \"never\") {\n return { t_ms: \"never\", [opaque_AbsoluteTime]: true };\n }\n if (t2.t_ms === \"never\") {\n return { t_ms: \"never\", [opaque_AbsoluteTime]: true };\n }\n return { t_ms: Math.max(t1.t_ms, t2.t_ms), [opaque_AbsoluteTime]: true };\n }\n\n export function difference(t1: AbsoluteTime, t2: AbsoluteTime): Duration {\n if (t1.t_ms === \"never\") {\n return { d_ms: \"forever\" };\n }\n if (t2.t_ms === \"never\") {\n return { d_ms: \"forever\" };\n }\n return { d_ms: Math.abs(t1.t_ms - t2.t_ms) };\n }\n\n export function isExpired(t: AbsoluteTime) {\n return cmp(t, now()) <= 0;\n }\n\n export function isNever(t: AbsoluteTime): boolean {\n return t.t_ms === \"never\";\n }\n\n export function fromProtocolTimestamp(\n t: TalerProtocolTimestamp,\n ): AbsoluteTime {\n if (t.t_s === \"never\") {\n return { t_ms: \"never\", [opaque_AbsoluteTime]: true };\n }\n return {\n t_ms: t.t_s * 1000,\n [opaque_AbsoluteTime]: true,\n };\n }\n\n export function fromStampMs(stampMs: number): AbsoluteTime {\n return {\n t_ms: stampMs,\n [opaque_AbsoluteTime]: true,\n };\n }\n\n export function fromPreciseTimestamp(t: TalerPreciseTimestamp): AbsoluteTime {\n if (t.t_s === \"never\") {\n return { t_ms: \"never\", [opaque_AbsoluteTime]: true };\n }\n const offsetUs = t.off_us ?? 0;\n return {\n t_ms: t.t_s * 1000 + Math.floor(offsetUs / 1000),\n [opaque_AbsoluteTime]: true,\n };\n }\n\n export function toStampMs(at: AbsoluteTime): number {\n if (at.t_ms === \"never\") {\n return Number.MAX_SAFE_INTEGER;\n }\n return at.t_ms;\n }\n\n export function toPreciseTimestamp(at: AbsoluteTime): TalerPreciseTimestamp {\n if (at.t_ms == \"never\") {\n return {\n t_s: \"never\",\n };\n }\n const t_s = Math.floor(at.t_ms / 1000);\n const off_us = Math.floor(1000 * (at.t_ms - t_s * 1000));\n return {\n t_s,\n off_us,\n };\n }\n\n export function toProtocolTimestamp(\n at: AbsoluteTime,\n ): TalerProtocolTimestamp {\n if (at.t_ms === \"never\") {\n return { t_s: \"never\" };\n }\n return {\n t_s: Math.floor(at.t_ms / 1000),\n };\n }\n\n export function isBetween(\n t: AbsoluteTime,\n start: AbsoluteTime,\n end: AbsoluteTime,\n ): boolean {\n if (cmp(t, start) < 0) {\n return false;\n }\n if (cmp(t, end) > 0) {\n return false;\n }\n return true;\n }\n\n export function toIsoString(t: AbsoluteTime): string {\n if (t.t_ms === \"never\") {\n return \"\";\n } else {\n return new Date(t.t_ms).toISOString();\n }\n }\n\n export function addDuration(t1: AbsoluteTime, d: Duration): AbsoluteTime {\n if (t1.t_ms === \"never\" || d.d_ms === \"forever\") {\n return { t_ms: \"never\", [opaque_AbsoluteTime]: true };\n }\n return { t_ms: t1.t_ms + d.d_ms, [opaque_AbsoluteTime]: true };\n }\n\n /**\n * Get the remaining duration until {@param t1}.\n *\n * If {@param t1} already happened, the remaining duration\n * is zero.\n */\n export function remaining(t1: AbsoluteTime): Duration {\n if (t1.t_ms === \"never\") {\n return Duration.getForever();\n }\n const stampNow = now();\n if (stampNow.t_ms === \"never\") {\n throw Error(\"invariant violated\");\n }\n return Duration.fromMilliseconds(Math.max(0, t1.t_ms - stampNow.t_ms));\n }\n\n export function subtractDuraction(\n t1: AbsoluteTime,\n d: Duration,\n ): AbsoluteTime {\n if (t1.t_ms === \"never\") {\n return { t_ms: \"never\", [opaque_AbsoluteTime]: true };\n }\n if (d.d_ms === \"forever\") {\n return { t_ms: 0, [opaque_AbsoluteTime]: true };\n }\n return { t_ms: Math.max(0, t1.t_ms - d.d_ms), [opaque_AbsoluteTime]: true };\n }\n\n export function stringify(t: AbsoluteTime): string {\n if (t.t_ms === \"never\") {\n return \"never\";\n }\n return new Date(t.t_ms).toISOString();\n }\n}\n\nconst SECONDS = 1000;\nconst MINUTES = SECONDS * 60;\nconst HOURS = MINUTES * 60;\nconst DAYS = HOURS * 24;\nconst MONTHS = DAYS * 30;\nconst YEARS = DAYS * 365;\n\nexport function durationMin(d1: Duration, d2: Duration): Duration {\n if (d1.d_ms === \"forever\") {\n return { d_ms: d2.d_ms };\n }\n if (d2.d_ms === \"forever\") {\n return { d_ms: d1.d_ms };\n }\n return { d_ms: Math.min(d1.d_ms, d2.d_ms) };\n}\n\nexport function durationMax(d1: Duration, d2: Duration): Duration {\n if (d1.d_ms === \"forever\") {\n return { d_ms: \"forever\" };\n }\n if (d2.d_ms === \"forever\") {\n return { d_ms: \"forever\" };\n }\n return { d_ms: Math.max(d1.d_ms, d2.d_ms) };\n}\n\nexport function durationMul(d: Duration, n: number): Duration {\n if (d.d_ms === \"forever\") {\n return { d_ms: \"forever\" };\n }\n return { d_ms: Math.round(d.d_ms * n) };\n}\n\nexport function durationAdd(d1: Duration, d2: Duration): Duration {\n if (d1.d_ms === \"forever\" || d2.d_ms === \"forever\") {\n return { d_ms: \"forever\" };\n }\n return { d_ms: d1.d_ms + d2.d_ms };\n}\n\nexport const codecForAbsoluteTime: Codec = {\n decode(x: any, c?: Context): AbsoluteTime {\n if (x === undefined) {\n throw Error(\n `got undefined and expected absolute time at ${renderContext(c)}`,\n );\n }\n const t_ms = x.t_ms;\n if (typeof t_ms === \"string\") {\n if (t_ms === \"never\") {\n return { t_ms: \"never\", [opaque_AbsoluteTime]: true };\n }\n } else if (typeof t_ms === \"number\") {\n return { t_ms, [opaque_AbsoluteTime]: true };\n }\n throw Error(`expected timestamp at ${renderContext(c)}`);\n },\n};\n\nexport const codecForTimestamp: Codec = {\n decode(x: any, c?: Context): TalerProtocolTimestamp {\n // Compatibility, should be removed soon.\n if (x === undefined) {\n throw Error(\n `got undefined and expected timestamp at ${renderContext(c)}`,\n );\n }\n const t_ms = x.t_ms;\n if (typeof t_ms === \"string\") {\n if (t_ms === \"never\") {\n return { t_s: \"never\" };\n }\n } else if (typeof t_ms === \"number\") {\n return { t_s: Math.floor(t_ms / 1000) };\n }\n const t_s = x.t_s;\n if (typeof t_s === \"string\") {\n if (t_s === \"never\") {\n return { t_s: \"never\" };\n }\n throw Error(`expected timestamp at ${renderContext(c)}`);\n }\n if (typeof t_s === \"number\") {\n return { t_s };\n }\n throw Error(`expected protocol timestamp at ${renderContext(c)}`);\n },\n};\n\nexport const codecForPreciseTimestamp: Codec = {\n decode(x: any, c?: Context): TalerPreciseTimestamp {\n const t_ms = x.t_ms;\n if (typeof t_ms === \"string\") {\n if (t_ms === \"never\") {\n return { t_s: \"never\" };\n }\n } else if (typeof t_ms === \"number\") {\n return { t_s: Math.floor(t_ms / 1000) };\n }\n throw Error(`expected precise timestamp at ${renderContext(c)}`);\n },\n};\n\nexport const codecForDuration: Codec = {\n decode(x: any, c?: Context): TalerProtocolDuration {\n const d_us = x.d_us;\n if (typeof d_us === \"string\") {\n if (d_us === \"forever\") {\n return { d_us: \"forever\" };\n }\n throw Error(`expected duration at ${renderContext(c)}`);\n }\n if (typeof d_us === \"number\") {\n return { d_us };\n }\n throw Error(`expected duration at ${renderContext(c)}`);\n },\n};\n\nexport const codecForDurationMs: Codec = {\n decode(x: any, c?: Context): Duration {\n const d_ms = x.d_ms;\n if (typeof d_ms === \"string\") {\n if (d_ms === \"forever\") {\n return { d_ms: \"forever\" };\n }\n throw Error(`expected duration at ${renderContext(c)}`);\n }\n if (typeof d_ms === \"number\") {\n return { d_ms };\n }\n throw Error(`expected duration at ${renderContext(c)}`);\n },\n};\n", "/*\n This file is part of GNU Taler\n (C) 2019-2020 Taler Systems SA\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { CancellationToken } from \"./CancellationToken.js\";\nimport { TalerErrorCode } from \"./taler-error-codes.js\";\nimport { AbsoluteTime } from \"./time.js\";\nimport {\n TransactionState,\n TransactionType,\n} from \"./types-taler-wallet-transactions.js\";\nimport {\n PaymentInsufficientBalanceDetails,\n TalerErrorDetail,\n} from \"./types-taler-wallet.js\";\n\n/**\n * Classes and helpers for error handling specific to wallet operations.\n *\n * @author Florian Dold \n */\n\ntype empty = Record;\n\nexport interface DetailsMap {\n [TalerErrorCode.WALLET_PAY_MERCHANT_KYC_MISSING]: {\n exchangeResponse: any;\n };\n [TalerErrorCode.WALLET_PENDING_OPERATION_FAILED]: {\n innerError: TalerErrorDetail;\n transactionId?: string;\n };\n [TalerErrorCode.WALLET_EXCHANGE_DENOMINATIONS_INSUFFICIENT]: {\n exchangeBaseUrl: string;\n };\n [TalerErrorCode.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE]: {\n exchangeProtocolVersion: string;\n walletProtocolVersion: string;\n };\n [TalerErrorCode.WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK]: empty;\n [TalerErrorCode.WALLET_REWARD_COIN_SIGNATURE_INVALID]: empty;\n [TalerErrorCode.WALLET_ORDER_ALREADY_CLAIMED]: {\n orderId: string;\n claimUrl: string;\n };\n [TalerErrorCode.WALLET_ORDER_ALREADY_PAID]: {\n orderId: string;\n fulfillmentUrl: string | undefined;\n };\n [TalerErrorCode.WALLET_CONTRACT_TERMS_MALFORMED]: empty;\n [TalerErrorCode.WALLET_CONTRACT_TERMS_SIGNATURE_INVALID]: {\n merchantPub: string;\n orderId: string;\n };\n [TalerErrorCode.WALLET_CONTRACT_TERMS_BASE_URL_MISMATCH]: {\n baseUrlForDownload: string;\n baseUrlFromContractTerms: string;\n };\n [TalerErrorCode.WALLET_INVALID_TALER_PAY_URI]: {\n talerPayUri: string;\n };\n [TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR]: {\n requestUrl: string;\n requestMethod: string;\n httpStatusCode: number;\n errorResponse?: any;\n };\n [TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION]: {\n stack?: string;\n };\n [TalerErrorCode.WALLET_BANK_INTEGRATION_PROTOCOL_VERSION_INCOMPATIBLE]: {\n bankProtocolVersion: string;\n walletProtocolVersion: string;\n };\n [TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN]: {\n operation: string;\n };\n [TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED]: {\n requestUrl: string;\n requestMethod: string;\n throttleStats: Record;\n };\n [TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT]: {\n requestUrl: string;\n requestMethod: string;\n timeoutMs: number;\n };\n [TalerErrorCode.GENERIC_TIMEOUT]: {\n requestUrl: string;\n requestMethod: string;\n timeoutMs: number;\n };\n [TalerErrorCode.WALLET_NETWORK_ERROR]: {\n requestUrl: string;\n requestMethod: string;\n };\n [TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE]: {\n requestUrl: string;\n requestMethod: string;\n httpStatusCode: number;\n /**\n * Original response which is malformed\n */\n response?: string;\n validationError?: string;\n /**\n * Content type of the response, usually only specified if not the\n * expected content type.\n */\n contentType?: string;\n };\n [TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR]: {\n operation: string;\n error: string;\n detail: TalerErrorDetail | undefined;\n };\n [TalerErrorCode.WALLET_EXCHANGE_COIN_SIGNATURE_INVALID]: empty;\n [TalerErrorCode.WALLET_WITHDRAWAL_GROUP_INCOMPLETE]: {\n numErrors: number;\n errorsPerCoin: Record;\n };\n [TalerErrorCode.WALLET_CORE_NOT_AVAILABLE]: {\n lastError?: TalerErrorDetail;\n };\n [TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR]: {\n httpStatusCode: number;\n };\n [TalerErrorCode.WALLET_PAY_MERCHANT_SERVER_ERROR]: {\n requestError: TalerErrorDetail;\n };\n [TalerErrorCode.WALLET_CRYPTO_WORKER_ERROR]: {\n innerError: TalerErrorDetail;\n };\n [TalerErrorCode.WALLET_CRYPTO_WORKER_BAD_REQUEST]: {\n detail: string;\n };\n [TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED]: {\n kycUrl: string;\n };\n [TalerErrorCode.WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE]: {\n insufficientBalanceDetails: PaymentInsufficientBalanceDetails;\n };\n [TalerErrorCode.WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE]: {\n insufficientBalanceDetails: PaymentInsufficientBalanceDetails;\n };\n [TalerErrorCode.WALLET_REFRESH_GROUP_INCOMPLETE]: {\n numErrors: number;\n /**\n * Errors, can be truncated.\n */\n errors: TalerErrorDetail[];\n };\n [TalerErrorCode.WALLET_EXCHANGE_BASE_URL_MISMATCH]: {\n urlWallet: string;\n urlExchange: string;\n };\n [TalerErrorCode.WALLET_EXCHANGE_UNAVAILABLE]: {\n exchangeBaseUrl: string;\n innerError: TalerErrorDetail | undefined;\n };\n [TalerErrorCode.WALLET_DB_UNAVAILABLE]: {\n innerError: TalerErrorDetail | undefined;\n };\n [TalerErrorCode.WALLET_EXCHANGE_TOS_NOT_ACCEPTED]: {\n exchangeBaseUrl: string;\n tosStatus: string;\n currentEtag: string | undefined;\n };\n [TalerErrorCode.WALLET_EXCHANGE_ENTRY_UPDATE_CONFLICT]: {\n detail?: string;\n };\n [TalerErrorCode.WALLET_REQUEST_TRANSACTION_STATE_UNSUPPORTED]: {\n message?: string;\n txState: TransactionState;\n debugStateNum?: number;\n };\n}\n\ntype ErrBody = Y extends keyof DetailsMap ? DetailsMap[Y] : empty;\n\nexport type TypedTalerErrorDetail = TalerErrorDetail &\n (Y extends keyof DetailsMap ? DetailsMap[Y] : {});\n\nexport function makeErrorDetail(\n code: C,\n detail: ErrBody,\n hint?: string,\n): TalerErrorDetail {\n if (!hint && !(detail as any).hint) {\n hint = getDefaultTalerErrorHint(code);\n }\n const when = AbsoluteTime.now();\n return { code, when, hint, ...detail };\n}\n\nexport function makePendingOperationFailedError(\n innerError: TalerErrorDetail,\n tag: TransactionType,\n uid: string,\n): TalerError {\n return TalerError.fromDetail(TalerErrorCode.WALLET_PENDING_OPERATION_FAILED, {\n innerError,\n transactionId: `${tag}:${uid}`,\n });\n}\n\nexport function summarizeTalerErrorDetail(ed: TalerErrorDetail): string {\n const errName = TalerErrorCode[ed.code] ?? \"\";\n return `Error (${ed.code}/${errName})`;\n}\n\nexport function getDefaultTalerErrorHint(code: number): string {\n const errName = TalerErrorCode[code];\n if (errName) {\n return `Error (${errName})`;\n } else {\n return `Error ()`;\n }\n}\n\nexport class TalerProtocolViolationError extends Error {\n constructor(hint?: string) {\n let msg: string;\n if (hint) {\n msg = `Taler protocol violation error (${hint})`;\n } else {\n msg = `Taler protocol violation error`;\n }\n super(msg);\n Object.setPrototypeOf(this, TalerProtocolViolationError.prototype);\n }\n}\n\n// compute a subset of TalerError, just for http request\ntype HttpErrors =\n | TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT\n | TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED\n | TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE\n | TalerErrorCode.WALLET_NETWORK_ERROR\n | TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR;\n\ntype TalerHttpErrorsDetails = {\n [code in HttpErrors]: TalerError;\n};\n\nexport type TalerHttpError =\n TalerHttpErrorsDetails[keyof TalerHttpErrorsDetails];\n\n/**\n * Construct typed error details.\n * Fills in the hint with a default based on the error code name.\n */\nexport function makeTalerErrorDetail(\n code: C,\n errBody: ErrBody,\n hint?: string,\n): TalerErrorDetail {\n if (!hint) {\n hint = getDefaultTalerErrorHint(code);\n }\n return { code, hint, ...errBody };\n}\n\nexport class TalerError extends Error {\n errorDetail: TalerErrorDetail & T;\n cause: Error | undefined;\n private constructor(d: TalerErrorDetail & T, cause?: Error) {\n super(d.hint ?? `Error (code ${d.code})`);\n this.errorDetail = d;\n this.cause = cause;\n Object.setPrototypeOf(this, TalerError.prototype);\n }\n\n static fromDetail(\n code: C,\n detail: ErrBody,\n hint?: string,\n cause?: Error,\n ): TalerError {\n if (!hint) {\n hint = getDefaultTalerErrorHint(code);\n }\n const when = AbsoluteTime.now();\n return new TalerError({ code, when, hint, ...detail }, cause);\n }\n\n static fromUncheckedDetail(d: TalerErrorDetail, c?: Error): TalerError {\n return new TalerError({ ...d }, c);\n }\n\n static fromException(e: any): TalerError {\n const errDetail = getErrorDetailFromException(e);\n return new TalerError(errDetail, e);\n }\n\n hasErrorCode(\n code: C,\n ): this is TalerError {\n return this.errorDetail.code === code;\n }\n\n toString(): string {\n return `TalerError: ${JSON.stringify(this.errorDetail)}`;\n }\n}\n\nexport function safeStringifyException(e: any): string {\n return JSON.stringify(getErrorDetailFromException(e), undefined, 2);\n}\n\n/**\n * Convert an exception (or anything that was thrown) into\n * a TalerErrorDetail object.\n */\nexport function getErrorDetailFromException(e: any): TalerErrorDetail {\n if (e instanceof TalerError) {\n return e.errorDetail;\n }\n if (e instanceof CancellationToken.CancellationError) {\n const err = makeErrorDetail(\n TalerErrorCode.WALLET_CORE_REQUEST_CANCELLED,\n {},\n );\n return err;\n }\n if (e instanceof Error) {\n const err = makeErrorDetail(\n TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,\n {\n stack: e.stack,\n },\n `unexpected exception (message: ${e.message})`,\n );\n return err;\n }\n // Something was thrown that is not even an exception!\n // Try to stringify it.\n let excString: string;\n try {\n excString = e.toString();\n } catch (e) {\n // Something went horribly wrong.\n excString = \"can't stringify exception\";\n }\n const err = makeErrorDetail(\n TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,\n {},\n `unexpected exception (not an exception, ${excString})`,\n );\n return err;\n}\n\n/**\n * This function should not be called at runtime.\n * Useful on switch/case to detect that all path has been contemplated.\n *\n * @param x\n */\nexport function assertUnreachable(x: never): never {\n throw new Error(\"Didn't expect to get here\");\n}\n", "/*\n This file is part of GNU Taler\n (C) 2023-2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL3.0-or-later\n*/\n\nimport { CancellationToken } from \"./CancellationToken.js\";\nimport { Codec } from \"./codec.js\";\nimport { makeErrorDetail, TalerError } from \"./errors.js\";\nimport { j2s } from \"./helpers.js\";\nimport { Logger } from \"./logging.js\";\nimport { TalerErrorCode } from \"./taler-error-codes.js\";\nimport { AbsoluteTime, Duration } from \"./time.js\";\nimport { TalerErrorDetail } from \"./types-taler-wallet.js\";\n\nconst textEncoder = new TextEncoder();\n\nconst logger = new Logger(\"http.ts\");\n\n/**\n * An HTTP response that is returned by all request methods of this library.\n */\nexport interface HttpResponse {\n requestUrl: string;\n requestMethod: string;\n status: number;\n headers: Headers;\n json(): Promise;\n text(): Promise;\n bytes(): Promise;\n}\n\nexport const DEFAULT_REQUEST_TIMEOUT_MS = 60000;\n\nexport interface HttpRequestOptions {\n method?: \"POST\" | \"PATCH\" | \"PUT\" | \"GET\" | \"DELETE\";\n headers?: { [name: string]: string | undefined };\n\n /**\n * Timeout after which the request should be aborted.\n */\n timeout?: Duration;\n\n /**\n * Cancellation token that should abort the request when\n * cancelled.\n */\n cancellationToken?: CancellationToken;\n\n body?: string | Uint8Array | object;\n\n /**\n * How to handle redirects.\n * Same semantics as WHATWG fetch.\n */\n redirect?: \"follow\" | \"error\" | \"manual\";\n\n /**\n * How to compress the payload\n */\n compress?: \"gzip\" | \"deflate\";\n}\n\n/**\n * Headers, roughly modeled after the fetch API's headers object.\n */\nexport interface Headers {\n get(name: string): string | null;\n set(name: string, value: string): void;\n toJSON(): any;\n}\n\nexport class HeadersImpl {\n private headerMap = new Map();\n\n get(name: string): string | null {\n const r = this.headerMap.get(name.toLowerCase());\n if (r) {\n return r;\n }\n return null;\n }\n\n set(name: string, value: string): void {\n const normalizedName = name.toLowerCase();\n const existing = this.headerMap.get(normalizedName);\n if (existing !== undefined) {\n this.headerMap.set(normalizedName, existing + \",\" + value);\n } else {\n this.headerMap.set(normalizedName, value);\n }\n }\n\n toJSON(): any {\n const m: Record = {};\n this.headerMap.forEach((v, k) => (m[k] = v));\n return m;\n }\n}\n\n/**\n * Interface for the HTTP request library used by the wallet.\n *\n * The request library is bundled into an interface to make mocking and\n * request tunneling easy.\n */\nexport interface HttpRequestLibrary {\n /**\n * Make an HTTP POST request with a JSON body.\n */\n fetch(url: string, opt?: HttpRequestOptions): Promise;\n}\n\ntype TalerErrorResponse = {\n code: number;\n} & unknown;\n\ntype ResponseOrError =\n | { isError: false; response: T }\n | { isError: true; talerErrorResponse: TalerErrorResponse };\n\n/**\n * Read Taler error details from an HTTP response.\n */\nexport async function readTalerErrorResponse(\n httpResponse: HttpResponse,\n): Promise {\n const contentType = httpResponse.headers.get(\"content-type\");\n let mediaType: string | undefined = undefined;\n if (contentType) {\n mediaType = contentType.split(\";\")[0].trim().toLowerCase();\n }\n if (mediaType !== \"application/json\") {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n contentType: mediaType || \"\",\n },\n \"Error response did not even contain JSON. The request URL might be wrong or the service might be unavailable.\",\n );\n }\n let errJson;\n try {\n errJson = await httpResponse.json();\n } catch (e) {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n validationError: e instanceof Error ? e.message : String(e),\n },\n \"Couldn't parse JSON format from error response\",\n );\n }\n\n const talerErrorCode = errJson.code;\n if (typeof talerErrorCode !== \"number\") {\n logger.warn(\n `malformed error response (status ${httpResponse.status}): ${j2s(\n errJson,\n )}`,\n );\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n },\n \"Error response did not contain error code\",\n );\n }\n return errJson;\n}\n\nexport async function readUnexpectedResponseDetails(\n httpResponse: HttpResponse,\n): Promise {\n let errJson;\n try {\n errJson = await httpResponse.json();\n } catch (e) {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n validationError: e instanceof Error ? e.message : String(e),\n },\n \"Couldn't parse JSON format from error response\",\n );\n }\n const talerErrorCode = errJson.code;\n if (typeof talerErrorCode !== \"number\") {\n return makeErrorDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n },\n \"Error response did not contain error code\",\n );\n }\n return makeErrorDetail(\n TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n errorResponse: errJson,\n },\n `Unexpected HTTP status (${httpResponse.status}) in response`,\n );\n}\n\nexport async function readSuccessResponseJsonOrErrorCode(\n httpResponse: HttpResponse,\n codec: Codec,\n): Promise> {\n if (!(httpResponse.status >= 200 && httpResponse.status < 300)) {\n return {\n isError: true,\n talerErrorResponse: await readTalerErrorResponse(httpResponse),\n };\n }\n let respJson;\n try {\n respJson = await httpResponse.json();\n } catch (e) {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n validationError: e instanceof Error ? e.message : String(e),\n },\n \"Couldn't parse JSON format from response\",\n );\n }\n let parsedResponse: T;\n try {\n parsedResponse = codec.decode(respJson);\n } catch (e) {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n validationError: e instanceof Error ? e.message : String(e),\n },\n \"Response invalid\",\n );\n }\n return {\n isError: false,\n response: parsedResponse,\n };\n}\n\nexport async function readResponseJsonOrThrow(\n httpResponse: HttpResponse,\n codec: Codec,\n): Promise {\n let respJson;\n try {\n respJson = await httpResponse.json();\n } catch (e) {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n validationError: e instanceof Error ? e.message : String(e),\n },\n \"Couldn't parse JSON format from response\",\n );\n }\n let parsedResponse: T;\n try {\n parsedResponse = codec.decode(respJson);\n } catch (e) {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n validationError: e instanceof Error ? e.message : String(e),\n },\n \"Response invalid\",\n );\n }\n return parsedResponse;\n}\n\ntype HttpErrorDetails = {\n requestUrl: string;\n requestMethod: string;\n httpStatusCode: number;\n};\n\nexport function getHttpResponseErrorDetails(\n httpResponse: HttpResponse,\n): HttpErrorDetails {\n return {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n };\n}\n\nexport function throwUnexpectedRequestError(\n httpResponse: HttpResponse,\n talerErrorResponse: TalerErrorResponse,\n): never {\n const errorDetails = {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n errorResponse: talerErrorResponse,\n };\n logger.trace(`unexpected request error: ${j2s(errorDetails)}`);\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,\n errorDetails,\n `Unexpected HTTP status ${httpResponse.status} in response`,\n );\n}\n\nexport async function readSuccessResponseJsonOrThrow(\n httpResponse: HttpResponse,\n codec: Codec,\n): Promise {\n const r = await readSuccessResponseJsonOrErrorCode(httpResponse, codec);\n if (!r.isError) {\n return r.response;\n }\n throwUnexpectedRequestError(httpResponse, r.talerErrorResponse);\n}\n\nexport async function expectSuccessResponseOrThrow(\n httpResponse: HttpResponse,\n): Promise {\n if (httpResponse.status >= 200 && httpResponse.status <= 299) {\n return;\n }\n const errResp = await readTalerErrorResponse(httpResponse);\n throwUnexpectedRequestError(httpResponse, errResp);\n}\n\nexport async function readSuccessResponseTextOrErrorCode(\n httpResponse: HttpResponse,\n): Promise> {\n if (!(httpResponse.status >= 200 && httpResponse.status < 300)) {\n let errJson;\n try {\n errJson = await httpResponse.json();\n } catch (e) {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n validationError: e instanceof Error ? e.message : String(e),\n },\n \"Couldn't parse JSON format from error response\",\n );\n }\n\n const talerErrorCode = errJson.code;\n if (typeof talerErrorCode !== \"number\") {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n httpStatusCode: httpResponse.status,\n requestUrl: httpResponse.requestUrl,\n response: await httpResponse.text(),\n requestMethod: httpResponse.requestMethod,\n },\n \"Error response did not contain error code\",\n );\n }\n return {\n isError: true,\n talerErrorResponse: errJson,\n };\n }\n const respJson = await httpResponse.text();\n return {\n isError: false,\n response: respJson,\n };\n}\n\nexport async function checkSuccessResponseOrThrow(\n httpResponse: HttpResponse,\n): Promise {\n if (!(httpResponse.status >= 200 && httpResponse.status < 300)) {\n let errJson;\n try {\n errJson = await httpResponse.json();\n } catch (e) {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n requestUrl: httpResponse.requestUrl,\n requestMethod: httpResponse.requestMethod,\n httpStatusCode: httpResponse.status,\n response: await httpResponse.text(),\n validationError: e instanceof Error ? e.message : String(e),\n },\n \"Couldn't parse JSON format from error response\",\n );\n }\n\n const talerErrorCode = errJson.code;\n if (typeof talerErrorCode !== \"number\") {\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,\n {\n httpStatusCode: httpResponse.status,\n requestUrl: httpResponse.requestUrl,\n response: await httpResponse.text(),\n requestMethod: httpResponse.requestMethod,\n },\n \"Error response did not contain error code\",\n );\n }\n throwUnexpectedRequestError(httpResponse, errJson);\n }\n}\n\nexport async function readSuccessResponseTextOrThrow(\n httpResponse: HttpResponse,\n): Promise {\n const r = await readSuccessResponseTextOrErrorCode(httpResponse);\n if (!r.isError) {\n return r.response;\n }\n throwUnexpectedRequestError(httpResponse, r.talerErrorResponse);\n}\n\n/**\n * Get the timestamp at which the response's content is considered expired.\n */\nexport function getExpiry(\n httpResponse: HttpResponse,\n opt: { minDuration?: Duration },\n): AbsoluteTime {\n const expiryDateMs = new Date(\n httpResponse.headers.get(\"expiry\") ?? \"\",\n ).getTime();\n let t: AbsoluteTime;\n if (Number.isNaN(expiryDateMs)) {\n t = AbsoluteTime.now();\n } else {\n t = AbsoluteTime.fromMilliseconds(expiryDateMs);\n }\n if (opt.minDuration) {\n const t2 = AbsoluteTime.addDuration(AbsoluteTime.now(), opt.minDuration);\n return AbsoluteTime.max(t, t2);\n }\n return t;\n}\n\nexport interface HttpLibArgs {\n enableThrottling?: boolean;\n /**\n * Only allow HTTPS connections, not plain http.\n */\n requireTls?: boolean;\n printAsCurl?: boolean;\n}\n\nexport function encodeBody(body: unknown): Uint8Array {\n if (body == null) {\n return new Uint8Array(0);\n }\n if (typeof body === \"string\") {\n return textEncoder.encode(body);\n } else if (ArrayBuffer.isView(body)) {\n return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);\n } else if (body instanceof ArrayBuffer) {\n return new Uint8Array(body);\n } else if (body instanceof URLSearchParams) {\n return textEncoder.encode(body.toString());\n } else if (typeof body === \"object\" && body.constructor.name === \"FormData\") {\n return new Uint8Array(body as ArrayBuffer);\n } else if (typeof body === \"object\") {\n return textEncoder.encode(JSON.stringify(body));\n }\n throw new TypeError(\"unsupported request body type\");\n}\n\nexport function getDefaultHeaders(method: string): Record {\n const headers: Record = {};\n\n if (method === \"POST\" || method === \"PUT\" || method === \"PATCH\") {\n // Default to JSON if we have a body\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n headers[\"Accept\"] = \"application/json\";\n\n return headers;\n}\n", "/*\n This file is part of TALER\n (C) 2017 GNUnet e.V.\n\n TALER is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n TALER is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n TALER; see the file COPYING. If not, see \n */\n\n/**\n * Semantic versioning, but libtool-style.\n * See https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html\n */\n\n/**\n * Result of comparing two libtool versions.\n */\nexport interface VersionMatchResult {\n /**\n * Is the first version compatible with the second?\n */\n compatible: boolean;\n\n /**\n * Is the first version older (-1), newer (+1) or\n * identical (0)?\n */\n currentCmp: number;\n}\n\nexport interface Version {\n current: number;\n revision: number;\n age: number;\n}\n\nexport namespace LibtoolVersion {\n /**\n * Compare two libtool-style version strings.\n */\n export function compare(\n me: string,\n other: string,\n ): VersionMatchResult | undefined {\n const meVer = parseVersion(me);\n const otherVer = parseVersion(other);\n\n if (!(meVer && otherVer)) {\n return undefined;\n }\n\n const compatible =\n meVer.current - meVer.age <= otherVer.current &&\n meVer.current >= otherVer.current - otherVer.age;\n\n const currentCmp = Math.sign(meVer.current - otherVer.current);\n\n return { compatible, currentCmp };\n }\n\n export function parseVersionOrThrow(v: string): Version {\n const res = parseVersion(v);\n if (!res) {\n throw Error(\"invalid libtool version\");\n }\n return res;\n }\n\n export function parseVersion(v: string): Version | undefined {\n const [currentStr, revisionStr, ageStr, ...rest] = v.split(\":\");\n if (rest.length !== 0) {\n return undefined;\n }\n const current = Number.parseInt(currentStr);\n const revision = Number.parseInt(revisionStr);\n const age = Number.parseInt(ageStr);\n\n if (Number.isNaN(current)) {\n return undefined;\n }\n\n if (Number.isNaN(revision)) {\n return undefined;\n }\n\n if (Number.isNaN(age)) {\n return undefined;\n }\n\n return { current, revision, age };\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\n/**\n * Type and schema definitions and helpers for the core GNU Taler protocol.\n *\n * Even though the rest of the wallet uses camelCase for fields, use snake_case\n * here, since that's the convention for the Taler JSON+HTTP API.\n */\n\n/**\n * Imports.\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport { CancellationToken } from \"./CancellationToken.js\";\nimport {\n Codec,\n buildCodecForObject,\n codecForAny,\n codecForBoolean,\n codecForConstString,\n codecForList,\n codecForMap,\n codecForNumber,\n codecForString,\n codecOptional,\n} from \"./codec.js\";\nimport { EddsaPrivP } from \"./taler-crypto.js\";\nimport {\n TalerProtocolDuration,\n TalerProtocolTimestamp,\n codecForTimestamp,\n} from \"./time.js\";\n\n// 64-byte hash code.\nexport type HashCode = string;\n\nexport type AmlOfficerPublicKeyP = string;\n\n// 32-byte hash code.\nexport type ShortHashCode = string;\n\nexport type SHA256HashCode = ShortHashCode;\n\nexport type SHA512HashCode = HashCode;\n\n// 32-byte nonce value, must only be used once.\nexport type CSNonce = string;\n\n// 32-byte nonce value, must only be used once.\nexport type RefreshMasterSeed = string;\n\n// 32-byte value representing a scalar multiplier\n// for scalar operations on points on Curve25519.\nexport type Cs25519Scalar = string;\n\n///\n/// KEYS\n///\n\n// 16-byte access token used to authorize access.\nexport type ClaimToken = string;\n\n// EdDSA and ECDHE public keys always point on Curve25519\n// and represented using the standard 256 bits Ed25519 compact format,\n// converted to Crockford Base32.\nexport type EddsaPublicKey = EddsaPublicKeyString;\n\n// EdDSA and ECDHE public keys always point on Curve25519\n// and represented using the standard 256 bits Ed25519 compact format,\n// converted to Crockford Base32.\nexport type EddsaPrivateKey = EddsaPrivateKeyString;\n\n// EdDSA signatures are transmitted as 64-bytes base32\n// binary-encoded objects with just the R and S values (base32_ binary-only).\nexport type EddsaSignature = EddsaSignatureString;\n\n// Edx25519 public keys are points on Curve25519 and represented using the\n// standard 256 bits Ed25519 compact format converted to Crockford\n// Base32.\n//export type Edx25519PublicKey = string;\n\n// Edx25519 private keys are always points on Curve25519\n// and represented using the standard 256 bits Ed25519 compact format,\n// converted to Crockford Base32.\n//export type Edx25519PrivateKey = string;\n\n// EdDSA and ECDHE public keys always point on Curve25519\n// and represented using the standard 256 bits Ed25519 compact format,\n// converted to Crockford Base32.\nexport type EcdhePublicKey = string;\n\n// Point on Curve25519 represented using the standard 256 bits Ed25519 compact format,\n// converted to Crockford Base32.\nexport type CsRPublic = string;\n\n// EdDSA and ECDHE public keys always point on Curve25519\n// and represented using the standard 256 bits Ed25519 compact format,\n// converted to Crockford Base32.\nexport type EcdhePrivateKey = string;\n\nexport type CoinPublicKey = EddsaPublicKey;\n\n// RSA public key converted to Crockford Base32.\nexport type RsaPublicKey = string;\n\nexport type WireTransferIdentifierRawP = string;\n// Subset of numbers: Integers in the\n// inclusive range 0 .. (2^53 - 1).\nexport type SafeUint64 = number;\n\nexport type WadId = string;\n\nexport type Timestamp = TalerProtocolTimestamp;\n\nexport type RelativeTime = TalerProtocolDuration;\n\nexport type RsaSignature = string;\n\nexport type BlindedRsaSignature = string;\n\n/**\n * DD51 https://docs.taler.net/design-documents/051-fractional-digits.html\n */\nexport interface CurrencySpecification {\n // Name of the currency.\n name: string;\n\n // how many digits the user may enter after the decimal_separator\n num_fractional_input_digits: Integer;\n\n // Number of fractional digits to render in normal font and size.\n num_fractional_normal_digits: Integer;\n\n // Number of fractional digits to render always, if needed by\n // padding with zeros.\n num_fractional_trailing_zero_digits: Integer;\n\n // map of powers of 10 to alternative currency names / symbols, must\n // always have an entry under \"0\" that defines the base name,\n // e.g. \"0 => \u20AC\" or \"3 => k\u20AC\". For BTC, would be \"0 => BTC, -3 => mBTC\".\n // Communicates the currency symbol to be used.\n alt_unit_names: { [log10: string]: string };\n\n common_amounts?: AmountString[];\n}\n\nexport interface InternationalizedString {\n [lang_tag: string]: string;\n}\n\nexport type RsaPublicKeyString = string;\nexport type AgeMask = number;\n\n// The string must be a data URL according to RFC 2397\n// with explicit mediatype and base64 parameters.\n//\n// data:;base64,\n//\n// Supported mediatypes are image/jpeg and image/png.\n// Invalid strings will be rejected by the wallet.\nexport type ImageDataUrl = string;\n\n/**\n * 32-byte value representing a point on Curve25519.\n */\nexport type Cs25519Point = string;\n\nexport type LitAmountString = `${string}:${number}`;\n\nexport type LibtoolVersionString = string;\n\nexport type DecimalNumber = string;\n\ndeclare const __amount_str: unique symbol;\nexport type AmountString =\n | (string & { [__amount_str]: true })\n | LitAmountString;\n// export type AmountString = string;\nexport type Base32String = string;\ndeclare const __eddsasign_str: unique symbol;\nexport type EddsaSignatureString = string; // & { [__eddsasign_str]: true };\ndeclare const __eddsapub_str: unique symbol;\nexport type EddsaPublicKeyString = string; // & { [__eddsapub_str]: true };\ndeclare const __eddsapriv_str: unique symbol;\nexport type EddsaPrivateKeyString = string; // & { [__eddsapriv_str]: true };\nexport type CoinPublicKeyString = string;\n\n// FIXME: implement this codec\nexport const codecForURLString = codecForString;\n// FIXME: implement this codec\nexport const codecForLibtoolVersion = codecForString;\n// FIXME: implement this codec\nexport const codecForCurrencyName = codecForString;\n// FIXME: implement this codec\nexport const codecForDecimalNumber = codecForString;\n// FIXME: implement this codec\nexport const codecForEddsaPublicKey =\n codecForString as () => Codec;\n// FIXME: implement this codec\nexport const codecForEddsaPrivateKey =\n codecForString as () => Codec;\n// FIXME: implement this codec\nexport const codecForEddsaSignature =\n codecForString as () => Codec;\n\nexport const codecForInternationalizedString =\n (): Codec => codecForMap(codecForString());\n\nexport const codecForCurrencySpecificiation =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"num_fractional_input_digits\", codecForNumber())\n .property(\"num_fractional_normal_digits\", codecForNumber())\n .property(\"num_fractional_trailing_zero_digits\", codecForNumber())\n .property(\"alt_unit_names\", codecForMap(codecForString()))\n .property(\n \"common_amounts\",\n codecOptional(codecForList(codecForAmountString())),\n )\n .deprecatedProperty(\"currency\")\n .build(\"CurrencySpecification\");\n\nexport interface TalerCommonConfigResponse {\n name: string;\n version: string;\n}\n\nexport const codecForTalerCommonConfigResponse =\n (): Codec =>\n buildCodecForObject()\n .allowExtra()\n .property(\"name\", codecForString())\n .property(\"version\", codecForString())\n .build(\"TalerCommonConfigResponse\");\n\nexport enum ExchangeProtocolVersion {\n /**\n * Current version supported by the wallet.\n */\n V12 = 12,\n}\n\nexport enum MerchantProtocolVersion {\n /**\n * Current version supported by the wallet.\n */\n V3 = 3,\n}\n\nexport type HashCodeString = string;\n\nexport type WireSalt = string;\n\nexport type Integer = number;\n\nexport interface BankConversionInfoConfig {\n // libtool-style representation of the Bank protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Name of the API.\n name: \"taler-conversion-info\";\n\n regional_currency: string;\n\n fiat_currency: string;\n\n // Currency used by this bank.\n regional_currency_specification: CurrencySpecification;\n\n // External currency used during conversion.\n fiat_currency_specification: CurrencySpecification;\n}\n\nexport const codecForBankConversionInfoConfig =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForConstString(\"taler-conversion-info\"))\n .property(\"version\", codecForString())\n .property(\"fiat_currency\", codecForString())\n .property(\"regional_currency\", codecForString())\n .property(\"fiat_currency_specification\", codecForCurrencySpecificiation())\n .property(\n \"regional_currency_specification\",\n codecForCurrencySpecificiation(),\n )\n .build(\"BankConversionInfoConfig\");\n\nexport interface DenominationExpiredMessage {\n // Taler error code. Note that beyond\n // expiration this message format is also\n // used if the key is not yet valid, or\n // has been revoked.\n code: number;\n\n // Signature by the exchange over a\n // TALER_DenominationExpiredAffirmationPS.\n // Must have purpose TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED.\n exchange_sig: EddsaSignatureString;\n\n // Public key of the exchange used to create\n // the 'exchange_sig.\n exchange_pub: EddsaPublicKeyString;\n\n // Hash of the denomination public key that is unknown.\n h_denom_pub: HashCodeString;\n\n // When was the signature created.\n timestamp: TalerProtocolTimestamp;\n\n // What kind of operation was requested that now\n // failed?\n oper: string;\n}\n\nexport const codecForDenominationExpiredMessage = () =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .property(\"h_denom_pub\", codecForString())\n .property(\"timestamp\", codecForTimestamp)\n .property(\"oper\", codecForString())\n .build(\"DenominationExpiredMessage\");\n\nexport interface CoinHistoryResponse {\n // Current balance of the coin.\n balance: AmountString;\n\n // Hash of the coin's denomination.\n h_denom_pub: HashCodeString;\n\n // Transaction history for the coin.\n history: any[];\n}\n\nexport const codecForCoinHistoryResponse = () =>\n buildCodecForObject()\n .property(\"balance\", codecForAmountString())\n .property(\"h_denom_pub\", codecForString())\n .property(\"history\", codecForAny())\n .build(\"CoinHistoryResponse\");\n\nexport type BankTokenScope =\n | \"readonly\"\n | \"readwrite\"\n | \"revenue\"\n | \"wiregateway\";\nexport interface TokenRequest {\n // Service-defined scope for the token.\n // Typical scopes would be \"readonly\" or \"readwrite\".\n scope: BankTokenScope;\n\n // Server may impose its own upper bound\n // on the token validity duration\n duration?: RelativeTime;\n\n // Is the token refreshable into a new token during its\n // validity?\n // Refreshable tokens effectively provide indefinite\n // access if they are refreshed in time.\n refreshable?: boolean;\n}\n\nexport interface TokenSuccessResponse {\n // Expiration determined by the server.\n // Can be based on the token_duration\n // from the request, but ultimately the\n // server decides the expiration.\n expiration: Timestamp;\n\n // Opque access token.\n access_token: AccessToken;\n}\n\nexport interface TokenInfos {\n tokens: TokenInfo[];\n}\n\nexport interface TokenInfo {\n // Time when the token was created.\n creation_time: Timestamp;\n\n // Time when the token expires.\n expiration: Timestamp;\n\n // Scope for the token.\n scope: string;\n\n // Is the token refreshable into a new token during its\n // validity?\n // Refreshable tokens effectively provide indefinite\n // access if they are refreshed in time.\n refreshable: boolean;\n\n // Optional token description\n description?: string;\n\n // Opaque unique ID used for pagination.\n serial: Integer;\n}\n\nexport const codecForTokenInfo = (): Codec =>\n buildCodecForObject()\n .property(\"creation_time\", codecForTimestamp)\n .property(\"expiration\", codecForTimestamp)\n .property(\"scope\", codecForString())\n .property(\"refreshable\", codecForBoolean())\n .property(\"description\", codecOptional(codecForString()))\n .property(\"serial\", codecForNumber())\n .build(\"TokenInfo\");\n\nexport const codecForTokenInfoList = (): Codec =>\n buildCodecForObject()\n .property(\"tokens\", codecForList(codecForTokenInfo()))\n .build(\"TokenInfoList\");\n\n//FIXME: implement this codec\nexport const codecForAccessToken = codecForString as () => Codec;\nexport const codecForTokenSuccessResponse = (): Codec =>\n buildCodecForObject()\n .property(\"access_token\", codecForAccessToken())\n .property(\"expiration\", codecForTimestamp)\n .build(\"TalerAuthentication.TokenSuccessResponse\");\n\n// FIXME: implement this codec\nexport const codecForURN = codecForString;\n\ndeclare const __ac_token: unique symbol;\n\n/**\n * Use `createAccessToken(string)` function to build one.\n */\nexport type AccessToken = string & {\n [__ac_token]: true;\n};\n\n/**\n * Create a rfc8959 access token.\n * Adds secret-token: prefix if there is none.\n * Encode the token with rfc7230 to send in a http header.\n *\n * @param token\n * @returns\n */\nexport function createRFC8959AccessTokenEncoded(token: string): AccessToken {\n return (\n token.startsWith(\"secret-token:\")\n ? token\n : `secret-token:${encodeURIComponent(token)}`\n ) as AccessToken;\n}\n\n/**\n * Create a rfc8959 access token.\n * Adds secret-token: prefix if there is none.\n *\n * @param token\n * @returns\n */\nexport function createRFC8959AccessTokenPlain(token: string): AccessToken {\n return (\n token.startsWith(\"secret-token:\") ? token : `secret-token:${token}`\n ) as AccessToken;\n}\n\n/**\n * Convert string to access token.\n *\n * @param clientSecret\n * @returns\n */\nexport function createClientSecretAccessToken(\n clientSecret: string,\n): AccessToken {\n return clientSecret as AccessToken;\n}\n\nexport type UserAndPassword = {\n username: string;\n password: string;\n};\n\nexport type UserAndToken = {\n username: string;\n token: AccessToken;\n};\n\ndeclare const opaque_OfficerAccount: unique symbol;\n/**\n * Sealed private key for AML officer\n */\nexport type LockedAccount = string & { [opaque_OfficerAccount]: true };\n\ndeclare const opaque_OfficerId: unique symbol;\n/**\n * Public key for AML officer\n */\nexport type OfficerId = string & { [opaque_OfficerId]: true };\n\ndeclare const opaque_OfficerSigningKey: unique symbol;\n\nexport interface OfficerSession {\n id: OfficerId;\n signingKey: EddsaPrivP;\n}\n\nexport interface ReserveAccount {\n id: EddsaPublicKeyString;\n signingKey: EddsaPrivP;\n}\n\nexport type PaginationParams = {\n /**\n * row identifier as the starting point of the query\n */\n offset?: string;\n /**\n * max number of element in the result response\n * always greater than 0\n */\n limit?: number;\n /**\n * order\n */\n order?: \"asc\" | \"dec\";\n};\n\nexport type LongPollParams = {\n /**\n * milliseconds the server should wait for at least one result to be shown\n */\n timeoutMs?: number;\n ct?: CancellationToken;\n};\n\nexport interface LoginToken {\n token: AccessToken;\n expiration: Timestamp;\n}\n", "/*\n This file is part of GNU Taler\n (C) 2023-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Imports.\n */\nimport { Codec } from \"./codec.js\";\nimport { TalerError } from \"./errors.js\";\nimport {\n HttpResponse,\n readResponseJsonOrThrow,\n readSuccessResponseJsonOrThrow,\n readTalerErrorResponse,\n} from \"./http-common.js\";\nimport { HttpStatusCode } from \"./http-status-codes.js\";\nimport { LibtoolVersion } from \"./libtool-version.js\";\nimport { TalerErrorCode } from \"./taler-error-codes.js\";\nimport { codecForTalerCommonConfigResponse } from \"./types-taler-common.js\";\nimport { TalerErrorDetail } from \"./types-taler-wallet.js\";\n\nexport type OperationResult =\n | OperationOk\n | OperationAlternative\n | OperationFail;\n\nexport function isOperationOk(\n c: OperationResult,\n): c is OperationOk {\n return c.type === \"ok\";\n}\n\nexport function isOperationFail(\n c: OperationResult,\n): c is OperationFail {\n return c.type === \"fail\";\n}\n\n/**\n * successful operation\n */\nexport interface OperationOk {\n type: \"ok\";\n\n case: \"ok\";\n\n /**\n * Parsed response body.\n */\n body: BodyT;\n}\n\n/**\n * unsuccessful operation, see details\n */\nexport interface OperationFail {\n type: \"fail\";\n\n /**\n * Error case (either HTTP status code or TalerErrorCode)\n */\n case: T;\n\n detail?: TalerErrorDetail;\n}\n\n/**\n * unsuccessful operation, see body\n */\nexport interface OperationAlternative {\n type: \"fail\";\n\n /**\n * Either a HTTP status code or Taler error code to distinguish\n * the response type.\n */\n case: T;\n\n body: B;\n}\n\nexport async function opSuccessFromHttp(\n resp: HttpResponse,\n codec: Codec,\n): Promise> {\n const body = await readSuccessResponseJsonOrThrow(resp, codec);\n return { type: \"ok\" as const, case: \"ok\", body };\n}\n\n/**\n * Success case, but instead of the body we're returning a fixed response\n * to the client.\n */\nexport function opFixedSuccess(body: T): OperationOk {\n return { type: \"ok\" as const, case: \"ok\", body };\n}\n\nexport function opEmptySuccess(): OperationOk {\n return { type: \"ok\" as const, case: \"ok\", body: undefined };\n}\n\nexport function opKnownFailure(case_: T): OperationFail {\n return { type: \"fail\", case: case_ };\n}\n\nexport function opKnownFailureWithBody(\n case_: T,\n body: B,\n): OperationAlternative {\n return { type: \"fail\", case: case_, body };\n}\n\n/**\n * Before using the codec, try read minimum json body and\n * verify that component and version matches.\n *\n * @param expectedName\n * @param clientVersion\n * @param httpResponse\n * @param codec\n * @returns\n */\nexport async function carefullyParseConfig(\n expectedName: string,\n clientVersion: string,\n httpResponse: HttpResponse,\n codec: Codec,\n) {\n const minBody = await readSuccessResponseJsonOrThrow(\n httpResponse,\n codecForTalerCommonConfigResponse(),\n );\n if (minBody.name !== expectedName) {\n throw TalerError.fromUncheckedDetail({\n code: TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,\n requestUrl: httpResponse.requestUrl,\n httpStatusCode: httpResponse.status,\n detail: `Unexpected server component name (got ${minBody.name}, expected ${expectedName}})`,\n });\n }\n\n if (!LibtoolVersion.compare(clientVersion, minBody.version)) {\n throw TalerError.fromUncheckedDetail({\n code: TalerErrorCode.GENERIC_CLIENT_UNSUPPORTED_PROTOCOL_VERSION,\n requestUrl: httpResponse.requestUrl,\n httpStatusCode: httpResponse.status,\n detail: `Unsupported protocol version, client supports ${clientVersion}, server supports ${minBody.version}`,\n });\n }\n // Now that we've checked the basic body, re-parse the full response.\n const body = await readSuccessResponseJsonOrThrow(httpResponse, codec);\n return opFixedSuccess(body);\n}\n\n/**\n *\n * @param resp\n * @param s\n * @param codec\n * @returns\n */\nexport async function opKnownAlternativeHttpFailure<\n T extends HttpStatusCode,\n B,\n>(\n resp: HttpResponse,\n s: T,\n codec: Codec,\n): Promise> {\n const body = await readResponseJsonOrThrow(resp, codec);\n return { type: \"fail\", case: s, body };\n}\n\n/**\n * Constructor of a failure response of the API that is already documented in the spec.\n * The `case` parameter is a reason of the error.\n *\n * @param case\n * @param resp\n * @returns\n */\nexport async function opKnownHttpFailure(\n _case: T,\n resp: HttpResponse,\n detail?: TalerErrorDetail,\n): Promise> {\n if (!detail) {\n detail = await readTalerErrorResponse(resp);\n }\n return { type: \"fail\", case: _case, detail };\n}\n\n/**\n * Constructor of an unexpected error, usually when the response of the API\n * is not in the spec.\n *\n * If the response hasn't already been read, this function will add the information\n * as detail\n *\n * @param resp\n * @param detail\n */\nexport async function opUnknownHttpFailure(\n resp: HttpResponse,\n detail?: TalerErrorDetail,\n): Promise {\n if (!detail) {\n detail = await readTalerErrorResponse(resp);\n }\n throw TalerError.fromDetail(\n TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,\n {\n requestUrl: resp.requestUrl,\n requestMethod: resp.requestMethod,\n httpStatusCode: resp.status,\n errorResponse: detail,\n },\n `Unexpected HTTP status ${resp.status} in response`,\n );\n}\n\n/**\n * Constructor of a failure response of the API that is already documented in the spec.\n * The `case` parameter is a reason of the error.\n *\n * @param case\n * @param resp\n * @returns\n */\nexport function opKnownTalerFailure(\n _case: T,\n detail: TalerErrorDetail,\n): OperationFail {\n return { type: \"fail\", case: _case, detail };\n}\n\nexport function opUnknownFailure(error: unknown): never {\n throw TalerError.fromException(error);\n}\n\n/**\n * The operation result should be ok\n * Return the body of the result\n *\n * @param resp\n * @returns\n */\nexport function succeedOrThrow(resp: OperationResult): R {\n if (isOperationOk(resp)) {\n return resp.body;\n }\n\n if (isOperationFail(resp)) {\n throw TalerError.fromUncheckedDetail({ ...resp, case: resp.case } as any);\n }\n throw TalerError.fromException(resp);\n}\n\n/**\n * The operation is expected to fail.\n * Return the error details.\n * Throw if the operation didn't fail with expected code.\n *\n * @param resp\n * @param s\n * @returns\n */\nexport function failOrThrow(\n resp: OperationResult,\n s: E,\n): TalerErrorDetail | undefined {\n if (isOperationOk(resp)) {\n throw TalerError.fromException(\n new Error(`request succeed but failure \"${s}\" was expected`),\n );\n }\n if (isOperationFail(resp) && resp.case === s) {\n return resp.detail;\n }\n throw TalerError.fromException(\n new Error(\n `request failed with \"${JSON.stringify(\n resp,\n )}\" but case \"${s}\" was expected`,\n ),\n );\n}\n\n/**\n * The operation is expected to fail with a body.\n * Return the body of the result.\n * Throw if the operation didn't fail with expected code.\n *\n * @param resp\n * @param s\n * @returns\n */\nexport function alternativeOrThrow(\n resp:\n | OperationOk\n | OperationAlternative\n | OperationFail,\n s: Error,\n): Alt {\n if (isOperationOk(resp)) {\n throw TalerError.fromException(\n new Error(`request succeed but failure \"${s}\" was expected`),\n );\n }\n if (isOperationFail(resp) && resp.case !== s) {\n throw TalerError.fromException(\n new Error(\n `request failed with \"${JSON.stringify(\n resp,\n )}\" but case \"${s}\" was expected`,\n ),\n );\n }\n return (resp as any).body;\n}\n\nexport type ResultByMethod<\n TT extends object,\n p extends keyof TT,\n> = TT[p] extends (...args: any[]) => infer Ret\n ? Ret extends Promise\n ? Result extends OperationResult\n ? Result\n : never\n : never //api always use Promises\n : never; //error cases just for functions\n\nexport type FailCasesByMethod = Exclude<\n ResultByMethod,\n OperationOk\n>;\n", "/*\n This file is part of GNU Taler\n (C) 2019 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Types and helper functions for dealing with Taler amounts.\n */\n\n/**\n * Imports.\n */\nimport {\n Codec,\n Context,\n DecodingError,\n buildCodecForObject,\n codecForNumber,\n codecForString,\n renderContext,\n} from \"./codec.js\";\nimport { opFixedSuccess, opKnownFailure } from \"./operation.js\";\nimport { AmountString, CurrencySpecification } from \"./types-taler-common.js\";\n\n/**\n * Number of fractional units that one value unit represents.\n */\nexport const amountFractionalBase = 1e8;\n\n/**\n * How many digits behind the comma are required to represent the\n * fractional value in human readable decimal format? Must match\n * lg(fractionalBase)\n */\nexport const amountFractionalLength = 8;\n\n/**\n * Maximum allowed value field of an amount.\n */\nexport const amountMaxValue = 2 ** 52;\n\n/**\n * Separator character between integer and fractional\n */\nexport const FRAC_SEPARATOR = \".\";\n\n/**\n * Separator character between integer and fractional\n */\nexport const CURRENCY_SEPARATOR = \":\";\n\n/**\n * Non-negative financial amount. Fractional values are expressed as multiples\n * of 1e-8.\n */\nexport interface AmountJson {\n /**\n * Value, must be an integer.\n */\n readonly value: number;\n\n /**\n * Fraction, must be an integer. Represent 1/1e8 of a unit.\n */\n readonly fraction: number;\n\n /**\n * Currency of the amount.\n */\n readonly currency: string;\n}\n\n/**\n * Immutable amount.\n */\nexport class Amount {\n static from(a: AmountLike): Amount {\n return new Amount(Amounts.parseOrThrow(a), 0);\n }\n\n static zeroOfCurrency(currency: string): Amount {\n return new Amount(Amounts.zeroOfCurrency(currency), 0);\n }\n\n add(...a: AmountLike[]): Amount {\n if (this.saturated) {\n return this;\n }\n const r = Amounts.add(this.val, ...a);\n return new Amount(r.amount, r.saturated ? 1 : 0);\n }\n\n isZero(): boolean {\n return this.val.fraction === 0 && this.val.value === 0;\n }\n\n sub(...a: AmountLike[]): Amount {\n if (this.saturated) {\n return this;\n }\n const r = Amounts.sub(this.val, ...a);\n return new Amount(r.amount, r.saturated ? 1 : 0);\n }\n\n mult(n: number): Amount {\n if (this.saturated) {\n return this;\n }\n const r = Amounts.mult(this, n);\n return new Amount(r.amount, r.saturated ? 1 : 0);\n }\n\n toJson(): AmountJson {\n return { ...this.val };\n }\n\n toString(): AmountString {\n return Amounts.stringify(this.val);\n }\n\n private constructor(\n private val: AmountJson,\n private saturated: number,\n ) {}\n}\n\nexport const codecForAmountJson = (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"value\", codecForNumber())\n .property(\"fraction\", codecForNumber())\n .build(\"AmountJson\");\n\nexport function codecForAmountString(): Codec {\n return {\n decode(x: any, c?: Context): AmountString {\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n if (Amounts.parse(x) === undefined) {\n throw new DecodingError(\n `invalid amount at ${renderContext(c)} got \"${x}\"`,\n );\n }\n return x as AmountString;\n },\n };\n}\n\n/**\n * Result of a possibly overflowing operation.\n */\nexport interface AmountResult {\n /**\n * Resulting, possibly saturated amount.\n */\n amount: AmountJson;\n /**\n * Was there an over-/underflow?\n */\n saturated: boolean;\n}\n\n/**\n * Type for things that are treated like amounts.\n */\nexport type AmountLike = string | AmountString | AmountJson | Amount;\n\nexport interface DivmodResult {\n quotient: number;\n remainder: AmountJson;\n}\n\nexport enum AmountParseError {\n /**\n * Should have a string separated with a colon\n */\n MISSING_CURRENCY,\n /**\n * Currency should be less than 11 characters\n */\n CURRENCY_TOO_LONG,\n /**\n * Currency should be only letter from a to z\n */\n BAD_CURRENCY,\n /**\n * Number can only be digits from 0 to 9\n */\n BAD_NUMBER,\n /**\n * Integer part should be less than 2 ** 52\n */\n TOO_HIGH,\n /**\n * Fractional part should be shorter than 8 digits\n */\n TOO_PRECISE,\n}\n\n/**\n * Helper class for dealing with amounts.\n */\nexport class Amounts {\n private constructor() {\n throw Error(\"not instantiable\");\n }\n\n static currencyOf(amount: AmountLike) {\n const amt = Amounts.parseOrThrow(amount);\n return amt.currency;\n }\n\n static zeroOfAmount(amount: AmountLike): AmountJson {\n const amt = Amounts.parseOrThrow(amount);\n return {\n currency: amt.currency,\n fraction: 0,\n value: 0,\n };\n }\n\n /**\n * Get an amount that represents zero units of a currency.\n */\n static zeroOfCurrency(currency: string): AmountJson {\n return {\n currency,\n fraction: 0,\n value: 0,\n };\n }\n\n static jsonifyAmount(amt: AmountLike): AmountJson {\n if (typeof amt === \"string\") {\n return Amounts.parseOrThrow(amt);\n }\n if (amt instanceof Amount) {\n return amt.toJson();\n }\n return amt;\n }\n\n static divmod(a1: AmountLike, a2: AmountLike): DivmodResult {\n const am1 = Amounts.jsonifyAmount(a1);\n const am2 = Amounts.jsonifyAmount(a2);\n if (am1.currency != am2.currency) {\n throw Error(`incompatible currency (${am1.currency} vs${am2.currency})`);\n }\n\n const x1 =\n BigInt(am1.value) * BigInt(amountFractionalBase) + BigInt(am1.fraction);\n const x2 =\n BigInt(am2.value) * BigInt(amountFractionalBase) + BigInt(am2.fraction);\n\n const quotient = x1 / x2;\n const remainderScaled = x1 % x2;\n\n return {\n quotient: Number(quotient),\n remainder: {\n currency: am1.currency,\n value: Number(remainderScaled / BigInt(amountFractionalBase)),\n fraction: Number(remainderScaled % BigInt(amountFractionalBase)),\n },\n };\n }\n\n static sum(amounts: AmountLike[]): AmountResult {\n if (amounts.length <= 0) {\n throw Error(\"can't sum zero amounts\");\n }\n const jsonAmounts = amounts.map((x) => Amounts.jsonifyAmount(x));\n return Amounts.add(jsonAmounts[0], ...jsonAmounts.slice(1));\n }\n\n static sumOrZero(currency: string, amounts: AmountLike[]): AmountResult {\n if (amounts.length <= 0) {\n return {\n amount: Amounts.zeroOfCurrency(currency),\n saturated: false,\n };\n }\n const jsonAmounts = amounts.map((x) => Amounts.jsonifyAmount(x));\n return Amounts.add(jsonAmounts[0], ...jsonAmounts.slice(1));\n }\n\n /**\n * Add two amounts. Return the result and whether\n * the addition overflowed. The overflow is always handled\n * by saturating and never by wrapping.\n *\n * Throws when currencies don't match.\n */\n static add(first: AmountLike, ...rest: AmountLike[]): AmountResult {\n const firstJ = Amounts.jsonifyAmount(first);\n const currency = firstJ.currency;\n let value =\n firstJ.value + Math.floor(firstJ.fraction / amountFractionalBase);\n if (value > amountMaxValue) {\n return {\n amount: {\n currency,\n value: amountMaxValue,\n fraction: amountFractionalBase - 1,\n },\n saturated: true,\n };\n }\n let fraction = firstJ.fraction % amountFractionalBase;\n for (const x of rest) {\n const xJ = Amounts.jsonifyAmount(x);\n if (xJ.currency.toUpperCase() !== currency.toUpperCase()) {\n throw Error(`Mismatched currency: ${xJ.currency} and ${currency}`);\n }\n\n value =\n value +\n xJ.value +\n Math.floor((fraction + xJ.fraction) / amountFractionalBase);\n fraction = Math.floor((fraction + xJ.fraction) % amountFractionalBase);\n if (value > amountMaxValue) {\n return {\n amount: {\n currency,\n value: amountMaxValue,\n fraction: amountFractionalBase - 1,\n },\n saturated: true,\n };\n }\n }\n return { amount: { currency, value, fraction }, saturated: false };\n }\n\n /**\n * Subtract two amounts. Return the result and whether\n * the subtraction overflowed. The overflow is always handled\n * by saturating and never by wrapping.\n *\n * Throws when currencies don't match.\n */\n static sub(a: AmountLike, ...rest: AmountLike[]): AmountResult {\n const aJ = Amounts.jsonifyAmount(a);\n const currency = aJ.currency;\n let value = aJ.value;\n let fraction = aJ.fraction;\n\n for (const b of rest) {\n const bJ = Amounts.jsonifyAmount(b);\n if (bJ.currency.toUpperCase() !== aJ.currency.toUpperCase()) {\n throw Error(`Mismatched currency: ${bJ.currency} and ${currency}`);\n }\n if (fraction < bJ.fraction) {\n if (value < 1) {\n return {\n amount: { currency, value: 0, fraction: 0 },\n saturated: true,\n };\n }\n value--;\n fraction += amountFractionalBase;\n }\n console.assert(fraction >= bJ.fraction);\n fraction -= bJ.fraction;\n if (value < bJ.value) {\n return { amount: { currency, value: 0, fraction: 0 }, saturated: true };\n }\n value -= bJ.value;\n }\n\n return { amount: { currency, value, fraction }, saturated: false };\n }\n\n /**\n * Compare two amounts. Returns 0 when equal, -1 when a < b\n * and +1 when a > b. Throws when currencies don't match.\n */\n static cmp(a: AmountLike, b: AmountLike): -1 | 0 | 1 {\n a = Amounts.jsonifyAmount(a);\n b = Amounts.jsonifyAmount(b);\n if (a.currency !== b.currency) {\n throw Error(`Mismatched currency: ${a.currency} and ${b.currency}`);\n }\n const av = a.value + Math.floor(a.fraction / amountFractionalBase);\n const af = a.fraction % amountFractionalBase;\n const bv = b.value + Math.floor(b.fraction / amountFractionalBase);\n const bf = b.fraction % amountFractionalBase;\n switch (true) {\n case av < bv:\n return -1;\n case av > bv:\n return 1;\n case af < bf:\n return -1;\n case af > bf:\n return 1;\n case af === bf:\n return 0;\n default:\n throw Error(\"assertion failed\");\n }\n }\n\n /**\n * Create a copy of an amount.\n */\n static copy(a: AmountJson): AmountJson {\n return {\n currency: a.currency,\n fraction: a.fraction,\n value: a.value,\n };\n }\n\n /**\n * Divide an amount. Throws on division by zero.\n */\n static divide(a: AmountJson, n: number): AmountJson {\n if (n === 0) {\n throw Error(`Division by 0`);\n }\n if (n === 1) {\n return { value: a.value, fraction: a.fraction, currency: a.currency };\n }\n const r = a.value % n;\n return {\n currency: a.currency,\n fraction: Math.floor((r * amountFractionalBase + a.fraction) / n),\n value: Math.floor(a.value / n),\n };\n }\n\n /**\n * Check if an amount is non-zero.\n */\n static isNonZero(a: AmountLike): boolean {\n a = Amounts.jsonifyAmount(a);\n return a.value > 0 || a.fraction > 0;\n }\n\n static isZero(a: AmountLike): boolean {\n a = Amounts.jsonifyAmount(a);\n return a.value === 0 && a.fraction === 0;\n }\n\n /**\n * Check whether a string is a valid currency for a Taler amount.\n */\n static isCurrency(s: string): boolean {\n return /^[a-zA-Z]{1,11}$/.test(s);\n }\n\n /**\n * Parse an amount like 'EUR:20.5' for 20 Euros and 50 ct.\n *\n * Currency name size limit is 11 of ASCII letters\n * Fraction size limit is 8\n */\n static parseWithError(s: string) {\n const c_idx = s.indexOf(CURRENCY_SEPARATOR);\n\n if (c_idx === -1 || c_idx === 0) {\n return opKnownFailure(AmountParseError.MISSING_CURRENCY);\n }\n if (c_idx > 11) {\n return opKnownFailure(AmountParseError.MISSING_CURRENCY);\n }\n const currency = s.substring(0, c_idx).toUpperCase();\n if (!/^[a-zA-Z]+$/.test(currency)) {\n return opKnownFailure(AmountParseError.BAD_CURRENCY);\n }\n const number = s.substring(c_idx + 1);\n const d_idx = number.indexOf(FRAC_SEPARATOR);\n const integerStr = d_idx === -1 ? number : number.substring(0, d_idx);\n const fractStr =\n d_idx === -1 || d_idx === number.length\n ? \"0\"\n : number.substring(d_idx + 1);\n\n if (!/^[0-9]+$/.test(integerStr) || !/^[0-9]+$/.test(fractStr)) {\n return opKnownFailure(AmountParseError.BAD_NUMBER);\n }\n\n const value = Number.parseInt(integerStr, 10);\n const fraction = Math.round(\n amountFractionalBase * Number.parseFloat(FRAC_SEPARATOR + fractStr),\n );\n if (!Number.isInteger(value) || !Number.isInteger(fraction)) {\n return opKnownFailure(AmountParseError.BAD_NUMBER);\n }\n if (value > amountMaxValue) {\n return opKnownFailure(AmountParseError.TOO_HIGH);\n }\n if (fractStr.length > amountFractionalLength) {\n return opKnownFailure(AmountParseError.TOO_PRECISE);\n }\n return opFixedSuccess({\n currency,\n fraction,\n value,\n });\n }\n\n /**\n * Parse an amount like 'EUR:20.5' for 20 Euros and 50 ct.\n *\n * Currency name size limit is 11 of ASCII letters\n * Fraction size limit is 8\n */\n static parse(s: string): AmountJson | undefined {\n const res = s.match(/^([a-zA-Z]{1,11}):([0-9]+)([.][0-9]{1,8})?$/);\n if (!res) {\n return undefined;\n }\n const tail = res[3] || FRAC_SEPARATOR + \"0\";\n if (tail.length > amountFractionalLength + 1) {\n return undefined;\n }\n const value = Number.parseInt(res[2]);\n if (value > amountMaxValue) {\n return undefined;\n }\n return {\n currency: res[1].toUpperCase(),\n fraction: Math.round(amountFractionalBase * Number.parseFloat(tail)),\n value,\n };\n }\n\n /**\n * Parse amount in standard string form (like 'EUR:20.5'),\n * throw if the input is not a valid amount.\n */\n static parseOrThrow(s: AmountLike): AmountJson {\n if (s instanceof Amount) {\n return s.toJson();\n }\n if (typeof s === \"object\") {\n if (typeof s.currency !== \"string\") {\n throw Error(\"invalid amount object\");\n }\n if (typeof s.value !== \"number\") {\n throw Error(\"invalid amount object\");\n }\n if (typeof s.fraction !== \"number\") {\n throw Error(\"invalid amount object\");\n }\n return { currency: s.currency, value: s.value, fraction: s.fraction };\n } else if (typeof s === \"string\") {\n const res = Amounts.parse(s);\n if (!res) {\n throw Error(`Can't parse amount: \"${s}\"`);\n }\n return res;\n } else {\n throw Error(\"invalid amount (illegal type)\");\n }\n }\n\n static min(a: AmountLike, b: AmountLike): AmountJson {\n const cr = Amounts.cmp(a, b);\n if (cr >= 0) {\n return Amounts.jsonifyAmount(b);\n } else {\n return Amounts.jsonifyAmount(a);\n }\n }\n\n static max(a: AmountLike, b: AmountLike): AmountJson {\n const cr = Amounts.cmp(a, b);\n if (cr >= 0) {\n return Amounts.jsonifyAmount(a);\n } else {\n return Amounts.jsonifyAmount(b);\n }\n }\n\n static mult(a: AmountLike, n: number): AmountResult {\n a = this.jsonifyAmount(a);\n if (!Number.isInteger(n)) {\n throw Error(\"amount can only be multiplied by an integer\");\n }\n if (n < 0) {\n throw Error(\"amount can only be multiplied by a positive integer\");\n }\n if (n == 0) {\n return {\n amount: Amounts.zeroOfCurrency(a.currency),\n saturated: false,\n };\n }\n let x = a;\n let acc = Amounts.zeroOfCurrency(a.currency);\n while (n > 1) {\n if (n % 2 == 0) {\n n = n / 2;\n } else {\n n = (n - 1) / 2;\n const r2 = Amounts.add(acc, x);\n if (r2.saturated) {\n return r2;\n }\n acc = r2.amount;\n }\n const r2 = Amounts.add(x, x);\n if (r2.saturated) {\n return r2;\n }\n x = r2.amount;\n }\n return Amounts.add(acc, x);\n }\n\n /**\n * Check if the argument is a valid amount in string form.\n */\n static check(a: any): boolean {\n if (typeof a !== \"string\") {\n return false;\n }\n try {\n const parsedAmount = Amounts.parse(a);\n return !!parsedAmount;\n } catch {\n return false;\n }\n }\n\n /**\n * Convert to standard human-readable string representation that's\n * also used in JSON formats.\n */\n static stringify(a: AmountLike): AmountString {\n a = Amounts.jsonifyAmount(a);\n const s = this.stringifyValue(a);\n\n return `${a.currency}:${s}` as AmountString;\n }\n\n /**\n * Show an amount in a form suitable for the user.\n * FIXME: In the future, this should consider currency-specific\n * settings such as significant digits or currency symbols.\n */\n static toPretty(amount: AmountJson): string {\n const x = amount.value + amount.fraction / amountFractionalBase;\n return `${x} ${amount.currency}`;\n }\n\n static amountHasSameCurrency(a1: AmountLike, a2: AmountLike): boolean {\n const x1 = this.jsonifyAmount(a1);\n const x2 = this.jsonifyAmount(a2);\n return x1.currency.toUpperCase() === x2.currency.toUpperCase();\n }\n\n static isSameCurrency(curr1: string, curr2: string): boolean {\n return curr1.toLowerCase() === curr2.toLowerCase();\n }\n\n static stringifyValue(a: AmountLike, minFractional = 0): string {\n const aJ = Amounts.jsonifyAmount(a);\n const av = aJ.value + Math.floor(aJ.fraction / amountFractionalBase);\n const af = aJ.fraction % amountFractionalBase;\n let s = av.toString();\n\n if (af || minFractional) {\n s = s + FRAC_SEPARATOR;\n let n = af;\n for (let i = 0; i < amountFractionalLength; i++) {\n if (!n && i >= minFractional) {\n break;\n }\n s = s + Math.floor((n / amountFractionalBase) * 10).toString();\n n = (n * 10) % amountFractionalBase;\n }\n }\n\n return s;\n }\n\n /**\n * Number of fractional digits needed to fully represent the amount\n * @param a amount\n * @returns\n */\n static maxFractionalDigits(a: AmountJson): number {\n if (a.fraction === 0) return 0;\n if (a.fraction < 0) {\n console.error(\"amount fraction can not be negative\", a);\n return 0;\n }\n let i = 0;\n let check = true;\n let rest = a.fraction;\n while (rest > 0 && check) {\n check = rest % 10 === 0;\n rest = rest / 10;\n i++;\n }\n return amountFractionalLength - i + 1;\n }\n\n static stringifyValueWithSpec(\n value: AmountJson,\n spec: CurrencySpecification,\n ): { currency: string; normal: string; small?: string } {\n const strValue = Amounts.stringifyValue(value);\n const pos = strValue.indexOf(FRAC_SEPARATOR);\n const originalPosition = pos < 0 ? strValue.length : pos;\n\n let currency = value.currency;\n const names = Object.keys(spec.alt_unit_names);\n let FRAC_POS_NEW_POSITION = originalPosition;\n //find symbol\n //FIXME: this should be based on a cache to speed up\n if (names.length > 0) {\n let unitIndex: string = \"0\"; //default entry by DD51\n names.forEach((index) => {\n const i = Number.parseInt(index, 10);\n if (Number.isNaN(i)) return; //skip\n if (originalPosition - i <= 0) return; //too big\n if (originalPosition - i < FRAC_POS_NEW_POSITION) {\n FRAC_POS_NEW_POSITION = originalPosition - i;\n unitIndex = index;\n }\n });\n currency = spec.alt_unit_names[unitIndex];\n }\n\n if (originalPosition === FRAC_POS_NEW_POSITION) {\n const { normal, small } = splitNormalAndSmall(\n strValue,\n originalPosition,\n spec,\n );\n return { currency, normal, small };\n }\n\n const intPart = strValue.substring(0, originalPosition);\n const fracPArt = strValue.substring(originalPosition + 1);\n //indexSize is always smaller than originalPosition\n const newValue =\n intPart.substring(0, FRAC_POS_NEW_POSITION) +\n FRAC_SEPARATOR +\n intPart.substring(FRAC_POS_NEW_POSITION) +\n fracPArt;\n const { normal, small } = splitNormalAndSmall(\n newValue,\n FRAC_POS_NEW_POSITION,\n spec,\n );\n return { currency, normal, small };\n }\n}\n\nfunction splitNormalAndSmall(\n decimal: string,\n fracSeparatorIndex: number,\n spec: CurrencySpecification,\n): { normal: string; small?: string } {\n let normal: string;\n let small: string | undefined;\n if (\n decimal.length - fracSeparatorIndex - 1 >\n spec.num_fractional_normal_digits\n ) {\n const limit = fracSeparatorIndex + spec.num_fractional_normal_digits + 1;\n normal = decimal.substring(0, limit);\n small = decimal.substring(limit);\n } else {\n normal = decimal;\n small = undefined;\n }\n return { normal, small };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL3.0-or-later\n*/\n\n/**\n * Imports.\n */\nimport {\n HttpRequestLibrary,\n HttpRequestOptions,\n HttpResponse,\n} from \"./http.js\";\n\n/**\n * Implementation of the HTTP request library interface for node.\n */\nexport class HttpLibImpl implements HttpRequestLibrary {\n fetch(\n url: string,\n opt?: HttpRequestOptions | undefined,\n ): Promise {\n throw new Error(\"Method not implemented.\");\n }\n}\n", "/*\n This file is part of TALER\n (C) 2016 GNUnet e.V.\n\n TALER is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n TALER is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n TALER; see the file COPYING. If not, see \n */\n\n/**\n * Helpers for doing XMLHttpRequest-s that are based on ES6 promises.\n * Allows for easy mocking for test cases.\n *\n * The API is inspired by the HTML5 fetch API.\n */\n\n/**\n * Imports\n */\n\nimport * as impl from \"#http-impl\";\nimport * as common from \"./http-common.js\";\n\nexport * from \"./http-common.js\";\n\nexport function createPlatformHttpLib(\n args?: common.HttpLibArgs,\n): common.HttpRequestLibrary {\n return new impl.HttpLibImpl(args);\n}\n", "// Converts an ArrayBuffer directly to base64, without any intermediate 'convert to string then\n// use window.btoa' step. According to my tests, this appears to be a faster approach:\n// http://jsperf.com/encoding-xhr-image-data/5\n\n/*\nMIT LICENSE\nCopyright 2011 Jon Leighton\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n\nexport function base64FromArrayBuffer(\n arrayBuffer: ArrayBuffer | ArrayBufferView,\n): string {\n var base64 = \"\";\n var encodings =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n let bytes: Uint8Array;\n if (ArrayBuffer.isView(arrayBuffer)) {\n bytes = new Uint8Array(\n arrayBuffer.buffer,\n arrayBuffer.byteOffset,\n arrayBuffer.byteLength,\n );\n } else {\n bytes = new Uint8Array(arrayBuffer);\n }\n var byteLength = bytes.byteLength;\n var byteRemainder = byteLength % 3;\n var mainLength = byteLength - byteRemainder;\n\n var a, b, c, d;\n var chunk;\n\n // Main loop deals with bytes in chunks of 3\n for (var i = 0; i < mainLength; i = i + 3) {\n // Combine the three bytes into a single integer\n chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];\n\n // Use bitmasks to extract 6-bit segments from the triplet\n a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18\n b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12\n c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6\n d = chunk & 63; // 63 = 2^6 - 1\n\n // Convert the raw binary segments to the appropriate ASCII encoding\n base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];\n }\n\n // Deal with the remaining bytes and padding\n if (byteRemainder == 1) {\n chunk = bytes[mainLength];\n\n a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2\n\n // Set the 4 least significant bits to zero\n b = (chunk & 3) << 4; // 3 = 2^2 - 1\n\n base64 += encodings[a] + encodings[b] + \"==\";\n } else if (byteRemainder == 2) {\n chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];\n\n a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10\n b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4\n\n // Set the 2 least significant bits to zero\n c = (chunk & 15) << 2; // 15 = 2^4 - 1\n\n base64 += encodings[a] + encodings[b] + encodings[c] + \"=\";\n }\n\n return base64;\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019 GNUnet e.V.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Native implementation of GNU Taler crypto primitives.\n */\n\n/**\n * Imports.\n */\nimport bigint from \"big-integer\";\nimport * as fflate from \"fflate\";\nimport { AmountLike, Amounts } from \"./amounts.js\";\nimport * as argon2 from \"./argon2.js\";\nimport { canonicalJson } from \"./helpers.js\";\nimport { hmacSha256, hmacSha512 } from \"./kdf.js\";\nimport { Logger } from \"./logging.js\";\nimport * as nacl from \"./nacl-fast.js\";\nimport { secretbox } from \"./nacl-fast.js\";\nimport { TalerSignaturePurpose } from \"./taler_signatures.js\";\nimport { TalerProtocolDuration, TalerProtocolTimestamp } from \"./time.js\";\nimport { CoinPublicKeyString, HashCodeString } from \"./types-taler-common.js\";\nimport {\n CoinEnvelope,\n DenomKeyType,\n DenominationPubKey,\n} from \"./types-taler-exchange.js\";\nimport { TokenEnvelope, TokenIssuePublicKey } from \"./types-taler-merchant.js\";\nimport { PayWalletData } from \"./types-taler-wallet.js\";\n\nconst isEddsaPubP: unique symbol = Symbol(\"isEddsaPubP\");\ntype FlavorEddsaPubP = {\n readonly flavor?: typeof isEddsaPubP;\n readonly _size?: 32;\n};\n\nconst isEddsaPrivP: unique symbol = Symbol(\"isEddsaPrivP\");\ntype FlavorEddsaPrivP = {\n readonly flavor?: typeof isEddsaPrivP;\n readonly _size?: 32;\n};\n\nconst isEddsaSigP: unique symbol = Symbol(\"isEddsaSigP\");\ntype FlavorEddsaSigP = {\n readonly flavor?: typeof isEddsaSigP;\n readonly _size?: 64;\n};\n\nconst isEdx25519PublicKey: unique symbol = Symbol(\"isEdx25519PublicKey\");\ntype FlavorEdx25519PublicKey = {\n readonly flavor?: typeof isEdx25519PublicKey;\n readonly _size?: 32;\n};\n\nconst isEdx25519PrivateKey: unique symbol = Symbol(\"isEdx25519PrivateKey\");\ntype FlavorEdx25519PrivateKey = {\n readonly flavor?: typeof isEdx25519PrivateKey;\n readonly _size?: 64;\n};\n\nconst isEcdhePrivP: unique symbol = Symbol(\"isEcdhePrivP\");\ntype FlavorEcdhePrivP = {\n readonly flavor?: typeof isEcdhePrivP;\n readonly _size?: 32;\n};\n\nconst isEdx25519Signature: unique symbol = Symbol(\"isEdx25519Signature\");\ntype FlavorEdx25519Signature = {\n readonly flavor?: typeof isEdx25519Signature;\n readonly _size?: 64;\n};\n\nconst isEdx25519PublicKeyEnc: unique symbol = Symbol(\"isEdx25519PublicKeyEnc\");\ntype FlavorEdx25519PublicKeyEnc = {\n readonly [isEdx25519PublicKeyEnc]?: true;\n};\n\nconst isEdx25519PrivateKeyEnc: unique symbol = Symbol(\n \"isEdx25519PrivateKeyEnc\",\n);\ntype FlavorEdx25519PrivateKeyEnc = {\n readonly [isEdx25519PrivateKeyEnc]?: true;\n};\n\nconst isEncryptionNonce: unique symbol = Symbol(\"isEncryptionNone\");\ntype FlavorEncryptionNonceP = {\n readonly flavor?: typeof isEncryptionNonce;\n};\n\ntype Sized = { readonly _size?: T };\n\nexport type EddsaPubP = Uint8Array & FlavorEddsaPubP;\nexport type EddsaPrivP = Uint8Array & FlavorEddsaPrivP;\nexport type EddsaSigP = Uint8Array & FlavorEddsaSigP;\n\nexport type EcdhePrivP = Uint8Array & FlavorEcdhePrivP;\n\nexport type OpaqueData = Uint8Array;\nexport type Edx25519PublicKey = Uint8Array & FlavorEdx25519PublicKey;\nexport type Edx25519PrivateKey = Uint8Array & FlavorEdx25519PrivateKey;\nexport type Edx25519Signature = Uint8Array & FlavorEdx25519Signature;\n\nexport type Edx25519PublicKeyEnc = string & FlavorEdx25519PublicKeyEnc;\nexport type Edx25519PrivateKeyEnc = string & FlavorEdx25519PrivateKeyEnc;\n\nexport type EncryptionNonceP = Uint8Array & FlavorEncryptionNonceP;\n\nexport type PursePublicKey = EddsaPubP;\n\nexport type ContractPrivateKey = EcdhePrivP;\nexport type MergePrivateKeyP = Uint8Array & EddsaPrivP;\n\nexport function getRandomBytes(n: N): Uint8Array & Sized {\n return nacl.randomBytes(n);\n}\n\nexport const useNative = true;\n\n/**\n * Interface of the native Taler runtime library.\n */\ninterface NativeTartLib {\n decodeUtf8(buf: Uint8Array): string;\n decodeUtf8(str: string): Uint8Array;\n randomBytes(n: number): Uint8Array;\n encodeCrock(buf: Uint8Array | ArrayBuffer): string;\n decodeCrock(str: string): Uint8Array;\n hash(buf: Uint8Array): Uint8Array;\n hashArgon2id(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n memorySize: number,\n hashLength: number,\n ): Uint8Array;\n eddsaGetPublic(buf: Uint8Array): Uint8Array;\n ecdheGetPublic(buf: Uint8Array): Uint8Array;\n eddsaSign(msg: Uint8Array, priv: Uint8Array): Uint8Array;\n eddsaVerify(msg: Uint8Array, sig: Uint8Array, pub: Uint8Array): boolean;\n kdf(\n outLen: number,\n ikm: Uint8Array,\n salt?: Uint8Array,\n info?: Uint8Array,\n ): Uint8Array;\n keyExchangeEcdhEddsa(ecdhPriv: Uint8Array, eddsaPub: Uint8Array): Uint8Array;\n keyExchangeEddsaEcdh(eddsaPriv: Uint8Array, ecdhPub: Uint8Array): Uint8Array;\n rsaBlind(hmsg: Uint8Array, bks: Uint8Array, rsaPub: Uint8Array): Uint8Array;\n rsaUnblind(\n blindSig: Uint8Array,\n rsaPub: Uint8Array,\n bks: Uint8Array,\n ): Uint8Array;\n rsaVerify(hmsg: Uint8Array, rsaSig: Uint8Array, rsaPub: Uint8Array): boolean;\n hashStateInit(): any;\n hashStateUpdate(st: any, data: Uint8Array): any;\n hashStateFinish(st: any): Uint8Array;\n}\n\n// @ts-ignore\nlet tart: NativeTartLib | undefined;\n\nif (useNative) {\n // @ts-ignore\n tart = globalThis._tart;\n}\n\nconst encTable = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nclass EncodingError extends Error {\n constructor() {\n super(\"Encoding error\");\n Object.setPrototypeOf(this, EncodingError.prototype);\n }\n}\n\nfunction getValue(chr: string): number {\n let a = chr;\n switch (chr) {\n case \"O\":\n case \"o\":\n a = \"0\";\n break;\n case \"i\":\n case \"I\":\n case \"l\":\n case \"L\":\n a = \"1\";\n break;\n case \"u\":\n case \"U\":\n a = \"V\";\n }\n\n if (a >= \"0\" && a <= \"9\") {\n return a.charCodeAt(0) - \"0\".charCodeAt(0);\n }\n\n if (a >= \"a\" && a <= \"z\") a = a.toUpperCase();\n let dec = 0;\n if (a >= \"A\" && a <= \"Z\") {\n if (\"I\" < a) dec++;\n if (\"L\" < a) dec++;\n if (\"O\" < a) dec++;\n if (\"U\" < a) dec++;\n return a.charCodeAt(0) - \"A\".charCodeAt(0) + 10 - dec;\n }\n throw new EncodingError();\n}\n\nexport function encodeCrock(data: ArrayBuffer | ArrayBufferView): string {\n let dataBytes: Uint8Array;\n if (ArrayBuffer.isView(data)) {\n dataBytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n } else {\n dataBytes = new Uint8Array(data);\n }\n if (tart) {\n return tart.encodeCrock(dataBytes);\n }\n let sb = \"\";\n const size = dataBytes.byteLength;\n let bitBuf = 0;\n let numBits = 0;\n let pos = 0;\n while (pos < size || numBits > 0) {\n if (pos < size && numBits < 5) {\n const d = dataBytes[pos++];\n bitBuf = (bitBuf << 8) | d;\n numBits += 8;\n }\n if (numBits < 5) {\n // zero-padding\n bitBuf = bitBuf << (5 - numBits);\n numBits = 5;\n }\n const v = (bitBuf >>> (numBits - 5)) & 31;\n sb += encTable[v];\n numBits -= 5;\n }\n return sb;\n}\n\nexport function kdf(\n outputLength: number,\n ikm: Uint8Array,\n salt?: Uint8Array,\n info?: Uint8Array,\n): Uint8Array {\n if (tart) {\n return tart.kdf(outputLength, ikm, salt, info);\n }\n salt = salt ?? new Uint8Array(64);\n // extract\n const prk = hmacSha512(salt, ikm);\n\n info = info ?? new Uint8Array(0);\n\n // expand\n const N = Math.ceil(outputLength / 32);\n const output = new Uint8Array(N * 32);\n for (let i = 0; i < N; i++) {\n let buf;\n if (i == 0) {\n buf = new Uint8Array(info.byteLength + 1);\n buf.set(info, 0);\n } else {\n buf = new Uint8Array(info.byteLength + 1 + 32);\n for (let j = 0; j < 32; j++) {\n buf[j] = output[(i - 1) * 32 + j];\n }\n buf.set(info, 32);\n }\n buf[buf.length - 1] = i + 1;\n const chunk = hmacSha256(prk, buf);\n output.set(chunk, i * 32);\n }\n\n return output.slice(0, outputLength);\n}\n\n/**\n * HMAC-SHA512-SHA256 (see RFC 5869).\n */\nexport function kdfKw(args: {\n outputLength: number;\n ikm: Uint8Array;\n salt?: Uint8Array;\n info?: Uint8Array;\n}) {\n return kdf(args.outputLength, args.ikm, args.salt, args.info);\n}\n\nexport function decodeCrock(encoded: string): Uint8Array {\n if (tart) {\n return tart.decodeCrock(encoded);\n }\n const size = encoded.length;\n let bitpos = 0;\n let bitbuf = 0;\n let readPosition = 0;\n const outLen = Math.floor((size * 5) / 8);\n const out = new Uint8Array(outLen);\n let outPos = 0;\n\n while (readPosition < size || bitpos > 0) {\n if (readPosition < size) {\n const v = getValue(encoded[readPosition++]);\n bitbuf = (bitbuf << 5) | v;\n bitpos += 5;\n }\n while (bitpos >= 8) {\n const d = (bitbuf >>> (bitpos - 8)) & 0xff;\n out[outPos++] = d;\n bitpos -= 8;\n }\n if (readPosition == size && bitpos > 0) {\n bitbuf = (bitbuf << (8 - bitpos)) & 0xff;\n bitpos = bitbuf == 0 ? 0 : 8;\n }\n }\n return out;\n}\n\nexport async function hashArgon2id(\n password: Uint8Array,\n salt: Uint8Array,\n iterations: number,\n memorySize: number,\n hashLength: number,\n): Promise {\n if (tart) {\n return tart.hashArgon2id(\n password,\n salt,\n iterations,\n memorySize,\n hashLength,\n );\n }\n return await argon2.hashArgon2id(\n password,\n salt,\n iterations,\n memorySize,\n hashLength,\n );\n}\n\nexport function eddsaGetPublic(eddsaPriv: Uint8Array): Uint8Array {\n if (tart) {\n return tart.eddsaGetPublic(eddsaPriv);\n }\n const pair = nacl.crypto_sign_keyPair_fromSeed(eddsaPriv);\n return pair.publicKey;\n}\n\nexport function ecdhGetPublic(ecdhePriv: Uint8Array): Uint8Array {\n if (tart) {\n return tart.ecdheGetPublic(ecdhePriv);\n }\n return nacl.scalarMult_base(ecdhePriv);\n}\n\nexport function keyExchangeEddsaEcdh(\n eddsaPriv: Uint8Array,\n ecdhPub: Uint8Array,\n): Uint8Array {\n if (tart) {\n return tart.keyExchangeEddsaEcdh(eddsaPriv, ecdhPub);\n }\n const ph = hash(eddsaPriv);\n const a = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n a[i] = ph[i];\n }\n const x = nacl.scalarMult(a, ecdhPub);\n return hash(x);\n}\n\nexport function keyExchangeEcdhEddsa(\n ecdhPriv: Uint8Array & FlavorEcdhePrivP,\n eddsaPub: Uint8Array & FlavorEddsaPubP,\n): Uint8Array {\n if (tart) {\n return tart.keyExchangeEcdhEddsa(ecdhPriv, eddsaPub);\n }\n const curve25519Pub = nacl.sign_ed25519_pk_to_curve25519(eddsaPub);\n const x = nacl.scalarMult(ecdhPriv, curve25519Pub);\n return hash(x);\n}\n\ninterface RsaPub {\n N: bigint.BigInteger;\n e: bigint.BigInteger;\n}\n\n/**\n * KDF modulo a big integer.\n */\nfunction kdfMod(\n n: bigint.BigInteger,\n ikm: Uint8Array,\n salt: Uint8Array,\n info: Uint8Array,\n): bigint.BigInteger {\n const nbits = n.bitLength().toJSNumber();\n const buflen = Math.floor((nbits - 1) / 8 + 1);\n const mask = (1 << (8 - (buflen * 8 - nbits))) - 1;\n let counter = 0;\n while (true) {\n const ctx = new Uint8Array(info.byteLength + 2);\n ctx.set(info, 0);\n ctx[ctx.length - 2] = (counter >>> 8) & 0xff;\n ctx[ctx.length - 1] = counter & 0xff;\n const buf = kdf(buflen, ikm, salt, ctx);\n const arr = Array.from(buf);\n arr[0] = arr[0] & mask;\n const r = bigint.fromArray(arr, 256, false);\n if (r.lt(n)) {\n return r;\n }\n counter++;\n }\n}\n\nfunction csKdfMod(\n n: bigint.BigInteger,\n ikm: Uint8Array,\n salt: Uint8Array,\n info: Uint8Array,\n): Uint8Array {\n const nbits = n.bitLength().toJSNumber();\n const buflen = Math.floor((nbits - 1) / 8 + 1);\n const mask = (1 << (8 - (buflen * 8 - nbits))) - 1;\n let counter = 0;\n while (true) {\n const ctx = new Uint8Array(info.byteLength + 2);\n ctx.set(info, 0);\n ctx[ctx.length - 2] = (counter >>> 8) & 0xff;\n ctx[ctx.length - 1] = counter & 0xff;\n const buf = kdf(buflen, ikm, salt, ctx);\n const arr = Array.from(buf);\n arr[0] = arr[0] & mask;\n const r = bigint.fromArray(arr, 256, false);\n if (r.lt(n)) {\n return new Uint8Array(arr);\n }\n counter++;\n }\n}\n\n// Newer versions of node have TextEncoder and TextDecoder as a global,\n// just like modern browsers.\n// In older versions of node or environments that do not have these\n// globals, they must be polyfilled (by adding them to global/globalThis)\n// before stringToBytes or bytesToString is called the first time.\n\nlet encoder: any;\nlet decoder: any;\n\nexport function stringToBytes(s: string): Uint8Array {\n if (!encoder) {\n encoder = new TextEncoder();\n }\n return encoder.encode(s);\n}\n\nexport function bytesToString(b: Uint8Array): string {\n if (!decoder) {\n decoder = new TextDecoder();\n }\n return decoder.decode(b);\n}\n\nfunction loadBigInt(arr: Uint8Array): bigint.BigInteger {\n return bigint.fromArray(Array.from(arr), 256, false);\n}\n\nfunction rsaBlindingKeyDerive(\n rsaPub: RsaPub,\n bks: Uint8Array,\n): bigint.BigInteger {\n const salt = stringToBytes(\"Blinding KDF extractor HMAC key\");\n const info = stringToBytes(\"Blinding KDF\");\n return kdfMod(rsaPub.N, bks, salt, info);\n}\n\n/*\n * Test for malicious RSA key.\n *\n * Assuming n is an RSA modulous and r is generated using a call to\n * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a\n * malicious RSA key designed to deanomize the user.\n *\n * @param r KDF result\n * @param n RSA modulus of the public key\n */\nfunction rsaGcdValidate(r: bigint.BigInteger, n: bigint.BigInteger): void {\n const t = bigint.gcd(r, n);\n if (!t.equals(bigint.one)) {\n throw Error(\"malicious RSA public key\");\n }\n}\n\nfunction rsaFullDomainHash(hm: Uint8Array, rsaPub: RsaPub): bigint.BigInteger {\n const info = stringToBytes(\"RSA-FDA FTpsW!\");\n const salt = rsaPubEncode(rsaPub);\n const r = kdfMod(rsaPub.N, hm, salt, info);\n rsaGcdValidate(r, rsaPub.N);\n return r;\n}\n\nfunction rsaPubDecode(rsaPub: Uint8Array): RsaPub {\n const modulusLength = (rsaPub[0] << 8) | rsaPub[1];\n const exponentLength = (rsaPub[2] << 8) | rsaPub[3];\n if (4 + exponentLength + modulusLength != rsaPub.length) {\n throw Error(\"invalid RSA public key (format wrong)\");\n }\n const modulus = rsaPub.slice(4, 4 + modulusLength);\n const exponent = rsaPub.slice(\n 4 + modulusLength,\n 4 + modulusLength + exponentLength,\n );\n const res = {\n N: loadBigInt(modulus),\n e: loadBigInt(exponent),\n };\n return res;\n}\n\nfunction rsaPubEncode(rsaPub: RsaPub): Uint8Array {\n const mb = rsaPub.N.toArray(256).value;\n const eb = rsaPub.e.toArray(256).value;\n const out = new Uint8Array(4 + mb.length + eb.length);\n out[0] = (mb.length >>> 8) & 0xff;\n out[1] = mb.length & 0xff;\n out[2] = (eb.length >>> 8) & 0xff;\n out[3] = eb.length & 0xff;\n out.set(mb, 4);\n out.set(eb, 4 + mb.length);\n return out;\n}\n\nexport function rsaBlind(\n hm: Uint8Array,\n bks: Uint8Array,\n rsaPubEnc: Uint8Array,\n): Uint8Array {\n if (tart) {\n return tart.rsaBlind(hm, bks, rsaPubEnc);\n }\n const rsaPub = rsaPubDecode(rsaPubEnc);\n const data = rsaFullDomainHash(hm, rsaPub);\n const r = rsaBlindingKeyDerive(rsaPub, bks);\n const r_e = r.modPow(rsaPub.e, rsaPub.N);\n const bm = r_e.multiply(data).mod(rsaPub.N);\n return new Uint8Array(bm.toArray(256).value);\n}\n\nexport function rsaUnblind(\n sig: Uint8Array,\n rsaPubEnc: Uint8Array,\n bks: Uint8Array,\n): Uint8Array {\n if (tart) {\n return tart.rsaUnblind(sig, rsaPubEnc, bks);\n }\n const rsaPub = rsaPubDecode(rsaPubEnc);\n const blinded_s = loadBigInt(sig);\n const r = rsaBlindingKeyDerive(rsaPub, bks);\n const r_inv = r.modInv(rsaPub.N);\n const s = blinded_s.multiply(r_inv).mod(rsaPub.N);\n return new Uint8Array(s.toArray(256).value);\n}\n\nexport function rsaVerify(\n hm: Uint8Array,\n rsaSig: Uint8Array,\n rsaPubEnc: Uint8Array,\n): boolean {\n if (tart) {\n return tart.rsaVerify(hm, rsaSig, rsaPubEnc);\n }\n const rsaPub = rsaPubDecode(rsaPubEnc);\n const d = rsaFullDomainHash(hm, rsaPub);\n const sig = loadBigInt(rsaSig);\n const sig_e = sig.modPow(rsaPub.e, rsaPub.N);\n return sig_e.equals(d);\n}\n\nexport type CsSignature = {\n s: Uint8Array;\n rPub: Uint8Array;\n};\n\nexport type CsBlindSignature = {\n sBlind: Uint8Array;\n rPubBlind: Uint8Array;\n};\n\nexport type CsBlindingSecrets = {\n alpha: [Uint8Array, Uint8Array];\n beta: [Uint8Array, Uint8Array];\n};\n\nexport function typedArrayConcat(chunks: Uint8Array[]): Uint8Array {\n let payloadLen = 0;\n for (const c of chunks) {\n payloadLen += c.byteLength;\n }\n const buf = new ArrayBuffer(payloadLen);\n const u8buf = new Uint8Array(buf);\n let p = 0;\n for (const c of chunks) {\n u8buf.set(c, p);\n p += c.byteLength;\n }\n return u8buf;\n}\n\n/**\n * Map to scalar subgroup function\n * perform clamping as described in RFC7748\n * @param scalar\n */\nfunction mtoSS(scalar: Uint8Array): Uint8Array {\n scalar[0] &= 248;\n scalar[31] &= 127;\n scalar[31] |= 64;\n return scalar;\n}\n\n/**\n * The function returns the CS blinding secrets from a seed\n * @param bseed seed to derive blinding secrets\n * @returns blinding secrets\n */\nexport function deriveSecrets(bseed: Uint8Array): CsBlindingSecrets {\n const outLen = 130;\n const salt = stringToBytes(\"alphabeta\");\n const rndout = kdf(outLen, bseed, salt);\n const secrets: CsBlindingSecrets = {\n alpha: [mtoSS(rndout.slice(0, 32)), mtoSS(rndout.slice(64, 96))],\n beta: [mtoSS(rndout.slice(32, 64)), mtoSS(rndout.slice(96, 128))],\n };\n return secrets;\n}\n\n/**\n * calculation of the blinded public point R in CS\n * @param csPub denomination publik key\n * @param secrets client blinding secrets\n * @param rPub public R received from /csr API\n */\nexport async function calcRBlind(\n csPub: Uint8Array,\n secrets: CsBlindingSecrets,\n rPub: [Uint8Array, Uint8Array],\n): Promise<[Uint8Array, Uint8Array]> {\n const aG0 = nacl.crypto_scalarmult_ed25519_base_noclamp(secrets.alpha[0]);\n const aG1 = nacl.crypto_scalarmult_ed25519_base_noclamp(secrets.alpha[1]);\n\n const bDp0 = nacl.crypto_scalarmult_ed25519_noclamp(secrets.beta[0], csPub);\n const bDp1 = nacl.crypto_scalarmult_ed25519_noclamp(secrets.beta[1], csPub);\n\n const res0 = nacl.crypto_core_ed25519_add(aG0, bDp0);\n const res1 = nacl.crypto_core_ed25519_add(aG1, bDp1);\n return [\n nacl.crypto_core_ed25519_add(rPub[0], res0),\n nacl.crypto_core_ed25519_add(rPub[1], res1),\n ];\n}\n\n/**\n * FDH function used in CS\n * @param hm message hash\n * @param rPub public R included in FDH\n * @param csPub denomination public key as context\n * @returns mapped Curve25519 scalar\n */\nfunction csFDH(\n hm: Uint8Array,\n rPub: Uint8Array,\n csPub: Uint8Array,\n): Uint8Array {\n const lMod = Array.from(\n new Uint8Array([\n 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6,\n 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed,\n ]),\n );\n const L = bigint.fromArray(lMod, 256, false);\n\n const info = stringToBytes(\"Curve25519FDH\");\n const preshash = hash(typedArrayConcat([rPub, hm]));\n return csKdfMod(L, preshash, csPub, info).reverse();\n}\n\n/**\n * blinding seed derived from coin private key\n * @param coinPriv private key of the corresponding coin\n * @param rPub public R received from /csr API\n * @returns blinding seed\n */\nexport function deriveBSeed(\n coinPriv: Uint8Array,\n rPub: [Uint8Array, Uint8Array],\n): Uint8Array {\n const outLen = 32;\n const salt = stringToBytes(\"b-seed\");\n const ikm = typedArrayConcat([coinPriv, rPub[0], rPub[1]]);\n return kdf(outLen, ikm, salt);\n}\n\n/**\n * Derive withdraw nonce, used in /csr request\n * Note: In withdraw protocol, the nonce is chosen randomly\n * @param coinPriv coin private key\n * @returns nonce\n */\nexport function deriveWithdrawNonce(coinPriv: Uint8Array): Uint8Array {\n const outLen = 32;\n const salt = stringToBytes(\"n\");\n return kdf(outLen, coinPriv, salt);\n}\n\n/**\n * Blind operation for CS signatures, used after /csr call\n * @param bseed blinding seed to derive blinding secrets\n * @param rPub public R received from /csr\n * @param csPub denomination public key\n * @param hm message to blind\n * @returns two blinded c\n */\nexport async function csBlind(\n bseed: Uint8Array,\n rPub: [Uint8Array, Uint8Array],\n csPub: Uint8Array,\n hm: Uint8Array,\n): Promise<[Uint8Array, Uint8Array]> {\n const secrets = deriveSecrets(bseed);\n const rPubBlind = await calcRBlind(csPub, secrets, rPub);\n const c_0 = csFDH(hm, rPubBlind[0], csPub);\n const c_1 = csFDH(hm, rPubBlind[1], csPub);\n return [\n nacl.crypto_core_ed25519_scalar_add(c_0, secrets.beta[0]),\n nacl.crypto_core_ed25519_scalar_add(c_1, secrets.beta[1]),\n ];\n}\n\n/**\n * Unblind operation to unblind the signature\n * @param bseed seed to derive secrets\n * @param rPub public R received from /csr\n * @param csPub denomination public key\n * @param b returned from exchange to select c\n * @param csSig blinded signature\n * @returns unblinded signature\n */\nexport async function csUnblind(\n bseed: Uint8Array,\n rPub: [Uint8Array, Uint8Array],\n csPub: Uint8Array,\n b: number,\n csSig: CsBlindSignature,\n): Promise {\n if (b != 0 && b != 1) {\n throw new Error();\n }\n const secrets = deriveSecrets(bseed);\n const rPubDash = (await calcRBlind(csPub, secrets, rPub))[b];\n const sig: CsSignature = {\n s: nacl.crypto_core_ed25519_scalar_add(csSig.sBlind, secrets.alpha[b]),\n rPub: rPubDash,\n };\n return sig;\n}\n\n/**\n * Verification algorithm for CS signatures\n * @param hm message signed\n * @param csSig unblinded signature\n * @param csPub denomination public key\n * @returns true if valid, false if invalid\n */\nexport async function csVerify(\n hm: Uint8Array,\n csSig: CsSignature,\n csPub: Uint8Array,\n): Promise {\n const cDash = csFDH(hm, csSig.rPub, csPub);\n const sG = nacl.crypto_scalarmult_ed25519_base_noclamp(csSig.s);\n const cbDp = nacl.crypto_scalarmult_ed25519_noclamp(cDash, csPub);\n const sGeq = nacl.crypto_core_ed25519_add(csSig.rPub, cbDp);\n return nacl.verify(sG, sGeq);\n}\n\nexport interface EddsaKeyPair {\n eddsaPub: Uint8Array;\n eddsaPriv: Uint8Array;\n}\n\nexport interface EcdheKeyPair {\n ecdhePub: Uint8Array;\n ecdhePriv: Uint8Array;\n}\n\nexport interface Edx25519Keypair {\n edxPub: string;\n edxPriv: string;\n}\n\nexport function createEddsaKeyPair(): EddsaKeyPair {\n const eddsaPriv = nacl.randomBytes(32);\n const eddsaPub = eddsaGetPublic(eddsaPriv);\n return { eddsaPriv, eddsaPub };\n}\n\nexport function createEcdheKeyPair(): EcdheKeyPair {\n const ecdhePriv = nacl.randomBytes(32);\n const ecdhePub = ecdhGetPublic(ecdhePriv);\n return { ecdhePriv, ecdhePub };\n}\n\nexport function hash(d: Uint8Array): Uint8Array {\n if (tart) {\n return tart.hash(d);\n }\n return nacl.hash(d);\n}\n\n/**\n * Hash the input with SHA-512 and truncate the result\n * to 32 bytes.\n */\nexport function hashTruncate32(d: Uint8Array): Uint8Array {\n const sha512HashCode = hash(d);\n return sha512HashCode.subarray(0, 32);\n}\n\nexport function hashCoinEv(\n coinEv: CoinEnvelope,\n denomPubHash: HashCodeString,\n): Uint8Array {\n const hashContext = createHashContext();\n hashContext.update(decodeCrock(denomPubHash));\n hashCoinEvInner(coinEv, hashContext);\n return hashContext.finish();\n}\n\nconst logger = new Logger(\"talerCrypto.ts\");\n\nexport function hashCoinEvInner(\n coinEv: CoinEnvelope,\n hashState: TalerHashState,\n): void {\n const hashInputBuf = new ArrayBuffer(4);\n const uint8ArrayBuf = new Uint8Array(hashInputBuf);\n const dv = new DataView(hashInputBuf);\n dv.setUint32(0, DenomKeyType.toIntTag(coinEv.cipher));\n hashState.update(uint8ArrayBuf);\n switch (coinEv.cipher) {\n case DenomKeyType.Rsa:\n hashState.update(decodeCrock(coinEv.rsa_blinded_planchet));\n return;\n default:\n throw new Error();\n }\n}\n\nexport function hashCoinPub(\n coinPub: CoinPublicKeyString,\n ach?: HashCodeString,\n): Uint8Array {\n if (!ach) {\n return hash(decodeCrock(coinPub));\n }\n\n return hash(typedArrayConcat([decodeCrock(coinPub), decodeCrock(ach)]));\n}\n\n/**\n * Hash a denomination public key.\n */\nexport function hashDenomPub(pub: DenominationPubKey): Uint8Array {\n if (pub.cipher === DenomKeyType.Rsa) {\n const pubBuf = decodeCrock(pub.rsa_public_key);\n const hashInputBuf = new ArrayBuffer(pubBuf.length + 4 + 4);\n const uint8ArrayBuf = new Uint8Array(hashInputBuf);\n const dv = new DataView(hashInputBuf);\n dv.setUint32(0, pub.age_mask ?? 0);\n dv.setUint32(4, DenomKeyType.toIntTag(pub.cipher));\n uint8ArrayBuf.set(pubBuf, 8);\n return hash(uint8ArrayBuf);\n } else if (pub.cipher === DenomKeyType.ClauseSchnorr) {\n const pubBuf = decodeCrock(pub.cs_public_key);\n const hashInputBuf = new ArrayBuffer(pubBuf.length + 4 + 4);\n const uint8ArrayBuf = new Uint8Array(hashInputBuf);\n const dv = new DataView(hashInputBuf);\n dv.setUint32(0, pub.age_mask ?? 0);\n dv.setUint32(4, DenomKeyType.toIntTag(pub.cipher));\n uint8ArrayBuf.set(pubBuf, 8);\n return hash(uint8ArrayBuf);\n } else {\n throw Error(\n `unsupported cipher (${\n (pub as DenominationPubKey).cipher\n }), unable to hash`,\n );\n }\n}\n\n/**\n * Hash a token issue public key.\n */\nexport function hashTokenIssuePub(pub: TokenIssuePublicKey): Uint8Array {\n if (pub.cipher === DenomKeyType.Rsa) {\n const dec = decodeCrock(pub.rsa_pub);\n return hash(dec);\n } else if (pub.cipher === DenomKeyType.ClauseSchnorr) {\n const dec = decodeCrock(pub.cs_pub);\n return hash(dec);\n } else {\n throw Error(\n `unsupported cipher (${\n (pub as TokenIssuePublicKey).cipher\n }), unable to hash`,\n );\n }\n}\n\n/**\n * Hash a token envelope.\n */\nexport function hashTokenEv(\n tokenEv: TokenEnvelope,\n tokenIssuePubHash: HashCodeString,\n): Uint8Array {\n const hashContext = createHashContext();\n hashContext.update(decodeCrock(tokenIssuePubHash));\n hashTokenEvInner(tokenEv, hashContext);\n return hashContext.finish();\n}\n\nexport function hashTokenEvInner(\n tokenEv: TokenEnvelope,\n hashState: TalerHashState,\n): void {\n const hashInputBuf = new ArrayBuffer(4);\n const uint8ArrayBuf = new Uint8Array(hashInputBuf);\n const dv = new DataView(hashInputBuf);\n dv.setUint32(0, DenomKeyType.toIntTag(tokenEv.cipher));\n hashState.update(uint8ArrayBuf);\n switch (tokenEv.cipher) {\n case DenomKeyType.Rsa:\n hashState.update(decodeCrock(tokenEv.rsa_blinded_planchet));\n return;\n default:\n throw new Error();\n }\n}\n\nexport function hashPayWalletData(walletData: PayWalletData): Uint8Array {\n const canon = canonicalJson(walletData) + \"\\0\";\n const bytes = stringToBytes(canon);\n return hash(bytes);\n}\n\nexport function eddsaSign(msg: Uint8Array, eddsaPriv: Uint8Array): Uint8Array {\n if (tart) {\n return tart.eddsaSign(msg, eddsaPriv);\n }\n const pair = nacl.crypto_sign_keyPair_fromSeed(eddsaPriv);\n return nacl.sign_detached(msg, pair.secretKey);\n}\n\nexport function eddsaVerify(\n msg: Uint8Array,\n sig: EddsaSigP,\n eddsaPub: EddsaPubP,\n): boolean {\n if (tart) {\n return tart.eddsaVerify(msg, sig, eddsaPub);\n }\n return nacl.sign_detached_verify(msg, sig, eddsaPub);\n}\n\nexport interface TalerHashState {\n update(data: Uint8Array): void;\n finish(): Uint8Array;\n}\n\nexport function createHashContext(): TalerHashState {\n if (tart) {\n const t = tart;\n const st = tart.hashStateInit();\n return {\n finish: () => t.hashStateFinish(st),\n update: (d) => t.hashStateUpdate(st, d),\n };\n }\n return new nacl.HashState();\n}\n\nexport interface FreshCoin {\n coinPub: Uint8Array;\n coinPriv: Uint8Array;\n bks: Uint8Array;\n maxAge: number;\n ageCommitmentProof: AgeCommitmentProof | undefined;\n}\n\nexport function bufferForUint32(n: number): Uint8Array {\n const arrBuf = new ArrayBuffer(4);\n const buf = new Uint8Array(arrBuf);\n const dv = new DataView(arrBuf);\n dv.setUint32(0, n);\n return buf;\n}\n\n/**\n * This makes the assumption that the uint64 fits a float,\n * which should be true for all Taler protocol messages.\n */\nexport function bufferForUint64(n: number): Uint8Array {\n const arrBuf = new ArrayBuffer(8);\n const buf = new Uint8Array(arrBuf);\n const dv = new DataView(arrBuf);\n if (n < 0 || !Number.isInteger(n)) {\n throw Error(\"non-negative integer expected\");\n }\n dv.setBigUint64(0, BigInt(n));\n return buf;\n}\n\nexport function bufferForUint8(n: number): Uint8Array {\n const arrBuf = new ArrayBuffer(1);\n const buf = new Uint8Array(arrBuf);\n const dv = new DataView(arrBuf);\n dv.setUint8(0, n);\n return buf;\n}\n\nexport async function setupTipPlanchet(\n secretSeed: Uint8Array,\n denomPub: DenominationPubKey,\n coinNumber: number,\n): Promise {\n const info = stringToBytes(\"taler-tip-coin-derivation\");\n const saltArrBuf = new ArrayBuffer(4);\n const salt = new Uint8Array(saltArrBuf);\n const saltDataView = new DataView(saltArrBuf);\n saltDataView.setUint32(0, coinNumber);\n const out = kdf(64, secretSeed, salt, info);\n const coinPriv = out.slice(0, 32);\n const bks = out.slice(32, 64);\n let maybeAcp: AgeCommitmentProof | undefined;\n if (denomPub.age_mask != 0) {\n maybeAcp = await AgeRestriction.restrictionCommitSeeded(\n denomPub.age_mask,\n AgeRestriction.AGE_UNRESTRICTED,\n secretSeed,\n );\n }\n return {\n bks,\n coinPriv,\n coinPub: eddsaGetPublic(coinPriv),\n maxAge: AgeRestriction.AGE_UNRESTRICTED,\n ageCommitmentProof: maybeAcp,\n };\n}\n/**\n *\n * @param paytoUri\n * @param salt 16-byte salt\n * @returns\n */\nexport function hashWire(paytoUri: string, salt: string): string {\n const r = kdf(\n 64,\n stringToBytes(paytoUri + \"\\0\"),\n decodeCrock(salt),\n stringToBytes(\"merchant-wire-signature\"),\n );\n return encodeCrock(r);\n}\n\nexport enum WalletAccountMergeFlags {\n /**\n * Not a legal mode!\n */\n None = 0,\n\n /**\n * We are merging a fully paid-up purse into a reserve.\n */\n MergeFullyPaidPurse = 1,\n\n CreateFromPurseQuota = 2,\n\n CreateWithPurseFee = 3,\n}\n\nexport class SignaturePurposeBuilder {\n private chunks: Uint8Array[] = [];\n\n constructor(private purposeNum: number) {}\n\n put(bytes: Uint8Array): SignaturePurposeBuilder {\n this.chunks.push(Uint8Array.from(bytes));\n return this;\n }\n\n build(): Uint8Array {\n let payloadLen = 0;\n for (const c of this.chunks) {\n payloadLen += c.byteLength;\n }\n const buf = new ArrayBuffer(4 + 4 + payloadLen);\n const u8buf = new Uint8Array(buf);\n let p = 8;\n for (const c of this.chunks) {\n u8buf.set(c, p);\n p += c.byteLength;\n }\n const dvbuf = new DataView(buf);\n dvbuf.setUint32(0, payloadLen + 4 + 4);\n dvbuf.setUint32(4, this.purposeNum);\n return u8buf;\n }\n}\n\nexport function buildSigPS(purposeNum: number): SignaturePurposeBuilder {\n return new SignaturePurposeBuilder(purposeNum);\n}\n\n/**\n * Convert a big integer to a fixed-size, little-endian array.\n */\nexport function bigintToNaclArr(\n x: bigint.BigInteger,\n size: number,\n): Uint8Array {\n const byteArr = new Uint8Array(size);\n const arr = x.toArray(256).value.reverse();\n byteArr.set(arr, 0);\n return byteArr;\n}\n\nexport function bigintFromNaclArr(arr: Uint8Array): bigint.BigInteger {\n let rev = new Uint8Array(arr);\n rev = rev.reverse();\n return bigint.fromArray(Array.from(rev), 256, false);\n}\n\nexport namespace Edx25519 {\n const revL = [\n 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2,\n 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10,\n ];\n\n const L = bigint.fromArray(revL.reverse(), 256, false);\n\n export async function keyCreateFromSeed(\n seed: OpaqueData,\n ): Promise {\n return nacl.crypto_edx25519_private_key_create_from_seed(seed);\n }\n\n export async function keyCreate(): Promise {\n return nacl.crypto_edx25519_private_key_create();\n }\n\n export async function getPublic(\n priv: Edx25519PrivateKey,\n ): Promise {\n return nacl.crypto_edx25519_get_public(priv);\n }\n\n export function sign(\n msg: OpaqueData,\n key: Edx25519PrivateKey,\n ): Promise {\n throw Error(\"not implemented\");\n }\n\n async function deriveFactor(\n pub: Edx25519PublicKey,\n seed: OpaqueData,\n ): Promise {\n const res = kdfKw({\n outputLength: 64,\n ikm: pub,\n salt: stringToBytes(\"edx25519-derivation\"),\n info: seed,\n });\n\n return res;\n }\n\n export async function privateKeyDerive(\n priv: Edx25519PrivateKey,\n seed: OpaqueData,\n ): Promise {\n const pub = await getPublic(priv);\n const privDec = priv;\n const a = bigintFromNaclArr(privDec.subarray(0, 32));\n const factorEnc = await deriveFactor(pub, seed);\n const factorModL = bigintFromNaclArr(factorEnc).mod(L);\n\n const aPrime = a.divide(8).multiply(factorModL).mod(L).multiply(8).mod(L);\n const bPrime = nacl\n .hash(typedArrayConcat([privDec.subarray(32, 64), factorEnc]))\n .subarray(0, 32);\n\n const newPriv = typedArrayConcat([bigintToNaclArr(aPrime, 32), bPrime]);\n\n return newPriv;\n }\n\n export async function publicKeyDerive(\n pub: Edx25519PublicKey,\n seed: OpaqueData,\n ): Promise {\n const factorEnc = await deriveFactor(pub, seed);\n const factorReduced = nacl.crypto_core_ed25519_scalar_reduce(factorEnc);\n const res = nacl.crypto_scalarmult_ed25519_noclamp(factorReduced, pub);\n return res;\n }\n}\n\nexport interface AgeCommitment {\n mask: number;\n\n /**\n * Public keys, one for each age group specified in the age mask.\n */\n publicKeys: Edx25519PublicKeyEnc[];\n}\n\nexport interface AgeProof {\n /**\n * Private keys. Typically smaller than the number of public keys,\n * because we drop private keys from age groups that are restricted.\n */\n privateKeys: Edx25519PrivateKeyEnc[];\n}\n\nexport interface AgeCommitmentProof {\n commitment: AgeCommitment;\n proof: AgeProof;\n}\n\nfunction invariant(cond: boolean): asserts cond {\n if (!cond) {\n throw Error(\"invariant failed\");\n }\n}\n\nexport namespace AgeRestriction {\n /**\n * Smallest age value that the protocol considers \"unrestricted\".\n */\n export const AGE_UNRESTRICTED = 32;\n\n export function hashCommitment(ac: AgeCommitment): HashCodeString {\n const hc = new nacl.HashState();\n for (const pub of ac.publicKeys) {\n hc.update(decodeCrock(pub));\n }\n return encodeCrock(hc.finish().subarray(0, 32));\n }\n\n export function countAgeGroups(mask: number): number {\n let count = 0;\n let m = mask;\n while (m > 0) {\n count += m & 1;\n m = m >> 1;\n }\n return count;\n }\n\n /**\n * Get the starting points for age groups in the mask.\n */\n export function getAgeGroupsFromMask(mask: number): number[] {\n const groups: number[] = [];\n let age = 1;\n let m = mask >> 1;\n while (m > 0) {\n if (m & 1) {\n groups.push(age);\n }\n m = m >> 1;\n age++;\n }\n return groups;\n }\n\n export function getAgeGroupIndex(mask: number, age: number): number {\n invariant((mask & 1) === 1);\n let i = 0;\n let m = mask;\n let a = age;\n while (m > 0) {\n if (a <= 0) {\n break;\n }\n m = m >> 1;\n i += m & 1;\n a--;\n }\n return i;\n }\n\n export function ageGroupSpecToMask(ageGroupSpec: string): number {\n throw Error(\"not implemented\");\n }\n\n export async function restrictionCommit(\n ageMask: number,\n age: number,\n ): Promise {\n invariant((ageMask & 1) === 1);\n const numPubs = countAgeGroups(ageMask) - 1;\n const numPrivs = getAgeGroupIndex(ageMask, age);\n\n const pubs: Edx25519PublicKey[] = [];\n const privs: Edx25519PrivateKey[] = [];\n\n for (let i = 0; i < numPubs; i++) {\n const priv = await Edx25519.keyCreate();\n const pub = await Edx25519.getPublic(priv);\n pubs.push(pub);\n if (i < numPrivs) {\n privs.push(priv);\n }\n }\n\n return {\n commitment: {\n mask: ageMask,\n publicKeys: pubs.map((x) => encodeCrock(x)),\n },\n proof: {\n privateKeys: privs.map((x) => encodeCrock(x)),\n },\n };\n }\n\n const PublishedAgeRestrictionBaseKey: Edx25519PublicKey = decodeCrock(\n \"CH0VKFDZ2GWRWHQBBGEK9MWV5YDQVJ0RXEE0KYT3NMB69F0R96TG\",\n );\n\n export async function restrictionCommitSeeded(\n ageMask: number,\n age: number,\n seed: Uint8Array,\n ): Promise {\n invariant((ageMask & 1) === 1);\n const numPubs = countAgeGroups(ageMask) - 1;\n const numPrivs = getAgeGroupIndex(ageMask, age);\n\n const pubs: Edx25519PublicKey[] = [];\n const privs: Edx25519PrivateKey[] = [];\n\n for (let i = 0; i < numPrivs; i++) {\n const privSeed = await kdfKw({\n outputLength: 32,\n ikm: seed,\n info: stringToBytes(\"age-commitment\"),\n salt: bufferForUint32(i),\n });\n\n const priv = await Edx25519.keyCreateFromSeed(privSeed);\n const pub = await Edx25519.getPublic(priv);\n pubs.push(pub);\n privs.push(priv);\n }\n\n for (let i = numPrivs; i < numPubs; i++) {\n const deriveSeed = await kdfKw({\n outputLength: 32,\n ikm: seed,\n info: stringToBytes(\"age-factor\"),\n salt: bufferForUint32(i),\n });\n const pub = await Edx25519.publicKeyDerive(\n PublishedAgeRestrictionBaseKey,\n deriveSeed,\n );\n pubs.push(pub);\n }\n\n return {\n commitment: {\n mask: ageMask,\n publicKeys: pubs.map((x) => encodeCrock(x)),\n },\n proof: {\n privateKeys: privs.map((x) => encodeCrock(x)),\n },\n };\n }\n\n /**\n * Check that c1 = c2*salt\n */\n export async function commitCompare(\n c1: AgeCommitment,\n c2: AgeCommitment,\n salt: OpaqueData,\n ): Promise {\n if (c1.publicKeys.length != c2.publicKeys.length) {\n return false;\n }\n for (let i = 0; i < c1.publicKeys.length; i++) {\n const k1 = decodeCrock(c1.publicKeys[i]);\n const k2 = await Edx25519.publicKeyDerive(\n decodeCrock(c2.publicKeys[i]),\n salt,\n );\n if (k1 != k2) {\n return false;\n }\n }\n return true;\n }\n\n export async function commitmentDerive(\n commitmentProof: AgeCommitmentProof,\n salt: OpaqueData,\n ): Promise {\n const newPrivs: Edx25519PrivateKey[] = [];\n const newPubs: Edx25519PublicKey[] = [];\n\n for (const oldPub of commitmentProof.commitment.publicKeys) {\n newPubs.push(await Edx25519.publicKeyDerive(decodeCrock(oldPub), salt));\n }\n\n for (const oldPriv of commitmentProof.proof.privateKeys) {\n newPrivs.push(\n await Edx25519.privateKeyDerive(decodeCrock(oldPriv), salt),\n );\n }\n\n return {\n commitment: {\n mask: commitmentProof.commitment.mask,\n publicKeys: newPubs.map((x) => encodeCrock(x)),\n },\n proof: {\n privateKeys: newPrivs.map((x) => encodeCrock(x)),\n },\n };\n }\n\n export function commitmentAttest(\n commitmentProof: AgeCommitmentProof,\n age: number,\n ): Edx25519Signature {\n const d = buildSigPS(TalerSignaturePurpose.WALLET_AGE_ATTESTATION)\n .put(bufferForUint32(commitmentProof.commitment.mask))\n .put(bufferForUint32(age))\n .build();\n const group = getAgeGroupIndex(commitmentProof.commitment.mask, age);\n if (group === 0) {\n // No attestation required.\n return new Uint8Array(64);\n }\n const priv = commitmentProof.proof.privateKeys[group - 1];\n const pub = commitmentProof.commitment.publicKeys[group - 1];\n const sig = nacl.crypto_edx25519_sign_detached(\n d,\n decodeCrock(priv),\n decodeCrock(pub),\n );\n return sig;\n }\n\n export function commitmentVerify(\n commitment: AgeCommitment,\n sig: string,\n age: number,\n ): boolean {\n const d = buildSigPS(TalerSignaturePurpose.WALLET_AGE_ATTESTATION)\n .put(bufferForUint32(commitment.mask))\n .put(bufferForUint32(age))\n .build();\n const group = getAgeGroupIndex(commitment.mask, age);\n if (group === 0) {\n // No attestation required.\n return true;\n }\n const pub = commitment.publicKeys[group - 1];\n return nacl.crypto_edx25519_sign_detached_verify(\n d,\n decodeCrock(sig),\n decodeCrock(pub),\n );\n }\n}\n\nasync function deriveKey(\n keySeed: OpaqueData,\n nonce: EncryptionNonceP,\n salt: string,\n): Promise {\n return kdfKw({\n outputLength: 32,\n salt: nonce,\n ikm: keySeed,\n info: stringToBytes(salt),\n });\n}\n\nexport async function encryptWithDerivedKey(\n nonce: EncryptionNonceP,\n keySeed: OpaqueData,\n plaintext: OpaqueData,\n salt: string,\n): Promise {\n const key = await deriveKey(keySeed, nonce, salt);\n const cipherText = secretbox(plaintext, nonce, key);\n return typedArrayConcat([nonce, cipherText]);\n}\n\nconst nonceSize = 24;\n\nexport async function decryptWithDerivedKey(\n ciphertext: OpaqueData,\n keySeed: OpaqueData,\n salt: string,\n): Promise {\n const ctBuf = ciphertext;\n const nonceBuf = ctBuf.slice(0, nonceSize);\n const enc = ctBuf.slice(nonceSize);\n const key = await deriveKey(keySeed, nonceBuf, salt);\n const clearText = nacl.secretbox_open(enc, nonceBuf, key);\n if (!clearText) {\n throw Error(\"could not decrypt\");\n }\n return clearText;\n}\n\nenum ContractFormatTag {\n PaymentOffer = 0,\n PaymentRequest = 1,\n}\n\nconst mergeSalt = \"p2p-merge-contract\";\nconst depositSalt = \"p2p-deposit-contract\";\n\nexport function encryptContractForMerge(\n pursePub: PursePublicKey,\n contractPriv: ContractPrivateKey,\n mergePriv: MergePrivateKeyP,\n contractTerms: any,\n nonce: EncryptionNonceP,\n): Promise {\n const contractTermsCanon = canonicalJson(contractTerms) + \"\\0\";\n const contractTermsBytes = stringToBytes(contractTermsCanon);\n const contractTermsCompressed = fflate.zlibSync(contractTermsBytes);\n const data = typedArrayConcat([\n bufferForUint32(ContractFormatTag.PaymentOffer),\n bufferForUint32(contractTermsBytes.length),\n mergePriv,\n contractTermsCompressed,\n ]);\n const key = keyExchangeEcdhEddsa(contractPriv, pursePub);\n return encryptWithDerivedKey(nonce, key, data, mergeSalt);\n}\n\nexport function encryptContractForDeposit(\n pursePub: PursePublicKey,\n contractPriv: ContractPrivateKey,\n contractTerms: any,\n nonce: EncryptionNonceP,\n): Promise {\n const contractTermsCanon = canonicalJson(contractTerms) + \"\\0\";\n const contractTermsBytes = stringToBytes(contractTermsCanon);\n const contractTermsCompressed = fflate.zlibSync(contractTermsBytes);\n const data = typedArrayConcat([\n bufferForUint32(ContractFormatTag.PaymentRequest),\n bufferForUint32(contractTermsBytes.length),\n contractTermsCompressed,\n ]);\n const key = keyExchangeEcdhEddsa(contractPriv, pursePub);\n return encryptWithDerivedKey(nonce, key, data, depositSalt);\n}\n\nexport interface DecryptForMergeResult {\n contractTerms: any;\n mergePriv: Uint8Array;\n}\n\nexport interface DecryptForDepositResult {\n contractTerms: any;\n}\n\nexport async function decryptContractForMerge(\n enc: OpaqueData,\n pursePub: PursePublicKey,\n contractPriv: ContractPrivateKey,\n): Promise {\n const key = keyExchangeEcdhEddsa(contractPriv, pursePub);\n const dec = await decryptWithDerivedKey(enc, key, mergeSalt);\n const mergePriv = dec.slice(8, 8 + 32);\n const contractTermsCompressed = dec.slice(8 + 32);\n const contractTermsBuf = fflate.unzlibSync(contractTermsCompressed);\n // Slice of the '\\0' at the end and decode to a string\n const contractTermsString = bytesToString(\n contractTermsBuf.slice(0, contractTermsBuf.length - 1),\n );\n return {\n mergePriv: mergePriv,\n contractTerms: JSON.parse(contractTermsString),\n };\n}\n\nexport async function decryptContractForDeposit(\n enc: OpaqueData,\n pursePub: PursePublicKey,\n contractPriv: ContractPrivateKey,\n): Promise {\n const key = keyExchangeEcdhEddsa(contractPriv, pursePub);\n const dec = await decryptWithDerivedKey(enc, key, depositSalt);\n const contractTermsCompressed = dec.slice(8);\n const contractTermsBuf = fflate.unzlibSync(contractTermsCompressed);\n // Slice of the '\\0' at the end and decode to a string\n const contractTermsString = bytesToString(\n contractTermsBuf.slice(0, contractTermsBuf.length - 1),\n );\n return {\n contractTerms: JSON.parse(contractTermsString),\n };\n}\n\nexport function bufferFromAmount(amount: AmountLike): Uint8Array {\n const amountJ = Amounts.jsonifyAmount(amount);\n const buffer = new ArrayBuffer(8 + 4 + 12);\n const dvbuf = new DataView(buffer);\n const u8buf = new Uint8Array(buffer);\n const curr = stringToBytes(amountJ.currency);\n if (typeof dvbuf.setBigUint64 !== \"undefined\") {\n dvbuf.setBigUint64(0, BigInt(amountJ.value));\n } else {\n const arr = bigint(amountJ.value).toArray(2 ** 8).value;\n let offset = 8 - arr.length;\n for (let i = 0; i < arr.length; i++) {\n dvbuf.setUint8(offset++, arr[i]);\n }\n }\n dvbuf.setUint32(8, amountJ.fraction);\n u8buf.set(curr, 8 + 4);\n\n return u8buf;\n}\n\nconst foreverNum = 2n ** 64n - 1n;\n\nexport function timestampRoundedToBuffer(\n ts: TalerProtocolTimestamp,\n): Uint8Array {\n const b = new ArrayBuffer(8);\n const v = new DataView(b);\n const numVal =\n ts.t_s === \"never\" ? foreverNum : BigInt(ts.t_s) * 1000n * 1000n;\n // The buffer we sign over represents the timestamp in microseconds.\n if (typeof v.setBigUint64 !== \"undefined\") {\n v.setBigUint64(0, numVal);\n } else {\n const s =\n ts.t_s === \"never\"\n ? bigint(foreverNum)\n : bigint(ts.t_s).multiply(1000 * 1000);\n const arr = s.toArray(2 ** 8).value;\n let offset = 8 - arr.length;\n for (let i = 0; i < arr.length; i++) {\n v.setUint8(offset++, arr[i]);\n }\n }\n return new Uint8Array(b);\n}\n\nexport function durationRoundedToBuffer(ts: TalerProtocolDuration): Uint8Array {\n const b = new ArrayBuffer(8);\n const v = new DataView(b);\n // The buffer we sign over represents the timestamp in microseconds.\n if (typeof v.setBigUint64 !== \"undefined\") {\n const s = BigInt(ts.d_us);\n v.setBigUint64(0, s);\n } else {\n const s = ts.d_us === \"forever\" ? bigint.zero : bigint(ts.d_us);\n const arr = s.toArray(2 ** 8).value;\n let offset = 8 - arr.length;\n for (let i = 0; i < arr.length; i++) {\n v.setUint8(offset++, arr[i]);\n }\n }\n return new Uint8Array(b);\n}\n\nexport function toHexString(byteArray: Uint8Array) {\n return byteArray.reduce(\n (output, elem) => output + (\"0\" + elem.toString(16)).slice(-2),\n \"\",\n );\n}\n\n// RFC 9180 Hybrid Public-Key Encryption\n// Currently, no agility implemented, we only support\n// DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20Poly1305\n\n// A X25519 public key\nexport type HpkePublicKey = Uint8Array;\n\n// A X25519 secret key\nexport type HpkeSecretKey = Uint8Array;\n\n// An X25519 public key\nexport type HpkeEncapsulation = Uint8Array;\n\n// This makes sure that sender confusion is\n// avoided.\n// In a non-oneshot API (currently not implemented)\n// this is a required input.\nexport enum HpkeRole {\n Sender,\n Receiver,\n}\n\n// We do support pre-shared keys in this API.\nexport enum HpkeMode {\n Base = 0x00,\n PSK = 0x01,\n}\n\n// Currently only used internally.\n// Necessary when we support anything\n// else than the oneshot APIs\nexport interface HpkeContext {\n key: Uint8Array;\n nonce: Uint8Array;\n seq: number;\n role: HpkeRole;\n}\n\nexport function hkdf_extract_sha256(\n ikm: Uint8Array,\n salt?: Uint8Array,\n): Uint8Array {\n salt = salt ?? new Uint8Array(64);\n // extract\n return hmacSha256(salt, ikm);\n}\n\nexport function hkdf_expand_sha256(\n outputLength: number,\n prk: Uint8Array,\n info?: Uint8Array,\n): Uint8Array {\n info = info ?? new Uint8Array(0);\n\n // expand\n const N = Math.ceil(outputLength / 32);\n const output = new Uint8Array(N * 32);\n for (let i = 0; i < N; i++) {\n let buf;\n if (i == 0) {\n buf = new Uint8Array(info.byteLength + 1);\n buf.set(info, 0);\n } else {\n buf = new Uint8Array(info.byteLength + 1 + 32);\n for (let j = 0; j < 32; j++) {\n buf[j] = output[(i - 1) * 32 + j];\n }\n buf.set(info, 32);\n }\n buf[buf.length - 1] = i + 1;\n const chunk = hmacSha256(prk, buf);\n output.set(chunk, i * 32);\n }\n\n return output.slice(0, outputLength);\n}\n\nexport function hpkeLabeledExpand(\n ctx: string,\n prk: Uint8Array,\n label: string,\n info: Uint8Array,\n suiteId: Uint8Array,\n outLength: number,\n): Uint8Array {\n const outLenBytes = new ArrayBuffer(2);\n const out = new DataView(outLenBytes);\n out.setUint16(0, outLength);\n const labelBytes = stringToBytes(label);\n const ctxBytes = stringToBytes(ctx);\n const labeledInfo = new Uint8Array([\n ...new Uint8Array(outLenBytes),\n ...ctxBytes,\n ...suiteId,\n ...labelBytes,\n ...info,\n ]);\n return hkdf_expand_sha256(outLength, prk, labeledInfo);\n}\n\nexport function hpkeLabeledExtract(\n ctx: string,\n label: Uint8Array,\n ikm: Uint8Array,\n suiteId: Uint8Array,\n salt?: Uint8Array,\n): Uint8Array {\n const ctxBytes = stringToBytes(ctx);\n const labeledIkm = new Uint8Array([\n ...ctxBytes,\n ...suiteId,\n ...label,\n ...ikm,\n ]);\n return hkdf_extract_sha256(labeledIkm, salt);\n}\n\nexport function ecdh_x25519(\n ecdhPriv: Uint8Array,\n ecdhPub: Uint8Array,\n): Uint8Array {\n var checkbyte = 0;\n const res = nacl.scalarMult(ecdhPriv, ecdhPub);\n for (let i = 0; i < res.length; i++) {\n checkbyte = res[i] | checkbyte;\n }\n if (checkbyte == 0) {\n throw Error(\"x25519 failed\");\n }\n return res;\n}\n\nexport function hpkeKemEncapsNorand(\n pkR: Uint8Array,\n skE: Uint8Array,\n): [HpkeEncapsulation, Uint8Array] {\n const enc = ecdhGetPublic(skE);\n const kem_context = new Uint8Array([...enc, ...pkR]);\n const dh = ecdh_x25519(skE, pkR);\n const suiteId = new Uint8Array([0x4b, 0x45, 0x4d, 0x00, 0x20]);\n const prk = hpkeLabeledExtract(\n \"HPKE-v1\",\n stringToBytes(\"eae_prk\"),\n dh,\n suiteId,\n );\n const ss = hpkeLabeledExpand(\n \"HPKE-v1\",\n prk,\n \"shared_secret\",\n kem_context,\n suiteId,\n 32,\n );\n return [enc, ss];\n}\n\nexport function hpkeKemDecaps(skR: Uint8Array, enc: Uint8Array): Uint8Array {\n const pkR = ecdhGetPublic(skR);\n const dh = ecdh_x25519(skR, enc);\n const kem_context = new Uint8Array([...enc, ...pkR]);\n const suiteId = new Uint8Array([0x4b, 0x45, 0x4d, 0x00, 0x20]);\n const prk = hpkeLabeledExtract(\n \"HPKE-v1\",\n stringToBytes(\"eae_prk\"),\n dh,\n suiteId,\n );\n const ss = hpkeLabeledExpand(\n \"HPKE-v1\",\n prk,\n \"shared_secret\",\n kem_context,\n suiteId,\n 32,\n );\n return ss;\n}\n\nexport function hpkeKeySchedule(\n role: HpkeRole,\n mode: HpkeMode,\n sharedSecret: Uint8Array,\n info: Uint8Array,\n psk?: Uint8Array,\n pskId?: Uint8Array,\n): HpkeContext {\n const suiteId = new ArrayBuffer(4 + 3 * 2);\n const v = new DataView(suiteId);\n v.setUint8(0, 0x48); // \"H\"\n v.setUint8(1, 0x50); // \"P\"\n v.setUint8(2, 0x4b); // \"K\"\n v.setUint8(3, 0x45); // \"E\"\n v.setUint16(4, 32); // kemID (DHKEM(X25519, HKDF-256))\n v.setUint16(6, 1); // KDF ID (HKDF-SHA256)\n v.setUint16(8, 3); // AEAD ID (ChaChaPoly1305)\n\n if (mode == HpkeMode.PSK) {\n if (!psk) {\n throw Error(\"Mode is PSK, but PSK not provided\");\n }\n if (!psk) {\n throw Error(\"Mode is PSK, but PSKID not provided\");\n }\n } else if (mode == HpkeMode.Base) {\n if (psk) {\n throw Error(\"PSK provided, but mode is Base\");\n }\n if (pskId) {\n throw Error(\"PSKID provided, but mode is Base\");\n }\n }\n const suiteIdBytes = new Uint8Array(suiteId);\n const pskIdHash = hpkeLabeledExtract(\n \"HPKE-v1\",\n stringToBytes(\"psk_id_hash\"),\n new Uint8Array([]),\n suiteIdBytes,\n );\n const infoHash = hpkeLabeledExtract(\n \"HPKE-v1\",\n stringToBytes(\"info_hash\"),\n info,\n suiteIdBytes,\n );\n const keyScheduleCtx = new Uint8Array([mode, ...pskIdHash, ...infoHash]);\n const secret = hpkeLabeledExtract(\n \"HPKE-v1\",\n stringToBytes(\"secret\"),\n psk || new Uint8Array([]),\n suiteIdBytes,\n sharedSecret,\n );\n const ctxKey = hpkeLabeledExpand(\n \"HPKE-v1\",\n secret,\n \"key\",\n keyScheduleCtx,\n suiteIdBytes,\n 32,\n ); // key 32 bytes / 256 bit\n const ctxNonce = hpkeLabeledExpand(\n \"HPKE-v1\",\n secret,\n \"base_nonce\",\n keyScheduleCtx,\n suiteIdBytes,\n 12,\n ); // nonce 12 bytes\n // We do not support secret export hence no secret export labeledExtract\n\n return { key: ctxKey, nonce: ctxNonce, role: role, seq: 0 };\n}\n\nexport function hpkeSenderSetupNorand(\n pkR: HpkePublicKey,\n skE: HpkeSecretKey,\n info: Uint8Array,\n): [HpkeEncapsulation, HpkeContext] {\n const [enc, sharedSecret] = hpkeKemEncapsNorand(pkR, skE);\n const ctx = hpkeKeySchedule(\n HpkeRole.Sender,\n HpkeMode.Base,\n sharedSecret,\n info,\n );\n return [enc, ctx];\n}\n\nexport function hpkeSenderSetup(\n pkR: HpkePublicKey,\n info: Uint8Array,\n): [HpkeEncapsulation, HpkeContext] {\n const keypair = createEcdheKeyPair();\n return hpkeSenderSetupNorand(pkR, keypair.ecdhePriv, info);\n}\n\nexport function hpkeComputeNonce(ctx: HpkeContext): Uint8Array {\n const nonce = new ArrayBuffer(12);\n const seqNboBuf = new ArrayBuffer(8);\n const v = new DataView(nonce);\n const vSeq = new DataView(seqNboBuf);\n const seqNbo = new Uint8Array(seqNboBuf);\n vSeq.setBigUint64(0, BigInt(ctx.seq));\n const offset = 12 - 8; // nonce length - sequence counter of 64 bits\n let i = 0;\n let j = 0;\n for (i = 0; i < 12; i++) {\n if (i < offset) {\n v.setUint8(i, ctx.nonce[i]);\n } else {\n v.setUint8(i, ctx.nonce[i] ^ seqNbo[j++]);\n }\n }\n return new Uint8Array(nonce);\n}\n\nexport function hpkeSealOneshotNorand(\n pkR: HpkePublicKey,\n skE: HpkeSecretKey,\n info: Uint8Array,\n aad: Uint8Array,\n plaintext: Uint8Array,\n): Uint8Array {\n const [enc, ctx] = hpkeSenderSetupNorand(pkR, skE, info);\n const nonce = hpkeComputeNonce(ctx);\n const ct = chacha20poly1305_ietf_encrypt(plaintext, aad, nonce, ctx.key);\n ctx.seq++;\n return new Uint8Array([...enc, ...ct]);\n}\n\nexport function hpkeSealOneshot(\n pkR: HpkePublicKey,\n info: Uint8Array,\n aad: Uint8Array,\n plaintext: Uint8Array,\n): Uint8Array {\n const [enc, ctx] = hpkeSenderSetup(pkR, info);\n const nonce = hpkeComputeNonce(ctx);\n const ct = chacha20poly1305_ietf_encrypt(plaintext, aad, nonce, ctx.key);\n ctx.seq++;\n return new Uint8Array([...enc, ...ct]);\n}\n\nexport function hpkeReceiverSetup(\n enc: Uint8Array,\n skR: HpkeSecretKey,\n info: Uint8Array,\n): HpkeContext {\n const sharedSecret = hpkeKemDecaps(skR, enc);\n return hpkeKeySchedule(HpkeRole.Receiver, HpkeMode.Base, sharedSecret, info);\n}\n\nexport function hpkeOpenOneshot(\n skR: HpkeSecretKey,\n info: Uint8Array,\n aad: Uint8Array,\n ciphertext: Uint8Array,\n): Uint8Array | undefined {\n try {\n const enc = ciphertext.slice(0, 32);\n const ctx = hpkeReceiverSetup(enc, skR, info);\n const nonce = hpkeComputeNonce(ctx);\n return chacha20poly1305_ietf_decrypt(\n ciphertext.slice(32),\n aad,\n nonce,\n ctx.key,\n );\n } catch (e) {\n logger.error(\"hpkeOpenOneshot failed:\" + e);\n return undefined;\n }\n}\n\nexport function hpkeSecretKeyGetPublic(sk: HpkeSecretKey): HpkePublicKey {\n return ecdhGetPublic(sk as Uint8Array) as HpkePublicKey;\n}\n\nexport function hpkeCreateSecretKey(): HpkeSecretKey {\n const keypair = createEcdheKeyPair();\n return keypair.ecdhePriv as HpkeSecretKey;\n}\n\n// RFC 8439 ChaCha20-Poly1305 (IETF variants)\n\nfunction chacha20_toUint32(data: Uint8Array | number[], index: number): number {\n return (\n data[index++] ^\n (data[index++] << 8) ^\n (data[index++] << 16) ^\n (data[index] << 24)\n );\n}\n\nfunction chacha20_rotl(data: number, shift: number): number {\n return (data << shift) | (data >>> (32 - shift));\n}\n\nexport function chacha20_quarterround(\n out: number[],\n a: number,\n b: number,\n c: number,\n d: number,\n) {\n out[d] = chacha20_rotl(out[d] ^ (out[a] += out[b]), 16);\n out[b] = chacha20_rotl(out[b] ^ (out[c] += out[d]), 12);\n out[d] = chacha20_rotl(out[d] ^ (out[a] += out[b]), 8);\n out[b] = chacha20_rotl(out[b] ^ (out[c] += out[d]), 7);\n\n out[a] >>>= 0;\n out[b] >>>= 0;\n out[c] >>>= 0;\n out[d] >>>= 0;\n}\n\nexport function chacha20_block(input: number[]): Uint8Array {\n const out = Array(64).fill(0);\n // copy param array to x\n const x = Array.from(input);\n var i = 0;\n var bytesWritten = 0;\n\n // 10 loops \u00D7 2 rounds/loop = 20 rounds\n for (i = 0; i < 20; i += 2) {\n // Odd round\n chacha20_quarterround(x, 0, 4, 8, 12);\n chacha20_quarterround(x, 1, 5, 9, 13);\n chacha20_quarterround(x, 2, 6, 10, 14);\n chacha20_quarterround(x, 3, 7, 11, 15);\n\n // Even round\n chacha20_quarterround(x, 0, 5, 10, 15);\n chacha20_quarterround(x, 1, 6, 11, 12);\n chacha20_quarterround(x, 2, 7, 8, 13);\n chacha20_quarterround(x, 3, 4, 9, 14);\n }\n\n for (i = 0; i < 16; i++) {\n // out[i] = x[i] + in[i]\n let tmp = x[i] + input[i];\n\n // update pad\n out[bytesWritten++] = tmp & 0xff;\n out[bytesWritten++] = (tmp >>> 8) & 0xff;\n out[bytesWritten++] = (tmp >>> 16) & 0xff;\n out[bytesWritten++] = (tmp >>> 24) & 0xff;\n }\n return new Uint8Array([...out]);\n}\n\nexport function chacha20_ietf_xor(\n key: Uint8Array,\n nonce: Uint8Array,\n m: Uint8Array,\n c?: number,\n): Uint8Array {\n invariant(0 != m.length);\n var bytesWritten = 0;\n const out = new Uint8Array(m.length);\n const sigma: number[] = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574];\n const keybytes = [\n chacha20_toUint32(key, 0),\n chacha20_toUint32(key, 4),\n chacha20_toUint32(key, 8),\n chacha20_toUint32(key, 12),\n chacha20_toUint32(key, 16),\n chacha20_toUint32(key, 20),\n chacha20_toUint32(key, 24),\n chacha20_toUint32(key, 28),\n ];\n const noncebytes = [\n chacha20_toUint32(nonce, 0),\n chacha20_toUint32(nonce, 4),\n chacha20_toUint32(nonce, 8),\n ];\n const param: number[] = [\n ...sigma,\n ...keybytes,\n c ? c : 0, // Counter, index is 12\n ...noncebytes,\n ];\n for (let i = 0; i < m.length; i++) {\n var pad;\n if (bytesWritten === 0 || bytesWritten === 64) {\n // generate new block //\n\n pad = chacha20_block(param);\n // counter increment\n param[12]++;\n\n // bytes counter for wrap around\n bytesWritten = 0;\n }\n invariant(pad != undefined);\n out[i] = m[i] ^ pad[bytesWritten++];\n }\n\n return out;\n}\n\nexport function chacha20_ietf(\n outBytes: number,\n key: Uint8Array,\n nonce: Uint8Array,\n): Uint8Array {\n var bytesWritten = 0;\n const m = Array(outBytes).fill(0);\n const out = new Uint8Array(m.length);\n const sigma: number[] = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574];\n const keybytes = [\n chacha20_toUint32(key, 0),\n chacha20_toUint32(key, 4),\n chacha20_toUint32(key, 8),\n chacha20_toUint32(key, 12),\n chacha20_toUint32(key, 16),\n chacha20_toUint32(key, 20),\n chacha20_toUint32(key, 24),\n chacha20_toUint32(key, 28),\n ];\n const noncebytes = [\n chacha20_toUint32(nonce, 0),\n chacha20_toUint32(nonce, 4),\n chacha20_toUint32(nonce, 8),\n ];\n const param: number[] = [\n ...sigma,\n ...keybytes,\n 0, // Counter, index is 12\n ...noncebytes,\n ];\n for (let i = 0; i < m.length; i++) {\n var pad;\n if (bytesWritten === 0 || bytesWritten === 64) {\n // generate new block //\n\n pad = chacha20_block(param);\n // counter increment\n param[12]++;\n\n // bytes counter for wrap around\n bytesWritten = 0;\n }\n invariant(pad != undefined);\n out[i] = m[i] ^ pad[bytesWritten++];\n }\n\n return out;\n}\n\nexport function chacha20poly1305_ietf_encrypt(\n m: Uint8Array,\n ad: Uint8Array,\n npub: Uint8Array,\n k: Uint8Array,\n): Uint8Array {\n invariant(k.length == 32);\n invariant(npub.length == 12);\n const slenBuf = new ArrayBuffer(8);\n const slenDv = new DataView(slenBuf);\n const pad0 = new Uint8Array(16).fill(0);\n const block0 = chacha20_ietf(64, k, npub);\n const tag = new Uint8Array(16);\n const p = new nacl.poly1305(block0);\n p.update(ad, 0, ad.length);\n p.update(pad0, 0, (0x10 - ad.length) & 0xf);\n const ct = chacha20_ietf_xor(k, npub, m, 1);\n p.update(ct, 0, ct.length);\n p.update(pad0, 0, (0x10 - m.length) & 0xf);\n slenDv.setBigUint64(0, BigInt(ad.length), true);\n p.update(new Uint8Array(slenBuf), 0, 8);\n slenDv.setBigUint64(0, BigInt(ct.length), true);\n p.update(new Uint8Array(slenBuf), 0, 8);\n p.finish(tag, 0);\n return new Uint8Array([...ct, ...tag]);\n}\n\nexport function chacha20poly1305_ietf_decrypt(\n ct: Uint8Array,\n ad: Uint8Array,\n npub: Uint8Array,\n k: Uint8Array,\n): Uint8Array | undefined {\n invariant(k.length == 32);\n invariant(npub.length == 12);\n const slenBuf = new ArrayBuffer(8);\n const slenDv = new DataView(slenBuf);\n const pad0 = new Uint8Array(16).fill(0);\n const block0 = chacha20_ietf(64, k, npub);\n const tag = new Uint8Array(16);\n const p = new nacl.poly1305(block0);\n const mlen = ct.length - tag.length;\n p.update(ad, 0, ad.length);\n p.update(pad0, 0, (0x10 - ad.length) & 0xf);\n p.update(ct, 0, mlen);\n p.update(pad0, 0, (0x10 - mlen) & 0xf);\n slenDv.setBigUint64(0, BigInt(ad.length), true);\n p.update(new Uint8Array(slenBuf), 0, 8);\n slenDv.setBigUint64(0, BigInt(mlen), true);\n p.update(new Uint8Array(slenBuf), 0, 8);\n p.finish(tag, 0);\n if (nacl.crypto_verify_16(tag, 0, ct, mlen) !== 0) {\n return undefined;\n }\n const m = chacha20_ietf_xor(k, npub, ct.slice(0, mlen), 1);\n return m;\n}\n", "// SHA-256 for JavaScript.\n//\n// Written in 2014-2016 by Dmitry Chestnykh.\n// Public domain, no warranty.\n//\n// Functions (accept and return Uint8Arrays):\n//\n// sha256(message) -> hash\n// sha256.hmac(key, message) -> mac\n//\n// Classes:\n//\n// new sha256.Hash()\nexport const digestLength = 32;\nexport const blockSize = 64;\n\n// SHA-256 constants\nconst K = new Uint32Array([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,\n 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\n 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\n 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,\n 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\n 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\n 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\n 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n]);\n\nfunction hashBlocks(\n w: Int32Array,\n v: Int32Array,\n p: Uint8Array,\n pos: number,\n len: number,\n): number {\n let a: number,\n b: number,\n c: number,\n d: number,\n e: number,\n f: number,\n g: number,\n h: number,\n u: number,\n i: number,\n j: number,\n t1: number,\n t2: number;\n while (len >= 64) {\n a = v[0];\n b = v[1];\n c = v[2];\n d = v[3];\n e = v[4];\n f = v[5];\n g = v[6];\n h = v[7];\n\n for (i = 0; i < 16; i++) {\n j = pos + i * 4;\n w[i] =\n ((p[j] & 0xff) << 24) |\n ((p[j + 1] & 0xff) << 16) |\n ((p[j + 2] & 0xff) << 8) |\n (p[j + 3] & 0xff);\n }\n\n for (i = 16; i < 64; i++) {\n u = w[i - 2];\n t1 =\n ((u >>> 17) | (u << (32 - 17))) ^\n ((u >>> 19) | (u << (32 - 19))) ^\n (u >>> 10);\n\n u = w[i - 15];\n t2 =\n ((u >>> 7) | (u << (32 - 7))) ^\n ((u >>> 18) | (u << (32 - 18))) ^\n (u >>> 3);\n\n w[i] = ((t1 + w[i - 7]) | 0) + ((t2 + w[i - 16]) | 0);\n }\n\n for (i = 0; i < 64; i++) {\n t1 =\n ((((((e >>> 6) | (e << (32 - 6))) ^\n ((e >>> 11) | (e << (32 - 11))) ^\n ((e >>> 25) | (e << (32 - 25)))) +\n ((e & f) ^ (~e & g))) |\n 0) +\n ((h + ((K[i] + w[i]) | 0)) | 0)) |\n 0;\n\n t2 =\n ((((a >>> 2) | (a << (32 - 2))) ^\n ((a >>> 13) | (a << (32 - 13))) ^\n ((a >>> 22) | (a << (32 - 22)))) +\n ((a & b) ^ (a & c) ^ (b & c))) |\n 0;\n\n h = g;\n g = f;\n f = e;\n e = (d + t1) | 0;\n d = c;\n c = b;\n b = a;\n a = (t1 + t2) | 0;\n }\n\n v[0] += a;\n v[1] += b;\n v[2] += c;\n v[3] += d;\n v[4] += e;\n v[5] += f;\n v[6] += g;\n v[7] += h;\n\n pos += 64;\n len -= 64;\n }\n return pos;\n}\n\n// Hash implements SHA256 hash algorithm.\nexport class HashSha256 {\n digestLength: number = digestLength;\n blockSize: number = blockSize;\n\n // Note: Int32Array is used instead of Uint32Array for performance reasons.\n private state: Int32Array = new Int32Array(8); // hash state\n private temp: Int32Array = new Int32Array(64); // temporary state\n private buffer: Uint8Array = new Uint8Array(128); // buffer for data to hash\n private bufferLength = 0; // number of bytes in buffer\n private bytesHashed = 0; // number of total bytes hashed\n\n finished = false; // indicates whether the hash was finalized\n\n constructor() {\n this.reset();\n }\n\n // Resets hash state making it possible\n // to reuse this instance to hash other data.\n reset(): this {\n this.state[0] = 0x6a09e667;\n this.state[1] = 0xbb67ae85;\n this.state[2] = 0x3c6ef372;\n this.state[3] = 0xa54ff53a;\n this.state[4] = 0x510e527f;\n this.state[5] = 0x9b05688c;\n this.state[6] = 0x1f83d9ab;\n this.state[7] = 0x5be0cd19;\n this.bufferLength = 0;\n this.bytesHashed = 0;\n this.finished = false;\n return this;\n }\n\n // Cleans internal buffers and re-initializes hash state.\n clean(): void {\n for (let i = 0; i < this.buffer.length; i++) {\n this.buffer[i] = 0;\n }\n for (let i = 0; i < this.temp.length; i++) {\n this.temp[i] = 0;\n }\n this.reset();\n }\n\n // Updates hash state with the given data.\n //\n // Optionally, length of the data can be specified to hash\n // fewer bytes than data.length.\n //\n // Throws error when trying to update already finalized hash:\n // instance must be reset to use it again.\n update(data: Uint8Array, dataLength: number = data.length): this {\n if (this.finished) {\n throw new Error(\"SHA256: can't update because hash was finished.\");\n }\n let dataPos = 0;\n this.bytesHashed += dataLength;\n if (this.bufferLength > 0) {\n while (this.bufferLength < 64 && dataLength > 0) {\n this.buffer[this.bufferLength++] = data[dataPos++];\n dataLength--;\n }\n if (this.bufferLength === 64) {\n hashBlocks(this.temp, this.state, this.buffer, 0, 64);\n this.bufferLength = 0;\n }\n }\n if (dataLength >= 64) {\n dataPos = hashBlocks(this.temp, this.state, data, dataPos, dataLength);\n dataLength %= 64;\n }\n while (dataLength > 0) {\n this.buffer[this.bufferLength++] = data[dataPos++];\n dataLength--;\n }\n return this;\n }\n\n // Finalizes hash state and puts hash into out.\n //\n // If hash was already finalized, puts the same value.\n finish(out: Uint8Array): this {\n if (!this.finished) {\n const bytesHashed = this.bytesHashed;\n const left = this.bufferLength;\n const bitLenHi = (bytesHashed / 0x20000000) | 0;\n const bitLenLo = bytesHashed << 3;\n const padLength = bytesHashed % 64 < 56 ? 64 : 128;\n\n this.buffer[left] = 0x80;\n for (let i = left + 1; i < padLength - 8; i++) {\n this.buffer[i] = 0;\n }\n this.buffer[padLength - 8] = (bitLenHi >>> 24) & 0xff;\n this.buffer[padLength - 7] = (bitLenHi >>> 16) & 0xff;\n this.buffer[padLength - 6] = (bitLenHi >>> 8) & 0xff;\n this.buffer[padLength - 5] = (bitLenHi >>> 0) & 0xff;\n this.buffer[padLength - 4] = (bitLenLo >>> 24) & 0xff;\n this.buffer[padLength - 3] = (bitLenLo >>> 16) & 0xff;\n this.buffer[padLength - 2] = (bitLenLo >>> 8) & 0xff;\n this.buffer[padLength - 1] = (bitLenLo >>> 0) & 0xff;\n\n hashBlocks(this.temp, this.state, this.buffer, 0, padLength);\n\n this.finished = true;\n }\n\n for (let i = 0; i < 8; i++) {\n out[i * 4 + 0] = (this.state[i] >>> 24) & 0xff;\n out[i * 4 + 1] = (this.state[i] >>> 16) & 0xff;\n out[i * 4 + 2] = (this.state[i] >>> 8) & 0xff;\n out[i * 4 + 3] = (this.state[i] >>> 0) & 0xff;\n }\n\n return this;\n }\n\n // Returns the final hash digest.\n digest(): Uint8Array {\n const out = new Uint8Array(this.digestLength);\n this.finish(out);\n return out;\n }\n\n // Internal function for use in HMAC for optimization.\n _saveState(out: Uint32Array): void {\n for (let i = 0; i < this.state.length; i++) {\n out[i] = this.state[i];\n }\n }\n\n // Internal function for use in HMAC for optimization.\n _restoreState(from: Uint32Array, bytesHashed: number): void {\n for (let i = 0; i < this.state.length; i++) {\n this.state[i] = from[i];\n }\n this.bytesHashed = bytesHashed;\n this.finished = false;\n this.bufferLength = 0;\n }\n}\n\n// HMAC implements HMAC-SHA256 message authentication algorithm.\nexport class HMAC {\n private inner: HashSha256 = new HashSha256();\n private outer: HashSha256 = new HashSha256();\n\n blockSize: number = this.inner.blockSize;\n digestLength: number = this.inner.digestLength;\n\n // Copies of hash states after keying.\n // Need for quick reset without hashing they key again.\n private istate: Uint32Array;\n private ostate: Uint32Array;\n\n constructor(key: Uint8Array) {\n const pad = new Uint8Array(this.blockSize);\n if (key.length > this.blockSize) {\n new HashSha256().update(key).finish(pad).clean();\n } else {\n for (let i = 0; i < key.length; i++) {\n pad[i] = key[i];\n }\n }\n for (let i = 0; i < pad.length; i++) {\n pad[i] ^= 0x36;\n }\n this.inner.update(pad);\n\n for (let i = 0; i < pad.length; i++) {\n pad[i] ^= 0x36 ^ 0x5c;\n }\n this.outer.update(pad);\n\n this.istate = new Uint32Array(8);\n this.ostate = new Uint32Array(8);\n\n this.inner._saveState(this.istate);\n this.outer._saveState(this.ostate);\n\n for (let i = 0; i < pad.length; i++) {\n pad[i] = 0;\n }\n }\n\n // Returns HMAC state to the state initialized with key\n // to make it possible to run HMAC over the other data with the same\n // key without creating a new instance.\n reset(): this {\n this.inner._restoreState(this.istate, this.inner.blockSize);\n this.outer._restoreState(this.ostate, this.outer.blockSize);\n return this;\n }\n\n // Cleans HMAC state.\n clean(): void {\n for (let i = 0; i < this.istate.length; i++) {\n this.ostate[i] = this.istate[i] = 0;\n }\n this.inner.clean();\n this.outer.clean();\n }\n\n // Updates state with provided data.\n update(data: Uint8Array): this {\n this.inner.update(data);\n return this;\n }\n\n // Finalizes HMAC and puts the result in out.\n finish(out: Uint8Array): this {\n if (this.outer.finished) {\n this.outer.finish(out);\n } else {\n this.inner.finish(out);\n this.outer.update(out, this.digestLength).finish(out);\n }\n return this;\n }\n\n // Returns message authentication code.\n digest(): Uint8Array {\n const out = new Uint8Array(this.digestLength);\n this.finish(out);\n return out;\n }\n}\n\n// Returns SHA256 hash of data.\nexport function sha256(data: Uint8Array): Uint8Array {\n const h = new HashSha256().update(data);\n const digest = h.digest();\n h.clean();\n return digest;\n}\n\n// Returns HMAC-SHA256 of data under the key.\nexport function hmacSha256(key: Uint8Array, data: Uint8Array): Uint8Array {\n const h = new HMAC(key).update(data);\n const digest = h.digest();\n h.clean();\n return digest;\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019 GNUnet e.V.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport * as nacl from \"./nacl-fast.js\";\nimport { sha256 } from \"./sha256.js\";\n\nexport function sha512(data: Uint8Array): Uint8Array {\n return nacl.hash(data);\n}\n\nexport function hmac(\n digest: (d: Uint8Array) => Uint8Array,\n blockSize: number,\n key: Uint8Array,\n message: Uint8Array,\n): Uint8Array {\n if (key.byteLength > blockSize) {\n key = digest(key);\n }\n if (key.byteLength < blockSize) {\n const k = key;\n key = new Uint8Array(blockSize);\n key.set(k, 0);\n }\n const okp = new Uint8Array(blockSize);\n const ikp = new Uint8Array(blockSize);\n for (let i = 0; i < blockSize; i++) {\n ikp[i] = key[i] ^ 0x36;\n okp[i] = key[i] ^ 0x5c;\n }\n const b1 = new Uint8Array(blockSize + message.byteLength);\n b1.set(ikp, 0);\n b1.set(message, blockSize);\n const h0 = digest(b1);\n const b2 = new Uint8Array(blockSize + h0.length);\n b2.set(okp, 0);\n b2.set(h0, blockSize);\n return digest(b2);\n}\n\nexport function hmacSha512(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(sha512, 128, key, message);\n}\n\nexport function hmacSha256(key: Uint8Array, message: Uint8Array): Uint8Array {\n return hmac(sha256, 64, key, message);\n}\n", "/*\n This file is part of GNU Taler\n Copyright (C) 2012-2025 Taler Systems SA\n\n GNU Taler is free software: you can redistribute it and/or modify it\n under the terms of the GNU Lesser General Public License as published\n by the Free Software Foundation, either version 3 of the License,\n or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but\n WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see .\n\n SPDX-License-Identifier: LGPL3.0-or-later\n\n Note: the LGPL does not apply to all components of GNU Taler,\n but it does apply to this file.\n */\n\nexport enum TalerSignaturePurpose {\n\n\n /**\n * Initialize or update the status of an AML key for an AML officer\n */\n MASTER_AML_KEY = 1017,\n\n\n /**\n * Affirm wiring of exchange profits to operator account.\n */\n MASTER_DRAIN_PROFIT = 1018,\n\n\n /**\n * Signature affirming a partner configuration for wads.\n */\n MASTER_PARTNER_DETAILS = 1019,\n\n\n /**\n * The given revocation key was revoked and must no longer be used.\n */\n MASTER_SIGNING_KEY_REVOKED = 1020,\n\n\n /**\n * Add payto URI to the list of our wire methods.\n */\n MASTER_ADD_WIRE = 1021,\n\n\n /**\n * Signature over global set of fees charged by the exchange.\n */\n MASTER_GLOBAL_FEES = 1022,\n\n\n /**\n * Remove payto URI from the list of our wire methods.\n */\n MASTER_DEL_WIRE = 1023,\n\n\n /**\n * Purpose for signing public keys signed by the exchange master key.\n */\n MASTER_SIGNING_KEY_VALIDITY = 1024,\n\n\n /**\n * Purpose for denomination keys signed by the exchange master key.\n */\n MASTER_DENOMINATION_KEY_VALIDITY = 1025,\n\n\n /**\n * Add an auditor to the list of our auditors.\n */\n MASTER_ADD_AUDITOR = 1026,\n\n\n /**\n * Remove an auditor from the list of our auditors.\n */\n MASTER_DEL_AUDITOR = 1027,\n\n\n /**\n * Fees charged per (aggregate) wire transfer to the merchant.\n */\n MASTER_WIRE_FEES = 1028,\n\n\n /**\n * The given revocation key was revoked and must no longer be used.\n */\n MASTER_DENOMINATION_KEY_REVOKED = 1029,\n\n\n /**\n * Signature where the Exchange confirms its IBAN details in the /wire response.\n */\n MASTER_WIRE_DETAILS = 1030,\n\n\n /**\n * Set the configuration of an extension (age-restriction or peer2peer)\n */\n MASTER_EXTENSION = 1031,\n\n\n /**\n * Purpose for the state of a reserve, signed by the exchange's signing key.\n */\n EXCHANGE_RESERVE_STATUS = 1032,\n\n\n /**\n * Signature where the Exchange confirms a deposit request.\n */\n EXCHANGE_CONFIRM_DEPOSIT = 1033,\n\n\n /**\n * Signature where the exchange (current signing key) confirms the no-reveal index for cut-and-choose and the validity of the melted coins.\n */\n EXCHANGE_CONFIRM_MELT = 1034,\n\n\n /**\n * Signature where the Exchange confirms the full /keys response set.\n */\n EXCHANGE_KEY_SET = 1035,\n\n\n /**\n * Signature where the Exchange confirms the /track/transaction response.\n */\n EXCHANGE_CONFIRM_WIRE = 1036,\n\n\n /**\n * Signature where the Exchange confirms the /wire/deposit response.\n */\n EXCHANGE_CONFIRM_WIRE_DEPOSIT = 1037,\n\n\n /**\n * Signature where the Exchange confirms a refund request.\n */\n EXCHANGE_CONFIRM_REFUND = 1038,\n\n\n /**\n * Signature where the Exchange confirms a recoup.\n */\n EXCHANGE_CONFIRM_RECOUP = 1039,\n\n\n /**\n * Signature where the Exchange confirms it closed a reserve.\n */\n EXCHANGE_RESERVE_CLOSED = 1040,\n\n\n /**\n * Signature where the Exchange confirms a recoup-refresh operation.\n */\n EXCHANGE_CONFIRM_RECOUP_REFRESH = 1041,\n\n\n /**\n * Signature where the Exchange confirms that it does not know a denomination (hash).\n */\n EXCHANGE_AFFIRM_DENOM_UNKNOWN = 1042,\n\n\n /**\n * Signature where the Exchange confirms that it does not consider a denomination valid for the given operation at this time.\n */\n EXCHANGE_AFFIRM_DENOM_EXPIRED = 1043,\n\n\n /**\n * Signature by which the exchange affirms that a purse was created with a certain amount deposited into it.\n */\n EXCHANGE_CONFIRM_PURSE_CREATION = 1045,\n\n\n /**\n * Signature by which the exchange affirms that a purse was merged into a reserve with a certain amount in it.\n */\n EXCHANGE_CONFIRM_PURSE_MERGED = 1046,\n\n\n /**\n * Purpose for the state of a purse, signed by the exchange's signing key.\n */\n EXCHANGE_PURSE_STATUS = 1047,\n\n\n /**\n * Signature by which the exchange attests identity attributes of a particular reserve owner.\n */\n EXCHANGE_RESERVE_ATTEST_DETAILS = 1048,\n\n\n /**\n * Signature by which the exchange confirms that a purse expired and a coin was refunded.\n */\n EXCHANGE_CONFIRM_PURSE_REFUND = 1049,\n\n\n /**\n * Signature where the Exchange confirms an (age-)withdraw.\n */\n EXCHANGE_CONFIRM_WITHDRAW = 1050,\n\n\n /**\n * Signature where the auditor confirms that he is aware of certain denomination keys from the exchange.\n */\n AUDITOR_EXCHANGE_KEYS = 1064,\n\n\n /**\n * Signature where the merchant confirms a contract (to the customer).\n */\n MERCHANT_CONTRACT = 1101,\n\n\n /**\n * Signature where the merchant confirms a refund (of a coin).\n */\n MERCHANT_REFUND = 1102,\n\n\n /**\n * Signature where the merchant confirms that he needs the wire transfer identifier for a deposit operation.\n */\n MERCHANT_TRACK_TRANSACTION = 1103,\n\n\n /**\n * Signature where the merchant confirms that the payment was successful\n */\n MERCHANT_PAYMENT_OK = 1104,\n\n\n /**\n * Signature where the merchant confirms its own (salted) wire details (not yet really used).\n */\n MERCHANT_WIRE_DETAILS = 1107,\n\n\n /**\n * Signature where the merchant issues a token by blindly signing it. Signed with the token issue private key.\n */\n MERCHANT_TOKEN_ISSUE = 1108,\n\n\n /**\n * Signature where the reserve key confirms a withdraw request. Signed with the reserve private key.\n */\n WALLET_RESERVE_WITHDRAW = 1200,\n\n\n /**\n * Signature made by the wallet of a user to confirm a deposit of a coin.\n */\n WALLET_COIN_DEPOSIT = 1201,\n\n\n /**\n * Signature using a coin key confirming the melting of a coin. Signed with the coin's private key.\n */\n WALLET_COIN_MELT = 1202,\n\n\n /**\n * Signature using a coin key requesting recoup. Signed with the coin's private key.\n */\n WALLET_COIN_RECOUP = 1203,\n\n\n /**\n * Signature using a coin key authenticating link data. Signed with the old coin's private key.\n */\n WALLET_COIN_LINK = 1204,\n\n\n /**\n * Signature using a reserve key by which a wallet requests a payment target UUID for itself. Signs over just a purpose (no body), as the signature only serves to demonstrate that the request comes from the wallet controlling the private key, and not some third party.\n */\n WALLET_ACCOUNT_SETUP = 1205,\n\n\n /**\n * Signature using a coin key requesting recoup-refresh. Signed with the coin private key.\n */\n WALLET_COIN_RECOUP_REFRESH = 1206,\n\n\n /**\n * Signature using a age restriction key for attestation of a particular age/age-group.\n */\n WALLET_AGE_ATTESTATION = 1207,\n\n\n /**\n * Request full or partial reserve history. Signed with the reserve private key.\n */\n WALLET_RESERVE_HISTORY = 1208,\n\n\n /**\n * Request full or partial coin history. Signed with the coin private key.\n */\n WALLET_COIN_HISTORY = 1209,\n\n\n /**\n * Request purse creation (without reserve). Signed by the purse private key.\n */\n WALLET_PURSE_CREATE = 1210,\n\n\n /**\n * Request coin to be deposited into a purse. Signed with the coin private key.\n */\n WALLET_PURSE_DEPOSIT = 1211,\n\n\n /**\n * Request purse status. Signed with the purse private key.\n */\n WALLET_PURSE_STATUS = 1212,\n\n\n /**\n * Request purse to be merged with a reserve. Signed with the purse private key.\n */\n WALLET_PURSE_MERGE = 1213,\n\n\n /**\n * Request purse to be merged with a reserve. Signed by the reserve private key.\n */\n WALLET_ACCOUNT_MERGE = 1214,\n\n\n /**\n * Request account to be closed. Signed with the reserve private key.\n */\n WALLET_RESERVE_CLOSE = 1215,\n\n\n /**\n * Associates encrypted contract with a purse. Signed with the purse private key.\n */\n WALLET_PURSE_ECONTRACT = 1216,\n\n\n /**\n * Request reserve to be kept open. Signed with the reserve private key.\n */\n WALLET_RESERVE_OPEN = 1217,\n\n\n /**\n * Request coin to be used to pay for reserve to be kept open. Signed with the coin private key.\n */\n WALLET_RESERVE_OPEN_DEPOSIT = 1218,\n\n\n /**\n * Request attestation about reserve owner. Signed by the reserve private key.\n */\n WALLET_RESERVE_ATTEST_DETAILS = 1219,\n\n\n /**\n * Signature by which a wallet requests a purse to be deleted.\n */\n WALLET_PURSE_DELETE = 1220,\n\n\n /**\n * Signature where the reserve key confirms an age-withdraw request. Signed with the reserve private key.\n */\n WALLET_RESERVE_AGE_WITHDRAW = 1221,\n\n\n /**\n * Signature where the token use key confirms the usage of a token on a pay request. Signed with the token use private key.\n */\n WALLET_TOKEN_USE = 1222,\n\n\n /**\n * Signature on a denomination key announcement.\n */\n SM_RSA_DENOMINATION_KEY = 1250,\n\n\n /**\n * Signature on an exchange message signing key announcement.\n */\n SM_SIGNING_KEY = 1251,\n\n\n /**\n * Signature on a denomination key announcement.\n */\n SM_CS_DENOMINATION_KEY = 1252,\n\n\n /**\n * EdDSA test signature.\n */\n CLIENT_TEST_EDDSA = 1302,\n\n\n /**\n * EdDSA test signature.\n */\n EXCHANGE_TEST_EDDSA = 1303,\n\n\n /**\n * Signature by which an AML officer signs an AML decision.\n */\n AML_DECISION = 1350,\n\n\n /**\n * Signature by which an AML officer requests AML data.\n */\n AML_QUERY = 1351,\n\n\n /**\n * Signature by which an account owner authorizes access to a KYC operation.\n */\n KYC_AUTH = 1360,\n\n\n /**\n * EdDSA signature for a policy upload.\n */\n ANASTASIS_POLICY_UPLOAD = 1400,\n\n\n /**\n * EdDSA signature for a backup upload.\n */\n SYNC_BACKUP_UPLOAD = 1450,\n\n\n /**\n * Signature over messages to delete in the mailbox service\n */\n MAILBOX_MESSAGES_DELETE = 1551,\n\n\n /**\n * Signature over new key set in key update\n */\n MAILBOX_KEYS_UPDATE = 1552,\n\n\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Result of a generic operation that can fail.\n */\nexport type Result = ResultOk | ResultError;\n\nexport interface ResultOk {\n readonly tag: \"ok\";\n readonly value: T;\n}\n\nexport interface ResultError {\n readonly tag: \"error\";\n readonly error: Err;\n readonly detail: Detail;\n}\n\nexport const Result = {\n of(value: T): ResultOk {\n return { tag: \"ok\", value };\n },\n error(error: Err): ResultError {\n return { tag: \"error\", error, detail: undefined };\n },\n errorWithDetail(\n error: Err,\n detail: Detail,\n ): ResultError {\n return { tag: \"error\", error, detail };\n },\n unpack(r: Result): T {\n if (r.tag !== \"ok\") {\n throw Error(\"expected success result\");\n }\n return r.value;\n },\n isOk(r: Result): r is ResultOk {\n return r.tag === \"ok\";\n },\n isError(r: Result): r is ResultError {\n return r.tag === \"error\";\n },\n orUndefined(r: Result): T | undefined {\n if (r.tag !== \"ok\") {\n return undefined;\n }\n return r.value;\n },\n orElse(r: Result, alt: TA): T | TA {\n if (r.tag !== \"ok\") {\n return alt;\n }\n return r.value;\n },\n};\n", "// Copyright (c) 2017, 2021 Pieter Wuille\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport { assertUnreachable } from \"./errors.js\";\nimport { BtAddrString } from \"./payto.js\";\nimport { Result } from \"./result.js\";\n\nvar CHARSET = \"qpzry9x8gf2tvdw0s3jn54khce6mua7l\";\nvar GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\n\nfunction polymod(values: Array): number {\n var chk = 1;\n for (var p = 0; p < values.length; ++p) {\n var top = chk >> 25;\n chk = ((chk & 0x1ffffff) << 5) ^ values[p];\n for (var i = 0; i < 5; ++i) {\n if ((top >> i) & 1) {\n chk ^= GENERATOR[i];\n }\n }\n }\n return chk;\n}\n\nfunction hrpExpand(hrp: string): Array {\n const ret: Array = [];\n for (let p = 0; p < hrp.length; ++p) {\n ret.push(hrp.charCodeAt(p) >> 5);\n }\n ret.push(0);\n for (let p = 0; p < hrp.length; ++p) {\n ret.push(hrp.charCodeAt(p) & 31);\n }\n return ret;\n}\n\nfunction getEncodingConst(enc: BitcoinBech32.Encodings): number {\n switch (enc) {\n case BitcoinBech32.Encodings.BECH32:\n return 1;\n case BitcoinBech32.Encodings.BECH32M:\n return 0x2bc830a3;\n\n default: {\n assertUnreachable(enc);\n }\n }\n}\n\nfunction verifyChecksum(\n hrp: string,\n data: Array,\n enc: BitcoinBech32.Encodings,\n): boolean {\n return polymod(hrpExpand(hrp).concat(data)) === getEncodingConst(enc);\n}\n\nfunction createChecksum(\n hrp: string,\n data: Array,\n enc: BitcoinBech32.Encodings,\n): Array {\n const values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);\n const mod = polymod(values) ^ getEncodingConst(enc);\n const ret: Array = [];\n for (let p = 0; p < 6; ++p) {\n ret.push((mod >> (5 * (5 - p))) & 31);\n }\n return ret;\n}\n\nexport namespace BitcoinBech32 {\n export enum Encodings {\n BECH32 = \"bech32\",\n BECH32M = \"bech32m\",\n }\n\n export function encode(\n hrp: string,\n data: Array,\n enc: Encodings,\n ): BtAddrString {\n var combined = data.concat(createChecksum(hrp, data, enc));\n var ret = hrp + \"1\";\n for (var p = 0; p < combined.length; ++p) {\n ret += CHARSET.charAt(combined[p]);\n }\n return ret as BtAddrString;\n }\n\n export enum BitcoinParseError {\n /**\n * Charset can only be from BECH32\n */\n WRONG_CHARSET,\n /**\n * All uppercased or all lowercased\n */\n MIXING_UPPER_AND_LOWER,\n /**\n * Separator is a '1' between addr and addrtype\n */\n MISSING_HRP,\n /**\n * Should be less or equal to 90 chars\n */\n TOO_LONG,\n /**\n * Addr should be greater or equal to 6 chars\n */\n TOO_SHORT,\n WRONG_CHECKSUM,\n }\n\n export function decode(\n bechString: string,\n enc?: Encodings,\n ): Result<\n {\n hrp: string;\n data: number[];\n },\n BitcoinParseError\n > {\n let p;\n let has_lower = false;\n let has_upper = false;\n for (p = 0; p < bechString.length; ++p) {\n if (bechString.charCodeAt(p) < 33 || bechString.charCodeAt(p) > 126) {\n return Result.error(BitcoinParseError.WRONG_CHARSET);\n }\n if (bechString.charCodeAt(p) >= 97 && bechString.charCodeAt(p) <= 122) {\n has_lower = true;\n }\n if (bechString.charCodeAt(p) >= 65 && bechString.charCodeAt(p) <= 90) {\n has_upper = true;\n }\n }\n if (has_lower && has_upper) {\n return Result.error(BitcoinParseError.MIXING_UPPER_AND_LOWER);\n }\n bechString = bechString.toLowerCase();\n const pos = bechString.lastIndexOf(\"1\");\n if (pos < 1) {\n return Result.error(BitcoinParseError.MISSING_HRP);\n }\n if (pos + 7 > bechString.length) {\n return Result.error(BitcoinParseError.TOO_SHORT);\n }\n if (bechString.length > 90) {\n return Result.error(BitcoinParseError.TOO_LONG);\n }\n const hrp = bechString.substring(0, pos);\n var data: Array = [];\n for (p = pos + 1; p < bechString.length; ++p) {\n var d = CHARSET.indexOf(bechString.charAt(p));\n if (d === -1) {\n return Result.error(BitcoinParseError.WRONG_CHARSET);\n }\n data.push(d);\n }\n if (enc && !verifyChecksum(hrp, data, enc)) {\n return Result.error(BitcoinParseError.WRONG_CHECKSUM);\n }\n return Result.of({ hrp, data: data.slice(0, data.length - 6) });\n }\n}\n", "// Copyright (c) 2017, 2021 Pieter Wuille\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport { BitcoinBech32 } from \"./bech32.js\";\nimport { opFixedSuccess, opKnownFailure } from \"./operation.js\";\nimport { Result } from \"./result.js\";\n\nfunction convertbits(\n data: Array,\n frombits: number,\n tobits: number,\n pad: boolean,\n): Array | null {\n let acc = 0;\n let bits = 0;\n const ret: Array = [];\n const maxv = (1 << tobits) - 1;\n for (let p = 0; p < data.length; ++p) {\n const value = data[p];\n if (value < 0 || value >> frombits !== 0) {\n return null;\n }\n acc = (acc << frombits) | value;\n bits += frombits;\n while (bits >= tobits) {\n bits -= tobits;\n ret.push((acc >> bits) & maxv);\n }\n }\n if (pad) {\n if (bits > 0) {\n ret.push((acc << (tobits - bits)) & maxv);\n }\n } else if (bits >= frombits || (acc << (tobits - bits)) & maxv) {\n return null;\n }\n return ret;\n}\n\nexport namespace BitcoinSewgit {\n export enum BitcoinSewgitParseError {\n /**\n * Input data is wrong\n */\n INVALID_DATA = \"invalid-data\",\n /**\n * Generic parsing problem\n */\n DECODING_PROBLEM = \"decoding-problem\",\n }\n export function decode(\n addr: string,\n enc?: BitcoinBech32.Encodings,\n ): Result<\n {\n version: number;\n program: number[];\n },\n BitcoinSewgitParseError | BitcoinBech32.BitcoinParseError\n > {\n const decResp = BitcoinBech32.decode(addr, enc);\n if (decResp.tag === \"error\") {\n return decResp;\n }\n const { value: dec } = decResp;\n\n if (dec.data.length < 1 || dec.data[0] > 16) {\n return Result.error(BitcoinSewgitParseError.INVALID_DATA);\n }\n const res = convertbits(dec.data.slice(1), 5, 8, false);\n if (res === null || res.length < 2 || res.length > 40) {\n return Result.error(BitcoinSewgitParseError.DECODING_PROBLEM);\n }\n if (dec.data[0] === 0 && res.length !== 20 && res.length !== 32) {\n return Result.error(BitcoinSewgitParseError.DECODING_PROBLEM);\n }\n if (dec.data[0] === 0 && enc === BitcoinBech32.Encodings.BECH32) {\n return Result.error(BitcoinSewgitParseError.DECODING_PROBLEM);\n }\n if (dec.data[0] !== 0 && enc === BitcoinBech32.Encodings.BECH32M) {\n return Result.error(BitcoinSewgitParseError.DECODING_PROBLEM);\n }\n return Result.of({ version: dec.data[0], program: res });\n }\n\n export function encode(hrp: string, version: number, program: Array) {\n const enc =\n version > 0\n ? BitcoinBech32.Encodings.BECH32M\n : BitcoinBech32.Encodings.BECH32;\n const bits = convertbits(program, 8, 5, true);\n if (!bits) {\n return opKnownFailure(BitcoinSewgitParseError.INVALID_DATA);\n }\n const ret = BitcoinBech32.encode(hrp, [version].concat(bits), enc);\n return opFixedSuccess(ret);\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n *\n * @author sebasjm\n */\n\n/**\n * Imports.\n */\nimport { AmountJson, Amounts } from \"./amounts.js\";\nimport { BtAddrString } from \"./payto.js\";\nimport { Result } from \"./result.js\";\nimport { BitcoinSewgit } from \"./segwit_addr.js\";\n\nexport enum GenerateSegwitAddrError {\n /**\n * The reserve pub used to generate the segwith is invalid\n */\n WRONG_RESERVE_PUB = \"wrong-reserve-pub\",\n /**\n * The net prefix of the addr is unsupported\n */\n WRONG_PREFIX = \"wrong-prefix\",\n /**\n * The process of generating a segwit failed\n */\n INVALID_SEGWIT = \"invalid-segwit\",\n}\n\nexport function generateFakeSegwitAddress(\n pub: Uint8Array,\n addr: string,\n): Result<[BtAddrString, BtAddrString], GenerateSegwitAddrError> {\n const first_rnd = new Uint8Array(4);\n first_rnd.set(pub.subarray(0, 4));\n const second_rnd = new Uint8Array(4);\n second_rnd.set(pub.subarray(0, 4));\n\n first_rnd[0] = first_rnd[0] & 0b0111_1111;\n second_rnd[0] = second_rnd[0] | 0b1000_0000;\n\n const first_part = new Uint8Array(first_rnd.length + pub.length / 2);\n first_part.set(first_rnd, 0);\n first_part.set(pub.subarray(0, 16), 4);\n\n const second_part = new Uint8Array(first_rnd.length + pub.length / 2);\n second_part.set(second_rnd, 0);\n second_part.set(pub.subarray(16, 32), 4);\n\n const prefix =\n addr[0] === \"t\" && addr[1] == \"b\"\n ? \"tb\"\n : addr[0] === \"b\" && addr[1] == \"c\" && addr[2] === \"r\" && addr[3] == \"t\"\n ? \"bcrt\"\n : addr[0] === \"b\" && addr[1] == \"c\"\n ? \"bc\"\n : undefined;\n if (prefix === undefined) {\n return Result.error(GenerateSegwitAddrError.WRONG_PREFIX);\n }\n\n const addr1 = BitcoinSewgit.encode(prefix, 0, Array.from(first_part));\n if (addr1.type === \"fail\") {\n return Result.error(GenerateSegwitAddrError.INVALID_SEGWIT);\n }\n const addr2 = BitcoinSewgit.encode(prefix, 0, Array.from(second_part));\n if (addr2.type === \"fail\") {\n return Result.error(GenerateSegwitAddrError.INVALID_SEGWIT);\n }\n const result: [BtAddrString, BtAddrString] = [addr1.body, addr2.body];\n return Result.of(result);\n}\n\n// https://github.com/bitcoin/bitcoin/blob/master/src/policy/policy.cpp\nexport function segwitMinAmount(currency: string): AmountJson {\n return Amounts.parseOrThrow(`${currency}:0.00000294`);\n}\n", "/*\n This file is part of GNU Taler\n (C) 2023 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { Result } from \"./result.js\";\n\n/**\n * IBAN validation.\n *\n * Currently only validates the checksum.\n *\n * It does not validate:\n * - Country-specific length\n * - Country-specific checksums\n *\n * The country list is also not complete.\n *\n * @author Florian Dold \n * @author sebasjm\n */\n\ndeclare const __iban: unique symbol;\nexport type IbanString = string & { [__iban]: true };\n\nexport enum ParseIbanError {\n /**\n * The country is not the one listed in https://www.swift.com/resource/iban-registry-pdf\n */\n UNSUPPORTED_COUNTRY,\n /**\n * The IBAN length should be less than 34 chars\n */\n TOO_LONG,\n /**\n * The IBAN length should be greater than 4 chars\n */\n TOO_SHORT,\n /**\n * The IBAN should only have letters and numbers\n */\n INVALID_CHARSET,\n /**\n * Computed MOD-97-10 checksum doesn't match\n */\n INVALID_CHECKSUM,\n}\n\n/**\n * @deprecated\n */\nexport type IbanValidationResult =\n | { type: \"invalid\"; code: ParseIbanError }\n | {\n type: \"valid\";\n normalizedIban: string;\n };\n\nexport interface IbanCountryInfo {\n name: string;\n isSepa?: boolean;\n length?: number;\n}\n\nconst ccZero = \"0\".charCodeAt(0);\nconst ccNine = \"9\".charCodeAt(0);\nconst ccA = \"A\".charCodeAt(0);\nconst ccZ = \"Z\".charCodeAt(0);\n\n/**\n * Append a IBAN digit(s) based on a char code.\n */\nfunction appendDigit(digits: number[], cc: number): boolean {\n if (cc >= ccZero && cc <= ccNine) {\n digits.push(cc - ccZero);\n } else if (cc >= ccA && cc <= ccZ) {\n const n = cc - ccA + 10;\n digits.push(Math.floor(n / 10) % 10);\n digits.push(n % 10);\n } else {\n return false;\n }\n return true;\n}\n\n/**\n * Compute MOD-97-10 as per ISO/IEC 7064:2003.\n */\nfunction mod97(digits: number[]): number {\n let i = 0;\n let modAccum = 0;\n while (i < digits.length) {\n let n = 0;\n while (n < 9 && i < digits.length) {\n modAccum = modAccum * 10 + digits[i];\n i++;\n n++;\n }\n modAccum = modAccum % 97;\n }\n return modAccum;\n}\n\nexport function convertHUF_BBANtoIBAN(\n value: string,\n): Result<\n IbanString,\n | ParseIbanError.TOO_LONG\n | ParseIbanError.TOO_SHORT\n | ParseIbanError.INVALID_CHARSET\n> {\n if (value.startsWith(\"HU\")) {\n const maybeIban = parseIban(value);\n if (Result.isOk(maybeIban)) {\n return Result.of(maybeIban.value);\n }\n }\n if (value.length > 24) {\n return Result.error(ParseIbanError.TOO_LONG);\n }\n if (value.length < 16) {\n return Result.error(ParseIbanError.TOO_SHORT);\n }\n if (!/[0-9+]/.test(value)) {\n return Result.error(ParseIbanError.INVALID_CHARSET);\n }\n\n const bban = value.length === 16 ? `${value}00000000` : value;\n return Result.of(constructIban(\"HU\", bban));\n}\n\n/**\n * Fake a BBAn conversion from CHF to IBAN.\n * Note that this conversion does not exist in practice,\n * it's only used for testing.\n */\nexport function convertCHF_BBANtoIBAN(\n value: string,\n): Result<\n IbanString,\n | ParseIbanError.TOO_LONG\n | ParseIbanError.TOO_SHORT\n | ParseIbanError.INVALID_CHARSET\n> {\n if (value.startsWith(\"CH\")) {\n const maybeIban = parseIban(value);\n if (maybeIban.tag === \"ok\") {\n return Result.of(maybeIban.value);\n }\n }\n if (value.length > 24) {\n return Result.error(ParseIbanError.TOO_LONG);\n }\n if (value.length < 16) {\n return Result.error(ParseIbanError.TOO_SHORT);\n }\n if (!/[0-9+]/.test(value)) {\n return Result.error(ParseIbanError.INVALID_CHARSET);\n }\n\n const bban = value;\n return Result.of(constructIban(\"CH\", bban));\n}\n\n/**\n * Check the IBAN is correct and return canonical form\n * @param ibanString\n * @returns\n */\nexport function parseIban(\n ibanString: string,\n): Result {\n if (ibanString.length < 4) {\n return Result.error(ParseIbanError.TOO_SHORT);\n }\n if (ibanString.length > 34) {\n return Result.error(ParseIbanError.TOO_LONG);\n }\n\n const myIban = ibanString.toUpperCase().replace(/[\\s-\\._]/g, \"\");\n const countryCode = myIban.substring(0, 2);\n const countryInfo = ibanCountryInfoTable[countryCode];\n\n if (!countryInfo) {\n return Result.error(ParseIbanError.UNSUPPORTED_COUNTRY);\n }\n\n let digits: number[] = [];\n\n for (let i = 4; i < myIban.length; i++) {\n const cc = myIban.charCodeAt(i);\n if (!appendDigit(digits, cc)) {\n return Result.error(ParseIbanError.INVALID_CHARSET);\n }\n }\n\n for (let i = 0; i < 4; i++) {\n const cc = myIban.charCodeAt(i);\n if (!appendDigit(digits, cc)) {\n return Result.error(ParseIbanError.INVALID_CHARSET);\n }\n }\n\n const rem = mod97(digits);\n if (rem === 1) {\n return Result.of(myIban as IbanString);\n } else {\n return Result.error(ParseIbanError.INVALID_CHECKSUM);\n }\n}\n\n/**\n * @deprecated use parseIban\n *\n * @param ibanString\n * @returns\n */\nexport function validateIban(ibanString: string): IbanValidationResult {\n if (ibanString.length < 4) {\n return {\n type: \"invalid\",\n code: ParseIbanError.TOO_SHORT,\n };\n }\n if (ibanString.length > 34) {\n return {\n type: \"invalid\",\n code: ParseIbanError.TOO_LONG,\n };\n }\n\n const myIban = ibanString.toLocaleUpperCase().replace(\" \", \"\");\n const countryCode = myIban.substring(0, 2);\n const countryInfo = ibanCountryInfoTable[countryCode];\n\n if (!countryInfo) {\n return {\n type: \"invalid\",\n code: ParseIbanError.UNSUPPORTED_COUNTRY,\n };\n }\n\n let digits: number[] = [];\n\n for (let i = 4; i < myIban.length; i++) {\n const cc = myIban.charCodeAt(i);\n if (!appendDigit(digits, cc)) {\n return {\n type: \"invalid\",\n code: ParseIbanError.INVALID_CHARSET,\n };\n }\n }\n\n for (let i = 0; i < 4; i++) {\n if (!appendDigit(digits, ibanString.charCodeAt(i))) {\n return {\n type: \"invalid\",\n code: ParseIbanError.INVALID_CHARSET,\n };\n }\n }\n\n const rem = mod97(digits);\n if (rem === 1) {\n return {\n type: \"valid\",\n normalizedIban: myIban,\n };\n } else {\n return {\n type: \"invalid\",\n code: ParseIbanError.INVALID_CHECKSUM,\n };\n }\n}\n\nexport function generateIban(countryCode: string, length: number): IbanString {\n let bban = \"\";\n\n for (let i = 0; i < length; i++) {\n const cc = ccZero + (Math.floor(Math.random() * 100) % 10);\n bban += String.fromCharCode(cc);\n }\n\n return constructIban(countryCode, bban);\n}\n\nexport function constructIban(countryCode: string, bban: string): IbanString {\n let ibanSuffix = \"\";\n let digits: number[] = [];\n\n for (let i = 0; i < bban.length; i++) {\n const cc = bban.charCodeAt(i);\n appendDigit(digits, cc);\n ibanSuffix += String.fromCharCode(cc);\n }\n\n appendDigit(digits, countryCode.charCodeAt(0));\n appendDigit(digits, countryCode.charCodeAt(1));\n\n // Try using \"00\" as check digits\n appendDigit(digits, ccZero);\n appendDigit(digits, ccZero);\n\n const requiredChecksum = 98 - mod97(digits);\n\n const checkDigit1 = Math.floor(requiredChecksum / 10) % 10;\n const checkDigit2 = requiredChecksum % 10;\n\n return (countryCode + checkDigit1 + checkDigit2 + ibanSuffix) as IbanString;\n}\n\n/**\n * Incomplete list, see https://www.swift.com/resource/iban-registry-pdf\n */\nexport const ibanCountryInfoTable: Record = {\n AE: { name: \"U.A.E.\" },\n AF: { name: \"Afghanistan\" },\n AL: { name: \"Albania\" },\n AM: { name: \"Armenia\" },\n AN: { name: \"Netherlands Antilles\" },\n AR: { name: \"Argentina\" },\n AT: { name: \"Austria\" },\n AU: { name: \"Australia\" },\n AZ: { name: \"Azerbaijan\" },\n BA: { name: \"Bosnia and Herzegovina\" },\n BD: { name: \"Bangladesh\" },\n BE: { name: \"Belgium\" },\n BG: { name: \"Bulgaria\" },\n BH: { name: \"Bahrain\" },\n BN: { name: \"Brunei Darussalam\" },\n BO: { name: \"Bolivia\" },\n BR: { name: \"Brazil\" },\n BT: { name: \"Bhutan\" },\n BY: { name: \"Belarus\" },\n BZ: { name: \"Belize\" },\n CA: { name: \"Canada\" },\n CG: { name: \"Congo\" },\n CH: { name: \"Switzerland\" },\n CI: { name: \"Cote d'Ivoire\" },\n CL: { name: \"Chile\" },\n CM: { name: \"Cameroon\" },\n CN: { name: \"People's Republic of China\" },\n CO: { name: \"Colombia\" },\n CR: { name: \"Costa Rica\" },\n CS: { name: \"Serbia and Montenegro\" },\n CZ: { name: \"Czech Republic\" },\n DE: { name: \"Germany\" },\n DK: { name: \"Denmark\" },\n DO: { name: \"Dominican Republic\" },\n DZ: { name: \"Algeria\" },\n EC: { name: \"Ecuador\" },\n EE: { name: \"Estonia\" },\n EG: { name: \"Egypt\" },\n ER: { name: \"Eritrea\" },\n ES: { name: \"Spain\" },\n ET: { name: \"Ethiopia\" },\n FI: { name: \"Finland\" },\n FO: { name: \"Faroe Islands\" },\n FR: { name: \"France\" },\n GB: { name: \"United Kingdom\" },\n GD: { name: \"Caribbean\" },\n GE: { name: \"Georgia\" },\n GL: { name: \"Greenland\" },\n GR: { name: \"Greece\" },\n GT: { name: \"Guatemala\" },\n HK: { name: \"Hong Kong S.A.R.\" },\n HN: { name: \"Honduras\" },\n HR: { name: \"Croatia\" },\n HT: { name: \"Haiti\" },\n HU: { name: \"Hungary\" },\n ID: { name: \"Indonesia\" },\n IE: { name: \"Ireland\" },\n IL: { name: \"Israel\" },\n IN: { name: \"India\" },\n IQ: { name: \"Iraq\" },\n IR: { name: \"Iran\" },\n IS: { name: \"Iceland\" },\n IT: { name: \"Italy\" },\n JM: { name: \"Jamaica\" },\n JO: { name: \"Jordan\" },\n JP: { name: \"Japan\" },\n KE: { name: \"Kenya\" },\n KG: { name: \"Kyrgyzstan\" },\n KH: { name: \"Cambodia\" },\n KR: { name: \"South Korea\" },\n KW: { name: \"Kuwait\" },\n KZ: { name: \"Kazakhstan\" },\n LA: { name: \"Laos\" },\n LB: { name: \"Lebanon\" },\n LI: { name: \"Liechtenstein\" },\n LK: { name: \"Sri Lanka\" },\n LT: { name: \"Lithuania\" },\n LU: { name: \"Luxembourg\" },\n LV: { name: \"Latvia\" },\n LY: { name: \"Libya\" },\n MA: { name: \"Morocco\" },\n MC: { name: \"Principality of Monaco\" },\n MD: { name: \"Moldava\" },\n ME: { name: \"Montenegro\" },\n MK: { name: \"Former Yugoslav Republic of Macedonia\" },\n ML: { name: \"Mali\" },\n MM: { name: \"Myanmar\" },\n MN: { name: \"Mongolia\" },\n MO: { name: \"Macau S.A.R.\" },\n MT: { name: \"Malta\" },\n MV: { name: \"Maldives\" },\n MX: { name: \"Mexico\" },\n MY: { name: \"Malaysia\" },\n NG: { name: \"Nigeria\" },\n NI: { name: \"Nicaragua\" },\n NL: { name: \"Netherlands\" },\n NO: { name: \"Norway\" },\n NP: { name: \"Nepal\" },\n NZ: { name: \"New Zealand\" },\n OM: { name: \"Oman\" },\n PA: { name: \"Panama\" },\n PE: { name: \"Peru\" },\n PH: { name: \"Philippines\" },\n PK: { name: \"Islamic Republic of Pakistan\" },\n PL: { name: \"Poland\" },\n PR: { name: \"Puerto Rico\" },\n PT: { name: \"Portugal\" },\n PY: { name: \"Paraguay\" },\n QA: { name: \"Qatar\" },\n RE: { name: \"Reunion\" },\n RO: { name: \"Romania\" },\n RS: { name: \"Serbia\" },\n RU: { name: \"Russia\" },\n RW: { name: \"Rwanda\" },\n SA: { name: \"Saudi Arabia\" },\n SE: { name: \"Sweden\" },\n SG: { name: \"Singapore\" },\n SI: { name: \"Slovenia\" },\n SK: { name: \"Slovak\" },\n SN: { name: \"Senegal\" },\n SO: { name: \"Somalia\" },\n SR: { name: \"Suriname\" },\n SV: { name: \"El Salvador\" },\n SY: { name: \"Syria\" },\n TH: { name: \"Thailand\" },\n TJ: { name: \"Tajikistan\" },\n TM: { name: \"Turkmenistan\" },\n TN: { name: \"Tunisia\" },\n TR: { name: \"Turkey\" },\n TT: { name: \"Trinidad and Tobago\" },\n TW: { name: \"Taiwan\" },\n TZ: { name: \"Tanzania\" },\n UA: { name: \"Ukraine\" },\n US: { name: \"United States\" },\n UY: { name: \"Uruguay\" },\n VA: { name: \"Vatican\" },\n VE: { name: \"Venezuela\" },\n VN: { name: \"Viet Nam\" },\n YE: { name: \"Yemen\" },\n ZA: { name: \"South Africa\" },\n ZW: { name: \"Zimbabwe\" },\n};\n", "/*\n This file is part of GNU Taler\n (C) 2019 GNUnet e.V.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { BitcoinBech32 } from \"./bech32.js\";\nimport { generateFakeSegwitAddress } from \"./bitcoin.js\";\nimport { Codec, Context, DecodingError, renderContext } from \"./codec.js\";\nimport { assertUnreachable } from \"./errors.js\";\nimport { IbanString, parseIban, ParseIbanError } from \"./iban.js\";\nimport { Result, ResultError, ResultOk } from \"./result.js\";\nimport {\n decodeCrock,\n encodeCrock,\n hashTruncate32,\n stringToBytes,\n} from \"./taler-crypto.js\";\nimport { URLSearchParams } from \"./url.js\";\n\n/**\n * @deprecated use NormalizedPayto or FullPayto\n */\nexport type PaytoString = string;\n\nconst PAYTO_PREFIX = \"payto://\";\n\nexport enum PaytoType {\n IBAN = \"iban\",\n Bitcoin = \"bitcoin\",\n Cyclos = \"cyclos\",\n TalerBank = \"x-taler-bank\",\n TalerReserve = \"taler-reserve\",\n TalerReserveHttp = \"taler-reserve-http\",\n Ethereum = \"ethereum\",\n}\n\nexport enum ReservePubParseError {\n /**\n * It should be 52 characters\n */\n WRONG_LENGTH,\n DECODE_ERROR,\n}\ndeclare const __hostport_str: unique symbol;\nexport type HostPortPath = string & { [__hostport_str]: true };\n\ndeclare const __btaddr_str: unique symbol;\nexport type BtAddrString = string & { [__btaddr_str]: true };\ndeclare const __ethaddr_str: unique symbol;\nexport type EthAddrString = string & { [__ethaddr_str]: true };\n\nexport enum PaytoParseError {\n /**\n * Payto should start with payto://\n */\n WRONG_PREFIX,\n /**\n * Payto should have a / after the target type\n */\n INCOMPLETE,\n /**\n * Target type is not in the list of supported types\n */\n UNSUPPORTED,\n /**\n * The quantity of components is wrong based on the target type\n */\n COMPONENTS_LENGTH,\n /**\n * The validation of one or more path components failed\n */\n INVALID_TARGET_PATH,\n}\n\n// TODO: use unique symbol to remove compat with string\n// TODO: verify in account aml types if we can merge it since this is also an aml account\nexport type PaytoHash = string;\n\nexport namespace Paytos {\n export type URI =\n | PaytoUnsupported\n | PaytoIBAN\n | PaytoTalerReserve\n | PaytoCyclos\n | PaytoTalerReserveHttp\n | PaytoTalerBank\n | PaytoEthereum\n | PaytoBitcoin;\n\n declare const __full_payto_str: unique symbol;\n export type FullPaytoString = string & { [__full_payto_str]: true };\n\n declare const __norm_payto_str: unique symbol;\n export type NormalizedPaytoString = string & { [__norm_payto_str]: true };\n\n interface PaytoGeneric {\n /**\n * String after the prefix and before the first /\n */\n targetType: PaytoType | undefined;\n /**\n * String after the first /\n */\n normalizedPath: string;\n /**\n * String after the first /\n */\n fullPath: string;\n /**\n * Return the account identification when the target type is already known. Useful to show in the UI\n */\n displayName: string;\n /**\n * All the URL params after the first ?\n */\n params: { [name: string]: string };\n }\n\n export interface PaytoUnsupported extends PaytoGeneric {\n targetType: undefined;\n target: string;\n }\n\n export interface PaytoIBAN extends PaytoGeneric {\n targetType: PaytoType.IBAN;\n iban: IbanString;\n bic?: string;\n }\n\n export interface PaytoTalerReserve extends PaytoGeneric {\n targetType: PaytoType.TalerReserve;\n exchange: HostPortPath;\n reservePub: Uint8Array;\n }\n\n export interface PaytoCyclos extends PaytoGeneric {\n targetType: PaytoType.Cyclos;\n url: HostPortPath;\n account: string;\n }\n\n export interface PaytoTalerReserveHttp extends PaytoGeneric {\n targetType: PaytoType.TalerReserveHttp;\n exchange: HostPortPath;\n reservePub: Uint8Array;\n }\n\n export interface PaytoTalerBank extends PaytoGeneric {\n targetType: PaytoType.TalerBank;\n /**\n * this is kept to keep compatibility with old parser\n * @deprecated use URL\n */\n host: string;\n url: HostPortPath;\n account: string;\n }\n\n export interface PaytoBitcoin extends PaytoGeneric {\n targetType: PaytoType.Bitcoin;\n address: BtAddrString;\n reservePub: Uint8Array | undefined;\n segwitAddrs: Array;\n }\n\n export interface PaytoEthereum extends PaytoGeneric {\n targetType: PaytoType.Ethereum;\n address: EthAddrString;\n }\n\n const supported_targets: Record = {\n iban: true,\n bitcoin: true,\n \"x-taler-bank\": true,\n \"taler-reserve\": true,\n \"taler-reserve-http\": true,\n ethereum: true,\n cyclos: true,\n };\n\n export function hash(p: NormalizedPaytoString | FullPaytoString): Uint8Array {\n return hashTruncate32(stringToBytes(p + \"\\0\"));\n }\n\n /**\n * A **normalized** payto-URI uniquely identifies a bank account (or\n * wallet) and must be able to serve as a canonical representation of such a\n * bank account. Thus, optional arguments such as the *receiver-name* or\n * optional path components such as the BIC must be removed and the account\n * must be given in a canonical form for the wire method (for example,\n * everything in lower-case)\n *\n * @param p\n * @returns\n */\n export function toNormalizedString(p: URI): NormalizedPaytoString {\n const url = new URL(`${PAYTO_PREFIX}${p.targetType}/${p.normalizedPath}`);\n return url.href as NormalizedPaytoString;\n }\n /**\n * A **full** payto-URI is not expected to have a canonical form for\n * a bank account (there can be many full payto-URIs for the same bank\n * account) and must include at least the *receiver-name* but possibly also\n * other (in RFC 8905 optional) arguments to identify the recipient, as\n * those may be needed to do a wire transfer.\n *\n * @param p\n * @returns\n */\n export function toFullString(p: URI): FullPaytoString {\n const url = new URL(`${PAYTO_PREFIX}${p.targetType}/${p.fullPath}`);\n const paramList = !p.params ? [] : Object.entries(p.params);\n url.search = createSearchParams(paramList);\n return url.href as FullPaytoString;\n }\n\n export function parseReservePub(\n reserve: string | undefined,\n ):\n | ResultOk\n | ResultError {\n if (!reserve) return Result.error(ReservePubParseError.WRONG_LENGTH);\n try {\n const pub = decodeCrock(reserve);\n if (!pub || pub.length !== 32) {\n return Result.error(ReservePubParseError.WRONG_LENGTH);\n }\n return Result.of(pub);\n } catch (e) {\n return Result.errorWithDetail(ReservePubParseError.DECODE_ERROR, {\n message: String(e),\n });\n }\n }\n /**\n * Check hostname is a valid string with form $host:$port/$path like\n * domain.com:22/some/path\n *\n * Return the canonical form.\n *\n * FIXME: new need a function that only takes una string: host+port+path and\n * parse it without using URL to prevent parsing unnecessary components and\n * better error reporting\n * https://bugs.gnunet.org/view.php?id=10467\n *\n * @param hostname\n * @param path\n * @param scheme\n * @returns\n */\n export function parseHostPortPath2(\n hostname: string,\n path: string | undefined,\n scheme: \"http\" | \"https\" = \"https\",\n ): HostPortPath | undefined {\n // maybe it should check that it doesn't contain search or hash?\n try {\n // https://url.spec.whatwg.org/#concept-basic-url-parser\n if (path === undefined) {\n path = \"\";\n }\n if (!path.endsWith(\"/\")) {\n path = path + \"/\";\n }\n const url = new URL(path, `${scheme}://${hostname.toLowerCase()}`);\n url.search = \"\";\n url.password = \"\";\n url.username = \"\";\n url.hash = \"\";\n return url.href as HostPortPath;\n } catch (e) {\n console.log(e);\n return undefined;\n }\n }\n function withoutScheme(h: HostPortPath): HostPortPath {\n return (\n h.startsWith(\"http://\")\n ? h.substring(7)\n : h.startsWith(\"https://\")\n ? h.substring(8)\n : h\n ) as HostPortPath;\n }\n /**\n * Same as `parseHostPortPath2` but only takes one string.\n * This should be the definitive signature.\n * https://bugs.gnunet.org/view.php?id=10467\n *\n * @param hostnameAndPath\n * @returns\n */\n export function parseHostPortPath(\n hostnameAndPath: string,\n ): HostPortPath | undefined {\n const [host, path] = hostnameAndPath.split(\"/\", 1);\n return parseHostPortPath2(host, path ?? \"\");\n }\n /**\n * FIXME: add ethereum address validator\n * @param str\n */\n export function parseEthereumAddress(str: String): EthAddrString | undefined {\n if (!str) {\n return undefined;\n }\n return str as EthAddrString;\n }\n\n /**\n * FIXME: add bank account name validation\n *\n * @param account\n * @returns\n */\n export function parseTalerBankAccount(account: string): string | undefined {\n if (!account) {\n return undefined;\n }\n return account;\n }\n //////////////////\n // function to create objs\n //////////////////\n export function createUnsupported(\n targetType: string,\n path: string,\n params: Record = {},\n ): PaytoUnsupported {\n return {\n targetType: undefined,\n target: targetType,\n params,\n normalizedPath: path.toLocaleLowerCase(),\n fullPath: path,\n displayName: path,\n };\n }\n export function createIban(\n iban: IbanString,\n bic: string | undefined,\n params: Record = {},\n ): PaytoIBAN {\n iban = iban.toUpperCase() as IbanString;\n return {\n targetType: PaytoType.IBAN,\n iban,\n bic,\n params,\n normalizedPath: iban,\n fullPath: !bic ? iban : `${bic}/${iban}`,\n displayName: iban,\n };\n }\n export function createBitcoin(\n address: BtAddrString,\n reservePub: Uint8Array | undefined,\n params: Record = {},\n ): PaytoBitcoin {\n const sgRes = !reservePub\n ? undefined\n : generateFakeSegwitAddress(reservePub, address);\n\n const segwitAddrs = !sgRes || !Result.isOk(sgRes) ? [] : sgRes.value;\n return {\n targetType: PaytoType.Bitcoin,\n address,\n reservePub,\n segwitAddrs,\n params,\n normalizedPath: address.toLocaleLowerCase(),\n fullPath: !reservePub ? address : `${address}/${encodeCrock(reservePub)}`,\n displayName: address,\n };\n }\n export function createEthereum(\n address: EthAddrString,\n params: Record = {},\n ): PaytoEthereum {\n return {\n targetType: PaytoType.Ethereum,\n address,\n params,\n normalizedPath: address,\n fullPath: address,\n displayName: address,\n };\n }\n export function createTalerReserve(\n exchange: HostPortPath,\n reservePub: Uint8Array,\n params: Record = {},\n ): PaytoTalerReserve {\n const path = withoutScheme(exchange);\n const pub = encodeCrock(reservePub);\n return {\n targetType: PaytoType.TalerReserve,\n exchange,\n reservePub,\n params,\n normalizedPath: `${path.toLocaleLowerCase()}${pub}`,\n fullPath: `${path}${pub}`,\n displayName: `${path}@${pub}`,\n };\n }\n export function createCyclos(\n url: HostPortPath,\n account: string,\n params: Record = {},\n ): PaytoCyclos {\n const path = withoutScheme(url);\n return {\n targetType: PaytoType.Cyclos,\n url,\n account,\n params,\n normalizedPath: `${path.toLocaleLowerCase()}${account}`,\n fullPath: `${path}${account}`,\n displayName: `${account}@${path}`,\n };\n }\n export function createTalerReserveHttp(\n exchange: HostPortPath,\n reservePub: Uint8Array,\n params: Record = {},\n ): PaytoTalerReserveHttp {\n const path = withoutScheme(exchange);\n const pub = encodeCrock(reservePub);\n return {\n targetType: PaytoType.TalerReserveHttp,\n exchange,\n reservePub,\n params,\n normalizedPath: `${path.toLocaleLowerCase()}${pub}`,\n fullPath: `${path}${pub}`,\n displayName: `${path}@${pub}`,\n };\n }\n export function createTalerBank(\n url: HostPortPath,\n account: string,\n params: Record = {},\n ): PaytoTalerBank {\n const path = withoutScheme(url);\n const host = path.endsWith(\"/\") ? path.substring(0, path.length - 1) : path;\n return {\n targetType: PaytoType.TalerBank,\n host,\n url,\n account,\n params,\n normalizedPath: `${path.toLocaleLowerCase()}${account}`,\n fullPath: `${path}${account}`,\n displayName: `${account}@${url}`,\n };\n }\n\n //////////////////////\n // parsing function\n ///////////////////////\n\n export function asString(p: FullPaytoString): Paytos.URI {\n return Result.unpack(fromString(p));\n }\n\n export interface ParsePaytoOptions {\n /**\n * do not check path component format\n */\n ignoreComponentError?: boolean;\n /**\n * take unknown target types as valid\n */\n allowUnsupported?: boolean;\n }\n\n export type TargetPathErrorDetail =\n | {\n targetType: PaytoType.Bitcoin;\n pos: 0;\n error: ResultError;\n }\n | {\n targetType: PaytoType.Bitcoin;\n pos: 1;\n error: ResultError<\n ReservePubParseError,\n { message: string } | undefined\n >;\n }\n | {\n targetType: PaytoType.IBAN;\n pos: 0 | 1;\n error: ResultError;\n }\n | {\n targetType: PaytoType.TalerBank;\n pos: 0 | 1;\n }\n | {\n targetType: PaytoType.TalerReserve;\n pos: 0;\n }\n | {\n targetType: PaytoType.TalerReserve;\n pos: 1;\n error: ResultError<\n ReservePubParseError,\n { message: string } | undefined\n >;\n }\n | {\n targetType: PaytoType.TalerReserveHttp;\n pos: 0;\n }\n | {\n targetType: PaytoType.TalerReserveHttp;\n pos: 1;\n error: ResultError<\n ReservePubParseError,\n { message: string } | undefined\n >;\n }\n | {\n targetType: PaytoType.Ethereum;\n pos: 0;\n }\n | {\n targetType: PaytoType.Cyclos;\n pos: 0;\n };\n\n export function fromString(\n s: string,\n opts: ParsePaytoOptions = {},\n ):\n | ResultOk\n | ResultError\n | ResultError\n | ResultError\n | ResultError\n | ResultError {\n if (!s.startsWith(PAYTO_PREFIX)) {\n return Result.error(PaytoParseError.WRONG_PREFIX);\n }\n\n const [acct, search] = s.slice(PAYTO_PREFIX.length).split(\"?\", 2);\n\n const firstSlashPos = acct.indexOf(\"/\");\n\n const targetType = (\n firstSlashPos === -1 ? acct : acct.slice(0, firstSlashPos)\n ) as PaytoType;\n if (!opts.allowUnsupported && !supported_targets[targetType]) {\n return Result.errorWithDetail(PaytoParseError.UNSUPPORTED, {\n targetType,\n });\n }\n const targetPath = acct.slice(firstSlashPos + 1);\n if (firstSlashPos === -1 || !targetPath) {\n return Result.errorWithDetail(PaytoParseError.INCOMPLETE, { targetType });\n }\n\n const params: { [k: string]: string } = {};\n if (search) {\n const searchParams = new URLSearchParams(search);\n searchParams.forEach((v, k) => {\n // URLSearchParams already decodes uri components\n params[k] = v;\n });\n }\n // get URI components\n const cs = targetPath.split(\"/\");\n switch (targetType) {\n case PaytoType.IBAN: {\n if (cs.length !== 1 && cs.length !== 2) {\n return Result.errorWithDetail(PaytoParseError.COMPONENTS_LENGTH, {\n targetType,\n });\n }\n const bic = cs.length === 2 ? cs[0] : undefined;\n const iban = cs.length === 1 ? cs[0] : cs[1];\n\n const ibaRes = parseIban(iban);\n\n if (!opts.ignoreComponentError && ibaRes.tag === \"error\") {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 0,\n targetType,\n error: ibaRes,\n } as const);\n }\n\n return Result.of(createIban(iban as IbanString, bic, params));\n }\n case PaytoType.Bitcoin: {\n if (cs.length !== 1 && cs.length !== 2) {\n return Result.errorWithDetail(PaytoParseError.COMPONENTS_LENGTH, {\n targetType,\n });\n }\n\n const address = cs[0].toLocaleLowerCase();\n const btRes = BitcoinBech32.decode(\n address,\n BitcoinBech32.Encodings.BECH32,\n );\n if (!opts.ignoreComponentError && Result.isError(btRes)) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 0 as const,\n targetType,\n error: btRes,\n });\n }\n\n const pubRes = cs.length === 1 ? undefined : parseReservePub(cs[1]);\n if (!opts.ignoreComponentError && pubRes && Result.isError(pubRes)) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 1 as const,\n targetType,\n error: pubRes,\n });\n }\n\n return Result.of(\n createBitcoin(\n address as BtAddrString,\n pubRes != null ? Result.orUndefined(pubRes) : undefined,\n params,\n ),\n );\n }\n\n case PaytoType.TalerBank: {\n if (cs.length < 2) {\n return Result.errorWithDetail(PaytoParseError.COMPONENTS_LENGTH, {\n targetType,\n });\n }\n\n const host = parseHostPortPath2(cs[0], cs.slice(1, -1).join(\"/\"));\n if (!opts.ignoreComponentError && !host) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 0,\n targetType,\n error: host,\n } as const);\n }\n const account = parseTalerBankAccount(cs[cs.length - 1]);\n if (!opts.ignoreComponentError && !account) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 1 as const,\n targetType,\n error: account,\n });\n }\n\n return Result.of(\n createTalerBank(\n host ?? (cs[0] as HostPortPath),\n account ?? cs[1],\n params,\n ),\n );\n }\n case PaytoType.TalerReserve: {\n if (cs.length < 2) {\n return Result.errorWithDetail(PaytoParseError.COMPONENTS_LENGTH, {\n targetType,\n });\n }\n const exchange = parseHostPortPath2(cs[0], cs.slice(1, -1).join(\"/\"));\n if (!opts.ignoreComponentError && !exchange) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 0 as const,\n targetType,\n error: exchange,\n });\n }\n\n const reservePub = cs[cs.length - 1];\n const pubRes = parseReservePub(reservePub);\n if (!opts.ignoreComponentError && !Result.isOk(pubRes)) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 1 as const,\n targetType,\n error: pubRes,\n });\n }\n\n return Result.of(\n createTalerReserve(\n exchange ?? (cs[0] as HostPortPath),\n Result.isOk(pubRes) ? pubRes.value : decodeCrock(reservePub),\n params,\n ),\n );\n }\n case PaytoType.TalerReserveHttp: {\n if (cs.length < 2) {\n return Result.errorWithDetail(PaytoParseError.COMPONENTS_LENGTH, {\n targetType,\n });\n }\n const exchange = parseHostPortPath2(\n cs[0],\n cs.slice(1, -1).join(\"/\"),\n \"http\",\n );\n if (!opts.ignoreComponentError && !exchange) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 0,\n targetType,\n error: exchange,\n } as const);\n }\n\n const reservePub = cs[cs.length - 1];\n const pubRes = parseReservePub(reservePub);\n if (!opts.ignoreComponentError && !Result.isOk(pubRes)) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 1,\n targetType,\n error: pubRes,\n } as const);\n }\n return Result.of(\n createTalerReserveHttp(\n exchange ?? (cs[0] as HostPortPath),\n Result.isOk(pubRes) ? pubRes.value : decodeCrock(reservePub),\n params,\n ),\n );\n }\n case PaytoType.Ethereum: {\n if (cs.length !== 1) {\n return Result.errorWithDetail(PaytoParseError.COMPONENTS_LENGTH, {\n targetType,\n });\n }\n const address = parseEthereumAddress(cs[0]);\n if (!opts.ignoreComponentError && !address) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 0,\n targetType,\n error: address,\n } as const);\n }\n return Result.of(\n createEthereum(address ?? (cs[0] as EthAddrString), params),\n );\n }\n case PaytoType.Cyclos: {\n if (cs.length < 2) {\n return Result.errorWithDetail(PaytoParseError.COMPONENTS_LENGTH, {\n targetType,\n });\n }\n const host = parseHostPortPath2(cs[0], cs.slice(1, -1).join(\"/\"));\n if (!opts.ignoreComponentError && !host) {\n return Result.errorWithDetail(PaytoParseError.INVALID_TARGET_PATH, {\n pos: 0 as const,\n targetType,\n error: host,\n });\n }\n\n const accountId = cs[cs.length - 1];\n\n return Result.of(\n createCyclos(host ?? (cs[0] as HostPortPath), accountId, params),\n );\n }\n default: {\n if (opts.allowUnsupported) {\n return Result.of(\n createUnsupported(targetType, targetPath, params),\n );\n }\n assertUnreachable(targetType);\n }\n }\n }\n}\n\nexport function codecForPaytoHash(): Codec {\n return {\n decode(x: any, c?: Context): PaytoHash {\n // TODO: implement a stronger validation and reject invalid hash\n // maybe check charset and also length\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n return x as PaytoHash;\n },\n };\n}\nexport function codecFullForPaytoString(): Codec {\n return {\n decode(x: any, c?: Context): Paytos.FullPaytoString {\n // TODO: implement a stronger validation and reject invalid paytos\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n if (!x.startsWith(PAYTO_PREFIX)) {\n throw new DecodingError(\n `expected start with payto at ${renderContext(c)} but got \"${x}\"`,\n );\n }\n return x as Paytos.FullPaytoString;\n },\n };\n}\n\nexport function codecNormalizedForPaytoString(): Codec {\n return {\n decode(x: any, c?: Context): Paytos.NormalizedPaytoString {\n // TODO: implement a stronger validation and reject invalid paytos\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n if (!x.startsWith(PAYTO_PREFIX)) {\n throw new DecodingError(\n `expected start with payto at ${renderContext(c)} but got \"${x}\"`,\n );\n }\n return x as Paytos.NormalizedPaytoString;\n },\n };\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport type PaytoUri =\n | PaytoUriUnknown\n | PaytoUriIBAN\n | PaytoUriTaler\n | PaytoUriCyclos\n | PaytoUriTalerHttp\n | PaytoUriTalerBank\n | PaytoUriEthereum\n | PaytoUriBitcoin;\n\n/**\n * @deprecated use codecForNormalizedPAyto or codecForFullPayto\n * @returns\n */\nexport function codecForPaytoString(): Codec {\n return {\n decode(x: any, c?: Context): PaytoString {\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n if (!x.startsWith(PAYTO_PREFIX)) {\n throw new DecodingError(\n `expected start with payto at ${renderContext(c)} but got \"${x}\"`,\n );\n }\n return x as PaytoString;\n },\n };\n}\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriGeneric {\n targetType: PaytoType | string;\n targetPath: string;\n params: { [name: string]: string };\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriUnknown extends PaytoUriGeneric {\n isKnown: false;\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriIBAN extends PaytoUriGeneric {\n isKnown: true;\n targetType: \"iban\";\n iban: string;\n bic?: string;\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriTaler extends PaytoUriGeneric {\n isKnown: true;\n targetType: \"taler-reserve\";\n exchange: string;\n reservePub: string;\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriTalerHttp extends PaytoUriGeneric {\n isKnown: true;\n targetType: \"taler-reserve-http\";\n exchange: string;\n reservePub: string;\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriTalerBank extends PaytoUriGeneric {\n isKnown: true;\n targetType: \"x-taler-bank\";\n host: string;\n account: string;\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriBitcoin extends PaytoUriGeneric {\n isKnown: true;\n targetType: \"bitcoin\";\n address: string;\n segwitAddrs: Array;\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriEthereum extends PaytoUriGeneric {\n isKnown: true;\n targetType: \"ethereum\";\n address: string;\n}\n\n/**\n * @deprecated use Paytos namespace\n */\nexport interface PaytoUriCyclos extends PaytoUriGeneric {\n isKnown: true;\n targetType: \"cyclos\";\n host: string;\n account: string;\n}\n\n/**\n * Add query parameters to a payto URI.\n *\n * Existing parameters are preserved.\n */\nexport function addPaytoQueryParams(\n s: string,\n params: { [name: string]: string },\n): string {\n const [acct, search] = s.slice(PAYTO_PREFIX.length).split(\"?\");\n const searchParams = new URLSearchParams(search || \"\");\n for (const [paramKey, paramValue] of Object.entries(params)) {\n searchParams.set(paramKey, paramValue);\n }\n const paramList = [...searchParams.entries()];\n if (paramList.length === 0) {\n return PAYTO_PREFIX + acct;\n }\n return PAYTO_PREFIX + acct + \"?\" + createSearchParams(paramList);\n}\n\n/**\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#encoding_for_rfc3986\n */\nfunction encodeRFC3986URIComponent(str: string): string {\n return encodeURIComponent(str).replace(\n /[!'()*]/g,\n (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n}\nconst rfc3986 = encodeRFC3986URIComponent;\n\n/**\n *\n * https://www.rfc-editor.org/rfc/rfc3986\n */\nfunction createSearchParams(paramList: [string, string][]): string {\n return paramList\n .map(([key, value]) => `${rfc3986(key)}=${rfc3986(value)}`)\n .join(\"&\");\n}\n\n/**\n * Serialize a PaytoURI into a valid payto:// string\n * @deprecated use paytos namespace\n *\n * @param p\n * @returns\n */\nexport function stringifyPaytoUri(p: PaytoUri): PaytoString {\n const url = new URL(`${PAYTO_PREFIX}${p.targetType}/${p.targetPath}`);\n const paramList = !p.params ? [] : Object.entries(p.params);\n url.search = createSearchParams(paramList);\n return url.href as PaytoString;\n}\n\n/**\n * @deprecated use paytos namespace\n */\nexport function hashFullPaytoUri(p: PaytoUri | string): Uint8Array {\n const paytoUri = typeof p === \"string\" ? p : stringifyPaytoUri(p);\n return hashTruncate32(stringToBytes(paytoUri + \"\\0\"));\n}\n\n/**\n * Normalize and then hash a payto URI.\n * @deprecated use paytos namespace\n */\nexport function hashNormalizedPaytoUri(p: PaytoUri | string): Uint8Array {\n const paytoUri = typeof p === \"string\" ? p : stringifyPaytoUri(p);\n if (typeof p === \"string\") {\n const parseRes = parsePaytoUri(p);\n if (!parseRes) {\n throw Error(\"invalid payto URI\");\n }\n p = parseRes;\n }\n let paytoStr: string;\n if (!p.isKnown) {\n const normalizedPayto: PaytoUri = {\n targetType: p.targetType,\n targetPath: p.targetPath,\n isKnown: false,\n params: {},\n };\n paytoStr = stringifyPaytoUri(normalizedPayto);\n } else {\n switch (p.targetType) {\n case \"iban\":\n // FIXME: Strip BIC?\n paytoStr = `payto://iban/${p.targetPath}`;\n break;\n case \"x-taler-bank\":\n paytoStr = `payto://x-taler-bank/${p.host}/${p.account}`;\n break;\n case \"bitcoin\":\n paytoStr = `payto://bitcoin/${p.address}`;\n break;\n case \"ethereum\":\n paytoStr = `payto://ethereum/${p.address}`;\n break;\n case \"cyclos\":\n paytoStr = `payto://cyclos/${p.host}/${p.account}`;\n break;\n case \"taler-reserve\":\n paytoStr = `payto://taler-reserve/${p.exchange}/${p.reservePub}`;\n break;\n case \"taler-reserve-http\":\n paytoStr = `payto://taler-reserve-http/${p.exchange}/${p.reservePub}`;\n break;\n }\n }\n return hashTruncate32(stringToBytes(paytoStr + \"\\0\"));\n}\n\n/**\n * @deprecated do not use this, create a taler-reserve payto and use\n * stringify\n *\n * @param exchangeBaseUrl\n * @param reservePub\n * @returns\n */\nexport function stringifyReservePaytoUri(\n exchangeBaseUrl: string,\n reservePub: string,\n): string {\n const url = new URL(exchangeBaseUrl);\n let target: string;\n let domainWithOptPort: string;\n if (url.protocol === \"https:\") {\n target = \"taler-reserve\";\n if (url.port != \"443\" && url.port !== \"\") {\n domainWithOptPort = `${url.hostname}:${url.port}`;\n } else {\n domainWithOptPort = `${url.hostname}`;\n }\n } else {\n target = \"taler-reserve-http\";\n if (url.port != \"80\" && url.port !== \"\") {\n domainWithOptPort = `${url.hostname}:${url.port}`;\n } else {\n domainWithOptPort = `${url.hostname}`;\n }\n }\n let optPath = \"\";\n if (url.pathname !== \"/\" && url.pathname !== \"\") {\n optPath = url.pathname;\n }\n return `payto://${target}/${domainWithOptPort}${optPath}/${reservePub}`;\n}\n\n/**\n * @deprecated use new Payto namespace functions\n *\n * @param s\n * @returns\n */\nexport function parsePaytoUriOrThrow(s: string): PaytoUri {\n const ret = parsePaytoUri(s);\n if (!ret) {\n throw Error(\"invalid payto URI\");\n }\n return ret;\n}\n\n/**\n * Parse a valid payto:// uri into a PaytoUri object\n * RFC 8905\n * @deprecated use new Payto namespace functions\n *\n * @param s\n * @returns\n */\nexport function parsePaytoUri(s: string): PaytoUri | undefined {\n if (!s.startsWith(PAYTO_PREFIX)) {\n return undefined;\n }\n\n const [acct, search] = s.slice(PAYTO_PREFIX.length).split(\"?\");\n\n const firstSlashPos = acct.indexOf(\"/\");\n\n if (firstSlashPos === -1) {\n return undefined;\n }\n\n const targetType = acct.slice(0, firstSlashPos) as PaytoType;\n const targetPath = acct.slice(firstSlashPos + 1);\n\n const params: { [k: string]: string } = {};\n\n const searchParams = new URLSearchParams(search || \"\");\n\n searchParams.forEach((v, k) => {\n // URLSearchParams already decodes uri components\n params[k] = v; //decodeURIComponent(v);\n });\n\n switch (targetType) {\n case \"iban\": {\n const parts = targetPath.split(\"/\");\n let iban: string | undefined = undefined;\n let bic: string | undefined = undefined;\n if (parts.length === 1) {\n iban = parts[0].toUpperCase();\n }\n if (parts.length === 2) {\n bic = parts[0];\n iban = parts[1].toUpperCase();\n } else {\n iban = targetPath.toUpperCase();\n }\n return {\n isKnown: true,\n targetPath,\n targetType,\n params,\n iban,\n bic,\n };\n }\n case \"bitcoin\": {\n const msg = /\\b([A-Z0-9]{52})\\b/.exec(params[\"message\"]);\n const reserve = !msg ? params[\"subject\"] : msg[0];\n const pubRes = !reserve ? undefined : Paytos.parseReservePub(reserve);\n const addr =\n !pubRes || !Result.isOk(pubRes)\n ? undefined\n : generateFakeSegwitAddress(pubRes.value, targetPath);\n const segwitAddrs = !addr || !Result.isOk(addr) ? [] : addr.value;\n\n const result: PaytoUriBitcoin = {\n isKnown: true,\n targetPath,\n targetType,\n address: targetPath,\n params,\n segwitAddrs,\n };\n\n return result;\n }\n case \"x-taler-bank\": {\n const parts = targetPath.split(\"/\");\n const host = parts[0];\n const account = parts[parts.length - 1];\n return {\n targetPath,\n targetType,\n params,\n isKnown: true,\n host,\n account,\n };\n }\n case \"cyclos\": {\n const parts = targetPath.split(\"/\");\n const host = parts[0];\n const account = parts[parts.length - 1];\n const result: PaytoUriCyclos = {\n isKnown: true,\n targetPath,\n targetType,\n host,\n account,\n params,\n };\n\n return result;\n }\n case \"taler-reserve\": {\n const parts = targetPath.split(\"/\");\n const exchange = parts[0];\n const reservePub = parts[1];\n return {\n targetPath,\n targetType,\n params,\n isKnown: true,\n exchange,\n reservePub,\n };\n }\n case \"ethereum\": {\n const result: PaytoUriEthereum = {\n isKnown: true,\n targetPath,\n targetType,\n address: targetPath,\n params,\n };\n return result;\n }\n default: {\n return {\n targetPath,\n targetType,\n params,\n isKnown: false,\n };\n }\n }\n}\n\n/**\n * @deprecated do not use this, create a payto object and use stringify\n *\n * @param exchangeBaseUrl\n * @param reservePub\n * @returns\n */\nexport function talerPaytoFromExchangeReserve(\n exchangeBaseUrl: string,\n reservePub: string,\n): string {\n const url = new URL(exchangeBaseUrl);\n let proto: string;\n if (url.protocol === \"http:\") {\n proto = \"taler-reserve-http\";\n } else if (url.protocol === \"https:\") {\n proto = \"taler-reserve\";\n } else {\n throw Error(`unsupported exchange base URL protocol (${url.protocol})`);\n }\n\n let path = url.pathname;\n if (!path.endsWith(\"/\")) {\n path = path + \"/\";\n }\n\n return `payto://${proto}/${url.host}${url.pathname}${reservePub}`;\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n Codec,\n buildCodecForObject,\n buildCodecForUnion,\n codecForAny,\n codecForBoolean,\n codecForConstString,\n codecForEither,\n codecForList,\n codecForMap,\n codecForNumber,\n codecForString,\n codecForStringURL,\n codecOptional,\n codecOptionalDefault,\n} from \"./codec.js\";\nimport { strcmp } from \"./helpers.js\";\nimport {\n PaytoHash,\n Paytos,\n codecForPaytoHash,\n codecForPaytoString,\n codecFullForPaytoString,\n} from \"./payto.js\";\n\nimport { Edx25519PublicKeyEnc } from \"./taler-crypto.js\";\nimport { TalerErrorCode } from \"./taler-error-codes.js\";\nimport { TalerFormAttributes } from \"./taler-form-attributes.js\";\nimport {\n TalerProtocolDuration,\n TalerProtocolTimestamp,\n codecForDuration,\n codecForTimestamp,\n} from \"./time.js\";\nimport {\n AccessToken,\n AmlOfficerPublicKeyP,\n AmountString,\n Base32String,\n CoinPublicKeyString,\n Cs25519Point,\n CurrencySpecification,\n EddsaPublicKeyString,\n EddsaSignatureString,\n HashCodeString,\n Integer,\n InternationalizedString,\n LibtoolVersionString,\n RelativeTime,\n RsaPublicKey,\n RsaPublicKeyString,\n Timestamp,\n WireSalt,\n codecForAccessToken,\n codecForCurrencySpecificiation,\n codecForEddsaPublicKey,\n codecForEddsaSignature,\n codecForInternationalizedString,\n codecForURLString,\n codecForURN,\n} from \"./types-taler-common.js\";\n\nexport type DenominationPubKey = RsaDenominationPubKey | CsDenominationPubKey;\n\nexport interface RsaDenominationPubKey {\n readonly cipher: DenomKeyType.Rsa;\n readonly rsa_public_key: string;\n readonly age_mask: number;\n}\n\nexport interface CsDenominationPubKey {\n readonly cipher: DenomKeyType.ClauseSchnorr;\n readonly age_mask: number;\n readonly cs_public_key: string;\n}\n\nexport namespace DenominationPubKey {\n export function cmp(\n p1: DenominationPubKey,\n p2: DenominationPubKey,\n ): -1 | 0 | 1 {\n if (p1.cipher < p2.cipher) {\n return -1;\n } else if (p1.cipher > p2.cipher) {\n return +1;\n } else if (\n p1.cipher === DenomKeyType.Rsa &&\n p2.cipher === DenomKeyType.Rsa\n ) {\n if ((p1.age_mask ?? 0) < (p2.age_mask ?? 0)) {\n return -1;\n } else if ((p1.age_mask ?? 0) > (p2.age_mask ?? 0)) {\n return 1;\n }\n return strcmp(p1.rsa_public_key, p2.rsa_public_key);\n } else if (\n p1.cipher === DenomKeyType.ClauseSchnorr &&\n p2.cipher === DenomKeyType.ClauseSchnorr\n ) {\n if ((p1.age_mask ?? 0) < (p2.age_mask ?? 0)) {\n return -1;\n } else if ((p1.age_mask ?? 0) > (p2.age_mask ?? 0)) {\n return 1;\n }\n return strcmp(p1.cs_public_key, p2.cs_public_key);\n } else {\n throw Error(\"unsupported cipher\");\n }\n }\n}\n\nexport const codecForRsaDenominationPubKey = () =>\n buildCodecForObject()\n .property(\"cipher\", codecForConstString(DenomKeyType.Rsa))\n .property(\"rsa_public_key\", codecForString())\n .property(\"age_mask\", codecForNumber())\n .build(\"DenominationPubKey\");\n\nexport const codecForCsDenominationPubKey = () =>\n buildCodecForObject()\n .property(\"cipher\", codecForConstString(DenomKeyType.ClauseSchnorr))\n .property(\"cs_public_key\", codecForString())\n .property(\"age_mask\", codecForNumber())\n .build(\"CsDenominationPubKey\");\n\nexport const codecForDenominationPubKey = () =>\n buildCodecForUnion()\n .discriminateOn(\"cipher\")\n .alternative(DenomKeyType.Rsa, codecForRsaDenominationPubKey())\n .alternative(DenomKeyType.ClauseSchnorr, codecForCsDenominationPubKey())\n .build(\"DenominationPubKey\");\n\n/**\n * Signature by the auditor that a particular denomination key is audited.\n */\nexport interface AuditorDenomSig {\n /**\n * Denomination public key's hash.\n */\n denom_pub_h: string;\n\n /**\n * The signature.\n */\n auditor_sig: string;\n}\n\n/**\n * Auditor information as given by the exchange in /keys.\n */\nexport interface ExchangeAuditor {\n /**\n * Auditor's public key.\n */\n auditor_pub: string;\n\n /**\n * Base URL of the auditor.\n */\n auditor_url: string;\n\n /**\n * List of signatures for denominations by the auditor.\n */\n denomination_keys: AuditorDenomSig[];\n}\n\nexport type ExchangeWithdrawValue =\n | ExchangeRsaWithdrawValue\n | ExchangeCsWithdrawValue;\n\nexport interface ExchangeRsaWithdrawValue {\n cipher: \"RSA\";\n}\n\nexport interface ExchangeCsWithdrawValue {\n cipher: \"CS\";\n\n /**\n * CSR R0 value\n */\n r_pub_0: string;\n\n /**\n * CSR R1 value\n */\n r_pub_1: string;\n}\n\nexport interface RecoupRequest {\n /**\n * Hashed denomination public key of the coin we want to get\n * paid back.\n */\n denom_pub_hash: string;\n\n /**\n * Signature over the coin public key by the denomination.\n *\n * The string variant is for the legacy exchange protocol.\n */\n denom_sig: UnblindedDenominationSignature;\n\n /**\n * Blinding key that was used during withdraw,\n * used to prove that we were actually withdrawing the coin.\n */\n coin_blind_key_secret: string;\n\n /**\n * Signature of TALER_RecoupRequestPS created with the coin's private key.\n */\n coin_sig: string;\n\n ewv: ExchangeWithdrawValue;\n}\n\nexport interface RecoupRefreshRequest {\n /**\n * Hashed enomination public key of the coin we want to get\n * paid back.\n */\n denom_pub_hash: string;\n\n /**\n * Signature over the coin public key by the denomination.\n *\n * The string variant is for the legacy exchange protocol.\n */\n denom_sig: UnblindedDenominationSignature;\n\n /**\n * Coin's blinding factor.\n */\n coin_blind_key_secret: string;\n\n /**\n * Signature of TALER_RecoupRefreshRequestPS created with\n * the coin's private key.\n */\n coin_sig: string;\n\n ewv: ExchangeWithdrawValue;\n}\n\n/**\n * Response that we get from the exchange for a payback request.\n */\nexport interface RecoupConfirmation {\n /**\n * Public key of the reserve that will receive the payback.\n */\n reserve_pub?: string;\n\n /**\n * Public key of the old coin that will receive the recoup,\n * provided if refreshed was true.\n */\n old_coin_pub?: string;\n}\n\nexport type UnblindedDenominationSignature = RsaUnblindedSignature;\n\nexport interface RsaUnblindedSignature {\n cipher: DenomKeyType.Rsa;\n rsa_signature: string;\n}\n\n/**\n * Deposit permission for a single coin.\n */\nexport interface CoinDepositPermission {\n /**\n * Signature by the coin.\n */\n coin_sig: string;\n\n /**\n * Public key of the coin being spend.\n */\n coin_pub: string;\n\n /**\n * Signature made by the denomination public key.\n *\n * The string variant is for legacy protocol support.\n */\n\n ub_sig: UnblindedDenominationSignature;\n\n /**\n * The denomination public key associated with this coin.\n */\n h_denom: string;\n\n /**\n * The amount that is subtracted from this coin with this payment.\n */\n contribution: string;\n\n /**\n * URL of the exchange this coin was withdrawn from.\n */\n exchange_url: string;\n\n minimum_age_sig?: EddsaSignatureString;\n\n age_commitment?: Edx25519PublicKeyEnc[];\n\n h_age_commitment?: string;\n}\n\n/**\n * Element of the payback list that the\n * exchange gives us in /keys.\n */\nexport interface Recoup {\n /**\n * The hash of the denomination public key for which the payback is offered.\n */\n h_denom_pub: string;\n}\n\n/**\n * Structure that the exchange gives us in /keys.\n */\nexport interface ExchangeKeysResponse {\n /**\n * Canonical, public base URL of the exchange.\n */\n base_url: string;\n\n /**\n * The exchange's currency or asset unit.\n */\n currency: string;\n\n // Open banking gateway base URL where wallets can\n // initiate wire transfers to withdraw\n // digital cash from this exchange.\n // @since protocol **v30**.\n open_banking_gateway?: string;\n\n // Instructs wallets to use certain bank-specific\n // language (for buttons) and/or other UI/UX customization\n // for compliance with the rules of that bank.\n // The specific customizations to apply are done on a per-wallet\n // basis as requested by the specific bank. They only\n // apply when it is clear that the wallet is using digital\n // cash from that bank. This is an advisory option, not\n // all wallets must support all compliance languages.\n // @since protocol **v24**.\n bank_compliance_language?: string;\n\n /**\n * Type of the asset. \"fiat\", \"crypto\", \"regional\"\n * or \"stock\". Wallets should adjust their UI/UX\n * based on this value.\n */\n asset_type: string;\n\n /**\n * How wallets should render the exchange's currency.\n */\n currency_specification?: CurrencySpecification;\n\n /**\n * The exchange's master public key.\n */\n master_public_key: string;\n\n /**\n * The list of auditors (partially) auditing the exchange.\n */\n auditors: ExchangeAuditor[];\n\n /**\n * Timestamp when this response was issued.\n */\n list_issue_date: TalerProtocolTimestamp;\n\n /**\n * List of revoked denominations.\n */\n recoup?: Recoup[];\n\n /**\n * Short-lived signing keys used to sign online\n * responses.\n */\n signkeys: ExchangeSignKeyJson[];\n\n /**\n * Protocol version.\n */\n version: string;\n\n reserve_closing_delay: TalerProtocolDuration;\n\n /**\n * Global fees, applicable only to p2p payments.\n */\n global_fees: GlobalFees[];\n\n accounts: ExchangeWireAccount[];\n\n wire_fees: { [methodName: string]: WireFeesJson[] };\n\n denominations: DenomGroup[];\n\n // Threshold amounts beyond which wallet should\n // trigger the KYC process of the issuing exchange.\n // Optional option, if not given there is no limit.\n // Currency must match currency.\n wallet_balance_limit_without_kyc?: AmountString[];\n\n // Array of limits that apply to all accounts.\n // All of the given limits will be hard limits.\n // Wallets and merchants are expected to obey them\n // and not even allow the user to cross them.\n // Since protocol **v21**.\n hard_limits?: AccountLimit[];\n\n // Array of limits with a soft threshold of zero\n // that apply to all accounts without KYC.\n // Wallets and merchants are expected to trigger\n // a KYC process before attempting any zero-limited\n // operations.\n // Since protocol **v21**.\n zero_limits?: ZeroLimitedOperation[];\n\n // Absolute cost offset for the STEFAN curve used\n // to (over) approximate fees payable by amount.\n stefan_abs: AmountString;\n\n // Factor to multiply the logarithm of the amount\n // with to (over) approximate fees payable by amount.\n // Note that the total to be paid is first to be\n // divided by the smallest denomination to obtain\n // the value that the logarithm is to be taken of.\n stefan_log: AmountString;\n\n // Linear cost factor for the STEFAN curve used\n // to (over) approximate fees payable by amount.\n //\n // Note that this is a scalar, as it is multiplied\n // with the actual amount.\n stefan_lin: number;\n\n // List of exchanges that this exchange is partnering\n // with to enable wallet-to-wallet transfers.\n wads: any;\n\n // Compact EdDSA signature (binary-only) over the\n // contatentation of all of the master_sigs (in reverse\n // chronological order by group) in the arrays under\n // \"denominations\". Signature of TALER_ExchangeKeySetPS\n exchange_sig: EddsaSignature;\n\n // Public EdDSA key of the exchange that was used to generate the signature.\n // Should match one of the exchange's signing keys from signkeys. It is given\n // explicitly as the client might otherwise be confused by clock skew as to\n // which signing key was used for the exchange_sig.\n exchange_pub: EddsaPublicKey;\n\n // Optional field with a dictionary of (name, object) pairs defining the\n // supported and enabled extensions, such as age_restriction.\n extensions?: { name: ExtensionManifest };\n\n // Signature by the exchange master key of the SHA-256 hash of the\n // normalized JSON-object of field extensions, if it was set.\n // The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS.\n extensions_sig?: EddsaSignature;\n\n // Set to true if this exchange has KYC enabled and thus\n // requires KYC auth wire transfers prior to a first deposit.\n // @since in protocol **v24**.\n kyc_enabled?: boolean;\n\n // Shopping URL where users may find shops that accept\n // digital cash issued by this exchange.\n // @since protocol **v21**.\n shopping_url?: string;\n\n // Small(est?) amount that can likely be transferred to\n // the exchange. Should be the default amount for KYC\n // authentication wire transfers to this exchange.\n // Optional, not present if not known or not configured.\n // @since protocol **v21**.\n tiny_amount?: Amount;\n\n // Set to TRUE if wallets should disable the direct deposit feature\n // and deposits should only go via Taler merchant APIs.\n // Mainly used for regional currency and event currency deployments\n // where wallets are not eligible to deposit back into originating\n // bank accounts and, because KYC is not enabled, wallets are thus\n // likely to send money to nirvana instead of where users want it.\n // @since in protocol **v30**.\n disable_direct_deposit?: boolean;\n}\n\nexport interface ExchangeMeltRequest {\n coin_pub: CoinPublicKeyString;\n confirm_sig: EddsaSignatureString;\n denom_pub_hash: HashCodeString;\n denom_sig: UnblindedDenominationSignature;\n rc: string;\n value_with_fee: AmountString;\n age_commitment_hash?: HashCodeString;\n}\n\n/**\n * Docs name: NewMeltRequest\n */\nexport interface ExchangeMeltRequestV2 {\n // The old coin's public key\n old_coin_pub: CoinPublicKeyString;\n\n // Hash of the denomination public key of the old coin, to determine total coin value.\n old_denom_pub_h: HashCodeString;\n\n // The hash of the age-commitment for the old coin. Only present\n // if the denomination has support for age restriction.\n old_age_commitment_h?: string;\n\n // Signature over the old coin public key by the denomination.\n old_denom_sig: UnblindedDenominationSignature;\n\n // Amount of the value of the old coin that should be melted as part of\n // this refresh operation, including melting fee.\n value_with_fee: Amount;\n\n // Array of n new hash codes of denomination public keys\n // for the new coins to order.\n denoms_h: HashCode[];\n\n // Seed from which the nonces for the n*\u03BA coin candidates are derived\n // from.\n refresh_seed: HashCode;\n\n // Master seed for the Clause-Schnorr R-value\n // creation. Must match the /blinding-prepare request.\n // Must not have been used in any prior melt request.\n // Must be present if one of the fresh coin's\n // denominations is of type Clause-Schnorr.\n blinding_seed?: string;\n\n // kappa arrays of n entries for blinded coin candidates,\n // each matching the respective entries in denoms_h.\n //\n // Note: These are essentially the m_i values in the RefreshDerivePQ\n // function.\n coin_evs: CoinEnvelope[][];\n\n // Signature by the coin over TALER_RefreshMeltCoinAffirmationPS.\n confirm_sig: EddsaSignatureString;\n}\n\nexport interface ExchangeMeltResponse {\n /**\n * Which of the kappa indices does the client not have to reveal.\n */\n noreveal_index: number;\n\n /**\n * Signature of TALER_RefreshMeltConfirmationPS whereby the exchange\n * affirms the successful melt and confirming the noreveal_index\n */\n exchange_sig: EddsaSignatureString;\n\n /*\n * public EdDSA key of the exchange that was used to generate the signature.\n * Should match one of the exchange's signing keys from /keys. Again given\n * explicitly as the client might otherwise be confused by clock skew as to\n * which signing key was used.\n */\n exchange_pub: EddsaPublicKeyString;\n\n /*\n * Base URL to use for operations on the refresh context\n * (so the reveal operation). If not given,\n * the base URL is the same as the one used for this request.\n * Can be used if the base URL for /refreshes/ differs from that\n * for /coins/, i.e. for load balancing. Clients SHOULD\n * respect the refresh_base_url if provided. Any HTTP server\n * belonging to an exchange MUST generate a 307 or 308 redirection\n * to the correct base URL should a client uses the wrong base\n * URL, or if the base URL has changed since the melt.\n *\n * When melting the same coin twice (technically allowed\n * as the response might have been lost on the network),\n * the exchange may return different values for the refresh_base_url.\n */\n refresh_base_url?: string;\n}\n\nexport interface ExchangeRevealItem {\n ev_sig: BlindedDenominationSignature;\n}\n\nexport interface ExchangeRevealResponse {\n // List of the exchange's blinded RSA signatures on the new coins.\n ev_sigs: ExchangeRevealItem[];\n}\n\nexport const codecForAuditorDenomSig = (): Codec =>\n buildCodecForObject()\n .property(\"denom_pub_h\", codecForString())\n .property(\"auditor_sig\", codecForString())\n .build(\"AuditorDenomSig\");\n\nexport const codecForAuditor = (): Codec =>\n buildCodecForObject()\n .property(\"auditor_pub\", codecForString())\n .property(\"auditor_url\", codecForString())\n .property(\"denomination_keys\", codecForList(codecForAuditorDenomSig()))\n .build(\"Auditor\");\n\n/**\n * Structure of one exchange signing key in the /keys response.\n */\nexport class ExchangeSignKeyJson {\n stamp_start: TalerProtocolTimestamp;\n stamp_expire: TalerProtocolTimestamp;\n stamp_end: TalerProtocolTimestamp;\n key: EddsaPublicKeyString;\n master_sig: EddsaSignatureString;\n}\n\nexport type DenomGroup =\n | DenomGroupRsa\n | DenomGroupCs\n | DenomGroupRsaAgeRestricted\n | DenomGroupCsAgeRestricted;\n\nexport interface DenomGroupCommon {\n // How much are coins of this denomination worth?\n value: AmountString;\n\n // Fee charged by the exchange for withdrawing a coin of this denomination.\n fee_withdraw: AmountString;\n\n // Fee charged by the exchange for depositing a coin of this denomination.\n fee_deposit: AmountString;\n\n // Fee charged by the exchange for refreshing a coin of this denomination.\n fee_refresh: AmountString;\n\n // Fee charged by the exchange for refunding a coin of this denomination.\n fee_refund: AmountString;\n}\n\nexport interface DenomCommon {\n // Signature of TALER_DenominationKeyValidityPS.\n master_sig: EddsaSignatureString;\n\n // When does the denomination key become valid?\n stamp_start: TalerProtocolTimestamp;\n\n // When is it no longer possible to deposit coins\n // of this denomination?\n stamp_expire_withdraw: TalerProtocolTimestamp;\n\n // Timestamp indicating by when legal disputes relating to these coins must\n // be settled, as the exchange will afterwards destroy its evidence relating to\n // transactions involving this coin.\n stamp_expire_legal: TalerProtocolTimestamp;\n\n stamp_expire_deposit: TalerProtocolTimestamp;\n\n // Set to 'true' if the exchange somehow \"lost\"\n // the private key. The denomination was not\n // necessarily revoked, but still cannot be used\n // to withdraw coins at this time (theoretically,\n // the private key could be recovered in the\n // future; coins signed with the private key\n // remain valid).\n lost?: boolean;\n}\n\nexport interface DenomGroupRsa extends DenomGroupCommon {\n cipher: \"RSA\";\n\n denoms: ({\n rsa_pub: RsaPublicKeyString;\n } & DenomCommon)[];\n}\n\nexport interface DenomGroupRsaAgeRestricted extends DenomGroupCommon {\n cipher: \"RSA+age_restricted\";\n age_mask: AgeMask;\n\n denoms: ({\n rsa_pub: RsaPublicKeyString;\n } & DenomCommon)[];\n}\n\nexport interface DenomGroupCs extends DenomGroupCommon {\n cipher: \"CS\";\n age_mask: AgeMask;\n\n denoms: ({\n cs_pub: Cs25519Point;\n } & DenomCommon)[];\n}\n\nexport interface DenomGroupCsAgeRestricted extends DenomGroupCommon {\n cipher: \"CS+age_restricted\";\n age_mask: AgeMask;\n\n denoms: ({\n cs_pub: Cs25519Point;\n } & DenomCommon)[];\n}\n\n/**\n * Wire fees as announced by the exchange.\n */\nexport class WireFeesJson {\n /**\n * Cost of a wire transfer.\n */\n wire_fee: string;\n\n /**\n * Cost of clising a reserve.\n */\n closing_fee: string;\n\n /**\n * Signature made with the exchange's master key.\n */\n sig: string;\n\n /**\n * Date from which the fee applies.\n */\n start_date: TalerProtocolTimestamp;\n\n /**\n * Data after which the fee doesn't apply anymore.\n */\n end_date: TalerProtocolTimestamp;\n}\n\nexport interface ExchangeWireAccount {\n // payto:// URI identifying the account and wire method\n payto_uri: string;\n\n // URI to convert amounts from or to the currency used by\n // this wire account of the exchange. Missing if no\n // conversion is applicable.\n conversion_url?: string;\n\n // Open banking gateway base URL where wallets can\n // initiate wire transfers to withdraw\n // digital cash from this exchange.\n // @since protocol **v34**.\n open_banking_gateway?: string;\n\n // Wire transfer gateway base URL where wallets and merchants can\n // request (short) wire transfer subjects to wire funds to this\n // exchange without having to encode the full public key.\n // @since protocol **v34**.\n wire_transfer_gateway?: string;\n\n // Restrictions that apply to bank accounts that would send\n // funds to the exchange (crediting this exchange bank account).\n // Optional, empty array for unrestricted.\n credit_restrictions: AccountRestriction[];\n\n // Restrictions that apply to bank accounts that would receive\n // funds from the exchange (debiting this exchange bank account).\n // Optional, empty array for unrestricted.\n debit_restrictions: AccountRestriction[];\n\n // Signature using the exchange's offline key over\n // a TALER_MasterWireDetailsPS\n // with purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS.\n master_sig: EddsaSignatureString;\n\n // Display label wallets should use to show this\n // bank account.\n // Since protocol **v19**.\n bank_label?: string;\n\n priority?: number;\n}\n\nexport const codecForExchangeWireAccount = (): Codec =>\n buildCodecForObject()\n .property(\"conversion_url\", codecOptional(codecForStringURL()))\n .property(\"open_banking_gateway\", codecOptional(codecForStringURL()))\n .property(\"wire_transfer_gateway\", codecOptional(codecForStringURL()))\n .property(\"credit_restrictions\", codecForList(codecForAny()))\n .property(\"debit_restrictions\", codecForList(codecForAny()))\n .property(\"master_sig\", codecForEddsaSignature())\n .property(\"payto_uri\", codecForString())\n .property(\"bank_label\", codecOptional(codecForString()))\n .property(\"priority\", codecOptional(codecForNumber()))\n .build(\"WireAccount\");\n\nexport interface ExchangeRefundRequest {\n // Amount to be refunded, can be a fraction of the\n // coin's total deposit value (including deposit fee);\n // must be larger than the refund fee.\n refund_amount: AmountString;\n\n // SHA-512 hash of the contact of the merchant with the customer.\n h_contract_terms: HashCodeString;\n\n // 64-bit transaction id of the refund transaction between merchant and customer.\n rtransaction_id: number;\n\n // EdDSA public key of the merchant.\n merchant_pub: EddsaPublicKeyString;\n\n // EdDSA signature of the merchant over a\n // TALER_RefundRequestPS with purpose\n // TALER_SIGNATURE_MERCHANT_REFUND\n // affirming the refund.\n merchant_sig: EddsaPublicKeyString;\n}\n\nexport interface ExchangeRefundSuccessResponse {\n // The EdDSA :ref:signature (binary-only) with purpose\n // TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND over\n // a TALER_RecoupRefreshConfirmationPS\n // using a current signing key of the\n // exchange affirming the successful refund.\n exchange_sig: EddsaSignatureString;\n\n // Public EdDSA key of the exchange that was used to generate the signature.\n // Should match one of the exchange's signing keys from /keys. It is given\n // explicitly as the client might otherwise be confused by clock skew as to\n // which signing key was used.\n exchange_pub: EddsaPublicKeyString;\n}\n\nexport const codecForExchangeRefundSuccessResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .property(\"exchange_sig\", codecForEddsaSignature())\n .build(\"ExchangeRefundSuccessResponse\");\n\nexport type AccountRestriction =\n | RegexAccountRestriction\n | DenyAllAccountRestriction;\n\nexport interface DenyAllAccountRestriction {\n type: \"deny\";\n}\n\n// Accounts interacting with this type of account\n// restriction must have a payto://-URI matching\n// the given regex.\nexport interface RegexAccountRestriction {\n type: \"regex\";\n\n // Regular expression that the payto://-URI of the\n // partner account must follow. The regular expression\n // should follow posix-egrep, but without support for character\n // classes, GNU extensions, back-references or intervals. See\n // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html\n // for a description of the posix-egrep syntax. Applications\n // may support regexes with additional features, but exchanges\n // must not use such regexes.\n payto_regex: string;\n\n // Hint for a human to understand the restriction\n // (that is hopefully easier to comprehend than the regex itself).\n human_hint: string;\n\n // Map from IETF BCP 47 language tags to localized\n // human hints.\n human_hint_i18n?: InternationalizedString;\n}\n\nexport type CoinEnvelope = CoinEnvelopeRsa | CoinEnvelopeCs;\n\nexport interface CoinEnvelopeRsa {\n cipher: DenomKeyType.Rsa;\n rsa_blinded_planchet: string;\n}\n\nexport interface CoinEnvelopeCs {\n cipher: DenomKeyType.ClauseSchnorr;\n // FIXME: add remaining fields\n}\n\nexport interface ExchangeLegacyWithdrawRequest {\n denom_pub_hash: HashCodeString;\n reserve_sig: EddsaSignatureString;\n coin_ev: CoinEnvelope;\n}\n\nexport interface ExchangeLegacyBatchWithdrawRequest {\n planchets: ExchangeLegacyWithdrawRequest[];\n}\n\nexport interface ExchangeRefreshRevealRequest {\n new_denoms_h: HashCodeString[];\n coin_evs: CoinEnvelope[];\n /**\n * kappa - 1 transfer private keys (ephemeral ECDHE keys).\n */\n transfer_privs: string[];\n\n transfer_pub: EddsaPublicKeyString;\n\n link_sigs: EddsaSignatureString[];\n\n /**\n * Iff the corresponding denomination has support for age restriction,\n * the client MUST provide the original age commitment, i.e. the vector\n * of public keys.\n */\n old_age_commitment?: Edx25519PublicKeyEnc[];\n}\n\nexport interface ExchangeRefreshRevealRequestV2 {\n // The commitment from the /melt/ step,\n // i.e. the SHA512 value of\n // 1. refresh_seed\n // 2. blinding_seed, if applicable, skip otherwise\n // 4. amount with fee (NBO)\n // 5. kappa*n blinded planchet hashes (which include denomination information),\n // depths first: [0..n)[0..n)[0..n)\n rc: string;\n\n // The disclosed kappa-1 signatures by the old coin's private key,\n // over Hash1a(\"Refresh\", Cp, r, i), where Cp is the melted coin's public key,\n // r is the public refresh nonce from the metling step and i runs over the\n // _disclosed_ kappa-1 indices.\n signatures: EddsaSignature[];\n\n // IFF the denomination of the old coin had support for age restriction,\n // the client MUST provide the original age commitment, i. e. the\n // vector of public keys, or omitted otherwise.\n // The size of the vector MUST be the number of age groups as defined by the\n // Exchange in the field .age_groups of the extension age_restriction.\n age_commitment?: Edx25519PublicKeyEnc[];\n}\n\nexport const codecForRecoup = (): Codec =>\n buildCodecForObject()\n .property(\"h_denom_pub\", codecForString())\n .build(\"Recoup\");\n\nexport const codecForExchangeSigningKey = (): Codec =>\n buildCodecForObject()\n .property(\"key\", codecForEddsaPublicKey())\n .property(\"master_sig\", codecForEddsaSignature())\n .property(\"stamp_end\", codecForTimestamp)\n .property(\"stamp_start\", codecForTimestamp)\n .property(\"stamp_expire\", codecForTimestamp)\n .build(\"ExchangeSignKeyJson\");\n\nexport const codecForGlobalFees = (): Codec =>\n buildCodecForObject()\n .property(\"start_date\", codecForTimestamp)\n .property(\"end_date\", codecForTimestamp)\n .property(\"history_fee\", codecForAmountString())\n .property(\"account_fee\", codecForAmountString())\n .property(\"purse_fee\", codecForAmountString())\n .property(\"history_expiration\", codecForDuration)\n .property(\"purse_account_limit\", codecForNumber())\n .property(\"purse_timeout\", codecForDuration)\n .property(\"master_sig\", codecForEddsaSignature())\n .build(\"GlobalFees\");\n\n// FIXME: Validate properly!\nexport const codecForNgDenominations: Codec = codecForAny();\n\nexport const codecForWireFeesJson = (): Codec =>\n buildCodecForObject()\n .property(\"wire_fee\", codecForAmountString())\n .property(\"closing_fee\", codecForAmountString())\n .property(\"sig\", codecForString())\n .property(\"start_date\", codecForTimestamp)\n .property(\"end_date\", codecForTimestamp)\n .build(\"WireFeesJson\");\n\nexport const codecForRecoupConfirmation = (): Codec =>\n buildCodecForObject()\n .property(\"reserve_pub\", codecOptional(codecForString()))\n .property(\"old_coin_pub\", codecOptional(codecForString()))\n .build(\"RecoupConfirmation\");\n\nexport const codecForLegacyWithdrawResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"ev_sig\", codecForBlindedDenominationSignature())\n .build(\"WithdrawResponse\");\n\nexport class ExchangeLegacyWithdrawResponse {\n ev_sig: BlindedDenominationSignature;\n}\n\nexport class ExchangeLegacyWithdrawBatchResponse {\n ev_sigs: ExchangeLegacyWithdrawResponse[];\n}\n\n/**\n * Docs name: WithdrawResponse\n */\nexport interface ExchangeWithdrawResponse {\n /**\n * Array of blinded signatures over each coin_evs,\n * in the same order as was given in the request.\n * The blinded signatures affirm the coin's validity\n * after unblinding.\n */\n ev_sigs: BlindedDenominationSignature[];\n}\n\nexport enum DenomKeyType {\n Rsa = \"RSA\",\n ClauseSchnorr = \"CS\",\n}\n\nexport namespace DenomKeyType {\n export function toIntTag(t: DenomKeyType): number {\n switch (t) {\n case DenomKeyType.Rsa:\n return 1;\n case DenomKeyType.ClauseSchnorr:\n return 2;\n }\n }\n}\n\n// export interface RsaBlindedDenominationSignature {\n// cipher: DenomKeyType.Rsa;\n// blinded_rsa_signature: string;\n// }\n\n// export interface CSBlindedDenominationSignature {\n// cipher: DenomKeyType.ClauseSchnorr;\n// }\n\n// export type BlindedDenominationSignature =\n// | RsaBlindedDenominationSignature\n// | CSBlindedDenominationSignature;\n\nexport const codecForRsaBlindedDenominationSignature = () =>\n buildCodecForObject()\n .property(\"cipher\", codecForConstString(DenomKeyType.Rsa))\n .property(\"blinded_rsa_signature\", codecForString())\n .build(\"RsaBlindedDenominationSignature\");\n\nexport const codecForBlindedDenominationSignature = () =>\n buildCodecForUnion()\n .discriminateOn(\"cipher\")\n .alternative(DenomKeyType.Rsa, codecForRsaBlindedDenominationSignature())\n .build(\"BlindedDenominationSignature\");\n\nexport const codecForExchangeLegacyWithdrawBatchResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"ev_sigs\", codecForList(codecForLegacyWithdrawResponse()))\n .build(\"WithdrawBatchResponse\");\n\nexport const codecForExchangeWithdrawResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"ev_sigs\", codecForList(codecForBlindedDenominationSignature()))\n .build(\"WithdrawResponse\");\n\nexport const codecForExchangeRevealMeltResponseV2 =\n (): Codec =>\n buildCodecForObject()\n .property(\"ev_sigs\", codecForList(codecForBlindedDenominationSignature()))\n .build(\"ExchangeRevealMeltResponseV2\");\n\nexport const codecForExchangeMeltResponse = (): Codec =>\n buildCodecForObject()\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"noreveal_index\", codecForNumber())\n .property(\"refresh_base_url\", codecOptional(codecForString()))\n .build(\"ExchangeMeltResponse\");\n\nexport const codecForExchangeRevealItem = (): Codec =>\n buildCodecForObject()\n .property(\"ev_sig\", codecForBlindedDenominationSignature())\n .build(\"ExchangeRevealItem\");\n\nexport const codecForExchangeRevealResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"ev_sigs\", codecForList(codecForExchangeRevealItem()))\n .build(\"ExchangeRevealResponse\");\n\nexport interface FutureKeysResponse {\n future_denoms: any[];\n\n future_signkeys: any[];\n\n master_pub: string;\n\n denom_secmod_public_key: string;\n\n // Public key of the signkey security module.\n signkey_secmod_public_key: string;\n}\n\nexport const codecForKeysManagementResponse = (): Codec =>\n buildCodecForObject()\n .property(\"master_pub\", codecForString())\n .property(\"future_signkeys\", codecForList(codecForAny()))\n .property(\"future_denoms\", codecForList(codecForAny()))\n .property(\"denom_secmod_public_key\", codecForAny())\n .property(\"signkey_secmod_public_key\", codecForAny())\n .build(\"FutureKeysResponse\");\n\nexport interface PurseDeposit {\n /**\n * Amount to be deposited, can be a fraction of the\n * coin's total value.\n */\n amount: AmountString;\n\n /**\n * Hash of denomination RSA key with which the coin is signed.\n */\n denom_pub_hash: HashCodeString;\n\n /**\n * Exchange's unblinded RSA signature of the coin.\n */\n ub_sig: UnblindedDenominationSignature;\n\n /**\n * Age commitment for the coin, if the denomination is age-restricted.\n */\n age_commitment?: string[];\n\n /**\n * Attestation for the minimum age, if the denomination is age-restricted.\n */\n attest?: string;\n\n /**\n * Signature over TALER_PurseDepositSignaturePS\n * of purpose TALER_SIGNATURE_WALLET_PURSE_DEPOSIT\n * made by the customer with the\n * coin's private key.\n */\n coin_sig: EddsaSignatureString;\n\n /**\n * Public key of the coin being deposited into the purse.\n */\n coin_pub: EddsaPublicKeyString;\n}\n\nexport interface ExchangePurseMergeRequest {\n // payto://-URI of the account the purse is to be merged into.\n // Must be of the form: 'payto://taler/$EXCHANGE_URL/$RESERVE_PUB'.\n payto_uri: string;\n\n // EdDSA signature of the account/reserve affirming the merge\n // over a TALER_AccountMergeSignaturePS.\n // Must be of purpose TALER_SIGNATURE_ACCOUNT_MERGE\n reserve_sig: EddsaSignatureString;\n\n // EdDSA signature of the purse private key affirming the merge\n // over a TALER_PurseMergeSignaturePS.\n // Must be of purpose TALER_SIGNATURE_PURSE_MERGE.\n merge_sig: EddsaSignatureString;\n\n // Client-side timestamp of when the merge request was made.\n merge_timestamp: TalerProtocolTimestamp;\n}\n\nexport interface ExchangeGetContractResponse {\n purse_pub: string;\n econtract_sig: string;\n econtract: string;\n}\n\nexport const codecForExchangeGetContractResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"purse_pub\", codecForString())\n .property(\"econtract_sig\", codecForString())\n .property(\"econtract\", codecForString())\n .build(\"ExchangeGetContractResponse\");\n\n/**\n * Doc name: api-exchange/MergeSuccess.\n */\nexport interface ExchangeMergeSuccessResponse {\n // Amount merged (excluding deposit fees).\n merge_amount: Amount;\n\n // Time at which the merge came into effect.\n // Maximum of the \"payment_timestamp\" and the\n // \"merge_timestamp\".\n exchange_timestamp: Timestamp;\n\n // EdDSA signature of the exchange affirming the merge of\n // purpose TALER_SIGNATURE_PURSE_MERGE_SUCCESS\n // over TALER_PurseMergeSuccessSignaturePS.\n // Signs over the above and the account public key.\n exchange_sig: EddsaSignatureString;\n\n // public key used to create the signature.\n exchange_pub: EddsaPublicKeyString;\n}\n\nexport const codecForExchangeMergeSuccessResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"merge_amount\", codecForAmountString())\n .property(\"exchange_timestamp\", codecForTimestamp)\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .build(\"ExchangeMergeSuccessResponse\");\n\nexport interface PurseCreateSuccessResponse {\n // Total amount deposited into the purse so far (without fees).\n total_deposited: AmountString;\n\n // Time at the exchange.\n exchange_timestamp: Timestamp;\n\n // EdDSA signature of the exchange affirming the payment,\n // of purpose TALER_SIGNATURE_PURSE_DEPOSIT_CONFIRMED\n // over a TALER_PurseDepositConfirmedSignaturePS.\n // Signs over the above and the purse public key and\n // the hash of the contract terms.\n exchange_sig: EddsaSignature;\n\n // public key used to create the signature.\n exchange_pub: EddsaPublicKey;\n}\n\nexport const codecForPurseCreateSuccessResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"total_deposited\", codecForAmountString())\n .property(\"exchange_timestamp\", codecForTimestamp)\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .build(\"PurseCreateSuccessResponse\");\n\n/**\n * Doc name: api-exchange/MergeConflict\n */\nexport interface ExchangeMergeConflictResponse {\n // Client-side timestamp of when the merge request was made.\n merge_timestamp: Timestamp;\n\n // EdDSA signature of the purse private key affirming the merge\n // over a TALER_PurseMergeSignaturePS.\n // Must be of purpose TALER_SIGNATURE_PURSE_MERGE.\n merge_sig: EddsaSignatureString;\n\n // Base URL of the exchange receiving the payment, only present\n // if the exchange hosting the reserve is not this exchange.\n partner_url?: string;\n\n // Public key of the reserve that the purse was merged into.\n reserve_pub: EddsaPublicKeyString;\n}\n\nexport const codecForExchangeMergeConflictResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"merge_timestamp\", codecForTimestamp)\n .property(\"merge_sig\", codecForEddsaSignature())\n .property(\"reserve_pub\", codecForEddsaPublicKey())\n .property(\"partner_url\", codecOptional(codecForString()))\n .build(\"ExchangeMergeConflictResponse\");\n\n/**\n * Contract terms between two wallets (as opposed to a merchant and wallet).\n */\nexport interface PeerContractTerms {\n amount: AmountString;\n summary: string;\n icon_id?: string;\n purse_expiration: TalerProtocolTimestamp;\n}\n\nexport interface EncryptedContract {\n // Encrypted contract.\n econtract: string;\n\n // Signature over the (encrypted) contract.\n econtract_sig: string;\n\n // Ephemeral public key for the DH operation to decrypt the encrypted contract.\n contract_pub: string;\n}\n\n/**\n * Payload for /reserves/{reserve_pub}/purse\n * endpoint of the exchange.\n */\nexport interface ExchangeReservePurseRequest {\n /**\n * Minimum amount that must be credited to the reserve, that is\n * the total value of the purse minus the deposit fees.\n * If the deposit fees are lower, the contribution to the\n * reserve can be higher!\n */\n purse_value: AmountString;\n\n // Minimum age required for all coins deposited into the purse.\n min_age: number;\n\n // Purse fee the reserve owner is willing to pay\n // for the purse creation. Optional, if not present\n // the purse is to be created from the purse quota\n // of the reserve.\n purse_fee: AmountString;\n\n // Optional encrypted contract, in case the buyer is\n // proposing the contract and thus establishing the\n // purse with the payment.\n econtract?: EncryptedContract;\n\n // EdDSA public key used to approve merges of this purse.\n merge_pub: EddsaPublicKeyString;\n\n // EdDSA signature of the purse private key affirming the merge\n // over a TALER_PurseMergeSignaturePS.\n // Must be of purpose TALER_SIGNATURE_PURSE_MERGE.\n merge_sig: EddsaSignatureString;\n\n // EdDSA signature of the account/reserve affirming the merge.\n // Must be of purpose TALER_SIGNATURE_WALLET_ACCOUNT_MERGE\n reserve_sig: EddsaSignatureString;\n\n // Purse public key.\n purse_pub: EddsaPublicKeyString;\n\n // EdDSA signature of the purse over\n // TALER_PurseRequestSignaturePS of\n // purpose TALER_SIGNATURE_PURSE_REQUEST\n // confirming that the\n // above details hold for this purse.\n purse_sig: EddsaSignatureString;\n\n // SHA-512 hash of the contact of the purse.\n h_contract_terms: HashCodeString;\n\n // Client-side timestamp of when the merge request was made.\n merge_timestamp: TalerProtocolTimestamp;\n\n // Indicative time by which the purse should expire\n // if it has not been paid.\n purse_expiration: TalerProtocolTimestamp;\n}\n\nexport interface ExchangePurseDeposits {\n // Array of coins to deposit into the purse.\n deposits: PurseDeposit[];\n}\n\n/**\n * @deprecated batch deposit should be used.\n */\nexport interface ExchangeDepositRequest {\n // Amount to be deposited, can be a fraction of the\n // coin's total value.\n contribution: AmountString;\n\n // The merchant's account details.\n // In case of an auction policy, it refers to the seller.\n merchant_payto_uri: string;\n\n // The salt is used to hide the payto_uri from customers\n // when computing the h_wire of the merchant.\n wire_salt: string;\n\n // SHA-512 hash of the contract of the merchant with the customer. Further\n // details are never disclosed to the exchange.\n h_contract_terms: HashCodeString;\n\n // Hash of denomination RSA key with which the coin is signed.\n denom_pub_hash: HashCodeString;\n\n // Exchange's unblinded RSA signature of the coin.\n ub_sig: UnblindedDenominationSignature;\n\n // Timestamp when the contract was finalized.\n timestamp: TalerProtocolTimestamp;\n\n // Indicative time by which the exchange undertakes to transfer the funds to\n // the merchant, in case of successful payment. A wire transfer deadline of 'never'\n // is not allowed.\n wire_transfer_deadline: TalerProtocolTimestamp;\n\n // EdDSA public key of the merchant, so that the client can identify the\n // merchant for refund requests.\n //\n // THIS FIELD WILL BE DEPRECATED, once the refund mechanism becomes a\n // policy via extension.\n merchant_pub: EddsaPublicKeyString;\n\n // Date until which the merchant can issue a refund to the customer via the\n // exchange, to be omitted if refunds are not allowed.\n //\n // THIS FIELD WILL BE DEPRECATED, once the refund mechanism becomes a\n // policy via extension.\n refund_deadline?: TalerProtocolTimestamp;\n\n // CAVEAT: THIS IS WORK IN PROGRESS\n // (Optional) policy for the deposit.\n // This might be a refund, auction or escrow policy.\n //\n // Note that support for policies is an optional feature of the exchange.\n // Optional features are so called \"extensions\" in Taler. The exchange\n // provides the list of supported extensions, including policies, in the\n // ExtensionsManifestsResponse response to the /keys endpoint.\n policy?: any;\n\n // Signature over TALER_DepositRequestPS, made by the customer with the\n // coin's private key.\n coin_sig: EddsaSignatureString;\n\n h_age_commitment?: string;\n}\n\nexport type TrackTransaction =\n | ({ type: \"accepted\" } & TrackTransactionAccepted)\n | ({ type: \"wired\" } & TrackTransactionWired);\n\nexport interface BatchDepositSuccess {\n // Optional base URL of the exchange for looking up wire transfers\n // associated with this transaction. If not given,\n // the base URL is the same as the one used for this request.\n // Can be used if the base URL for ``/transactions/`` differs from that\n // for ``/coins/``, i.e. for load balancing. Clients SHOULD\n // respect the ``transaction_base_url`` if provided. Any HTTP server\n // belonging to an exchange MUST generate a 307 or 308 redirection\n // to the correct base URL should a client uses the wrong base\n // URL, or if the base URL has changed since the deposit.\n transaction_base_url?: string;\n\n // Timestamp when the deposit was received by the exchange.\n exchange_timestamp: TalerProtocolTimestamp;\n\n // `Public EdDSA key of the exchange ` that was used to\n // generate the signature.\n // Should match one of the exchange's signing keys from ``/keys``. It is given\n // explicitly as the client might otherwise be confused by clock skew as to\n // which signing key was used.\n exchange_pub: EddsaPublicKeyString;\n\n // Array of deposit confirmation signatures from the exchange\n // Entries must be in the same order the coins were given\n // in the batch deposit request.\n exchange_sig: EddsaSignatureString;\n}\n\nexport const codecForBatchDepositSuccess = (): Codec =>\n buildCodecForObject()\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"exchange_timestamp\", codecForTimestamp)\n .property(\"transaction_base_url\", codecOptional(codecForString()))\n .build(\"BatchDepositSuccess\");\n\nexport interface ExchangePurseStatus {\n // Total amount deposited into the purse so far.\n // If 'total_deposit_amount' minus 'deposit_fees'\n // exceeds 'merge_value_after_fees', and a\n // 'merge_request' exists for the purse, then the\n // purse will (have been) merged with the account.\n balance: AmountString;\n\n // Time of the merge, missing if \"never\".\n deposit_timestamp?: TalerProtocolTimestamp;\n\n // Time of the deposits being complete, missing if \"never\".\n // Note that this time may not be \"stable\": once sufficient\n // deposits have been made, is \"now\" before the purse\n // expiration, and otherwise set to the purse expiration.\n // However, this should also not be relied upon. The key\n // property is that it is either \"never\" or in the past.\n merge_timestamp?: TalerProtocolTimestamp;\n}\n\nexport const codecForExchangePurseStatus = (): Codec =>\n buildCodecForObject()\n .property(\"balance\", codecForAmountString())\n .property(\"deposit_timestamp\", codecOptional(codecForTimestamp))\n .property(\"merge_timestamp\", codecOptional(codecForTimestamp))\n .build(\"ExchangePurseStatus\");\n\nexport interface TrackTransactionWired {\n // Raw wire transfer identifier of the deposit.\n wtid: Base32String;\n\n // When was the wire transfer given to the bank.\n execution_time: TalerProtocolTimestamp;\n\n // The contribution of this coin to the total (without fees)\n coin_contribution: AmountString;\n\n // Binary-only Signature_ with purpose TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE\n // over a TALER_ConfirmWirePS\n // whereby the exchange affirms the successful wire transfer.\n exchange_sig: EddsaSignatureString;\n\n // Public EdDSA key of the exchange that was used to generate the signature.\n // Should match one of the exchange's signing keys from /keys. Again given\n // explicitly as the client might otherwise be confused by clock skew as to\n // which signing key was used.\n exchange_pub: EddsaPublicKeyString;\n}\n\nexport const codecForTackTransactionWired = (): Codec =>\n buildCodecForObject()\n .property(\"wtid\", codecForString())\n .property(\"execution_time\", codecForTimestamp)\n .property(\"coin_contribution\", codecForAmountString())\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .build(\"TackTransactionWired\");\n\nexport interface TrackTransactionAccepted {\n // Legitimization target that the merchant should\n // use to check for its KYC status using\n // the /kyc-check/$REQUIREMENT_ROW/... endpoint.\n // Optional, not present if the deposit has not\n // yet been aggregated to the point that a KYC\n // need has been evaluated.\n requirement_row?: number;\n\n // True if the KYC check for the merchant has been\n // satisfied. False does not mean that KYC\n // is strictly needed, unless also a\n // legitimization_uuid is provided.\n kyc_ok: boolean;\n\n // Time by which the exchange currently thinks the deposit will be executed.\n // Actual execution may be later if the KYC check is not satisfied by then.\n execution_time: TalerProtocolTimestamp;\n\n // Public key associated with the account. The client must sign\n // the initial request for the KYC status using the corresponding\n // private key. Will be the merchant (instance) public key.\n //\n // Absent if no public key is currently associated\n // with the account and the client MUST thus first\n // credit the exchange via an inbound wire transfer\n // to associate a public key with the debited account.\n // @since protocol **v20**.\n account_pub: EddsaPublicKeyString | undefined;\n}\n\nexport const codecForTackTransactionAccepted =\n (): Codec =>\n buildCodecForObject()\n .property(\"requirement_row\", codecOptional(codecForNumber()))\n .property(\"kyc_ok\", codecForBoolean())\n .property(\"execution_time\", codecForTimestamp)\n .property(\"account_pub\", codecOptional(codecForEddsaPublicKey()))\n .build(\"TackTransactionAccepted\");\n\nexport const codecForPeerContractTerms = (): Codec =>\n buildCodecForObject()\n .property(\"summary\", codecForString())\n .property(\"amount\", codecForAmountString())\n .property(\"purse_expiration\", codecForTimestamp)\n .property(\"icon_id\", codecOptional(codecForString()))\n .build(\"PeerContractTerms\");\n\nexport interface ExchangeBatchDepositRequest {\n // The merchant's account details.\n merchant_payto_uri: string;\n\n // Merchant's signature over the h_contract_terms.\n // @since v22\n merchant_sig: EddsaSignatureString;\n\n // The salt is used to hide the ``payto_uri`` from customers\n // when computing the ``h_wire`` of the merchant.\n wire_salt: WireSalt;\n\n // SHA-512 hash of the contract of the merchant with the customer. Further\n // details are never disclosed to the exchange.\n h_contract_terms: HashCodeString;\n\n // The list of coins that are going to be deposited with this Request.\n coins: BatchDepositRequestCoin[];\n\n // Timestamp when the contract was finalized.\n timestamp: TalerProtocolTimestamp;\n\n // Indicative time by which the exchange undertakes to transfer the funds to\n // the merchant, in case of successful payment. A wire transfer deadline of 'never'\n // is not allowed.\n wire_transfer_deadline: TalerProtocolTimestamp;\n\n // EdDSA `public key of the merchant `, so that the client can identify the\n // merchant for refund requests.\n merchant_pub: EddsaPublicKeyString;\n\n // Date until which the merchant can issue a refund to the customer via the\n // exchange, to be omitted if refunds are not allowed.\n //\n // THIS FIELD WILL BE DEPRECATED, once the refund mechanism becomes a\n // policy via extension.\n refund_deadline?: TalerProtocolTimestamp;\n\n // CAVEAT: THIS IS WORK IN PROGRESS\n // (Optional) policy for the batch-deposit.\n // This might be a refund, auction or escrow policy.\n policy?: any;\n}\n\nexport interface BatchDepositRequestCoin {\n // EdDSA public key of the coin being deposited.\n coin_pub: EddsaPublicKeyString;\n\n // Hash of denomination RSA key with which the coin is signed.\n denom_pub_hash: HashCodeString;\n\n // Exchange's unblinded RSA signature of the coin.\n ub_sig: UnblindedDenominationSignature;\n\n // Amount to be deposited, can be a fraction of the\n // coin's total value.\n contribution: AmountString;\n\n // Signature over `TALER_DepositRequestPS`, made by the customer with the\n // `coin's private key `.\n coin_sig: EddsaSignatureString;\n\n h_age_commitment?: string;\n}\n\nexport interface AvailableMeasureSummary {\n // Available original measures that can be\n // triggered directly by default rules.\n roots: { [measure_name: string]: MeasureInformation };\n\n // Available AML programs.\n programs: { [prog_name: string]: AmlProgramRequirement };\n\n // Available KYC checks.\n checks: { [check_name: string]: KycCheckInformation };\n\n // Default KYC rules. This is the set of KYC rules that\n // applies by default to new \"accounts\". Note that some\n // rules only apply to wallets, while others only apply to\n // bank accounts. The returned array is the union of all\n // possible rules, applications should consider the\n // operation_type to filter for rules that actually\n // apply to a specific situation.\n // @since protocol **v28**.\n default_rules: KycRule[];\n}\n\nexport interface MeasureInformation {\n // Name of a KYC check.\n check_name: string;\n\n // Name of an AML program.\n prog_name?: string;\n\n // Context for the check. Optional.\n context?: Object;\n\n // Operation that this measure relates to.\n // NULL if unknown. Useful as a hint to the\n // user if there are many (voluntary) measures\n // and some related to unlocking certain operations.\n // (and due to zero-amount thresholds, no measure\n // was actually specifically triggered).\n //\n // Must be one of \"WITHDRAW\", \"DEPOSIT\",\n // (p2p) \"MERGE\", (wallet) \"BALANCE\",\n // (reserve) \"CLOSE\", \"AGGREGATE\",\n // \"TRANSACTION\" or \"REFUND\".\n // New in protocol **v21**.\n operation_type?: LimitOperationType;\n\n // Can this measure be undertaken voluntarily?\n // Optional, default is false.\n // Since protocol **vATTEST**.\n voluntary?: boolean;\n}\n\nexport interface AmlProgramRequirement {\n // Description of what the AML program does.\n description: string;\n\n // List of required field names in the context to run this\n // AML program. SPA must check that the AML staff is providing\n // adequate CONTEXT when defining a measure using this program.\n context: string[];\n\n // List of required attribute names in the\n // input of this AML program. These attributes\n // are the minimum that the check must produce\n // (it may produce more).\n inputs: string[];\n}\n\nexport interface KycCheckInformation {\n // Description of the KYC check. Should be shown\n // to the AML staff but will also be shown to the\n // client when they initiate the check in the KYC SPA.\n description: string;\n\n // Map from IETF BCP 47 language tags to localized\n // description texts.\n description_i18n?: { [lang_tag: string]: string };\n\n // Names of the fields that the CONTEXT must provide\n // as inputs to this check.\n // SPA must check that the AML staff is providing\n // adequate CONTEXT when defining a measure using\n // this check.\n requires: string[];\n\n // Names of the attributes the check will output.\n // SPA must check that the outputs match the\n // required inputs when combining a KYC check\n // with an AML program into a measure.\n outputs: string[];\n\n // Name of a root measure taken when this check fails.\n fallback: string;\n}\n\nexport interface AmlDecisionDetails {\n // Array of AML decisions made for this account. Possibly\n // contains only the most recent decision if \"history\" was\n // not set to 'true'.\n aml_history: AmlDecisionDetail[];\n\n // Array of KYC attributes obtained for this account.\n kyc_attributes: KycDetail[];\n}\n\nexport interface AmlDecisionDetail {\n // What was the justification given?\n justification: string;\n\n // What is the new AML state.\n new_state: Integer;\n\n // When was this decision made?\n decision_time: Timestamp;\n\n // What is the new AML decision threshold (in monthly transaction volume)?\n new_threshold: AmountString;\n\n // Who made the decision?\n decider_pub: AmlOfficerPublicKeyP;\n}\n\nexport interface KycDetail {\n // Name of the configuration section that specifies the provider\n // which was used to collect the KYC details\n provider_section: string;\n\n // The collected KYC data. NULL if the attribute data could not\n // be decrypted (internal error of the exchange, likely the\n // attribute key was changed).\n attributes?: Object;\n\n // Time when the KYC data was collected\n collection_time: Timestamp;\n\n // Time when the validity of the KYC data will expire\n expiration_time: Timestamp;\n}\n\nexport type AmlDecisionRequestWithoutSignature = Omit<\n AmlDecisionRequest,\n \"officer_sig\"\n>;\n\nexport enum AmlSpaDialect {\n TOPS = \"tops\",\n GLS = \"gls\",\n TESTING = \"testing\",\n}\n\nexport interface ExchangeVersionResponse {\n // libtool-style representation of the Exchange protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Name of the protocol.\n name: \"taler-exchange\";\n\n // URN of the implementation (needed to interpret 'revision' in version).\n // @since v18, may become mandatory in the future.\n implementation?: string;\n\n // Currency supported by this exchange, given\n // as a currency code (\"USD\" or \"EUR\").\n currency: string;\n\n // How wallets should render this currency.\n currency_specification: CurrencySpecification;\n\n // Names of supported KYC requirements.\n supported_kyc_requirements?: string[];\n\n // Bank-specific dialect for the AML SPA. Determines\n // which set of forms is available as well as statistics\n // to show and sets of properties/events to trigger in\n // AML decisions.\n // @since protocol **v24**.\n aml_spa_dialect?: AmlSpaDialect;\n\n // Open banking gateway base URL where wallets can\n // initiate wire transfers to withdraw\n // digital cash from this exchange.\n // @since protocol **v30**.\n open_banking_gateway?: string;\n}\n\nexport interface WalletKycRequest {\n // Balance threshold (not necessarily exact balance)\n // to be crossed by the wallet that (may) trigger\n // additional KYC requirements.\n balance: AmountString;\n\n // EdDSA signature of the wallet affirming the\n // request, must be of purpose\n // TALER_SIGNATURE_WALLET_ACCOUNT_SETUP\n reserve_sig: EddsaSignatureString;\n\n // long-term wallet reserve-account\n // public key used to create the signature.\n reserve_pub: EddsaPublicKeyString;\n}\n\n/**\n * Doc name: api-exchange/WalletKycCheckResponse\n */\nexport interface WalletKycCheckResponse {\n // Next balance limit above which a KYC check\n // may be required. Optional, not given if no\n // threshold exists (assume infinity).\n next_threshold?: AmountString;\n\n // When does the current set of AML/KYC rules\n // expire and the wallet needs to check again\n // for updated thresholds.\n expiration_time: Timestamp;\n}\n\n// Implemented in this style since exchange\n// protocol **v20**.\nexport interface LegitimizationNeededResponse {\n // Numeric error code unique to the condition.\n // Should always be TALER_EC_EXCHANGE_GENERIC_KYC_REQUIRED.\n code: number;\n\n // Human-readable description of the error, i.e. \"missing parameter\",\n // \"commitment violation\", ... Should give a human-readable hint\n // about the error's nature. Optional, may change without notice!\n hint?: string;\n\n // Hash of the payto:// account URI for which KYC\n // is required.\n // The account holder can uses the /kyc-check/$H_PAYTO\n // endpoint to check the KYC status or initiate the KYC process.\n h_payto: PaytoHash;\n\n // Public key associated with the account. The client must sign\n // the initial request for the KYC status using the corresponding\n // private key. Will be either a reserve public key or a merchant\n // (instance) public key.\n //\n // Absent if no public key is currently associated\n // with the account and the client MUST thus first\n // credit the exchange via an inbound wire transfer\n // to associate a public key with the debited account.\n account_pub?: EddsaPublicKeyString;\n\n // Identifies a set of measures that were triggered and that are\n // now preventing this operation from proceeding. Gives developers\n // a starting point for understanding why the transaction was\n // blocked and how to lift it.\n // Can be zero (which means there is no requirement row),\n // especially if bad_kyc_auth is set.\n requirement_row: Integer;\n\n // True if the operation was denied because the\n // KYC auth key does not match the merchant public\n // key. In this case, a KYC auth wire transfer\n // with the merchant public key must be performed\n // first.\n // Since exchange protocol **v21**.\n bad_kyc_auth?: boolean;\n}\n\nexport interface AccountKycStatus {\n // Current AML state for the target account. True if\n // operations are not happening due to staff processing\n // paperwork *or* due to legal requirements (so the\n // client cannot do anything but wait).\n //\n // Note that not every AML staff action may be legally\n // exposed to the client, so this is merely a hint that\n // a client should be told that AML staff is currently\n // reviewing the account. AML staff *may* review\n // accounts without this flag being set!\n aml_review: boolean;\n\n // Monotonically increasing number identifying the decision.\n // 0 if no decision was taken for this account. Useful for\n // long-polling via min_rule to long-poll for any change\n // to the rules or limits.\n rule_gen: Integer;\n\n // Access token needed to construct the /kyc-spa/\n // URL that the user should open in a browser to\n // proceed with the KYC process (optional if the status\n // type is 200 Ok, mandatory if the HTTP status\n // is 202 Accepted).\n access_token: AccessToken;\n\n // Array with limitations that currently apply to this\n // account and that may be increased or lifted if the\n // KYC check is passed.\n // Note that additional limits *may* exist and not be\n // communicated to the client. If such limits are\n // reached, this *may* be indicated by the account\n // going into aml_review state. However, it is\n // also possible that the exchange may legally have\n // to deny operations without being allowed to provide\n // any justification.\n // The limits should be used by the client to\n // possibly structure their operations (e.g. withdraw\n // what is possible below the limit, ask the user to\n // pass KYC checks or withdraw the rest after the time\n // limit is passed, warn the user to not withdraw too\n // much or even prevent the user from generating a\n // request that would cause it to exceed hard limits).\n limits?: AccountLimit[];\n}\n\nexport enum LimitOperationType {\n withdraw = \"WITHDRAW\",\n deposit = \"DEPOSIT\",\n merge = \"MERGE\",\n aggregate = \"AGGREGATE\",\n balance = \"BALANCE\",\n refund = \"REFUND\",\n close = \"CLOSE\",\n transaction = \"TRANSACTION\",\n}\n\nexport interface AccountLimit {\n // Operation that is limited.\n operation_type: LimitOperationType;\n\n // Timeframe during which the limit applies.\n timeframe: RelativeTime;\n\n // Maximum amount allowed during the given timeframe.\n // Zero if the operation is simply forbidden.\n threshold: AmountString;\n\n // True if this is a soft limit that could be raised\n // by passing KYC checks. Clients *may* deliberately\n // try to cross limits and trigger measures resulting\n // in 451 responses to begin KYC processes.\n // Clients that are aware of hard limits *should*\n // inform users about the hard limit and prevent flows\n // in the UI that would cause violations of hard limits.\n // Made optional in **v21** with a default of 'false' if missing.\n soft_limit?: boolean;\n\n // FIXME: undocumented\n rule_name?: string;\n}\n\nexport interface KycProcessClientInformation {\n // Array of requirements.\n requirements: KycRequirementInformation[];\n\n // True if the client is expected to eventually satisfy all requirements.\n // Default (if missing) is false.\n is_and_combinator?: boolean;\n\n // List of available voluntary checks the client could pay for.\n // Since **vATTEST**.\n voluntary_measures?: KycRequirementInformation[];\n}\n\nexport type KycProcessClientInformationWithEtag =\n KycProcessClientInformation & { etag: string | undefined };\n\ndeclare const opaque_brand: unique symbol;\n\ndeclare const opaque_kycReq: unique symbol;\n\nexport type KycRequirementInformationId = string & {\n [opaque_brand]?: typeof opaque_kycReq;\n};\ndeclare const opaque_formId: unique symbol;\nexport type KycBuiltInFromId = string & { [opaque_formId]: true };\n\nexport interface KycRequirementInformation {\n // Which form should be used? Common values include \"INFO\"\n // (to just show the descriptions but allow no action),\n // \"LINK\" (to enable the user to obtain a link via\n // /kyc-start/) or any built-in form name supported\n // by the SPA.\n form: \"LINK\" | \"INFO\" | KycBuiltInFromId;\n\n // English description of the requirement.\n description: string;\n\n // Object with arbitrary additional context, completely depends on\n // the specific form.\n context?: Object;\n\n // Map from IETF BCP 47 language tags to localized\n // description texts.\n description_i18n?: { [lang_tag: string]: string };\n\n // ID of the requirement, useful to construct the\n // /kyc-upload/$ID or /kyc-start/$ID endpoint URLs.\n // Present if and only if \"form\" is not \"INFO\". The\n // $ID value may itself contain / or ? and\n // basically encode any URL path (and optional arguments).\n id?: KycRequirementInformationId;\n}\n\nexport type ExchangeKycUploadFormRequest = {\n // Which form is being submitted. Further details depend on the form.\n // @since protocol v26.\n // form_id: string;\n [TalerFormAttributes.FORM_ID]: string;\n [TalerFormAttributes.FORM_VERSION]: number;\n};\n\n// Since **vATTEST**.\nexport interface KycCheckPublicInformation {\n // English description of the check.\n description: string;\n\n // Map from IETF BCP 47 language tags to localized\n // description texts.\n description_i18n?: { [lang_tag: string]: string };\n\n // FIXME: is the above in any way sufficient\n // to begin the check? Do we not need at least\n // something more??!?\n}\n\nexport interface AmlStatisticsResponse {\n statistics: EventCounter[];\n}\nexport interface EventCounter {\n // Name of the statistic that is being returned.\n name: string;\n\n // Number of events of the specified type in\n // the given range.\n counter: Integer;\n}\n\nexport interface AmlDecisionsResponse {\n // Array of AML decisions matching the query.\n records: AmlDecision[];\n}\n\nexport interface LegitimizationMeasuresList {\n // Legitimization measures.\n measures: LegitimizationMeasureDetails[];\n}\n\nexport interface LegitimizationMeasures {\n // Array of legitimization measures that\n // are to be applied.\n measures: MeasureInformation[];\n\n // True if the client is expected to eventually satisfy all requirements.\n // Default (if missing) is false.\n is_and_combinator?: boolean;\n\n // True if the requested operation is categorically forbidden.\n // The measures array will be empty in this case.\n verboten: boolean;\n}\n\nexport interface LegitimizationMeasureDetails {\n // Hash of the normalized payto:// URI of the account the\n // measure applies to.\n h_payto: HashCode;\n\n // Row of the measure in the exchange database.\n rowid: Integer;\n\n // When was the measure started?\n start_time: Timestamp;\n\n // The the actual measures.\n measures: LegitimizationMeasures;\n\n // Was this measure finished by the customer?\n is_finished: boolean;\n}\n\nexport interface AmlDecision {\n // Which payto-address is this record about.\n // Identifies a GNU Taler wallet or an affected bank account.\n h_payto: PaytoHash;\n\n full_payto?: string;\n\n // True if the underlying payto://-URI is for a wallet\n // Since protocol **v25**.\n is_wallet: boolean;\n\n // Row ID of the record. Used to filter by offset.\n rowid: Integer;\n\n // Justification for the decision. NULL if none\n // is available.\n justification?: string;\n\n // When was the decision made?\n decision_time: Timestamp;\n\n // Free-form properties about the account.\n // Can be used to store properties such as PEP,\n // risk category, type of business, hits on\n // sanctions lists, etc.\n properties?: AccountProperties;\n\n // What are the new rules?\n limits: LegitimizationRuleSet;\n\n // True if the account is under investigation by AML staff\n // after this decision.\n to_investigate: boolean;\n\n // True if this is the active decision for the\n // account.\n is_active: boolean;\n}\n\n// All fields in this object are optional. The actual\n// properties collected depend fully on the discretion\n// of the exchange operator;\n// however, some common fields are standardized\n// and thus described here.\nexport interface AccountProperties {\n // True if this is a politically exposed account.\n // Rules for classifying accounts as politically\n // exposed are country-dependent.\n pep?: boolean;\n\n // True if this is a sanctioned account.\n // Rules for classifying accounts as sanctioned\n // are country-dependent.\n sanctioned?: boolean;\n\n // True if this is a high-risk account.\n // Rules for classifying accounts as at-risk\n // are exchange operator-dependent.\n high_risk?: boolean;\n\n // Business domain of the account owner.\n // The list of possible business domains is\n // operator- or country-dependent.\n business_domain?: string;\n\n // Is the client's account currently frozen?\n is_frozen?: boolean;\n\n // Was the client's account reported to the authorities?\n was_reported?: boolean;\n\n /**\n * Additional free-form properties.\n */\n [x: string]: any;\n}\n\nexport interface LegitimizationRuleSet {\n // When does this set of rules expire and\n // we automatically transition to the successor\n // measure?\n expiration_time: Timestamp;\n\n // Name of the measure to apply when the expiration time is\n // reached. If not set, we refer to the default\n // set of rules (and the default account state).\n successor_measure?: string;\n\n // Legitimization rules that are to be applied\n // to this account.\n rules: KycRule[];\n\n // Custom measures that KYC rules and the\n // successor_measure may refer to.\n custom_measures: { [measure_name: string]: MeasureInformation };\n}\n\nexport interface AmlDecisionRequest {\n // Human-readable justification for the decision.\n justification: string;\n\n // Which payto-address is the decision about?\n // Identifies a GNU Taler wallet or an affected bank account.\n h_payto: PaytoHash;\n\n // Payto address of the account the decision is about.\n // Optional. Must be given if the account is not yet\n // known to the exchange. If given, must match h_payto.\n // New since protocol **v21**.\n payto_uri?: string;\n\n // What are the new rules?\n // New since protocol **v20**.\n new_rules: LegitimizationRuleSet;\n\n // What are the new account properties?\n // New since protocol **v20**.\n properties: AccountProperties;\n\n // Array of AML/KYC events to trigger for statistics.\n // Note that this information is not covered by the signature\n // (which is OK as events are just for statistics).\n // New since protocol **v24**.\n events?: string[];\n\n // Space-separated list of measures to trigger\n // immediately on the account.\n // Prefixed with a \"+\" to indicate that the\n // measures should be ANDed.\n // Should typically be used to give the user some\n // information or request additional information.\n // New since protocol **v21**.\n new_measures?: string;\n\n // True if the account should remain under investigation by AML staff.\n // New since protocol **v20**.\n keep_investigating: boolean;\n\n /**\n * Signature by the AML officer over a TALER_AmlDecisionPS.\n * Must have purpose TALER_SIGNATURE_MASTER_AML_KEY.\n */\n officer_sig: EddsaSignatureString;\n\n /**\n * When was the decision made?\n */\n decision_time: Timestamp;\n\n // KYC attributes uploaded by the AML officer\n // The object *must* contain high-entropy salt,\n // as the hash of the attributes will be\n // stored in plain text.\n attributes?: Object;\n\n // Expiration timestamp of the attributes.\n // Mandatory if attributes are present.\n attributes_expiration?: Timestamp;\n}\n\nexport interface KycRule {\n // Type of operation to which the rule applies.\n operation_type: LimitOperationType;\n\n // The measures will be taken if the given\n // threshold is crossed over the given timeframe.\n threshold: AmountString;\n\n // Over which duration should the threshold be\n // computed. All amounts of the respective\n // operation_type will be added up for this\n // duration and the sum compared to the threshold.\n timeframe: RelativeTime;\n\n // Array of names of measures to apply.\n // Names listed can be original measures or\n // custom measures from the AmlOutcome.\n // A special measure \"verboten\" is used if the\n // threshold may never be crossed.\n measures: string[];\n\n // If multiple rules apply to the same account\n // at the same time, the number with the highest\n // rule determines which set of measures will\n // be activated and thus become visible for the\n // user.\n display_priority: Integer;\n\n // True if the rule (specifically, operation_type,\n // threshold, timeframe) and the general nature of\n // the measures (verboten or approval required)\n // should be exposed to the client.\n // Defaults to \"false\" if not set.\n exposed?: boolean;\n\n // True if all the measures will eventually need to\n // be satisfied, false if any of the measures should\n // do. Primarily used by the SPA to indicate how\n // the measures apply when showing them to the user;\n // in the end, AML programs will decide after each\n // measure what to do next.\n // Default (if missing) is false.\n is_and_combinator?: boolean;\n\n // Name of the configuration section this rule\n // originates from. Not available for all rules.\n // Primarily informational, but also useful to\n // explicitly manipulate rules by-name in AML programs.\n rule_name?: string;\n}\n\nexport interface KycAttributes {\n // Matching KYC attribute history of the account.\n details: KycAttributeCollectionEvent[];\n}\nexport interface KycAttributeCollectionEvent {\n // Row ID of the record. Used to filter by offset.\n rowid: Integer;\n\n // Name of the provider\n // which was used to collect the attributes. NULL if they were\n // just uploaded via a form by the account owner.\n provider_name?: string;\n\n // The collected KYC data. NULL if the attribute data could not\n // be decrypted (internal error of the exchange, likely the\n // attribute key was changed).\n attributes?: { [x: string]: unknown };\n\n // Time when the KYC data was collected\n collection_time: Timestamp;\n}\n\nexport enum AmlState {\n normal = 0,\n pending = 1,\n frozen = 2,\n}\ntype Float = number;\n\nexport interface ZeroLimitedOperation {\n // Operation that is limited to an amount of\n // zero until the client has passed some KYC check.\n // Must be one of \"WITHDRAW\", \"DEPOSIT\",\n // (p2p) \"MERGE\", (wallet) \"BALANCE\",\n // (reserve) \"CLOSE\", \"AGGREGATE\",\n // \"TRANSACTION\" or \"REFUND\".\n operation_type: LimitOperationType;\n}\n\ninterface ExtensionManifest {\n // The criticality of the extension MUST be provided. It has the same\n // semantics as \"critical\" has for extensions in X.509:\n // - if \"true\", the client must \"understand\" the extension before\n // proceeding,\n // - if \"false\", clients can safely skip extensions they do not\n // understand.\n // (see https://datatracker.ietf.org/doc/html/rfc5280#section-4.2)\n critical: boolean;\n\n // The version information MUST be provided in Taler's protocol version\n // ranges notation, see\n // https://docs.taler.net/core/api-common.html#protocol-version-ranges\n version: LibtoolVersionString;\n\n // Optional configuration object, defined by the feature itself\n config?: object;\n}\n\nexport interface GlobalFees {\n // What date (inclusive) does these fees go into effect?\n start_date: Timestamp;\n\n // What date (exclusive) does this fees stop going into effect?\n end_date: Timestamp;\n\n // Account history fee, charged when a user wants to\n // obtain a reserve/account history.\n history_fee: AmountString;\n\n // Annual fee charged for having an open account at the\n // exchange. Charged to the account. If the account\n // balance is insufficient to cover this fee, the account\n // is automatically deleted/closed. (Note that the exchange\n // will keep the account history around for longer for\n // regulatory reasons.)\n account_fee: AmountString;\n\n // Purse fee, charged only if a purse is abandoned\n // and was not covered by the account limit.\n purse_fee: AmountString;\n\n // How long will the exchange preserve the account history?\n // After an account was deleted/closed, the exchange will\n // retain the account history for legal reasons until this time.\n history_expiration: RelativeTime;\n\n // Non-negative number of concurrent purses that any\n // account holder is allowed to create without having\n // to pay the purse_fee.\n purse_account_limit: Integer;\n\n // How long does an exchange keep a purse around after a purse\n // has expired (or been successfully merged)? A 'GET' request\n // for a purse will succeed until the purse expiration time\n // plus this value.\n purse_timeout: RelativeTime;\n\n // Signature of TALER_GlobalFeesPS.\n master_sig: EddsaSignatureString;\n}\n\nexport interface AggregateTransferFee {\n // Per transfer wire transfer fee.\n wire_fee: AmountString;\n\n // Per transfer closing fee.\n closing_fee: AmountString;\n\n // What date (inclusive) does this fee go into effect?\n // The different fees must cover the full time period in which\n // any of the denomination keys are valid without overlap.\n start_date: Timestamp;\n\n // What date (exclusive) does this fee stop going into effect?\n // The different fees must cover the full time period in which\n // any of the denomination keys are valid without overlap.\n end_date: Timestamp;\n\n // Signature of TALER_MasterWireFeePS with\n // purpose TALER_SIGNATURE_MASTER_WIRE_FEES.\n sig: EddsaSignatureString;\n}\n\n// Binary representation of the age groups.\n// The bits set in the mask mark the edges at the beginning of a next age\n// group. F.e. for the age groups\n// 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-21, 21-*\n// the following bits are set:\n//\n// 31 24 16 8 0\n// | | | | |\n// oooooooo oo1oo1o1 o1o1o1o1 ooooooo1\n//\n// A value of 0 means that the exchange does not support the extension for\n// age-restriction.\ntype AgeMask = Integer;\n\ntype DenominationKey = RsaDenominationKey | CSDenominationKey;\n\ninterface RsaDenominationKey {\n cipher: \"RSA\";\n\n // 32-bit age mask.\n age_mask: Integer;\n\n // RSA public key\n rsa_public_key: RsaPublicKey;\n}\n\ninterface CSDenominationKey {\n cipher: \"CS\";\n\n // 32-bit age mask.\n age_mask: Integer;\n\n // Public key of the denomination.\n cs_public_key: Cs25519Point;\n}\n\nexport const codecForAmlSpaDialect = codecForEither(\n codecForConstString(AmlSpaDialect.GLS),\n codecForConstString(AmlSpaDialect.TOPS),\n codecForConstString(AmlSpaDialect.TESTING),\n);\n\nexport const codecForExchangeConfig = (): Codec =>\n buildCodecForObject()\n .property(\"version\", codecForString())\n .property(\"name\", codecForConstString(\"taler-exchange\"))\n .property(\"implementation\", codecOptional(codecForURN()))\n .property(\"currency\", codecForString())\n .property(\"currency_specification\", codecForCurrencySpecificiation())\n .property(\n \"supported_kyc_requirements\",\n codecOptional(codecForList(codecForString())),\n )\n .property(\"aml_spa_dialect\", codecOptional(codecForAmlSpaDialect))\n .deprecatedProperty(\"shopping_url\")\n .deprecatedProperty(\"wallet_balance_limit_without_kyc\")\n .build(\"TalerExchangeApi.ExchangeVersionResponse\");\n\n// FIXME: complete the codec to check for valid exchange response\nexport const codecForExchangeKeysResponse = (): Codec =>\n buildCodecForObject()\n .property(\"version\", codecForString())\n .property(\"base_url\", codecForURLString())\n .property(\"currency\", codecForString())\n .property(\"accounts\", codecForAny())\n .property(\"asset_type\", codecForAny())\n .property(\"auditors\", codecForAny())\n .property(\"currency_specification\", codecForAny())\n .property(\"zero_limits\", codecForAny())\n .property(\"hard_limits\", codecForAny())\n .property(\"denominations\", codecForAny())\n .property(\"exchange_pub\", codecForAny())\n .property(\"exchange_sig\", codecForAny())\n .property(\"extensions\", codecForAny())\n .property(\"extensions_sig\", codecForAny())\n .property(\"global_fees\", codecForAny())\n .property(\"list_issue_date\", codecForAny())\n .property(\"master_public_key\", codecForAny())\n .property(\"recoup\", codecForAny())\n .property(\"reserve_closing_delay\", codecForAny())\n .property(\"signkeys\", codecForAny())\n .property(\"stefan_abs\", codecForAny())\n .property(\"stefan_lin\", codecForAny())\n .property(\"stefan_log\", codecForAny())\n .property(\"wads\", codecForAny())\n .property(\"wallet_balance_limit_without_kyc\", codecForAny())\n .property(\"wire_fees\", codecForAny())\n .property(\"kyc_enabled\", codecOptional(codecForBoolean()))\n .property(\"shopping_url\", codecOptional(codecForString()))\n .property(\"tiny_amount\", codecOptional(codecForAmountString()))\n .property(\"disable_direct_deposit\", codecOptional(codecForBoolean()))\n .property(\"bank_compliance_language\", codecOptional(codecForString()))\n .property(\"open_banking_gateway\", codecOptional(codecForURLString()))\n .deprecatedProperty(\"rewards_allowed\")\n .build(\"TalerExchangeApi.ExchangeKeysResponse\");\n\nexport const codecForAmlStatisticsResponse = (): Codec =>\n buildCodecForObject()\n .property(\"statistics\", codecForList(codecForEventCounter()))\n .build(\"TalerExchangeApi.AmlStatisticsResponse\");\n\nexport const codecForEventCounter = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"counter\", codecForNumber())\n .build(\"TalerExchangeApi.EventCounter\");\n\nexport const codecForLegitimizationMeasuresList =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"measures\",\n codecForList(codecForLegitimizationMeasureDetails()),\n )\n .build(\"TalerExchangeApi.LegitimizationMeasuresList\");\n\nexport const codecForLegitimizationMeasureDetails =\n (): Codec =>\n buildCodecForObject()\n .property(\"h_payto\", codecForAny())\n .property(\"rowid\", codecForAny())\n .property(\"start_time\", codecForAny())\n .property(\"measures\", codecForAny())\n .property(\"is_finished\", codecForAny())\n .build(\"TalerExchangeApi.LegitimizationMeasureDetails\");\n\nexport const codecForLegitimizationMeasures =\n (): Codec =>\n buildCodecForObject()\n .property(\"is_and_combinator\", codecForAny())\n .property(\"verboten\", codecForAny())\n .property(\"measures\", codecForList(codecForMeasureInformation()))\n .build(\"TalerExchangeApi.LegitimizationMeasures\");\n\nexport const codecForAvailableMeasureSummary =\n (): Codec =>\n buildCodecForObject()\n .property(\"checks\", codecForMap(codecForKycCheckInformation()))\n .property(\"programs\", codecForMap(codecForAmlProgramRequirement()))\n .property(\"roots\", codecForMap(codecForMeasureInformation()))\n .property(\"default_rules\", codecForList(codecForKycRules()))\n .build(\"TalerExchangeApi.AvailableMeasureSummary\");\n\nexport const codecForAmlProgramRequirement = (): Codec =>\n buildCodecForObject()\n .property(\"description\", codecForString())\n .property(\"context\", codecForList(codecForString()))\n .property(\"inputs\", codecForList(codecForString()))\n .build(\"TalerExchangeApi.AmlProgramRequirement\");\n\nexport const codecForKycCheckInformation = (): Codec =>\n buildCodecForObject()\n .property(\"description\", codecForString())\n .property(\n \"description_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"fallback\", codecForString())\n .property(\"outputs\", codecForList(codecForString()))\n .property(\"requires\", codecForList(codecForString()))\n .build(\"TalerExchangeApi.KycCheckInformation\");\n\nexport const codecForMeasureInformation = (): Codec =>\n buildCodecForObject()\n .property(\"prog_name\", codecOptional(codecForString()))\n .property(\"check_name\", codecForString())\n .property(\"context\", codecForAny())\n .property(\"operation_type\", codecOptional(codecForOperationType))\n .property(\"voluntary\", codecOptional(codecForBoolean()))\n .build(\"TalerExchangeApi.MeasureInformation\");\n\nexport const codecForAmlDecisionsResponse = (): Codec =>\n buildCodecForObject()\n .property(\"records\", codecForList(codecForAmlDecision()))\n .build(\"TalerExchangeApi.AmlDecisionsResponse\");\n\nexport interface CustomerAccountSummary {\n // Which payto-address is this record about.\n // Identifies a GNU Taler wallet or an affected bank account.\n h_payto: PaytoHash;\n\n // Full payto URL of the account that the decision is\n // about.\n full_payto: Paytos.FullPaytoString;\n\n // True if the account was assessed as being high risk.\n high_risk: boolean;\n\n // Latest comments about the account (if any).\n comments?: string;\n\n // Row of the account in the exchange tables. Useful to filter\n // by offset.\n rowid: Integer;\n\n // When was the account opened? \"never\" if it was never opened.\n open_time: Timestamp;\n\n // When was the account opened? \"never\" if it was never closed.\n close_time: Timestamp;\n\n // True if the account is under investigation by AML staff\n // after this decision.\n to_investigate: boolean;\n}\nexport interface AmlAccountsResponse {\n // Array of customer accounts matching the query.\n accounts: CustomerAccountSummary[];\n}\nexport const codecForAmlCustomerAccountSummary =\n (): Codec =>\n buildCodecForObject()\n .property(\"h_payto\", codecForPaytoHash())\n .property(\"close_time\", codecForTimestamp)\n .property(\"open_time\", codecForTimestamp)\n .property(\"comments\", codecOptional(codecForString()))\n .property(\"full_payto\", codecFullForPaytoString())\n .property(\"high_risk\", codecForBoolean())\n .property(\"rowid\", codecForNumber())\n .property(\"to_investigate\", codecForBoolean())\n .build(\"TalerExchangeApi.CustomerAccountSummary\");\n\nexport const codecForAmlDecisionsAccounts = (): Codec =>\n buildCodecForObject()\n .property(\"accounts\", codecForList(codecForAmlCustomerAccountSummary()))\n .build(\"TalerExchangeApi.AmlAccountsResponse\");\n\n// export const codecForAmlDecisionDetails = (): Codec =>\n// buildCodecForObject()\n// .property(\"aml_history\", codecForList(codecForAmlDecisionDetail()))\n// .property(\"kyc_attributes\", codecForList(codecForKycDetail()))\n// .build(\"TalerExchangeApi.AmlDecisionDetails\");\n\n// export const codecForAmlDecisionDetail = (): Codec =>\n// buildCodecForObject()\n// .property(\"justification\", codecForString())\n// .property(\"new_state\", codecForNumber())\n// .property(\"decision_time\", codecForTimestamp)\n// .property(\"new_threshold\", codecForAmountString())\n// .property(\"decider_pub\", codecForString())\n// .build(\"TalerExchangeApi.AmlDecisionDetail\");\n\nexport const codecForKycDetail = (): Codec =>\n buildCodecForObject()\n .property(\"provider_section\", codecForString())\n .property(\"attributes\", codecOptional(codecForAny()))\n .property(\"collection_time\", codecForTimestamp)\n .property(\"expiration_time\", codecForTimestamp)\n .build(\"TalerExchangeApi.KycDetail\");\n\nexport const codecForAmlDecision = (): Codec =>\n buildCodecForObject()\n .property(\"h_payto\", codecForString())\n .property(\"full_payto\", codecOptional(codecForString()))\n .property(\"rowid\", codecForNumber())\n .property(\"is_wallet\", codecForBoolean())\n .property(\"justification\", codecOptional(codecForString()))\n .property(\"decision_time\", codecForTimestamp)\n .property(\"properties\", codecOptional(codecForAccountProperties()))\n .property(\"limits\", codecForLegitimizationRuleSet())\n .property(\"to_investigate\", codecForBoolean())\n .property(\"is_active\", codecForBoolean())\n .build(\"TalerExchangeApi.AmlDecision\");\n\nexport const codecForAccountProperties = (): Codec =>\n buildCodecForObject()\n .property(\"pep\", codecOptional(codecForBoolean()))\n .property(\"sanctioned\", codecOptional(codecForBoolean()))\n .property(\"high_risk\", codecOptional(codecForBoolean()))\n .property(\"business_domain\", codecOptional(codecForString()))\n .property(\"is_frozen\", codecOptional(codecForBoolean()))\n .property(\"was_reported\", codecOptional(codecForBoolean()))\n .allowExtra()\n .build(\"TalerExchangeApi.AccountProperties\");\n\nexport const codecForLegitimizationRuleSet = (): Codec =>\n buildCodecForObject()\n .property(\"expiration_time\", codecForTimestamp)\n .property(\"successor_measure\", codecOptional(codecForString()))\n .property(\"rules\", codecForList(codecForKycRules()))\n .property(\"custom_measures\", codecForMap(codecForMeasureInformation()))\n .build(\"TalerExchangeApi.LegitimizationRuleSet\");\n\nexport const codecForKycRules = (): Codec =>\n buildCodecForObject()\n .property(\"operation_type\", codecForOperationType)\n .property(\"threshold\", codecForAmountString())\n .property(\"timeframe\", codecForDuration)\n .property(\"measures\", codecForList(codecForString()))\n .property(\"display_priority\", codecForNumber())\n .property(\"exposed\", codecOptional(codecForBoolean()))\n .property(\"is_and_combinator\", codecOptional(codecForBoolean()))\n .property(\"rule_name\", codecOptional(codecForString()))\n .build(\"TalerExchangeApi.KycRule\");\n\nexport const codecForAmlKycAttributes = (): Codec =>\n buildCodecForObject()\n .property(\"details\", codecForList(codecForKycAttributeCollectionEvent()))\n .build(\"TalerExchangeApi.KycAttributes\");\n\nexport const codecForKycAttributeCollectionEvent =\n (): Codec =>\n buildCodecForObject()\n .property(\"rowid\", codecForNumber())\n .property(\"provider_name\", codecOptional(codecForString()))\n .property(\"collection_time\", codecForTimestamp)\n .property(\"attributes\", codecOptional(codecForAny()))\n .build(\"TalerExchangeApi.KycAttributeCollectionEvent\");\n\nexport const codecForAmlWalletKycCheckResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"next_threshold\", codecOptional(codecForAmountString()))\n .property(\"expiration_time\", codecForTimestamp)\n .build(\"TalerExchangeApi.WalletKycCheckResponse\");\n\nexport const codecForLegitimizationNeededResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"hint\", codecOptional(codecForString()))\n .property(\"h_payto\", codecForString())\n .property(\"account_pub\", codecOptional(codecForEddsaPublicKey()))\n .property(\"requirement_row\", codecForNumber())\n .property(\"bad_kyc_auth\", codecOptional(codecForBoolean()))\n .build(\"TalerExchangeApi.LegitimizationNeededResponse\");\n\nexport const codecForAccountKycStatus = (): Codec =>\n buildCodecForObject()\n .property(\"aml_review\", codecForBoolean())\n .property(\"access_token\", codecForAccessToken())\n .property(\"limits\", codecOptional(codecForList(codecForAccountLimit())))\n .property(\"rule_gen\", codecForNumber())\n .build(\"TalerExchangeApi.AccountKycStatus\");\n\nexport const codecForOperationType = codecForEither(\n codecForConstString(LimitOperationType.withdraw),\n codecForConstString(LimitOperationType.deposit),\n codecForConstString(LimitOperationType.merge),\n codecForConstString(LimitOperationType.balance),\n codecForConstString(LimitOperationType.close),\n codecForConstString(LimitOperationType.aggregate),\n codecForConstString(LimitOperationType.transaction),\n codecForConstString(LimitOperationType.refund),\n);\n\nexport const codecForAccountLimit = (): Codec =>\n buildCodecForObject()\n .property(\"operation_type\", codecForOperationType)\n .property(\"timeframe\", codecForDuration)\n .property(\"threshold\", codecForAmountString())\n .property(\"soft_limit\", codecOptional(codecForBoolean()))\n .property(\"rule_name\", codecOptional(codecForString()))\n .build(\"TalerExchangeApi.AccountLimit\");\n\nexport const codecForZeroLimitedOperation = (): Codec =>\n buildCodecForObject()\n .property(\"operation_type\", codecForOperationType)\n .build(\"TalerExchangeApi.ZeroLimitedOperation\");\n\nexport const codecForKycCheckPublicInformation =\n (): Codec =>\n buildCodecForObject()\n .property(\"description\", codecForString())\n .property(\n \"description_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .build(\"TalerExchangeApi.KycCheckPublicInformation\");\n\nexport const codecForKycRequirementInformationId =\n (): Codec =>\n codecForString() as Codec;\nexport const codecForKycFormId = (): Codec =>\n codecForString() as Codec;\n\nexport const codecForKycRequirementInformation =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"form\",\n codecForEither(\n codecForConstString(\"LINK\"),\n codecForConstString(\"INFO\"),\n codecForKycFormId(),\n ),\n )\n .property(\"description\", codecForString())\n .property(\"context\", codecOptional(codecForAny()))\n .property(\n \"description_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"id\", codecOptional(codecForKycRequirementInformationId()))\n .build(\"TalerExchangeApi.KycRequirementInformation\");\n\nexport const codecForKycProcessClientInformation =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"requirements\",\n codecOptionalDefault(\n codecForList(codecForKycRequirementInformation()),\n [],\n ),\n )\n .property(\"is_and_combinator\", codecOptional(codecForBoolean()))\n .property(\n \"voluntary_measures\",\n codecOptional(codecForList(codecForKycRequirementInformation())),\n )\n .build(\"TalerExchangeApi.KycProcessClientInformation\");\n\nexport const codecForExchangeTransferList = (): Codec =>\n buildCodecForObject()\n .property(\"transfers\", codecForList(codecForExchangeTransferListEntry()))\n .build(\"TalerExchangeApi.ExchangeTransferList\");\n\nexport const codecForExchangeTransferListEntry =\n (): Codec =>\n buildCodecForObject()\n .property(\"rowid\", codecForNumber())\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"amount\", codecForAmountString())\n .property(\"execution_time\", codecForTimestamp)\n .build(\"TalerExchangeApi.ExchangeTransferListEntry\");\n\nexport interface ExchangeTransferList {\n // Matching transaction of the exchange\n transfers: ExchangeTransferListEntry[];\n}\n\nexport interface ExchangeTransferListEntry {\n // Row ID of the record. Used to filter by offset.\n rowid: Integer;\n\n // payto://-URI of the other account.\n payto_uri: string;\n\n // The amount involved.\n amount: Amount;\n\n // Time when the transfer was made\n execution_time: Timestamp;\n}\n\nexport interface KycProcessStartInformation {\n // URL to open.\n redirect_url: string;\n}\n\nexport const codecForKycProcessStartInformation =\n (): Codec =>\n buildCodecForObject()\n .property(\"redirect_url\", codecForURLString())\n .build(\"TalerExchangeApi.KycProcessStartInformation\");\n\nexport interface BatchWithdrawResponse {\n // Array of blinded signatures, in the same order as was\n // given in the request.\n ev_sigs: WithdrawResponse[];\n}\nexport interface WithdrawResponse {\n // The blinded signature over the 'coin_ev', affirms the coin's\n // validity after unblinding.\n ev_sig: BlindedDenominationSignature;\n}\nexport type BlindedDenominationSignature =\n | RsaBlindedDenominationSignature\n | CSBlindedDenominationSignature;\n\nexport interface RsaBlindedDenominationSignature {\n cipher: DenomKeyType.Rsa;\n\n // (blinded) RSA signature\n blinded_rsa_signature: BlindedRsaSignature;\n}\n\nexport interface CSBlindedDenominationSignature {\n cipher: DenomKeyType.ClauseSchnorr;\n\n // Signer chosen bit value, 0 or 1, used\n // in Clause Blind Schnorr to make the\n // ROS problem harder.\n b: Integer;\n\n // Blinded scalar calculated from c_b.\n s: Cs25519Scalar;\n}\n\ntype BlindedRsaSignature = string;\ntype Cs25519Scalar = string;\ntype HashCode = string;\ntype EddsaSignature = string;\ntype EddsaPublicKey = string;\ntype Amount = AmountString;\ntype Base32 = string;\n\nexport interface WithdrawError {\n // Text describing the error.\n hint: string;\n\n // Detailed error code.\n code: Integer;\n\n // Amount left in the reserve.\n balance: AmountString;\n\n // History of the reserve's activity, in the same format\n // as returned by /reserve/$RID/history.\n history: TransactionHistoryItem[];\n}\nexport type TransactionHistoryItem =\n | AccountSetupTransaction\n | ReserveWithdrawTransaction\n | ReserveAgeWithdrawTransaction\n | ReserveCreditTransaction\n | ReserveClosingTransaction\n | ReserveOpenRequestTransaction\n | ReserveCloseRequestTransaction\n | PurseMergeTransaction;\n\nenum TransactionHistoryType {\n setup = \"SETUP\",\n withdraw = \"WITHDRAW\",\n ageWithdraw = \"AGEWITHDRAW\",\n credit = \"CREDIT\",\n closing = \"CLOSING\",\n open = \"OPEN\",\n close = \"CLOSE\",\n merge = \"MERGE\",\n}\ninterface AccountSetupTransaction {\n type: TransactionHistoryType.setup;\n\n // Offset of this entry in the reserve history.\n // Useful to request incremental histories via\n // the \"start\" query parameter.\n history_offset: Integer;\n\n // KYC fee agreed to by the reserve owner.\n kyc_fee: AmountString;\n\n // Time when the KYC was triggered.\n kyc_timestamp: Timestamp;\n\n // Hash of the wire details of the account.\n // Note that this hash is unsalted and potentially\n // private (as it could be inverted), hence access\n // to this endpoint must be authorized using the\n // private key of the reserve.\n h_wire: HashCode;\n\n // Signature created with the reserve's private key.\n // Must be of purpose TALER_SIGNATURE_ACCOUNT_SETUP_REQUEST over\n // a TALER_AccountSetupRequestSignaturePS.\n reserve_sig: EddsaSignature;\n}\ninterface ReserveWithdrawTransaction {\n type: \"WITHDRAW\";\n\n // Offset of this entry in the reserve history.\n // Useful to request incremental histories via\n // the \"start\" query parameter.\n history_offset: Integer;\n\n // Amount withdrawn.\n amount: Amount;\n\n // Hash of the denomination public key of the coin.\n h_denom_pub: HashCode;\n\n // Hash of the blinded coin to be signed.\n h_coin_envelope: HashCode;\n\n // Signature over a TALER_WithdrawRequestPS\n // with purpose TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW\n // created with the reserve's private key.\n reserve_sig: EddsaSignature;\n\n // Fee that is charged for withdraw.\n withdraw_fee: Amount;\n}\ninterface ReserveAgeWithdrawTransaction {\n type: \"AGEWITHDRAW\";\n\n // Offset of this entry in the reserve history.\n // Useful to request incremental histories via\n // the \"start\" query parameter.\n history_offset: Integer;\n\n // Total Amount withdrawn.\n amount: Amount;\n\n // Commitment of all n*kappa blinded coins.\n h_commitment: HashCode;\n\n // Signature over a TALER_AgeWithdrawRequestPS\n // with purpose TALER_SIGNATURE_WALLET_RESERVE_AGE_WITHDRAW\n // created with the reserve's private key.\n reserve_sig: EddsaSignature;\n\n // Fee that is charged for withdraw.\n withdraw_fee: Amount;\n}\ninterface ReserveCreditTransaction {\n type: \"CREDIT\";\n\n // Offset of this entry in the reserve history.\n // Useful to request incremental histories via\n // the \"start\" query parameter.\n history_offset: Integer;\n\n // Amount deposited.\n amount: Amount;\n\n // Sender account payto:// URL.\n sender_account_url: string;\n\n // Opaque identifier internal to the exchange that\n // uniquely identifies the wire transfer that credited the reserve.\n wire_reference: Integer;\n\n // Timestamp of the incoming wire transfer.\n timestamp: Timestamp;\n}\ninterface ReserveClosingTransaction {\n type: \"CLOSING\";\n\n // Offset of this entry in the reserve history.\n // Useful to request incremental histories via\n // the \"start\" query parameter.\n history_offset: Integer;\n\n // Closing balance.\n amount: Amount;\n\n // Closing fee charged by the exchange.\n closing_fee: Amount;\n\n // Wire transfer subject.\n wtid: Base32;\n\n // payto:// URI of the wire account into which the funds were returned to.\n receiver_account_details: string;\n\n // This is a signature over a\n // struct TALER_ReserveCloseConfirmationPS with purpose\n // TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED.\n exchange_sig: EddsaSignature;\n\n // Public key used to create 'exchange_sig'.\n exchange_pub: EddsaPublicKey;\n\n // Time when the reserve was closed.\n timestamp: Timestamp;\n}\ninterface ReserveOpenRequestTransaction {\n type: \"OPEN\";\n\n // Offset of this entry in the reserve history.\n // Useful to request incremental histories via\n // the \"start\" query parameter.\n history_offset: Integer;\n\n // Open fee paid from the reserve.\n open_fee: Amount;\n\n // This is a signature over\n // a struct TALER_ReserveOpenPS with purpose\n // TALER_SIGNATURE_WALLET_RESERVE_OPEN.\n reserve_sig: EddsaSignature;\n\n // Timestamp of the open request.\n request_timestamp: Timestamp;\n\n // Requested expiration.\n requested_expiration: Timestamp;\n\n // Requested number of free open purses.\n requested_min_purses: Integer;\n}\ninterface ReserveCloseRequestTransaction {\n type: \"CLOSE\";\n\n // Offset of this entry in the reserve history.\n // Useful to request incremental histories via\n // the \"start\" query parameter.\n history_offset: Integer;\n\n // This is a signature over\n // a struct TALER_ReserveClosePS with purpose\n // TALER_SIGNATURE_WALLET_RESERVE_CLOSE.\n reserve_sig: EddsaSignature;\n\n // Target account payto://, optional.\n h_payto?: PaytoHash;\n\n // Timestamp of the close request.\n request_timestamp: Timestamp;\n}\ninterface PurseMergeTransaction {\n type: \"MERGE\";\n\n // Offset of this entry in the reserve history.\n // Useful to request incremental histories via\n // the \"start\" query parameter.\n history_offset: Integer;\n\n // SHA-512 hash of the contact of the purse.\n h_contract_terms: HashCode;\n\n // EdDSA public key used to approve merges of this purse.\n merge_pub: EddsaPublicKey;\n\n // Minimum age required for all coins deposited into the purse.\n min_age: Integer;\n\n // Number that identifies who created the purse\n // and how it was paid for.\n flags: Integer;\n\n // Purse public key.\n purse_pub: EddsaPublicKey;\n\n // EdDSA signature of the account/reserve affirming the merge\n // over a TALER_AccountMergeSignaturePS.\n // Must be of purpose TALER_SIGNATURE_ACCOUNT_MERGE\n reserve_sig: EddsaSignature;\n\n // Client-side timestamp of when the merge request was made.\n merge_timestamp: Timestamp;\n\n // Indicative time by which the purse should expire\n // if it has not been merged into an account. At this\n // point, all of the deposits made should be\n // auto-refunded.\n purse_expiration: Timestamp;\n\n // Purse fee the reserve owner paid for the purse creation.\n purse_fee: Amount;\n\n // Total amount merged into the reserve.\n // (excludes fees).\n amount: Amount;\n\n // True if the purse was actually merged.\n // If false, only the purse_fee has an impact\n // on the reserve balance!\n merged: boolean;\n}\n\n/**\n * Docs name: WithdrawRequest\n */\nexport interface ExchangeWithdrawRequest {\n // Cipher that is used for the rerserve's signatures.\n // For now, only ed25519 signatures are applicable,\n // but this might change in future versions.\n cipher: \"ED25519\";\n\n // The reserve's public key, for the the cipher ED25519,\n // to verify the signature reserve_sig.\n reserve_pub: EddsaPublicKey;\n\n // Array of n hash codes of denomination public keys to order.\n // The sum of all denomination's values and fees MUST be\n // at most the balance of the reserve. The balance of\n // the reserve will be immediately reduced by that amount.\n // If max_age is set, these denominations MUST support\n // age restriction as defined in the output to /keys.\n denoms_h: HashCode[];\n\n // If set, the maximum age to commit to. This implies:\n // 1.) it MUST be the same value as the maximum age\n // of the reserve.\n // 2.) coin_evs MUST be an array of n*kappa\n // 3.) the denominations in denoms_h MUST support\n // age restriction.\n max_age?: number;\n\n // Array of blinded coin envelopes of type CoinEnvelope.\n // If max_age is not set, MUST be n entries.\n // If max_age is set, MUST be n*kappa entries,\n // arranged in [0..n)..[0..n), with the first n entries\n // belonging to kappa=0 etc.\n // In case of age restriction, the exchange will\n // respond with an index gamma, which is the index\n // that shall remain undisclosed during the subsequent\n // reveal phase.\n // This hash value along with the reserve's public key\n // will also be used for recoup operations, if needed.\n coin_evs: CoinEnvelope[];\n\n // Signature of TALER_WithdrawRequestPS created with\n // the reserves's private key.\n reserve_sig: EddsaSignature;\n}\n\nexport type PurseConflict =\n | DepositDoubleSpendError\n | PurseCreateConflict\n | PurseDepositConflict\n | PurseContractConflict;\n\nexport type PurseConflictPartial =\n | PurseCreateConflict\n | PurseDepositConflict\n | PurseContractConflict;\n\ninterface DepositDoubleSpendError {\n code: TalerErrorCode.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS;\n\n // A string explaining that the user tried to\n // double-spend.\n hint: string;\n\n // EdDSA public key of a coin being double-spent.\n coin_pub: EddsaPublicKey;\n}\ninterface PurseCreateConflict {\n code: TalerErrorCode.EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA;\n\n // Total amount to be merged into the reserve.\n // (excludes fees).\n amount: Amount;\n\n // Minimum age required for all coins deposited into the purse.\n min_age: Integer;\n\n // Indicative time by which the purse should expire\n // if it has not been merged into an account. At this\n // point, all of the deposits made should be\n // auto-refunded.\n purse_expiration: Timestamp;\n\n // EdDSA signature of the purse over\n // TALER_PurseMergeSignaturePS of\n // purpose TALER_SIGNATURE_WALLET_PURSE_MERGE\n // confirming that the\n // above details hold for this purse.\n purse_sig: EddsaSignature;\n\n // SHA-512 hash of the contact of the purse.\n h_contract_terms: HashCode;\n\n // EdDSA public key used to approve merges of this purse.\n merge_pub: EddsaPublicKey;\n}\ninterface PurseDepositConflict {\n code: TalerErrorCode.EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA;\n\n // Public key of the coin being deposited into the purse.\n coin_pub: EddsaPublicKey;\n\n // Signature over TALER_PurseDepositSignaturePS\n // of purpose TALER_SIGNATURE_WALLET_PURSE_DEPOSIT\n // made by the customer with the\n // coin's private key.\n coin_sig: EddsaSignature;\n\n // Target exchange URL for the purse. Not present for the\n // same exchange.\n partner_url?: string;\n\n // Amount to be contributed to the purse by this coin.\n amount: AmountString;\n}\ninterface PurseContractConflict {\n code: TalerErrorCode.EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA;\n\n // Hash of the encrypted contract.\n h_econtract: HashCode;\n\n // Signature over the contract.\n econtract_sig: EddsaSignature;\n\n // Ephemeral public key for the DH operation to decrypt the contract.\n contract_pub: EddsaPublicKey;\n}\n\nexport interface PurseCreate {\n // Total value of the purse, excluding fees.\n amount: Amount;\n\n // Minimum age required for all coins deposited into the purse.\n min_age: Integer;\n\n // Optional encrypted contract, in case the buyer is\n // proposing the contract and thus establishing the\n // purse with the payment.\n econtract?: EncryptedContract;\n\n // EdDSA public key used to approve merges of this purse.\n merge_pub: EddsaPublicKey;\n\n // EdDSA signature of the purse over a\n // TALER_PurseRequestSignaturePS\n // of purpose TALER_SIGNATURE_WALLET_PURSE_CREATE\n // confirming the key\n // invariants associated with the purse.\n // (amount, h_contract_terms, expiration).\n purse_sig: EddsaSignature;\n\n // SHA-512 hash of the contact of the purse.\n h_contract_terms: HashCode;\n\n // Array of coins being deposited into the purse.\n // Maximum length is 128.\n deposits: PurseDeposit[];\n\n // Indicative time by which the purse should expire\n // if it has not been merged into an account. At this\n // point, all of the deposits made will be auto-refunded.\n purse_expiration: Timestamp;\n}\n\nexport const codecForPurseConflict = () =>\n buildCodecForUnion()\n .discriminateOn(\"code\")\n .alternative(\n TalerErrorCode.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,\n codecForDepositDoubleSpendError(),\n )\n .alternative(\n TalerErrorCode.EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA,\n codecForPurseCreateConflict(),\n )\n .alternative(\n TalerErrorCode.EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA,\n codecForPurseDepositConflict(),\n )\n .alternative(\n TalerErrorCode.EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA,\n codecForPurseContractConflict(),\n )\n .build(\"PurseConflict\");\nexport const codecForPurseConflictPartial = () =>\n buildCodecForUnion()\n .discriminateOn(\"code\")\n .alternative(\n TalerErrorCode.EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA,\n codecForPurseCreateConflict(),\n )\n .alternative(\n TalerErrorCode.EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA,\n codecForPurseDepositConflict(),\n )\n .alternative(\n TalerErrorCode.EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA,\n codecForPurseContractConflict(),\n )\n .build(\"PurseConflictPartial\");\nexport const codecForDepositDoubleSpendError = () =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"hint\", codecForString())\n .property(\"coin_pub\", codecForString())\n .build(\"DepositDoubleSpendError\");\nexport const codecForPurseCreateConflict = () =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"amount\", codecForAmountString())\n .property(\"min_age\", codecForNumber())\n .property(\"purse_expiration\", codecForTimestamp)\n .property(\"purse_sig\", codecForString())\n .property(\"h_contract_terms\", codecForString())\n .property(\"merge_pub\", codecForString())\n .build(\"PurseCreateConflict\");\nexport const codecForPurseDepositConflict = () =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"coin_pub\", codecForString())\n .property(\"partner_url\", codecOptional(codecForString()))\n .property(\"amount\", codecForAmountString())\n .build(\"PurseDepositConflict\");\nexport const codecForPurseContractConflict = () =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"h_econtract\", codecForString())\n .property(\"econtract_sig\", codecForString())\n .property(\"contract_pub\", codecForString())\n .build(\"PurseContractConflict\");\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Imports.\n */\nimport { base64FromArrayBuffer } from \"../base64.js\";\nimport { stringToBytes } from \"../taler-crypto.js\";\nimport {\n AccessToken,\n LongPollParams,\n PaginationParams,\n} from \"../types-taler-common.js\";\n\n/**\n * rfc8959\n * @param token\n * @returns\n */\nexport function makeBearerTokenAuthHeader(token: AccessToken): string {\n return `Bearer ${token}`;\n}\n\nexport type BasicOrTokenAuth = BasicAuth | TokenAuth;\n\nexport type BasicAuth = {\n type: \"basic\";\n username: string;\n password: string;\n};\n\nexport type TokenAuth = {\n type: \"bearer\";\n token: AccessToken;\n};\n\nexport function authHeaders(auth?: BasicOrTokenAuth): Record {\n if (!auth) return {};\n switch (auth.type) {\n case \"basic\": {\n const credentials = `${auth.username}:${auth.password}`;\n const authEncoded: string = base64FromArrayBuffer(\n stringToBytes(credentials),\n );\n return {\n Authorization: `Basic ${authEncoded}`,\n };\n }\n case \"bearer\": {\n return {\n Authorization: makeBearerTokenAuthHeader(auth.token),\n };\n }\n }\n}\n\nexport function addPaginationParams(url: URL, pagination?: PaginationParams) {\n if (!pagination) return;\n if (pagination.offset) {\n url.searchParams.set(\"offset\", pagination.offset);\n }\n const order = !pagination || pagination.order === \"asc\" ? 1 : -1;\n const limit =\n !pagination || !pagination.limit || pagination.limit === 0\n ? 5\n : Math.abs(pagination.limit);\n //always send limit\n url.searchParams.set(\"limit\", String(order * limit));\n}\n\nexport function addLongPollingParam(url: URL, param?: LongPollParams) {\n if (!param) return;\n if (param.timeoutMs) {\n url.searchParams.set(\"timeout_ms\", String(param.timeoutMs));\n }\n}\n\nexport interface CacheEvictor {\n notifySuccess: (op: T) => Promise;\n}\n\nexport const nullEvictor: CacheEvictor = {\n notifySuccess: () => Promise.resolve(),\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Client for the Taler (demo-)bank.\n */\n\n/**\n * Imports.\n */\nimport {\n AmountString,\n base64FromArrayBuffer,\n buildCodecForObject,\n Codec,\n codecForAny,\n codecForString,\n encodeCrock,\n getRandomBytes,\n HttpStatusCode,\n j2s,\n Logger,\n opEmptySuccess,\n opKnownHttpFailure,\n opUnknownHttpFailure,\n PaytoString,\n stringToBytes,\n TalerCorebankApi,\n TalerError,\n TalerErrorCode,\n} from \"@gnu-taler/taler-util\";\nimport {\n createPlatformHttpLib,\n expectSuccessResponseOrThrow,\n HttpRequestLibrary,\n readSuccessResponseJsonOrThrow,\n} from \"@gnu-taler/taler-util/http\";\nimport { authHeaders } from \"./http-client/utils.js\";\n\nconst logger = new Logger(\"bank-api-client.ts\");\n\nexport enum CreditDebitIndicator {\n Credit = \"credit\",\n Debit = \"debit\",\n}\n\nexport interface BankAccountBalanceResponse {\n balance: {\n amount: AmountString;\n credit_debit_indicator: CreditDebitIndicator;\n };\n}\n\nexport interface BankUser {\n username: string;\n password: string;\n accountPaytoUri: PaytoString;\n}\n\nexport interface WithdrawalOperationInfo {\n withdrawal_id: string;\n taler_withdraw_uri: string;\n}\n\nconst codecForWithdrawalOperationInfo = (): Codec =>\n buildCodecForObject()\n .property(\"withdrawal_id\", codecForString())\n .property(\"taler_withdraw_uri\", codecForString())\n .build(\"WithdrawalOperationInfo\");\n\nexport interface BankAccessApiClientArgs {\n auth?: { username: string; password: string };\n httpClient?: HttpRequestLibrary;\n}\n\nexport interface AccountBalance {\n amount: AmountString;\n credit_debit_indicator: \"credit\" | \"debit\";\n}\n\nexport interface ConfirmWithdrawalArgs {\n withdrawalOperationId: string;\n}\n\n/**\n * Client for the Taler corebank API.\n *\n * @deprecated use TalerCoreBankHttpClient instead\n */\nexport class TalerCorebankApiClient {\n httpLib: HttpRequestLibrary;\n\n constructor(\n public baseUrl: string,\n private args: BankAccessApiClientArgs = {},\n ) {\n this.httpLib = args.httpClient ?? createPlatformHttpLib();\n }\n\n setAuth(auth: { username: string; password: string }) {\n this.args.auth = auth;\n }\n\n private makeAuthHeader(): Record {\n if (!this.args.auth) {\n return {};\n }\n return authHeaders({\n type: \"basic\",\n username: this.args.auth.username,\n password: this.args.auth.password,\n });\n }\n\n async getAccountBalance(\n username: string,\n ): Promise {\n const url = new URL(`accounts/${username}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n headers: this.makeAuthHeader(),\n });\n return readSuccessResponseJsonOrThrow(resp, codecForAny());\n }\n\n async makeTransaction(\n amount: AmountString,\n target: PaytoString,\n ): Promise {\n const reqUrl = new URL(\n `accounts/${this.args.auth!.username}/transactions`,\n this.baseUrl,\n );\n const resp = await this.httpLib.fetch(reqUrl.href, {\n method: \"POST\",\n body: {\n amount,\n payto_uri: target,\n },\n headers: {\n ...this.makeAuthHeader(),\n \"Content-Type\": \"application/json\",\n },\n });\n\n const res = await readSuccessResponseJsonOrThrow(resp, codecForAny());\n logger.info(`result: ${j2s(res)}`);\n }\n\n async getTransactions(username: string): Promise {\n const reqUrl = new URL(`accounts/${username}/transactions`, this.baseUrl);\n const resp = await this.httpLib.fetch(reqUrl.href, {\n method: \"GET\",\n headers: {\n ...this.makeAuthHeader(),\n },\n });\n\n const res = await readSuccessResponseJsonOrThrow(resp, codecForAny());\n logger.info(`result: ${j2s(res)}`);\n }\n\n async registerAccountExtended(\n req: TalerCorebankApi.RegisterAccountRequest,\n ): Promise {\n const url = new URL(\"accounts\", this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body: req,\n headers: this.makeAuthHeader(),\n });\n\n if (\n resp.status !== 200 &&\n resp.status !== 201 &&\n resp.status !== 202 &&\n resp.status !== 204\n ) {\n logger.error(`unexpected status ${resp.status} from POST ${url.href}`);\n logger.error(`${j2s(await resp.json())}`);\n throw TalerError.fromDetail(\n TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,\n {\n httpStatusCode: resp.status,\n },\n );\n }\n }\n\n /**\n * Register a new account and return information about it.\n *\n * This is a helper, as it does both the registration and the\n * account info query.\n */\n async registerAccount(username: string, password: string): Promise {\n const url = new URL(\"accounts\", this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body: {\n username,\n password,\n name: username,\n },\n headers: this.makeAuthHeader(),\n });\n if (\n resp.status !== 200 &&\n resp.status !== 201 &&\n resp.status !== 202 &&\n resp.status !== 204\n ) {\n logger.error(`unexpected status ${resp.status} from POST ${url.href}`);\n logger.error(`${j2s(await resp.json())}`);\n throw TalerError.fromDetail(\n TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,\n {\n httpStatusCode: resp.status,\n },\n );\n }\n // FIXME: Corebank should directly return this info!\n const infoUrl = new URL(`accounts/${username}`, this.baseUrl);\n const infoResp = await this.httpLib.fetch(infoUrl.href, {\n headers: authHeaders({\n type: \"basic\",\n username,\n password,\n }),\n });\n // FIXME: Validate!\n const acctInfo: TalerCorebankApi.AccountData =\n await readSuccessResponseJsonOrThrow(infoResp, codecForAny());\n return {\n password,\n username,\n accountPaytoUri: acctInfo.payto_uri,\n };\n }\n\n async createRandomBankUser(): Promise {\n const username = \"user-\" + encodeCrock(getRandomBytes(10)).toLowerCase();\n const password = \"pw-\" + encodeCrock(getRandomBytes(10)).toLowerCase();\n return await this.registerAccount(username, password);\n }\n\n async createWithdrawalOperation(\n user: string,\n amount: string | undefined,\n ): Promise {\n const url = new URL(`accounts/${user}/withdrawals`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body: {\n amount,\n },\n headers: this.makeAuthHeader(),\n });\n return readSuccessResponseJsonOrThrow(\n resp,\n codecForWithdrawalOperationInfo(),\n );\n }\n\n async confirmWithdrawalOperation(\n username: string,\n wopi: ConfirmWithdrawalArgs,\n ) {\n const url = new URL(\n `accounts/${username}/withdrawals/${wopi.withdrawalOperationId}/confirm`,\n this.baseUrl,\n );\n logger.info(`confirming withdrawal operation via ${url.href}`);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body: {},\n headers: this.makeAuthHeader(),\n });\n logger.info(`confirm response status ${resp.status}`);\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n async abortWithdrawalOperation(wopi: WithdrawalOperationInfo): Promise {\n const url = new URL(\n `withdrawals/${wopi.withdrawal_id}/abort`,\n this.baseUrl,\n );\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body: {},\n headers: this.makeAuthHeader(),\n });\n await readSuccessResponseJsonOrThrow(resp, codecForAny());\n }\n\n async abortWithdrawalOperationV2(\n username: string,\n wopi: WithdrawalOperationInfo,\n ): Promise {\n const url = new URL(\n `accounts/${username}/withdrawals/${wopi.withdrawal_id}/abort`,\n this.baseUrl,\n );\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body: {},\n headers: this.makeAuthHeader(),\n });\n await expectSuccessResponseOrThrow(resp);\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\n/**\n * Types used by clients of the wallet.\n *\n * These types are defined in a separate file make tree shaking easier, since\n * some components use these types (via RPC) but do not depend on the wallet\n * code directly.\n *\n * @author Florian Dold \n */\n\n/**\n * Imports.\n */\nimport { AmountJson, codecForAmountString } from \"./amounts.js\";\nimport {\n Codec,\n Context,\n DecodingError,\n buildCodecForObject,\n buildCodecForUnion,\n codecForAny,\n codecForBoolean,\n codecForConstString,\n codecForEither,\n codecForList,\n codecForMap,\n codecForNumber,\n codecForString,\n codecForStringUnion,\n codecOptional,\n renderContext,\n} from \"./codec.js\";\nimport { canonicalizeBaseUrl } from \"./helpers.js\";\nimport { PaytoString, codecForPaytoString } from \"./payto.js\";\nimport { PerformanceTable } from \"./performance.js\";\nimport { QrCodeSpec } from \"./qr.js\";\nimport { AgeCommitmentProof } from \"./taler-crypto.js\";\nimport { TalerErrorCode } from \"./taler-error-codes.js\";\nimport { TalerUri, TemplateParams } from \"./taleruri.js\";\nimport {\n AbsoluteTime,\n DurationUnitSpec,\n TalerPreciseTimestamp,\n TalerProtocolDuration,\n TalerProtocolTimestamp,\n codecForAbsoluteTime,\n codecForTimestamp,\n} from \"./time.js\";\nimport { BlindedDonationReceiptKeyPair } from \"./types-donau.js\";\nimport { WithdrawalOperationStatusFlag } from \"./types-taler-bank-integration.js\";\nimport {\n AmountString,\n CurrencySpecification,\n EddsaPrivateKeyString,\n EddsaPublicKeyString,\n EddsaSignatureString,\n HashCode,\n HashCodeString,\n Timestamp,\n codecForEddsaPrivateKey,\n} from \"./types-taler-common.js\";\nimport {\n AccountRestriction,\n AuditorDenomSig,\n CoinEnvelope,\n DenomKeyType,\n DenominationPubKey,\n ExchangeAuditor,\n ExchangeRefundRequest,\n ExchangeWireAccount,\n PeerContractTerms,\n UnblindedDenominationSignature,\n codecForExchangeWireAccount,\n codecForPeerContractTerms,\n} from \"./types-taler-exchange.js\";\nimport {\n MerchantContractTerms,\n MerchantContractTermsV0,\n MerchantContractTermsV1,\n TokenEnvelope,\n TokenIssuePublicKey,\n WalletTemplateDetailsResponse,\n codecForMerchantContractTerms,\n codecForMerchantContractTermsV0,\n} from \"./types-taler-merchant.js\";\nimport { BackupRecovery } from \"./types-taler-sync.js\";\nimport {\n TransactionMajorState,\n TransactionMinorState,\n TransactionState,\n TransactionStateWildcard,\n} from \"./types-taler-wallet-transactions.js\";\n\n/**\n * Identifier for a transaction in the wallet.\n */\ndeclare const __txId: unique symbol;\nexport type TransactionIdStr = `txn:${string}:${string}` & { [__txId]: true };\n\n/**\n * Identifier for a pending task in the wallet.\n */\ndeclare const __pndId: unique symbol;\nexport type PendingIdStr = `pnd:${string}:${string}` & { [__pndId]: true };\n\ndeclare const __tmbId: unique symbol;\nexport type TombstoneIdStr = `tmb:${string}:${string}` & { [__tmbId]: true };\n\nfunction codecForTransactionIdStr(): Codec {\n return {\n decode(x: any, c?: Context): TransactionIdStr {\n if (typeof x === \"string\" && x.startsWith(\"txn:\")) {\n return x as TransactionIdStr;\n }\n throw new DecodingError(\n `expected string starting with \"txn:\" at ${renderContext(\n c,\n )} but got ${x}`,\n );\n },\n };\n}\n\nfunction codecForPendingIdStr(): Codec {\n return {\n decode(x: any, c?: Context): PendingIdStr {\n if (typeof x === \"string\" && x.startsWith(\"txn:\")) {\n return x as PendingIdStr;\n }\n throw new DecodingError(\n `expected string starting with \"txn:\" at ${renderContext(\n c,\n )} but got ${x}`,\n );\n },\n };\n}\n\nfunction codecForTombstoneIdStr(): Codec {\n return {\n decode(x: any, c?: Context): TombstoneIdStr {\n if (typeof x === \"string\" && x.startsWith(\"tmb:\")) {\n return x as TombstoneIdStr;\n }\n throw new DecodingError(\n `expected string starting with \"tmb:\" at ${renderContext(\n c,\n )} but got ${x}`,\n );\n },\n };\n}\n\nexport function codecForCanonBaseUrl(): Codec {\n return {\n decode(x: any, c?: Context): string {\n if (typeof x === \"string\") {\n const canon = canonicalizeBaseUrl(x);\n if (x !== canon) {\n throw new DecodingError(\n `expected canonicalized base URL at ${renderContext(\n c,\n )} but got value '${x}'`,\n );\n }\n return x;\n }\n throw new DecodingError(\n `expected base URL at ${renderContext(c)} but got type ${typeof x}`,\n );\n },\n };\n}\n\nexport enum ScopeType {\n Global = \"global\",\n Exchange = \"exchange\",\n Auditor = \"auditor\",\n}\n\nexport type ScopeInfoGlobal = { type: ScopeType.Global; currency: string };\n\nexport type ScopeInfoExchange = {\n type: ScopeType.Exchange;\n currency: string;\n url: string;\n};\n\nexport type ScopeInfoAuditor = {\n type: ScopeType.Auditor;\n currency: string;\n url: string;\n};\n\nexport type ScopeInfo = ScopeInfoGlobal | ScopeInfoExchange | ScopeInfoAuditor;\n\nexport const codecForScopeInfo = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(ScopeType.Global, codecForScopeInfoGlobal())\n .alternative(ScopeType.Exchange, codecForScopeInfoExchange())\n .alternative(ScopeType.Auditor, codecForScopeInfoAuditor())\n .build(\"ScopeInfo\");\n\n/**\n * Response for the create reserve request to the wallet.\n */\nexport class CreateReserveResponse {\n /**\n * Exchange URL where the bank should create the reserve.\n * The URL is canonicalized in the response.\n */\n exchange: string;\n\n /**\n * Reserve public key of the newly created reserve.\n */\n reservePub: string;\n}\n\nexport interface GetBalanceDetailRequest {\n currency: string;\n}\n\nexport const codecForGetBalanceDetailRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .build(\"GetBalanceDetailRequest\");\n\n/**\n * How the amount should be interpreted in a transaction\n * Effective = how the balance is change\n * Raw = effective amount without fee\n *\n * Depending on the transaction, raw can be higher than effective\n */\nexport enum TransactionAmountMode {\n Effective = \"effective\",\n Raw = \"raw\",\n}\n\nexport interface ConvertAmountRequest {\n amount: AmountString;\n type: TransactionAmountMode;\n depositPaytoUri: PaytoString;\n}\n\nexport const codecForConvertAmountRequest =\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"depositPaytoUri\", codecForPaytoString())\n .property(\n \"type\",\n codecForEither(\n codecForConstString(TransactionAmountMode.Raw),\n codecForConstString(TransactionAmountMode.Effective),\n ),\n )\n .build(\"ConvertAmountRequest\");\n\nexport interface GetMaxDepositAmountRequest {\n /**\n * Currency to deposit.\n */\n currency: string;\n\n /**\n * Target bank account to deposit into.\n */\n depositPaytoUri?: string;\n\n /**\n * Restrict the deposit to a certain scope.\n */\n restrictScope?: ScopeInfo;\n}\n\nexport const codecForGetMaxDepositAmountRequest = () =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"depositPaytoUri\", codecOptional(codecForString()))\n .property(\"restrictScope\", codecOptional(codecForScopeInfo()))\n .build(\"GetAmountRequest\");\n\nexport interface GetMaxPeerPushDebitAmountRequest {\n currency: string;\n /**\n * Preferred exchange to use for the p2p payment.\n */\n exchangeBaseUrl?: string;\n restrictScope?: ScopeInfo;\n}\n\nexport const codecForGetMaxPeerPushDebitAmountRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"exchangeBaseUrl\", codecOptional(codecForString()))\n .property(\"restrictScope\", codecOptional(codecForScopeInfo()))\n .build(\"GetMaxPeerPushDebitRequest\");\n\nexport interface GetMaxDepositAmountResponse {\n effectiveAmount: AmountString;\n rawAmount: AmountString;\n\n /**\n * Account restrictions that affect the max deposit amount.\n */\n depositRestrictions?: {\n [exchangeBaseUrl: string]: { [paytoUri: string]: AccountRestriction[] };\n };\n}\n\nexport interface GetMaxPeerPushDebitAmountResponse {\n effectiveAmount: AmountString;\n rawAmount: AmountString;\n exchangeBaseUrl?: string;\n}\n\nexport interface AmountResponse {\n effectiveAmount: AmountString;\n rawAmount: AmountString;\n}\n\nexport const codecForAmountResponse = (): Codec =>\n buildCodecForObject()\n .property(\"effectiveAmount\", codecForAmountString())\n .property(\"rawAmount\", codecForAmountString())\n .build(\"AmountResponse\");\n\nexport enum BalanceFlag {\n IncomingKyc = \"incoming-kyc\",\n IncomingAml = \"incoming-aml\",\n IncomingConfirmation = \"incoming-confirmation\",\n OutgoingKyc = \"outgoing-kyc\",\n}\n\nexport interface WalletBalance {\n scopeInfo: ScopeInfo;\n available: AmountString;\n pendingIncoming: AmountString;\n pendingOutgoing: AmountString;\n\n flags: BalanceFlag[];\n\n /**\n * Available URLs for pages that list\n * where money in this scope can be spent.\n */\n shoppingUrls?: string[];\n\n /**\n * Are p2p payments disabled for this scope?\n */\n disablePeerPayments?: boolean;\n\n /**\n * Are wallet deposits enabled for this scope?\n */\n disableDirectDeposits?: boolean;\n}\n\nexport const codecForScopeInfoGlobal = (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"type\", codecForConstString(ScopeType.Global))\n .build(\"ScopeInfoGlobal\");\n\nexport const codecForScopeInfoExchange = (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"type\", codecForConstString(ScopeType.Exchange))\n .property(\"url\", codecForString())\n .build(\"ScopeInfoExchange\");\n\nexport const codecForScopeInfoAuditor = (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"type\", codecForConstString(ScopeType.Auditor))\n .property(\"url\", codecForString())\n .build(\"ScopeInfoAuditor\");\n\nexport interface GetCurrencySpecificationRequest {\n scope: ScopeInfo;\n}\n\nexport const codecForGetCurrencyInfoRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"scope\", codecForScopeInfo())\n .build(\"GetCurrencySpecificationRequest\");\n\nexport interface GetCurrencySpecificationResponse {\n currencySpecification: CurrencySpecification;\n}\n\nexport interface BuiltinExchange {\n exchangeBaseUrl: string;\n currencyHint: string;\n}\n\nexport interface PartialWalletRunConfig {\n testing?: Partial;\n features?: Partial;\n lazyTaskLoop?: Partial;\n logLevel?: Partial;\n}\n\nexport interface WalletRunConfig {\n /**\n * Unsafe options which it should only be used to create\n * testing environment.\n */\n testing: {\n devModeActive: boolean;\n insecureTrustExchange: boolean;\n preventThrottling: boolean;\n skipDefaults: boolean;\n emitObservabilityEvents?: boolean;\n };\n\n /**\n * Configurations values that may be safe to show to the user\n */\n features: {\n allowHttp: boolean;\n\n /**\n * If set to true, enable V1 contracts. Otherwise, emulate v0 contracts\n * to wallet-core clients.\n *\n * Will become enabled by default in the future.\n *\n * Added 2025-08-19.\n */\n enableV1Contracts: boolean;\n };\n\n /**\n * Start processing tasks only when explicitly required, even after\n * init has been called.\n *\n * Useful when the wallet is started to make single read-only request,\n * as otherwise wallet-core starts making network request and process\n * unrelated pending tasks.\n */\n lazyTaskLoop: boolean;\n\n /**\n * Global log level.\n */\n logLevel: string;\n}\n\nexport interface InitRequest {\n config?: PartialWalletRunConfig;\n}\n\nexport const codecForInitRequest = (): Codec =>\n buildCodecForObject()\n .property(\"config\", codecForAny())\n .build(\"InitRequest\");\n\nexport interface InitResponse {\n versionInfo: WalletCoreVersion;\n}\n\n/**\n * Shorter version of stringifyScopeInfo\n */\nexport function stringifyScopeInfoShort(si: ScopeInfo): string {\n switch (si.type) {\n case ScopeType.Global:\n return `${si.currency}`;\n case ScopeType.Exchange:\n return `${si.currency}/${encodeURIComponent(si.url)}`;\n case ScopeType.Auditor:\n return `${si.currency}:${encodeURIComponent(si.url)}`;\n }\n}\nexport function parseScopeInfoShort(si: string): ScopeInfo | undefined {\n const indexOfColon = si.indexOf(\":\");\n const indexOfSlash = si.indexOf(\"/\");\n if (indexOfColon === -1 && indexOfSlash === -1) {\n return {\n type: ScopeType.Global,\n currency: si,\n };\n }\n if (indexOfColon > 0) {\n return {\n type: ScopeType.Auditor,\n currency: si.substring(0, indexOfColon),\n url: decodeURIComponent(si.substring(indexOfColon + 1)),\n };\n }\n if (indexOfSlash > 0) {\n return {\n type: ScopeType.Exchange,\n currency: si.substring(0, indexOfSlash),\n url: decodeURIComponent(si.substring(indexOfSlash + 1)),\n };\n }\n return undefined;\n}\n\n/**\n * Encode scope info as a string.\n *\n * Format must be stable as it's used in the database.\n */\nexport function stringifyScopeInfo(si: ScopeInfo): string {\n switch (si.type) {\n case ScopeType.Global:\n return `taler-si:global/${si.currency}`;\n case ScopeType.Auditor:\n return `taler-si:auditor/${si.currency}/${encodeURIComponent(si.url)}`;\n case ScopeType.Exchange:\n return `taler-si:exchange/${si.currency}/${encodeURIComponent(si.url)}`;\n }\n}\n\nexport interface DonauSummaryItem {\n /** Base URL of the donau service. */\n donauBaseUrl: string;\n /** Legal domain of the donau service (if available). */\n legalDomain?: string;\n /** Year of the donation(s). */\n year: number;\n /**\n * Sum of donation receipts we received from merchants in the\n * applicable year.\n */\n amountReceiptsAvailable: AmountString;\n /**\n * Sum of donation receipts that were already submitted\n * to the donau in the applicable year.\n */\n amountReceiptsSubmitted: AmountString;\n /**\n * Amount of the latest available statement. Missing if no statement\n * was requested yet.\n */\n amountStatement?: AmountString;\n}\n\n/**\n * Response to a getBalances request.\n */\nexport interface BalancesResponse {\n /** Electronic cash balances, per currency scope. */\n balances: WalletBalance[];\n /** Does the user have non-demo money? */\n haveProdBalance: boolean;\n /* Summary of donations, per donau/year/currency. */\n donauSummary?: DonauSummaryItem[];\n}\n\nexport interface BalancesScopeRequest {\n /** Electronic cash balances, per currency scope. */\n balances: WalletBalance[];\n /* Summary of donations, per donau/year/currency. */\n donauSummary?: DonauSummaryItem[];\n}\nexport interface BalancesScopeResponse {\n /** Electronic cash balance. */\n balance: WalletBalance;\n}\n\nexport const codecForBalance = (): Codec =>\n buildCodecForObject()\n .property(\"scopeInfo\", codecForAny()) // FIXME\n .property(\"available\", codecForAmountString())\n .property(\"pendingIncoming\", codecForAmountString())\n .property(\"pendingOutgoing\", codecForAmountString())\n .property(\"flags\", codecForAny()) // FIXME\n .build(\"Balance\");\n\n/**\n * For terseness.\n */\nexport function mkAmount(\n value: number,\n fraction: number,\n currency: string,\n): AmountJson {\n return { value, fraction, currency };\n}\n\n/**\n * Status of a coin.\n */\nexport enum CoinStatus {\n /**\n * Withdrawn and never shown to anybody.\n */\n Fresh = \"fresh\",\n\n /**\n * Coin was lost as the denomination is not usable anymore.\n */\n DenomLoss = \"denom-loss\",\n\n /**\n * Fresh, but currently marked as \"suspended\", thus won't be used\n * for spending. Used for testing.\n */\n FreshSuspended = \"fresh-suspended\",\n\n /**\n * A coin that has been spent and refreshed.\n */\n Dormant = \"dormant\",\n}\n\nexport type WalletCoinHistoryItem =\n | {\n type: \"withdraw\";\n transactionId: TransactionIdStr;\n }\n | {\n type: \"spend\";\n transactionId: TransactionIdStr;\n amount: AmountString;\n }\n | {\n type: \"refresh\";\n transactionId: TransactionIdStr;\n amount: AmountString;\n }\n | {\n type: \"recoup\";\n transactionId: TransactionIdStr;\n amount: AmountString;\n }\n | {\n type: \"refund\";\n transactionId: TransactionIdStr;\n amount: AmountString;\n };\n\n/**\n * Easy to process format for the public data of coins\n * managed by the wallet.\n */\nexport interface CoinDumpJson {\n coins: Array<{\n /**\n * The coin's denomination's public key.\n */\n denomPub: DenominationPubKey;\n /**\n * Hash of denom_pub.\n */\n denomPubHash: string;\n /**\n * Value of the denomination (without any fees).\n */\n denomValue: string;\n /**\n * Public key of the coin.\n */\n coinPub: string;\n /**\n * Base URL of the exchange for the coin.\n */\n exchangeBaseUrl: string;\n /**\n * Public key of the parent coin.\n * Only present if this coin was obtained via refreshing.\n */\n refreshParentCoinPub: string | undefined;\n /**\n * Public key of the reserve for this coin.\n * Only present if this coin was obtained via refreshing.\n */\n withdrawalReservePub: string | undefined;\n /**\n * Status of the coin.\n */\n coinStatus: CoinStatus;\n /**\n * Information about the age restriction\n */\n ageCommitmentProof: AgeCommitmentProof | undefined;\n history: WalletCoinHistoryItem[];\n }>;\n}\n\nexport enum ConfirmPayResultType {\n Done = \"done\",\n Pending = \"pending\",\n}\n\n/**\n * Result for confirmPay\n */\nexport interface ConfirmPayResultDone {\n type: ConfirmPayResultType.Done;\n contractTerms: MerchantContractTermsV0;\n transactionId: TransactionIdStr;\n}\n\nexport interface ConfirmPayResultPending {\n type: ConfirmPayResultType.Pending;\n transactionId: TransactionIdStr;\n lastError: TalerErrorDetail | undefined;\n}\n\nexport const codecForTalerErrorDetail = (): Codec =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"when\", codecOptional(codecForAbsoluteTime))\n .property(\"hint\", codecOptional(codecForString()))\n .build(\"TalerErrorDetail\");\n\nexport type ConfirmPayResult = ConfirmPayResultDone | ConfirmPayResultPending;\n\nexport const codecForConfirmPayResultPending =\n (): Codec =>\n buildCodecForObject()\n .property(\"lastError\", codecOptional(codecForTalerErrorDetail()))\n .property(\"transactionId\", codecForTransactionIdStr())\n .property(\"type\", codecForConstString(ConfirmPayResultType.Pending))\n .build(\"ConfirmPayResultPending\");\n\nexport const codecForConfirmPayResultDone = (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(ConfirmPayResultType.Done))\n .property(\"transactionId\", codecForTransactionIdStr())\n .property(\"contractTerms\", codecForMerchantContractTermsV0())\n .build(\"ConfirmPayResultDone\");\n\nexport const codecForConfirmPayResult = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\n ConfirmPayResultType.Pending,\n codecForConfirmPayResultPending(),\n )\n .alternative(ConfirmPayResultType.Done, codecForConfirmPayResultDone())\n .build(\"ConfirmPayResult\");\n\n/**\n * Information about all sender wire details known to the wallet,\n * as well as exchanges that accept these wire types.\n */\nexport interface SenderWireInfos {\n /**\n * Mapping from exchange base url to list of accepted\n * wire types.\n */\n exchangeWireTypes: { [exchangeBaseUrl: string]: string[] };\n\n /**\n * Sender wire information stored in the wallet.\n */\n senderWires: string[];\n}\n\nexport enum PreparePayResultType {\n PaymentPossible = \"payment-possible\",\n InsufficientBalance = \"insufficient-balance\",\n AlreadyConfirmed = \"already-confirmed\",\n ChoiceSelection = \"choice-selection\",\n}\n\nexport const codecForPreparePayResultPaymentPossible =\n (): Codec =>\n buildCodecForObject()\n .property(\"amountEffective\", codecForAmountString())\n .property(\"amountRaw\", codecForAmountString())\n .property(\"contractTerms\", codecForMerchantContractTermsV0())\n .property(\"transactionId\", codecForTransactionIdStr())\n .property(\"contractTermsHash\", codecForString())\n .property(\"scopes\", codecForList(codecForScopeInfo()))\n .property(\"talerUri\", codecForString())\n .property(\n \"status\",\n codecForConstString(PreparePayResultType.PaymentPossible),\n )\n .build(\"PreparePayResultPaymentPossible\");\n\nexport enum InsufficientBalanceHint {\n /**\n * Merchant doesn't accept money from exchange(s) that the wallet supports.\n */\n MerchantAcceptInsufficient = \"merchant-accept-insufficient\",\n\n /**\n * Merchant accepts funds from a matching exchange, but the funds can't be\n * deposited with the wire method.\n */\n MerchantDepositInsufficient = \"merchant-deposit-insufficient\",\n\n /**\n * While in principle the balance is sufficient,\n * the age restriction on coins causes the spendable\n * balance to be insufficient.\n */\n AgeRestricted = \"age-restricted\",\n\n /**\n * Wallet has enough available funds,\n * but the material funds are insufficient. Usually because there is a\n * pending refresh operation.\n */\n WalletBalanceMaterialInsufficient = \"wallet-balance-material-insufficient\",\n\n /**\n * The wallet simply doesn't have enough available funds.\n * This is the \"obvious\" case of insufficient balance.\n */\n WalletBalanceAvailableInsufficient = \"wallet-balance-available-insufficient\",\n\n /**\n * Exchange is missing the global fee configuration, thus fees are unknown\n * and funds from this exchange can't be used for p2p payments.\n */\n ExchangeMissingGlobalFees = \"exchange-missing-global-fees\",\n\n /**\n * Even though the balance looks sufficient for the instructed amount,\n * the fees can be covered by neither the merchant nor the remaining wallet\n * balance.\n */\n FeesNotCovered = \"fees-not-covered\",\n}\n\n/**\n * Detailed reason for why the wallet's balance is insufficient.\n */\nexport interface PaymentInsufficientBalanceDetails {\n /**\n * Amount requested by the merchant.\n */\n amountRequested: AmountString;\n\n /**\n * Wire method for the requested payment, only applicable\n * for merchant payments.\n */\n wireMethod?: string | undefined;\n\n /**\n * Hint as to why the balance is insufficient.\n *\n * If this hint is not provided, the balance hints of\n * the individual exchanges should be shown, as the overall\n * reason might be a combination of the reasons for different exchanges.\n */\n causeHint?: InsufficientBalanceHint;\n\n /**\n * Balance of type \"available\" (see balance.ts for definition).\n */\n balanceAvailable: AmountString;\n\n /**\n * Balance of type \"material\" (see balance.ts for definition).\n */\n balanceMaterial: AmountString;\n\n /**\n * Balance of type \"age-acceptable\" (see balance.ts for definition).\n */\n balanceAgeAcceptable: AmountString;\n\n /**\n * Balance of type \"receiver-acceptable\" (see balance.ts for definition).\n *\n * @deprecated (2025-12-05) use balanceReceiver[...]Acceptable instead.\n */\n balanceReceiverAcceptable: AmountString;\n\n /**\n * Balance of type \"receiver-exchange-url-acceptable\" (see balance.ts for definition).\n */\n balanceReceiverExchangeUrlAcceptable: AmountString;\n\n /**\n * Balance of type \"receiver-exchange-pub-acceptable\" (see balance.ts for definition).\n */\n balanceReceiverExchangePubAcceptable: AmountString;\n\n /**\n * Balance of type \"receiver-auditor-url-acceptable\" (see balance.ts for definition).\n */\n balanceReceiverAuditorUrlAcceptable: AmountString;\n\n /**\n * Balance of type \"merchant-depositable\" (see balance.ts for definition).\n */\n balanceReceiverDepositable: AmountString;\n\n balanceExchangeDepositable: AmountString;\n\n /**\n * Maximum effective amount that the wallet can spend,\n * when all fees are paid by the wallet.\n */\n maxEffectiveSpendAmount: AmountString;\n\n perExchange: {\n [url: string]: {\n balanceAvailable: AmountString;\n balanceMaterial: AmountString;\n balanceExchangeDepositable: AmountString;\n balanceAgeAcceptable: AmountString;\n\n /**\n * @deprecated (2025-12-05) use balanceReceiver[...]Acceptable instead.\n */\n balanceReceiverAcceptable: AmountString;\n\n balanceReceiverExchangeUrlAcceptable: AmountString;\n balanceReceiverExchangePubAcceptable: AmountString;\n balanceReceiverAuditorUrlAcceptable: AmountString;\n balanceReceiverDepositable: AmountString;\n maxEffectiveSpendAmount: AmountString;\n\n /**\n * The exchange master public key configured by the merchant\n * backend differs from the one of the coins stored in the wallet.\n */\n exchangeMasterPubMismatch: boolean;\n\n /**\n * Exchange doesn't have global fees configured for the relevant year,\n * p2p payments aren't possible.\n *\n * @deprecated (2025-02-18) use causeHint instead\n */\n missingGlobalFees: boolean;\n\n /**\n * Hint that UIs should show to explain the insufficient\n * balance.\n */\n causeHint?: InsufficientBalanceHint | undefined;\n };\n };\n}\n\nexport interface PaymentTokenAvailabilityDetails {\n /**\n * Number of tokens requested by the merchant.\n */\n tokensRequested: number;\n\n /**\n * Number of tokens available to use.\n */\n tokensAvailable: number;\n\n /**\n * Number of tokens for which the merchant is unexpected.\n *\n * Can be used to pay (i.e. with forced selection),\n * but a warning should be displayed to the user.\n */\n tokensUnexpected: number;\n\n /**\n * Number of tokens for which the merchant is untrusted.\n *\n * Cannot be used to pay, so an error should be displayed.\n */\n tokensUntrusted: number;\n\n perTokenFamily: {\n [slug: string]: {\n causeHint?: TokenAvailabilityHint;\n requested: number;\n available: number;\n unexpected: number;\n untrusted: number;\n };\n };\n}\n\nexport enum TokenAvailabilityHint {\n WalletTokensAvailableInsufficient = \"wallet-tokens-available-insufficient\",\n MerchantUnexpected = \"merchant-unexpected\",\n MerchantUntrusted = \"merchant-untrusted\",\n}\n\nexport const codecForPayMerchantInsufficientBalanceDetails =\n (): Codec =>\n buildCodecForObject()\n .property(\"amountRequested\", codecForAmountString())\n .property(\"wireMethod\", codecOptional(codecForString()))\n .property(\"balanceAgeAcceptable\", codecForAmountString())\n .property(\"balanceAvailable\", codecForAmountString())\n .property(\"balanceMaterial\", codecForAmountString())\n .property(\"balanceReceiverAcceptable\", codecForAmountString())\n .property(\"balanceReceiverExchangeUrlAcceptable\", codecForAmountString())\n .property(\"balanceReceiverExchangePubAcceptable\", codecForAmountString())\n .property(\"balanceReceiverAuditorUrlAcceptable\", codecForAmountString())\n .property(\"balanceReceiverDepositable\", codecForAmountString())\n .property(\"balanceExchangeDepositable\", codecForAmountString())\n .property(\"perExchange\", codecForAny())\n .property(\"maxEffectiveSpendAmount\", codecForAmountString())\n .deprecatedProperty(\"balanceReceiverAcceptable\")\n .build(\"PayMerchantInsufficientBalanceDetails\");\n\nexport const codecForPreparePayResultInsufficientBalance =\n (): Codec =>\n buildCodecForObject()\n .property(\"amountRaw\", codecForAmountString())\n .property(\"contractTerms\", codecForMerchantContractTermsV0())\n .property(\"talerUri\", codecForString())\n .property(\"transactionId\", codecForTransactionIdStr())\n .property(\n \"status\",\n codecForConstString(PreparePayResultType.InsufficientBalance),\n )\n .property(\"scopes\", codecForList(codecForScopeInfo()))\n .property(\n \"balanceDetails\",\n codecForPayMerchantInsufficientBalanceDetails(),\n )\n .build(\"PreparePayResultInsufficientBalance\");\n\nexport const codecForPreparePayResultAlreadyConfirmed =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"status\",\n codecForConstString(PreparePayResultType.AlreadyConfirmed),\n )\n .property(\"amountEffective\", codecOptional(codecForAmountString()))\n .property(\"amountRaw\", codecForAmountString())\n .property(\"scopes\", codecForList(codecForScopeInfo()))\n .property(\"paid\", codecForBoolean())\n .property(\"talerUri\", codecForString())\n .property(\"contractTerms\", codecForMerchantContractTermsV0())\n .property(\"contractTermsHash\", codecForString())\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"PreparePayResultAlreadyConfirmed\");\n\nexport const codecForPreparePayResultChoiceSelection =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"status\",\n codecForConstString(PreparePayResultType.ChoiceSelection),\n )\n .property(\"transactionId\", codecForTransactionIdStr())\n .property(\"contractTerms\", codecForMerchantContractTerms())\n .property(\"contractTermsHash\", codecForString())\n .property(\"talerUri\", codecForString())\n .build(\"PreparePayResultChoiceSelection\");\n\nexport const codecForPreparePayResult = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"status\")\n .alternative(\n PreparePayResultType.AlreadyConfirmed,\n codecForPreparePayResultAlreadyConfirmed(),\n )\n .alternative(\n PreparePayResultType.InsufficientBalance,\n codecForPreparePayResultInsufficientBalance(),\n )\n .alternative(\n PreparePayResultType.PaymentPossible,\n codecForPreparePayResultPaymentPossible(),\n )\n .alternative(\n PreparePayResultType.ChoiceSelection,\n codecForPreparePayResultChoiceSelection(),\n )\n .build(\"PreparePayResult\");\n\n/**\n * Result of a prepare pay operation.\n */\nexport type PreparePayResult =\n | PreparePayResultInsufficientBalance\n | PreparePayResultAlreadyConfirmed\n | PreparePayResultPaymentPossible\n | PreparePayResultChoiceSelection;\n\n/**\n * Payment is possible.\n *\n * This response is only returned for v0 contracts\n * or when v1 are not enabled yet.\n */\nexport interface PreparePayResultPaymentPossible {\n status: PreparePayResultType.PaymentPossible;\n\n transactionId: TransactionIdStr;\n\n contractTerms: MerchantContractTermsV0;\n\n /**\n * Scopes involved in this transaction.\n */\n scopes: ScopeInfo[];\n\n amountRaw: AmountString;\n\n amountEffective: AmountString;\n\n /**\n * FIXME: Unclear why this is needed. Remove?\n */\n contractTermsHash: string;\n\n /**\n * FIXME: Unclear why this is needed! Remove?\n */\n talerUri: string;\n}\n\nexport interface PreparePayResultInsufficientBalance {\n status: PreparePayResultType.InsufficientBalance;\n transactionId: TransactionIdStr;\n\n /**\n * Scopes involved in this transaction.\n *\n * For the insufficient balance response, contains scopes\n * of *possible* payment providers.\n */\n scopes: ScopeInfo[];\n\n contractTerms: MerchantContractTermsV0;\n\n amountRaw: AmountString;\n\n talerUri: string;\n\n balanceDetails: PaymentInsufficientBalanceDetails;\n}\n\nexport interface PreparePayResultAlreadyConfirmed {\n status: PreparePayResultType.AlreadyConfirmed;\n\n transactionId: TransactionIdStr;\n\n contractTerms: MerchantContractTerms;\n\n paid: boolean;\n\n amountRaw: AmountString;\n\n amountEffective: AmountString | undefined;\n\n /**\n * Scopes involved in this transaction.\n */\n scopes: ScopeInfo[];\n\n contractTermsHash: string;\n\n talerUri: string;\n}\n\n/**\n * Unconfirmed contract v1 payment.\n */\nexport interface PreparePayResultChoiceSelection {\n status: PreparePayResultType.ChoiceSelection;\n\n transactionId: TransactionIdStr;\n\n contractTerms: MerchantContractTerms;\n\n contractTermsHash: string;\n\n talerUri: string;\n}\n\nexport interface BankWithdrawDetails {\n status: WithdrawalOperationStatusFlag;\n currency: string;\n amount: AmountJson | undefined;\n editableAmount: boolean;\n maxAmount: AmountJson | undefined;\n wireFee: AmountJson | undefined;\n senderWire?: string;\n exchange?: string;\n editableExchange: boolean;\n confirmTransferUrl?: string;\n wireTypes: string[];\n operationId: string;\n apiBaseUrl: string;\n}\n\nexport interface AcceptWithdrawalResponse {\n confirmTransferUrl?: string;\n transactionId: TransactionIdStr;\n}\n\n/**\n * Details about a purchase, including refund status.\n */\nexport interface PurchaseDetails {\n contractTerms: Record;\n hasRefund: boolean;\n totalRefundAmount: AmountJson;\n totalRefundAndRefreshFees: AmountJson;\n}\n\nexport interface WalletDiagnostics {\n walletManifestVersion: string;\n walletManifestDisplayVersion: string;\n errors: string[];\n firefoxIdbProblem: boolean;\n dbOutdated: boolean;\n}\n\nexport interface TalerErrorDetail {\n code: TalerErrorCode;\n when?: AbsoluteTime;\n hint?: string;\n [x: string]: unknown;\n}\n\n/**\n * Minimal information needed about a planchet for unblinding a signature.\n *\n * Can be a withdrawal/refresh planchet.\n */\nexport interface PlanchetUnblindInfo {\n denomPub: DenominationPubKey;\n blindingKey: string;\n}\n\nexport interface WithdrawalPlanchet {\n coinPub: string;\n coinPriv: string;\n reservePub: string;\n denomPubHash: string;\n denomPub: DenominationPubKey;\n blindingKey: string;\n withdrawSig: string;\n coinEv: CoinEnvelope;\n coinValue: AmountJson;\n coinEvHash: string;\n ageCommitmentProof?: AgeCommitmentProof;\n}\n\nexport interface PlanchetCreationRequest {\n secretSeed: string;\n coinIndex: number;\n value: AmountJson;\n feeWithdraw: AmountJson;\n denomPub: DenominationPubKey;\n reservePub: string;\n reservePriv: string;\n restrictAge?: number;\n}\n\n/**\n * Minimal information needed about a slate for unblinding a signature.\n */\nexport interface SlateUnblindInfo {\n tokenIssuePub: TokenIssuePublicKey;\n blindingKey: string;\n}\n\nexport interface Slate {\n tokenPub: string;\n tokenPriv: string;\n tokenIssuePub: TokenIssuePublicKey;\n tokenIssuePubHash: string;\n tokenWalletData: PayWalletData;\n tokenEv: TokenEnvelope;\n tokenEvHash: string;\n blindingKey: string;\n}\n\nexport interface SlateCreationRequest {\n secretSeed: string;\n choiceIndex: number;\n outputIndex: number;\n tokenIssuePub: TokenIssuePublicKey;\n genTokenUseSig: boolean;\n contractTerms: MerchantContractTermsV1;\n contractTermsHash: string;\n}\n\nexport interface SignTokenUseRequest {\n tokenUsePriv: string;\n walletDataHash: string;\n contractTermsHash: string;\n}\n\n/**\n * Reasons for why a coin is being refreshed.\n */\nexport enum RefreshReason {\n Manual = \"manual\",\n PayMerchant = \"pay-merchant\",\n PayDeposit = \"pay-deposit\",\n PayPeerPush = \"pay-peer-push\",\n PayPeerPull = \"pay-peer-pull\",\n Refund = \"refund\",\n AbortPay = \"abort-pay\",\n AbortDeposit = \"abort-deposit\",\n AbortPeerPushDebit = \"abort-peer-push-debit\",\n AbortPeerPullDebit = \"abort-peer-pull-debit\",\n Recoup = \"recoup\",\n BackupRestored = \"backup-restored\",\n Scheduled = \"scheduled\",\n}\n\n/**\n * Request to refresh a single coin.\n */\nexport interface CoinRefreshRequest {\n readonly coinPub: string;\n readonly amount: AmountString;\n readonly refundRequest?: ExchangeRefundRequest;\n}\n\n/**\n * Private data required to make a deposit permission.\n */\nexport interface DepositInfo {\n exchangeBaseUrl: string;\n contractTermsHash: string;\n coinPub: string;\n coinPriv: string;\n spendAmount: AmountJson;\n timestamp: TalerProtocolTimestamp;\n refundDeadline: TalerProtocolTimestamp;\n merchantPub: string;\n feeDeposit: AmountJson;\n wireInfoHash: string;\n denomKeyType: DenomKeyType;\n denomPubHash: string;\n denomSig: UnblindedDenominationSignature;\n\n requiredMinimumAge?: number;\n\n ageCommitmentProof?: AgeCommitmentProof;\n\n walletDataHash?: string;\n}\n\nexport interface ExchangesShortListResponse {\n exchanges: ShortExchangeListItem[];\n}\n\nexport interface ExchangesListResponse {\n exchanges: ExchangeListItem[];\n}\n\nexport interface ListExchangesRequest {\n /**\n * Filter results to only include exchanges in the given scope.\n */\n filterByScope?: ScopeInfo;\n\n /**\n * Filter results to only include exchanges\n * with the given status.\n */\n filterByExchangeEntryStatus?: ExchangeEntryStatus;\n\n /**\n * Filter results to only include exchanges with the\n * given type.\n */\n filterByType?: ExchangeType;\n}\n\nexport type ExchangeType = \"demo\" | \"prod\";\n\nexport const codecForExchangeType = () => codecForStringUnion(\"demo\", \"prod\");\n\nexport const codecForListExchangesRequest = (): Codec =>\n buildCodecForObject()\n .property(\"filterByScope\", codecOptional(codecForScopeInfo()))\n .property(\n \"filterByExchangeEntryStatus\",\n codecOptional(codecForExchangeEntryStatus()),\n )\n .property(\"filterByType\", codecOptional(codecForExchangeType()))\n .build(\"ListExchangesRequest\");\n\nexport interface ExchangeDetailedResponse {\n exchange: ExchangeFullDetails;\n}\n\nexport interface AddContactRequest {\n contact: ContactEntry;\n}\n\nexport interface DeleteContactRequest {\n contact: ContactEntry;\n}\n\nexport interface ContactListResponse {\n contacts: ContactEntry[];\n}\n\nexport interface MailboxConfiguration {\n mailboxBaseUrl: string;\n privateKey: EddsaPrivateKeyString;\n privateEncryptionKey: string;\n expiration: Timestamp;\n payUri?: TalerUri;\n}\n\nexport const codecForMailboxConfiguration = (): Codec =>\n buildCodecForObject()\n .property(\"mailboxBaseUrl\", codecForString())\n .property(\"privateEncryptionKey\", codecForString())\n .property(\"privateKey\", codecForEddsaPrivateKey())\n .property(\"expiration\", codecForTimestamp)\n .build(\"MailboxConfiguration\");\n\nexport interface SendTalerUriMailboxMessageRequest {\n contact: ContactEntry;\n talerUri: string;\n}\n\nexport interface AddMailboxMessageRequest {\n message: MailboxMessageRecord;\n}\n\nexport interface DeleteMailboxMessageRequest {\n message: MailboxMessageRecord;\n}\n\nexport interface MailboxMessagesResponse {\n messages: MailboxMessageRecord[];\n}\n\nexport const codecForContactEntry = (): Codec =>\n buildCodecForObject()\n .property(\"alias\", codecForString())\n .property(\"aliasType\", codecForString())\n .property(\"mailboxBaseUri\", codecForString())\n .property(\"mailboxAddress\", codecForString())\n .property(\"source\", codecForString())\n .property(\"petname\", codecForString())\n .build(\"ContactListItem\");\n\nexport const codecForAddContactRequest = (): Codec =>\n buildCodecForObject()\n .property(\"contact\", codecForContactEntry())\n .build(\"AddContactRequest\");\n\nexport const codecForDeleteContactRequest = (): Codec =>\n buildCodecForObject()\n .property(\"contact\", codecForContactEntry())\n .build(\"DeleteContactRequest\");\n\nexport const codecForAddMailboxMessageRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"message\", codecForAny())\n .build(\"AddContactRequest\");\n\nexport const codecForDeleteMailboxMessageRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"message\", codecForAny())\n .build(\"DeleteContactRequest\");\n\nexport const codecForSendTalerUriMailboxMessageRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"contact\", codecForContactEntry())\n .property(\"talerUri\", codecForString())\n .build(\"SendTalerUriMailboxMessageRequest\");\n\nexport interface WalletCoreVersion {\n implementationSemver: string;\n implementationGitHash: string;\n\n /**\n * Wallet-core protocol version supported by this implementation\n * of the API (\"server\" version).\n */\n version: string;\n exchange: string;\n merchant: string;\n\n bankIntegrationApiRange: string;\n bankConversionApiRange: string;\n corebankApiRange: string;\n\n /**\n * @deprecated as bank was split into multiple APIs with separate versioning\n */\n bank: string;\n\n /**\n * @deprecated\n */\n hash: string | undefined;\n\n /**\n * @deprecated will be removed\n */\n devMode: boolean;\n}\n\nexport interface WalletBankAccountInfo {\n bankAccountId: string;\n\n paytoUri: string;\n\n /**\n * Did we previously complete a KYC process for this bank account?\n *\n * @deprecated no enough information since the kyc can be completed for one exchange but not for another\n * https://bugs.gnunet.org/view.php?id=9696\n */\n kycCompleted: boolean;\n\n /**\n * Currencies supported by the bank, if known.\n */\n currencies: string[] | undefined;\n\n label: string | undefined;\n}\n\nexport interface ListBankAccountsResponse {\n accounts: WalletBankAccountInfo[];\n}\n\nexport type GetBankAccountByIdResponse = WalletBankAccountInfo;\n\nexport interface GetBankAccountByIdRequest {\n bankAccountId: string;\n}\n\nexport const codecForGetBankAccountByIdRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"bankAccountId\", codecForString())\n .build(\"GetBankAccountByIdRequest\");\n\n/**\n * Wire fee for one wire method\n */\nexport interface WireFee {\n /**\n * Fee for wire transfers.\n */\n wireFee: AmountString;\n\n /**\n * Fees to close and refund a reserve.\n */\n closingFee: AmountString;\n\n /**\n * Start date of the fee.\n */\n startStamp: TalerProtocolTimestamp;\n\n /**\n * End date of the fee.\n */\n endStamp: TalerProtocolTimestamp;\n\n /**\n * Signature made by the exchange master key.\n */\n sig: string;\n}\n\nexport type WireFeeMap = { [wireMethod: string]: WireFee[] };\n\nexport interface WireInfo {\n feesForType: WireFeeMap;\n accounts: ExchangeWireAccount[];\n}\n\nexport interface ExchangeGlobalFees {\n startDate: TalerProtocolTimestamp;\n endDate: TalerProtocolTimestamp;\n\n historyFee: AmountString;\n accountFee: AmountString;\n purseFee: AmountString;\n\n historyTimeout: TalerProtocolDuration;\n purseTimeout: TalerProtocolDuration;\n\n purseLimit: number;\n\n signature: string;\n}\n\nconst codecForWireFee = (): Codec =>\n buildCodecForObject()\n .property(\"sig\", codecForString())\n .property(\"wireFee\", codecForAmountString())\n .property(\"closingFee\", codecForAmountString())\n .property(\"startStamp\", codecForTimestamp)\n .property(\"endStamp\", codecForTimestamp)\n .build(\"codecForWireFee\");\n\nconst codecForWireInfo = (): Codec =>\n buildCodecForObject()\n .property(\"feesForType\", codecForMap(codecForList(codecForWireFee())))\n .property(\"accounts\", codecForList(codecForExchangeWireAccount()))\n .build(\"codecForWireInfo\");\n\nexport interface DenominationInfo {\n /**\n * Value of one coin of the denomination.\n */\n value: AmountString;\n\n /**\n * Hash of the denomination public key.\n * Stored in the database for faster lookups.\n */\n denomPubHash: string;\n\n denomPub: DenominationPubKey;\n\n /**\n * Fee for withdrawing.\n */\n feeWithdraw: AmountString;\n\n /**\n * Fee for depositing.\n */\n feeDeposit: AmountString;\n\n /**\n * Fee for refreshing.\n */\n feeRefresh: AmountString;\n\n /**\n * Fee for refunding.\n */\n feeRefund: AmountString;\n\n /**\n * Validity start date of the denomination.\n */\n stampStart: TalerProtocolTimestamp;\n\n /**\n * Date after which the currency can't be withdrawn anymore.\n */\n stampExpireWithdraw: TalerProtocolTimestamp;\n\n /**\n * Date after the denomination officially doesn't exist anymore.\n */\n stampExpireLegal: TalerProtocolTimestamp;\n\n /**\n * Data after which coins of this denomination can't be deposited anymore.\n */\n stampExpireDeposit: TalerProtocolTimestamp;\n\n exchangeBaseUrl: string;\n\n exchangeMasterPub: string;\n\n isLost: boolean;\n\n isOffered: boolean;\n\n masterSig: string;\n}\n\nexport type DenomOperation = \"deposit\" | \"withdraw\" | \"refresh\" | \"refund\";\nexport type DenomOperationMap = { [op in DenomOperation]: T };\n\nexport interface FeeDescription {\n group: string;\n from: AbsoluteTime;\n until: AbsoluteTime;\n fee?: AmountString;\n}\n\nexport interface FeeDescriptionPair {\n group: string;\n from: AbsoluteTime;\n until: AbsoluteTime;\n left?: AmountString;\n right?: AmountString;\n}\n\nexport interface TimePoint {\n id: string;\n group: string;\n fee: AmountString;\n type: \"start\" | \"end\";\n moment: AbsoluteTime;\n denom: T;\n}\n\nexport interface ExchangeFullDetails {\n exchangeBaseUrl: string;\n currency: string;\n paytoUris: string[];\n auditors: ExchangeAuditor[];\n wireInfo: WireInfo;\n denomFees: DenomOperationMap;\n transferFees: Record;\n globalFees: FeeDescription[];\n}\n\nexport enum ExchangeTosStatus {\n Pending = \"pending\",\n Proposed = \"proposed\",\n Accepted = \"accepted\",\n MissingTos = \"missing-tos\",\n}\n\nexport enum ExchangeEntryStatus {\n Preset = \"preset\",\n Ephemeral = \"ephemeral\",\n Used = \"used\",\n}\n\nexport const codecForExchangeEntryStatus = (): Codec =>\n codecForEither(\n codecForConstString(ExchangeEntryStatus.Ephemeral),\n codecForConstString(ExchangeEntryStatus.Preset),\n codecForConstString(ExchangeEntryStatus.Used),\n );\n\nexport enum ExchangeUpdateStatus {\n Initial = \"initial\",\n InitialUpdate = \"initial-update\",\n Suspended = \"suspended\",\n UnavailableUpdate = \"unavailable-update\",\n Ready = \"ready\",\n ReadyUpdate = \"ready-update\",\n OutdatedUpdate = \"outdated-update\",\n}\n\nexport enum ExchangeWalletKycStatus {\n Done = \"done\",\n /**\n * Wallet needs to request KYC status.\n */\n LegiInit = \"legi-init\",\n /**\n * User requires KYC or AML.\n */\n Legi = \"legi\",\n}\n\nexport interface OperationErrorInfo {\n error: TalerErrorDetail;\n}\n\nexport interface ShortExchangeListItem {\n exchangeBaseUrl: string;\n}\n\n/**\n * Info about an exchange entry in the wallet.\n */\nexport interface ExchangeListItem {\n exchangeBaseUrl: string;\n masterPub: string | undefined;\n currency: string;\n paytoUris: string[];\n tosStatus: ExchangeTosStatus;\n exchangeEntryStatus: ExchangeEntryStatus;\n exchangeUpdateStatus: ExchangeUpdateStatus;\n ageRestrictionOptions: number[];\n\n walletKycStatus?: ExchangeWalletKycStatus;\n walletKycReservePub?: string;\n walletKycAccessToken?: string;\n walletKycUrl?: string;\n\n /** Threshold that we've requested to satisfy. */\n walletKycRequestedThreshold?: string;\n\n /**\n * P2P payments are disabled with this exchange\n * (e.g. because no global fees are configured).\n */\n peerPaymentsDisabled: boolean;\n\n directDepositsDisabled: boolean;\n\n /** Set to true if this exchange doesn't charge any fees. */\n noFees: boolean;\n\n /** Most general scope that the exchange is a part of. */\n scopeInfo: ScopeInfo;\n\n /**\n * Instructs wallets to use certain bank-specific\n * language (for buttons) and/or other UI/UX customization\n * for compliance with the rules of that bank.\n */\n bankComplianceLanguage?: string;\n\n lastUpdateTimestamp: TalerPreciseTimestamp | undefined;\n\n /**\n * Information about the last error that occurred when trying\n * to update the exchange info.\n */\n lastUpdateErrorInfo?: OperationErrorInfo;\n\n /**\n * Currency spec for the currency offered\n * by the exchange.\n */\n currencySpec: CurrencySpecification;\n}\n\nexport interface ContactEntry {\n /**\n * Contact alias\n */\n alias: string;\n\n /**\n * Alias type\n */\n aliasType: string;\n\n /**\n * mailbox URI\n */\n mailboxBaseUri: string;\n\n /**\n * mailbox identity\n */\n mailboxAddress: HashCodeString;\n\n /**\n * The source of this contact\n * may be a URI\n */\n source: string;\n\n /**\n * The local petname of the contact\n */\n petname: string;\n}\n\n/**\n * Record metadata for mailbox messages\n */\nexport interface MailboxMessageRecord {\n // Origin mailbox\n originMailboxBaseUrl: string;\n\n // Time of download\n downloadedAt: Timestamp;\n\n // Taler URI in message\n talerUri: string;\n}\n\nconst codecForAuditorDenomSig = (): Codec =>\n buildCodecForObject()\n .property(\"denom_pub_h\", codecForString())\n .property(\"auditor_sig\", codecForString())\n .build(\"AuditorDenomSig\");\n\nconst codecForExchangeAuditor = (): Codec =>\n buildCodecForObject()\n .property(\"auditor_pub\", codecForString())\n .property(\"auditor_url\", codecForString())\n .property(\"denomination_keys\", codecForList(codecForAuditorDenomSig()))\n .build(\"codecForExchangeAuditor\");\n\nexport const codecForFeeDescriptionPair = (): Codec =>\n buildCodecForObject()\n .property(\"group\", codecForString())\n .property(\"from\", codecForAbsoluteTime)\n .property(\"until\", codecForAbsoluteTime)\n .property(\"left\", codecOptional(codecForAmountString()))\n .property(\"right\", codecOptional(codecForAmountString()))\n .build(\"FeeDescriptionPair\");\n\nexport const codecForFeeDescription = (): Codec =>\n buildCodecForObject()\n .property(\"group\", codecForString())\n .property(\"from\", codecForAbsoluteTime)\n .property(\"until\", codecForAbsoluteTime)\n .property(\"fee\", codecOptional(codecForAmountString()))\n .build(\"FeeDescription\");\n\nexport const codecForFeesByOperations = (): Codec<\n DenomOperationMap\n> =>\n buildCodecForObject>()\n .property(\"deposit\", codecForList(codecForFeeDescription()))\n .property(\"withdraw\", codecForList(codecForFeeDescription()))\n .property(\"refresh\", codecForList(codecForFeeDescription()))\n .property(\"refund\", codecForList(codecForFeeDescription()))\n .build(\"DenomOperationMap\");\n\nexport const codecForExchangeFullDetails = (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"paytoUris\", codecForList(codecForString()))\n .property(\"auditors\", codecForList(codecForExchangeAuditor()))\n .property(\"wireInfo\", codecForWireInfo())\n .property(\"denomFees\", codecForFeesByOperations())\n .property(\n \"transferFees\",\n codecForMap(codecForList(codecForFeeDescription())),\n )\n .property(\"globalFees\", codecForList(codecForFeeDescription()))\n .build(\"ExchangeFullDetails\");\n\nexport interface AcceptManualWithdrawalResult {\n /**\n * Payto URIs that can be used to fund the withdrawal.\n *\n * @deprecated in favor of withdrawalAccountsList\n */\n exchangePaytoUris: string[];\n\n /**\n * Public key of the newly created reserve.\n */\n reservePub: string;\n\n withdrawalAccountsList: WithdrawalExchangeAccountDetails[];\n\n transactionId: TransactionIdStr;\n}\n\nexport interface WithdrawalDetailsForAmount {\n /**\n * Exchange base URL for the withdrawal.\n */\n exchangeBaseUrl: string;\n\n /**\n * Amount that the user will transfer to the exchange.\n */\n amountRaw: AmountString;\n\n /**\n * Amount that will be added to the user's wallet balance.\n */\n amountEffective: AmountString;\n\n /**\n * Number of coins that would be used for withdrawal.\n *\n * The UIs should warn if this number is too high (roughly at >100).\n */\n numCoins: number;\n\n /**\n * Ways to pay the exchange, including accounts that require currency conversion.\n */\n withdrawalAccountsList: WithdrawalExchangeAccountDetails[];\n\n /**\n * If the exchange supports age-restricted coins it will return\n * the array of ages.\n */\n ageRestrictionOptions?: number[];\n\n /**\n * Scope info of the currency withdrawn.\n */\n scopeInfo: ScopeInfo;\n\n /**\n * KYC soft limit.\n *\n * Withdrawals over that amount will require KYC.\n */\n kycSoftLimit?: AmountString;\n\n /**\n * KYC soft limits.\n *\n * Withdrawals over that amount will be denied.\n */\n kycHardLimit?: AmountString;\n\n /**\n * Ways to pay the exchange.\n *\n * @deprecated in favor of withdrawalAccountsList\n */\n paytoUris: string[];\n\n /**\n * Did the user accept the current version of the exchange's\n * terms of service?\n *\n * @deprecated the client should query the exchange entry instead\n */\n tosAccepted: boolean;\n}\n\nexport interface DenomSelItem {\n denomPubHash: string;\n count: number;\n /**\n * Number of denoms/planchets to skip, because\n * a re-denomination effectively deleted them.\n *\n * For denom revocations, this equals count.\n * But for re-denominations to a smaller withdrawal\n * amounts, skip < count is possible.\n */\n skip?: number;\n}\n\n/**\n * Selected denominations with some extra info.\n */\nexport interface DenomSelectionState {\n totalCoinValue: AmountString;\n totalWithdrawCost: AmountString;\n selectedDenoms: DenomSelItem[];\n hasDenomWithAgeRestriction: boolean;\n}\n\n/**\n * Information about what will happen doing a withdrawal.\n *\n * Sent to the wallet frontend to be rendered and shown to the user.\n */\nexport interface ExchangeWithdrawalDetails {\n exchangePaytoUris: string[];\n\n /**\n * Filtered wire info to send to the bank.\n */\n exchangeWireAccounts: string[];\n\n exchangeCreditAccountDetails: WithdrawalExchangeAccountDetails[];\n\n /**\n * Selected denominations for withdraw.\n */\n selectedDenoms: DenomSelectionState;\n\n /**\n * Did the user already accept the current terms of service for the exchange?\n */\n termsOfServiceAccepted: boolean;\n\n /**\n * Amount that will be subtracted from the reserve's balance.\n */\n withdrawalAmountRaw: AmountString;\n\n /**\n * Amount that will actually be added to the wallet's balance.\n */\n withdrawalAmountEffective: AmountString;\n\n /**\n * If the exchange supports age-restricted coins it will return\n * the array of ages.\n *\n */\n ageRestrictionOptions?: number[];\n\n scopeInfo: ScopeInfo;\n\n /**\n * KYC soft limit.\n *\n * Withdrawals over that amount will require KYC.\n */\n kycSoftLimit?: AmountString;\n\n /**\n * KYC soft limits.\n *\n * Withdrawals over that amount will be denied.\n */\n kycHardLimit?: AmountString;\n}\n\nexport interface GetExchangeTosResult {\n /**\n * Markdown version of the current ToS.\n */\n content: string;\n\n /**\n * Version tag of the current ToS.\n */\n currentEtag: string;\n\n /**\n * Version tag of the last ToS that the user has accepted,\n * if any.\n */\n acceptedEtag: string | undefined;\n\n /**\n * Accepted content type\n */\n contentType: string;\n\n /**\n * Language of the returned content.\n *\n * If missing, language is unknown.\n */\n contentLanguage: string | undefined;\n\n /**\n * Available languages as advertised by the exchange.\n */\n tosAvailableLanguages: string[];\n\n tosStatus: ExchangeTosStatus;\n}\n\nexport interface TestPayArgs {\n merchantBaseUrl: string;\n merchantAuthToken?: string;\n amount: AmountString;\n summary: string;\n forcedCoinSel?: ForcedCoinSel;\n}\n\nexport const codecForTestPayArgs = (): Codec =>\n buildCodecForObject()\n .property(\"merchantBaseUrl\", codecForCanonBaseUrl())\n .property(\"merchantAuthToken\", codecOptional(codecForString()))\n .property(\"amount\", codecForAmountString())\n .property(\"summary\", codecForString())\n .property(\"forcedCoinSel\", codecForAny())\n .build(\"TestPayArgs\");\n\nexport interface IntegrationTestArgs {\n exchangeBaseUrl: string;\n corebankApiBaseUrl: string;\n merchantBaseUrl: string;\n merchantAuthToken?: string;\n amountToWithdraw: AmountString;\n amountToSpend: AmountString;\n}\n\nexport const codecForIntegrationTestArgs = (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"merchantBaseUrl\", codecForCanonBaseUrl())\n .property(\"merchantAuthToken\", codecOptional(codecForString()))\n .property(\"amountToSpend\", codecForAmountString())\n .property(\"amountToWithdraw\", codecForAmountString())\n .property(\"corebankApiBaseUrl\", codecForCanonBaseUrl())\n .build(\"IntegrationTestArgs\");\n\nexport interface IntegrationTestV2Args {\n exchangeBaseUrl: string;\n corebankApiBaseUrl: string;\n merchantBaseUrl: string;\n merchantAuthToken?: string;\n}\n\nexport const codecForIntegrationTestV2Args = (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"merchantBaseUrl\", codecForCanonBaseUrl())\n .property(\"merchantAuthToken\", codecOptional(codecForString()))\n .property(\"corebankApiBaseUrl\", codecForCanonBaseUrl())\n .build(\"IntegrationTestV2Args\");\n\nexport interface GetExchangeEntryByUrlRequest {\n exchangeBaseUrl: string;\n}\n\nexport const codecForGetExchangeDetailedInfoRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .build(\"GetExchangeDetailedInfoRequest\");\n\nexport interface GetExchangeDetailedInfoRequest {\n exchangeBaseUrl: string;\n}\n\nexport const codecForGetExchangeEntryByUrlRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .build(\"GetExchangeEntryByUrlRequest\");\n\nexport type GetExchangeEntryByUrlResponse = ExchangeListItem;\n\nexport interface AddExchangeRequest {\n /**\n * Either an http(s) exchange base URL or\n * a taler://add-exchange/ URI.\n */\n uri?: string;\n\n /**\n * Only ephemerally add the exchange.\n */\n ephemeral?: boolean;\n\n /**\n * Allow passing incomplete URLs. The wallet will try to complete\n * the URL and throw an error if completion is not possible.\n */\n allowCompletion?: boolean;\n\n /**\n * @deprecated use a separate API call to start a forced exchange update instead\n */\n forceUpdate?: boolean;\n\n /**\n * @deprecated Use {@link uri} instead\n */\n exchangeBaseUrl?: string;\n}\n\nexport interface AddExchangeResponse {\n /**\n * Base URL of the exchange that was added to the wallet.\n */\n exchangeBaseUrl: string;\n}\n\nexport const codecForAddExchangeRequest = (): Codec =>\n buildCodecForObject()\n .property(\"allowCompletion\", codecOptional(codecForBoolean()))\n .property(\"exchangeBaseUrl\", codecOptional(codecForCanonBaseUrl()))\n .property(\"uri\", codecOptional(codecForString()))\n .property(\"forceUpdate\", codecOptional(codecForBoolean()))\n .property(\"ephemeral\", codecOptional(codecForBoolean()))\n .build(\"AddExchangeRequest\");\n\nexport interface UpdateExchangeEntryRequest {\n exchangeBaseUrl: string;\n force?: boolean;\n}\n\nexport const codecForUpdateExchangeEntryRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"force\", codecOptional(codecForBoolean()))\n .build(\"UpdateExchangeEntryRequest\");\n\nexport interface GetExchangeResourcesRequest {\n exchangeBaseUrl: string;\n}\n\nexport const codecForGetExchangeResourcesRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .build(\"GetExchangeResourcesRequest\");\n\nexport interface GetExchangeResourcesResponse {\n hasResources: boolean;\n}\n\nexport interface DeleteExchangeRequest {\n exchangeBaseUrl: string;\n\n /**\n * Delete the exchange even if it's in use.\n */\n purge?: boolean;\n}\n\nexport const codecForDeleteExchangeRequest = (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"purge\", codecOptional(codecForBoolean()))\n .build(\"DeleteExchangeRequest\");\n\nexport interface ForceExchangeUpdateRequest {\n exchangeBaseUrl: string;\n}\n\nexport const codecForForceExchangeUpdateRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .build(\"AddExchangeRequest\");\n\nexport interface GetExchangeTosRequest {\n exchangeBaseUrl: string;\n acceptedFormat?: string[];\n acceptLanguage?: string;\n}\n\nexport const codecForGetExchangeTosRequest = (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"acceptedFormat\", codecOptional(codecForList(codecForString())))\n .property(\"acceptLanguage\", codecOptional(codecForString()))\n .build(\"GetExchangeTosRequest\");\n\nexport interface AcceptManualWithdrawalRequest {\n exchangeBaseUrl: string;\n amount: AmountString;\n restrictAge?: number;\n\n /**\n * Instead of generating a fresh, random reserve key pair,\n * use the provided reserve private key.\n *\n * Use with caution. Usage of this field may be restricted\n * to developer mode.\n */\n forceReservePriv?: EddsaPrivateKeyString;\n}\n\nexport const codecForAcceptManualWithdrawalRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"amount\", codecForAmountString())\n .property(\"restrictAge\", codecOptional(codecForNumber()))\n .property(\"forceReservePriv\", codecOptional(codecForEddsaPrivateKey()))\n .build(\"AcceptManualWithdrawalRequest\");\n\nexport interface GetWithdrawalDetailsForAmountRequest {\n exchangeBaseUrl?: string;\n\n /**\n * Specify currency scope for the withdrawal.\n *\n * May only be used when exchangeBaseUrl is not specified.\n */\n restrictScope?: ScopeInfo;\n\n amount: AmountString;\n\n restrictAge?: number;\n\n /**\n * ID provided by the client to cancel the request.\n *\n * If the same request is made again with the same clientCancellationId,\n * all previous requests are cancelled.\n *\n * The cancelled request will receive an error response with\n * an error code that indicates the cancellation.\n *\n * The cancellation is best-effort, responses might still arrive.\n */\n clientCancellationId?: string;\n}\n\nexport interface PrepareBankIntegratedWithdrawalRequest {\n talerWithdrawUri: string;\n}\n\nexport const codecForPrepareBankIntegratedWithdrawalRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"talerWithdrawUri\", codecForString())\n .build(\"PrepareBankIntegratedWithdrawalRequest\");\n\nexport interface PrepareBankIntegratedWithdrawalResponse {\n transactionId: TransactionIdStr;\n info: WithdrawUriInfoResponse;\n}\n\nexport interface ConfirmWithdrawalRequest {\n transactionId: string;\n exchangeBaseUrl: string;\n amount: AmountString | undefined;\n forcedDenomSel?: ForcedDenomSel;\n restrictAge?: number;\n}\n\nexport const codecForConfirmWithdrawalRequestRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForString())\n .property(\"amount\", codecForAmountString())\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"forcedDenomSel\", codecForAny())\n .property(\"restrictAge\", codecOptional(codecForNumber()))\n .build(\"ConfirmWithdrawalRequest\");\n\nexport interface AcceptBankIntegratedWithdrawalRequest {\n talerWithdrawUri: string;\n exchangeBaseUrl: string;\n forcedDenomSel?: ForcedDenomSel;\n /**\n * Amount to withdraw.\n * If the bank's withdrawal operation uses a fixed amount,\n * this field must either be left undefined or its value must match\n * the amount from the withdrawal operation.\n */\n amount?: AmountString;\n restrictAge?: number;\n}\n\nexport const codecForAcceptBankIntegratedWithdrawalRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"talerWithdrawUri\", codecForString())\n .property(\"forcedDenomSel\", codecForAny())\n .property(\"amount\", codecOptional(codecForAmountString()))\n .property(\"restrictAge\", codecOptional(codecForNumber()))\n .build(\"AcceptBankIntegratedWithdrawalRequest\");\n\nexport const codecForGetWithdrawalDetailsForAmountRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecOptional(codecForCanonBaseUrl()))\n .property(\"restrictScope\", codecOptional(codecForScopeInfo()))\n .property(\"amount\", codecForAmountString())\n .property(\"restrictAge\", codecOptional(codecForNumber()))\n .property(\"clientCancellationId\", codecOptional(codecForString()))\n .build(\"GetWithdrawalDetailsForAmountRequest\");\n\nexport interface AcceptExchangeTosRequest {\n exchangeBaseUrl: string;\n}\n\nexport const codecForAcceptExchangeTosRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .build(\"AcceptExchangeTosRequest\");\n\nexport interface ForgetExchangeTosRequest {\n exchangeBaseUrl: string;\n}\n\nexport const codecForForgetExchangeTosRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .build(\"ForgetExchangeTosRequest\");\n\nexport interface AcceptRefundRequest {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForApplyRefundRequest = (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"AcceptRefundRequest\");\n\nexport interface ApplyRefundFromPurchaseIdRequest {\n purchaseId: string;\n}\n\nexport const codecForApplyRefundFromPurchaseIdRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"purchaseId\", codecForString())\n .build(\"ApplyRefundFromPurchaseIdRequest\");\n\nexport interface GetWithdrawalDetailsForUriRequest {\n talerWithdrawUri: string;\n /**\n * @deprecated not used\n */\n restrictAge?: number;\n}\n\nexport const codecForGetWithdrawalDetailsForUri =\n (): Codec =>\n buildCodecForObject()\n .property(\"talerWithdrawUri\", codecForString())\n .property(\"restrictAge\", codecOptional(codecForNumber()))\n .build(\"GetWithdrawalDetailsForUriRequest\");\n\nexport interface ListBankAccountsRequest {\n currency?: string;\n}\n\nexport const codecForListBankAccounts = (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecOptional(codecForString()))\n .build(\"ListBankAccountsRequest\");\n\nexport interface AddBankAccountRequest {\n /**\n * Payto URI of the bank account that should be added.\n */\n paytoUri: string;\n\n /**\n * Human-readable label for the account.\n */\n label: string;\n\n /**\n * Currencies supported by the bank (if known).\n */\n currencies?: string[] | undefined;\n\n /**\n * Bank account that this new account should replace.\n */\n replaceBankAccountId?: string;\n}\n\nexport interface AddBankAccountResponse {\n /**\n * Identifier of the added bank account.\n */\n bankAccountId: string;\n}\n\nexport const codecForAddBankAccountRequest = (): Codec =>\n buildCodecForObject()\n .property(\"replaceBankAccountId\", codecOptional(codecForString()))\n .property(\"paytoUri\", codecForString())\n .property(\"label\", codecForString())\n .property(\"currencies\", codecOptional(codecForList(codecForString())))\n .build(\"AddBankAccountRequest\");\n\nexport interface ForgetBankAccountRequest {\n bankAccountId: string;\n}\n\nexport const codecForForgetBankAccount = (): Codec =>\n buildCodecForObject()\n .property(\"bankAccountId\", codecForString())\n .build(\"ForgetBankAccountsRequest\");\n\nexport interface PreparePayRequest {\n talerPayUri: string;\n}\n\nexport const codecForPreparePayRequest = (): Codec =>\n buildCodecForObject()\n .property(\"talerPayUri\", codecForString())\n .build(\"PreparePay\");\n\nexport interface GetChoicesForPaymentRequest {\n transactionId: string;\n forcedCoinSel?: ForcedCoinSel;\n}\n\nexport const codecForGetChoicesForPaymentRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForString())\n .property(\"forcedCoinSel\", codecForAny())\n .build(\"GetChoicesForPaymentRequest\");\n\nexport enum ChoiceSelectionDetailType {\n PaymentPossible = \"payment-possible\",\n InsufficientBalance = \"insufficient-balance\",\n}\n\nexport type ChoiceSelectionDetail =\n | ChoiceSelectionDetailPaymentPossible\n | ChoiceSelectionDetailInsufficientBalance;\n\nexport interface ChoiceSelectionDetailPaymentPossible {\n status: ChoiceSelectionDetailType.PaymentPossible;\n amountRaw: AmountString;\n amountEffective: AmountString;\n tokenDetails?: PaymentTokenAvailabilityDetails;\n}\n\nexport interface ChoiceSelectionDetailInsufficientBalance {\n status: ChoiceSelectionDetailType.InsufficientBalance;\n amountRaw: AmountString;\n balanceDetails?: PaymentInsufficientBalanceDetails;\n tokenDetails?: PaymentTokenAvailabilityDetails;\n}\n\nexport type GetChoicesForPaymentResult = {\n /**\n * Details for all choices in the contract.\n *\n * The index in this array corresponds to the choice\n * index in the original contract v1. For contract v0\n * orders, it will only contain a single choice with no\n * inputs/outputs.\n */\n choices: ChoiceSelectionDetail[];\n\n /**\n * Index of the choice in @e choices array to present\n * to the user as default.\n *\n * Won\u00B4t be set if no default selection is configured\n * or no choice is payable, otherwise, it will always\n * be 0 for v0 orders.\n */\n defaultChoiceIndex?: number;\n\n /**\n * Whether the choice referenced by @e automaticExecutableIndex\n * should be confirmed automatically without\n * user interaction.\n *\n * If true, the wallet should call `confirmPay'\n * immediately afterwards, if false, the user\n * should be first prompted to select and\n * confirm a choice. Undefined when no choices\n * are payable.\n */\n automaticExecution?: boolean;\n\n /**\n * Index of the choice that would be set to automatically\n * execute if the choice was payable. When @e automaticExecution\n * is set to true, the payment should be confirmed with this\n * choice index without user interaction.\n */\n automaticExecutableIndex?: number;\n\n /**\n * Data extracted from the contract terms that\n * is relevant for payment processing in the wallet.\n */\n contractTerms: MerchantContractTerms;\n};\n\nexport interface SharePaymentRequest {\n merchantBaseUrl: string;\n orderId: string;\n}\nexport const codecForSharePaymentRequest = (): Codec =>\n buildCodecForObject()\n .property(\"merchantBaseUrl\", codecForCanonBaseUrl())\n .property(\"orderId\", codecForString())\n .build(\"SharePaymentRequest\");\n\nexport interface SharePaymentResult {\n privatePayUri: string;\n}\nexport const codecForSharePaymentResult = (): Codec =>\n buildCodecForObject()\n .property(\"privatePayUri\", codecForString())\n .build(\"SharePaymentResult\");\n\nexport interface CheckPayTemplateRequest {\n talerPayTemplateUri: string;\n}\n\nexport type CheckPayTemplateReponse = {\n templateDetails: WalletTemplateDetailsResponse;\n supportedCurrencies: string[];\n};\n\nexport const codecForCheckPayTemplateRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"talerPayTemplateUri\", codecForString())\n .build(\"CheckPayTemplateRequest\");\n\nexport interface PreparePayTemplateRequest {\n talerPayTemplateUri: string;\n templateParams?: TemplateParams;\n}\n\nexport const codecForPreparePayTemplateRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"talerPayTemplateUri\", codecForString())\n .property(\"templateParams\", codecForAny())\n .build(\"PreparePayTemplate\");\n\nexport interface ConfirmPayRequest {\n transactionId: TransactionIdStr;\n useDonau?: boolean;\n sessionId?: string;\n forcedCoinSel?: ForcedCoinSel;\n\n /**\n * Whether token selection should be forced\n * e.g. use tokens with non-matching `expected_domains'\n *\n * Only applies to v1 orders.\n */\n forcedTokenSel?: boolean;\n\n /**\n * Only applies to v1 orders.\n */\n choiceIndex?: number;\n}\n\nexport const codecForConfirmPayRequest = (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .property(\"sessionId\", codecOptional(codecForString()))\n .property(\"forcedCoinSel\", codecForAny())\n .property(\"forcedTokenSel\", codecOptional(codecForBoolean()))\n .property(\"choiceIndex\", codecOptional(codecForNumber()))\n .property(\"useDonau\", codecOptional(codecForBoolean()))\n .build(\"ConfirmPay\");\n\nexport interface ListDiscountsRequest {\n /**\n * Filter by hash of token issue public key.\n */\n tokenIssuePubHash?: string;\n\n /**\n * Filter by merchant base URL.\n */\n merchantBaseUrl?: string;\n}\n\nexport interface ListDiscountsResponse {\n discounts: DiscountListDetail[];\n}\n\nexport interface DiscountListDetail {\n /**\n * Hash of token family info.\n */\n tokenFamilyHash: string;\n\n /**\n * Hash of token issue public key.\n */\n tokenIssuePubHash: string;\n\n /**\n * URL of the merchant issuing the token.\n */\n merchantBaseUrl: string;\n\n /**\n * Human-readable name for the token family.\n */\n name: string;\n\n /**\n * Human-readable description for the token family.\n */\n description: string;\n\n /**\n * Optional map from IETF BCP 47 language tags to localized descriptions.\n */\n descriptionI18n: any | undefined;\n\n /**\n * Start time of the token's validity period.\n */\n validityStart: Timestamp;\n\n /**\n * End time of the token's validity period.\n */\n validityEnd: Timestamp;\n\n /**\n * Number of tokens available to use.\n */\n tokensAvailable: number;\n}\n\nexport interface DeleteDiscountRequest {\n /**\n * Hash of token family info.\n */\n tokenFamilyHash: string;\n}\n\nexport type ListSubscriptionsRequest = ListDiscountsRequest;\n\nexport interface ListSubscriptionsResponse {\n subscriptions: SubscriptionListDetail[];\n}\n\nexport type SubscriptionListDetail = Omit<\n DiscountListDetail,\n \"tokensAvailable\"\n>;\n\nexport interface DeleteSubscriptionRequest {\n /**\n * Hash of token family info.\n */\n tokenFamilyHash: string;\n}\n\nexport const codecForListDiscountsRequest = (): Codec =>\n buildCodecForObject()\n .property(\"tokenIssuePubHash\", codecOptional(codecForString()))\n .property(\"merchantBaseUrl\", codecOptional(codecForCanonBaseUrl()))\n .build(\"ListDiscounts\");\n\nexport const codecForDeleteDiscountRequest = (): Codec =>\n buildCodecForObject()\n .property(\"tokenFamilyHash\", codecForString())\n .build(\"DeleteDiscount\");\n\nexport const codecForListSubscriptionsRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"tokenIssuePubHash\", codecOptional(codecForString()))\n .property(\"merchantBaseUrl\", codecOptional(codecForCanonBaseUrl()))\n .build(\"ListSubscriptions\");\n\nexport const codecForDeleteSubscriptionRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"tokenFamilyHash\", codecForString())\n .build(\"DeleteSubscription\");\n\nexport interface CoreApiRequestEnvelope {\n id: string;\n operation: string;\n args: unknown;\n}\n\nexport type CoreApiResponse = CoreApiResponseSuccess | CoreApiResponseError;\n\nexport type CoreApiMessageEnvelope = CoreApiResponse | CoreApiNotification;\n\nexport interface CoreApiNotification {\n type: \"notification\";\n payload: unknown;\n}\n\nexport interface CoreApiResponseSuccess {\n // To distinguish the message from notifications\n type: \"response\";\n operation: string;\n id: string;\n result: unknown;\n}\n\nexport interface CoreApiResponseError {\n // To distinguish the message from notifications\n type: \"error\";\n operation: string;\n id: string;\n error: TalerErrorDetail;\n}\n\nexport interface WithdrawTestBalanceRequest {\n /**\n * Amount to withdraw.\n */\n amount: AmountString;\n\n /**\n * Corebank API base URL.\n */\n corebankApiBaseUrl: string;\n\n /**\n * Exchange to use for withdrawal.\n */\n exchangeBaseUrl: string;\n\n /**\n * Force the usage of a particular denomination selection.\n *\n * Only useful for testing.\n */\n forcedDenomSel?: ForcedDenomSel;\n\n /**\n * If set to true, treat the account created during\n * the withdrawal as a foreign withdrawal account.\n */\n useForeignAccount?: boolean;\n}\n\n/**\n * Request to the crypto worker to make a sync signature.\n */\nexport interface MakeSyncSignatureRequest {\n accountPriv: string;\n oldHash: string | undefined;\n newHash: string;\n}\n\n/**\n * Planchet for a coin during refresh.\n */\nexport interface RefreshPlanchetInfo {\n /**\n * Public key for the coin.\n */\n coinPub: string;\n\n /**\n * Private key for the coin.\n */\n coinPriv: string;\n\n /**\n * Blinded public key.\n */\n coinEv: CoinEnvelope;\n\n coinEvHash: string;\n\n /**\n * Blinding key used.\n */\n blindingKey: string;\n\n maxAge: number;\n\n ageCommitmentProof?: AgeCommitmentProof;\n}\n\n/**\n * Strategy for loading recovery information.\n */\nexport enum RecoveryMergeStrategy {\n /**\n * Keep the local wallet root key, import and take over providers.\n */\n Ours = \"ours\",\n\n /**\n * Migrate to the wallet root key from the recovery information.\n */\n Theirs = \"theirs\",\n}\n\n/**\n * Load recovery information into the wallet.\n */\nexport interface RecoveryLoadRequest {\n recovery: BackupRecovery;\n strategy?: RecoveryMergeStrategy;\n}\n\nexport const codecForWithdrawTestBalance =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"forcedDenomSel\", codecForAny())\n .property(\"corebankApiBaseUrl\", codecForCanonBaseUrl())\n .property(\"useForeignAccount\", codecOptional(codecForBoolean()))\n .build(\"WithdrawTestBalanceRequest\");\n\nexport interface SetCoinSuspendedRequest {\n coinPub: string;\n suspended: boolean;\n}\n\nexport const codecForSetCoinSuspendedRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"coinPub\", codecForString())\n .property(\"suspended\", codecForBoolean())\n .build(\"SetCoinSuspendedRequest\");\n\nexport interface RefreshCoinSpec {\n coinPub: string;\n amount?: AmountString;\n}\n\nexport const codecForRefreshCoinSpec = (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"coinPub\", codecForString())\n .build(\"ForceRefreshRequest\");\n\nexport interface ForceRefreshRequest {\n refreshCoinSpecs: RefreshCoinSpec[];\n}\n\nexport interface ForceRefreshResponse {\n refreshGroupId: string;\n}\n\nexport const codecForForceRefreshRequest = (): Codec =>\n buildCodecForObject()\n .property(\"refreshCoinSpecs\", codecForList(codecForRefreshCoinSpec()))\n .build(\"ForceRefreshRequest\");\n\nexport interface PrepareRefundRequest {\n talerRefundUri: string;\n}\n\nexport interface StartRefundQueryForUriResponse {\n /**\n * Transaction id of the *payment* where the refund query was started.\n */\n transactionId: TransactionIdStr;\n}\n\nexport const codecForPrepareRefundRequest = (): Codec =>\n buildCodecForObject()\n .property(\"talerRefundUri\", codecForString())\n .build(\"PrepareRefundRequest\");\n\nexport interface StartRefundQueryRequest {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForStartRefundQueryRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"StartRefundQueryRequest\");\n\nexport interface FailTransactionRequest {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForFailTransactionRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"FailTransactionRequest\");\n\nexport interface SuspendTransactionRequest {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForSuspendTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"SuspendTransactionRequest\");\n\nexport interface ResumeTransactionRequest {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForResumeTransaction = (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"ResumeTransactionRequest\");\n\nexport interface AbortTransactionRequest {\n transactionId: TransactionIdStr;\n}\n\nexport interface FailTransactionRequest {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForAbortTransaction = (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"AbortTransactionRequest\");\n\nexport interface DepositGroupFees {\n coin: AmountString;\n wire: AmountString;\n refresh: AmountString;\n}\n\nexport interface CreateDepositGroupRequest {\n depositPaytoUri: string;\n\n /**\n * Amount to deposit (effective amount).\n */\n amount: AmountString;\n\n /**\n * Restrict the deposit to a certain scope.\n */\n restrictScope?: ScopeInfo;\n\n /**\n * Use a fixed merchant private key.\n */\n testingFixedPriv?: string;\n\n /**\n * Optional wire deadline for the deposits.\n */\n wireDeadline?: TalerProtocolTimestamp;\n\n /**\n * Pre-allocated transaction ID.\n * Allows clients to easily handle notifications\n * that occur while the operation has been created but\n * before the creation request has returned.\n */\n transactionId?: TransactionIdStr;\n}\n\nexport interface CheckDepositRequest {\n /**\n * Payto URI to identify the (bank) account that the exchange will wire\n * the money to.\n */\n depositPaytoUri: string;\n\n /**\n * Amount that should be deposited.\n *\n * Raw amount, fees will be added on top.\n */\n amount: AmountString;\n\n /**\n * Restrict the deposit to a certain scope.\n */\n restrictScope?: ScopeInfo;\n\n /**\n * ID provided by the client to cancel the request.\n *\n * If the same request is made again with the same clientCancellationId,\n * all previous requests are cancelled.\n *\n * The cancelled request will receive an error response with\n * an error code that indicates the cancellation.\n *\n * The cancellation is best-effort, responses might still arrive.\n */\n clientCancellationId?: string;\n}\n\nexport const codecForCheckDepositRequest = (): Codec =>\n buildCodecForObject()\n .property(\"restrictScope\", codecOptional(codecForScopeInfo()))\n .property(\"amount\", codecForAmountString())\n .property(\"depositPaytoUri\", codecForString())\n .property(\"clientCancellationId\", codecOptional(codecForString()))\n .build(\"CheckDepositRequest\");\n\nexport interface CheckDepositResponse {\n totalDepositCost: AmountString;\n effectiveDepositAmount: AmountString;\n fees: DepositGroupFees;\n\n kycSoftLimit?: AmountString;\n kycHardLimit?: AmountString;\n\n /**\n * Base URL of exchanges that would likely require soft KYC.\n */\n kycExchanges?: string[];\n}\n\nexport const codecForCreateDepositGroupRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"restrictScope\", codecOptional(codecForScopeInfo()))\n .property(\"amount\", codecForAmountString())\n .property(\"depositPaytoUri\", codecForString())\n .property(\"transactionId\", codecOptional(codecForTransactionIdStr()))\n .property(\"testingFixedPriv\", codecOptional(codecForString()))\n .property(\"wireDeadline\", codecOptional(codecForTimestamp))\n .build(\"CreateDepositGroupRequest\");\n\n/**\n * Response to a createDepositGroup request.\n */\nexport interface CreateDepositGroupResponse {\n /**\n * Transaction ID of the newly created deposit transaction.\n */\n transactionId: TransactionIdStr;\n\n /**\n * Current state of the new deposit transaction.\n * Returned as a performance optimization, so that the UI\n * doesn't have to do a separate getTransactionById.\n */\n txState: TransactionState;\n\n /**\n * @deprecated 2025-06-03, use transactionId instead.\n */\n depositGroupId: string;\n}\n\nexport interface TxIdResponse {\n transactionId: TransactionIdStr;\n}\n\nexport interface WithdrawUriInfoResponse {\n operationId: string;\n status: WithdrawalOperationStatusFlag;\n confirmTransferUrl?: string;\n currency: string;\n amount: AmountString | undefined;\n\n /**\n * Set to true if the user is allowed to edit the amount.\n *\n * Note that even with a non-editable amount, the amount\n * might be undefined at the beginning of the withdrawal\n * process.\n */\n editableAmount: boolean;\n maxAmount: AmountString | undefined;\n wireFee: AmountString | undefined;\n defaultExchangeBaseUrl?: string;\n editableExchange: boolean;\n possibleExchanges: ExchangeListItem[];\n}\n\nexport interface WalletCurrencyInfo {\n trustedAuditors: {\n currency: string;\n auditorPub: string;\n auditorBaseUrl: string;\n }[];\n trustedExchanges: {\n currency: string;\n exchangeMasterPub: string;\n exchangeBaseUrl: string;\n }[];\n}\n\nexport interface TestingListTasksForTransactionRequest {\n transactionId: TransactionIdStr;\n}\n\nexport interface TestingListTasksForTransactionsResponse {\n taskIdList: string[];\n}\n\nexport const codecForTestingListTasksForTransactionRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"TestingListTasksForTransactionRequest\");\n\nexport interface DeleteTransactionRequest {\n transactionId: TransactionIdStr;\n}\n\nexport interface RetryTransactionRequest {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForDeleteTransactionRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"DeleteTransactionRequest\");\n\nexport const codecForRetryTransactionRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"RetryTransactionRequest\");\n\nexport interface WithdrawFakebankRequest {\n amount: AmountString;\n exchange: string;\n bank: string;\n}\n\nexport const codecForWithdrawFakebankRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"bank\", codecForString())\n .property(\"exchange\", codecForString())\n .build(\"WithdrawFakebankRequest\");\n\nexport interface ActiveTask {\n taskId: string;\n transaction: TransactionIdStr | undefined;\n firstTry: AbsoluteTime | undefined;\n nextTry: AbsoluteTime | undefined;\n retryCounter: number | undefined;\n lastError: TalerErrorDetail | undefined;\n}\n\nexport interface GetActiveTasksResponse {\n tasks: ActiveTask[];\n}\n\nexport const codecForActiveTask = (): Codec =>\n buildCodecForObject()\n .property(\"taskId\", codecForString())\n .property(\"transaction\", codecOptional(codecForTransactionIdStr()))\n .property(\"retryCounter\", codecOptional(codecForNumber()))\n .property(\"firstTry\", codecOptional(codecForAbsoluteTime))\n .property(\"nextTry\", codecOptional(codecForAbsoluteTime))\n .property(\"lastError\", codecOptional(codecForTalerErrorDetail()))\n .build(\"ActiveTask\");\n\nexport const codecForGetActiveTasks = (): Codec =>\n buildCodecForObject()\n .property(\"tasks\", codecForList(codecForActiveTask()))\n .build(\"GetActiveTasks\");\n\nexport interface ImportDbRequest {\n dump: any;\n}\n\nexport const codecForImportDbRequest = (): Codec =>\n buildCodecForObject()\n .property(\"dump\", codecForAny())\n .build(\"ImportDbRequest\");\n\nexport interface ForcedDenomSel {\n denoms: {\n value: AmountString;\n count: number;\n }[];\n}\n\n/**\n * Forced coin selection for deposits/payments.\n */\nexport interface ForcedCoinSel {\n coins: {\n value: AmountString;\n contribution: AmountString;\n }[];\n}\n\nexport interface TestPayResult {\n /**\n * Number of coins used for the payment.\n */\n numCoins: number;\n}\n\nexport interface SelectedCoin {\n denomPubHash: string;\n coinPub: string;\n contribution: AmountString;\n exchangeBaseUrl: string;\n}\n\nexport interface SelectedProspectiveCoin {\n denomPubHash: string;\n contribution: AmountString;\n exchangeBaseUrl: string;\n}\n\n/**\n * Result of selecting coins, contains the exchange, and selected\n * coins with their denomination.\n */\nexport interface PayCoinSelection {\n coins: SelectedCoin[];\n\n /**\n * How much of the wire fees is the customer paying?\n */\n customerWireFees: AmountString;\n\n /**\n * How much of the deposit fees is the customer paying?\n */\n customerDepositFees: AmountString;\n\n /**\n * How much of the deposit fees does the exchange charge in total?\n */\n totalDepositFees: AmountString;\n}\n\nexport interface ProspectivePayCoinSelection {\n prospectiveCoins: SelectedProspectiveCoin[];\n\n /**\n * How much of the wire fees is the customer paying?\n */\n customerWireFees: AmountString;\n\n /**\n * How much of the deposit fees is the customer paying?\n */\n customerDepositFees: AmountString;\n}\n\nexport interface CheckPeerPushDebitRequest {\n /**\n * Preferred exchange to use for the p2p payment.\n */\n exchangeBaseUrl?: string;\n\n /**\n * Instructed amount.\n *\n * FIXME: Allow specifying the instructed amount type.\n */\n amount: AmountString;\n\n /**\n * Restrict the scope of funds that can be spent via the given\n * scope info.\n */\n restrictScope?: ScopeInfo;\n\n /**\n * ID provided by the client to cancel the request.\n *\n * If the same request is made again with the same clientCancellationId,\n * all previous requests are cancelled.\n *\n * The cancelled request will receive an error response with\n * an error code that indicates the cancellation.\n *\n * The cancellation is best-effort, responses might still arrive.\n */\n clientCancellationId?: string;\n}\n\nexport const codecForCheckPeerPushDebitRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecOptional(codecForCanonBaseUrl()))\n .property(\"restrictScope\", codecOptional(codecForScopeInfo()))\n .property(\"amount\", codecForAmountString())\n .property(\"clientCancellationId\", codecOptional(codecForString()))\n .build(\"CheckPeerPushDebitRequest\");\n\nexport type CheckPeerPushDebitResponse =\n | CheckPeerPushDebitOkResponse\n | CheckPeerPushDebitInsufficientBalanceResponse;\n\nexport interface CheckPeerPushDebitInsufficientBalanceResponse {\n type: \"insufficient-balance\";\n\n insufficientBalanceDetails: PaymentInsufficientBalanceDetails;\n}\n\nexport interface CheckPeerPushDebitOkResponse {\n type: \"ok\";\n\n amountRaw: AmountString;\n\n amountEffective: AmountString;\n\n /**\n * Exchange base URL.\n */\n exchangeBaseUrl: string;\n\n /**\n * Maximum expiration date, based on how close the coins\n * used for the payment are to expiry.\n *\n * The value is based on when the wallet would typically\n * automatically refresh the coins on its own, leaving enough\n * time to get a refund for the push payment and refresh the\n * coin.\n */\n maxExpirationDate: TalerProtocolTimestamp;\n}\n\nexport interface InitiatePeerPushDebitRequest {\n exchangeBaseUrl?: string;\n\n /**\n * Restrict the scope of funds that can be spent via the given\n * scope info.\n */\n restrictScope?: ScopeInfo;\n\n partialContractTerms: PeerContractTerms;\n}\n\nexport interface InitiatePeerPushDebitResponse {\n exchangeBaseUrl: string;\n pursePub: string;\n mergePriv: string;\n contractPriv: string;\n transactionId: TransactionIdStr;\n}\n\nexport const codecForInitiatePeerPushDebitRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"partialContractTerms\", codecForPeerContractTerms())\n .property(\"exchangeBaseUrl\", codecOptional(codecForCanonBaseUrl()))\n .property(\"restrictScope\", codecOptional(codecForScopeInfo()))\n .build(\"InitiatePeerPushDebitRequest\");\n\n/**\n * Result of initiating a peer-push-credit payment.\n *\n * Either {@link talerUri} or {@link transactionId} must be specified.\n */\nexport interface PreparePeerPushCreditRequest {\n talerUri?: string;\n transactionId?: string;\n}\n\n/**\n * Result of initiating a peer-pull-debit payment.\n *\n * Either {@link talerUri} or {@link transactionId} must be specified.\n */\nexport interface PreparePeerPullDebitRequest {\n talerUri?: string;\n transactionId?: string;\n}\n\nexport interface PreparePeerPushCreditResponse {\n contractTerms: PeerContractTerms;\n amountRaw: AmountString;\n amountEffective: AmountString;\n\n transactionId: TransactionIdStr;\n\n /**\n * State of the existing or newly created transaction.\n */\n txState: TransactionState;\n\n exchangeBaseUrl: string;\n\n scopeInfo: ScopeInfo;\n\n /**\n * @deprecated\n */\n amount: AmountString;\n}\n\nexport interface PreparePeerPullDebitResponse {\n contractTerms: PeerContractTerms;\n\n amountRaw: AmountString;\n amountEffective: AmountString;\n\n transactionId: TransactionIdStr;\n\n /**\n * State of the existing or newly created transaction.\n */\n txState: TransactionState;\n\n exchangeBaseUrl: string;\n\n scopeInfo: ScopeInfo;\n\n /**\n * @deprecated Redundant field with bad name, will be removed soon.\n */\n amount: AmountString;\n}\n\nexport const codecForPreparePeerPushCreditRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"talerUri\", codecOptional(codecForString()))\n .property(\"transactionId\", codecOptional(codecForString()))\n .build(\"CheckPeerPushPaymentRequest\");\n\nexport const codecForCheckPeerPullPaymentRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"talerUri\", codecOptional(codecForString()))\n .property(\"transactionId\", codecOptional(codecForString()))\n .build(\"PreparePeerPullDebitRequest\");\n\nexport interface ConfirmPeerPushCreditRequest {\n transactionId: string;\n}\nexport interface AcceptPeerPushPaymentResponse {\n transactionId: TransactionIdStr;\n}\n\nexport interface AcceptPeerPullPaymentResponse {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForConfirmPeerPushPaymentRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForString())\n .build(\"ConfirmPeerPushCreditRequest\");\n\nexport interface ConfirmPeerPullDebitRequest {\n transactionId: TransactionIdStr;\n}\n\nexport interface ApplyDevExperimentRequest {\n devExperimentUri: string;\n}\n\nexport const codecForApplyDevExperiment =\n (): Codec =>\n buildCodecForObject()\n .property(\"devExperimentUri\", codecForString())\n .build(\"ApplyDevExperimentRequest\");\n\nexport const codecForAcceptPeerPullPaymentRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"ConfirmPeerPullDebitRequest\");\n\nexport interface CheckPeerPullCreditRequest {\n /**\n * Require using this particular exchange for this operation.\n */\n exchangeBaseUrl?: string;\n\n restrictScope?: ScopeInfo;\n\n amount: AmountString;\n\n /**\n * ID provided by the client to cancel the request.\n *\n * If the same request is made again with the same clientCancellationId,\n * all previous requests are cancelled.\n *\n * The cancelled request will receive an error response with\n * an error code that indicates the cancellation.\n *\n * The cancellation is best-effort, responses might still arrive.\n */\n clientCancellationId?: string;\n}\n\nexport const codecForPreparePeerPullPaymentRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"exchangeBaseUrl\", codecOptional(codecForCanonBaseUrl()))\n .property(\"restrictScope\", codecOptional(codecForScopeInfo()))\n .property(\"clientCancellationId\", codecOptional(codecForString()))\n .build(\"CheckPeerPullCreditRequest\");\n\nexport interface CheckPeerPullCreditResponse {\n exchangeBaseUrl: string;\n amountRaw: AmountString;\n amountEffective: AmountString;\n\n /**\n * Number of coins that will be used,\n * can be used by the UI to warn if excessively large.\n */\n numCoins: number;\n}\n\nexport interface InitiatePeerPullCreditRequest {\n exchangeBaseUrl?: string;\n partialContractTerms: PeerContractTerms;\n}\n\nexport const codecForInitiatePeerPullPaymentRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"partialContractTerms\", codecForPeerContractTerms())\n .property(\"exchangeBaseUrl\", codecOptional(codecForCanonBaseUrl()))\n .build(\"InitiatePeerPullCreditRequest\");\n\nexport interface InitiatePeerPullCreditResponse {\n /**\n * Taler URI for the other party to make the payment\n * that was requested.\n *\n * @deprecated since it's not necessarily valid yet until the tx is in the right state\n */\n talerUri: string;\n\n transactionId: TransactionIdStr;\n}\n\nexport interface CanonicalizeBaseUrlRequest {\n url: string;\n}\n\nexport const codecForCanonicalizeBaseUrlRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"url\", codecForString())\n .build(\"CanonicalizeBaseUrlRequest\");\n\nexport interface CanonicalizeBaseUrlResponse {\n url: string;\n}\n\nexport interface ValidateIbanRequest {\n iban: string;\n}\n\nexport const codecForValidateIbanRequest = (): Codec =>\n buildCodecForObject()\n .property(\"iban\", codecForString())\n .build(\"ValidateIbanRequest\");\n\nexport interface ValidateIbanResponse {\n valid: boolean;\n}\n\nexport const codecForValidateIbanResponse = (): Codec =>\n buildCodecForObject()\n .property(\"valid\", codecForBoolean())\n .build(\"ValidateIbanResponse\");\n\nexport type TransactionStateFilter = \"nonfinal\";\n\nexport interface TransactionRecordFilter {\n onlyState?: TransactionStateFilter;\n onlyCurrency?: string;\n}\n\nexport interface StoredBackupList {\n storedBackups: {\n name: string;\n }[];\n}\n\nexport interface CreateStoredBackupResponse {\n name: string;\n}\n\nexport interface RecoverStoredBackupRequest {\n name: string;\n}\n\nexport interface DeleteStoredBackupRequest {\n name: string;\n}\n\nexport const codecForDeleteStoredBackupRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .build(\"DeleteStoredBackupRequest\");\n\nexport const codecForRecoverStoredBackupRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .build(\"RecoverStoredBackupRequest\");\n\nexport interface TestingSetTimetravelRequest {\n offsetMs: number;\n}\n\nexport const codecForTestingSetTimetravelRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"offsetMs\", codecForNumber())\n .build(\"TestingSetTimetravelRequest\");\n\nexport interface AllowedAuditorInfo {\n auditorBaseUrl: string;\n auditorPub: string;\n}\n\nexport interface AllowedExchangeInfo {\n exchangeBaseUrl: string;\n exchangePub: string;\n}\n\n/**\n * Data extracted from the contract terms that is relevant for payment\n * processing in the wallet.\n */\nexport interface DownloadedContractData {\n contractTermsRaw: any;\n contractTerms: MerchantContractTerms;\n contractTermsHash: HashCode;\n}\n\nexport type PayWalletData = {\n choice_index?: number;\n tokens_evs: TokenEnvelope[];\n\n // Request for donation receipts to be issued.\n // @since protocol **v21**\n donau?: DonationRequestData;\n};\n\nexport interface DonationRequestData {\n // Base URL of the selected Donau\n url: string;\n\n // Year for which the donation receipts are expected.\n // Also determines which keys are used to sign the\n // blinded donation receipts.\n year: number;\n\n // Array of blinded donation receipts to sign.\n // Must NOT be empty (if no donation receipts\n // are desired, just leave the entire donau\n // argument blank).\n budikeypairs: BlindedDonationReceiptKeyPair[];\n}\n\nexport interface TestingWaitExchangeStateRequest {\n exchangeBaseUrl: string;\n walletKycStatus?: ExchangeWalletKycStatus;\n}\n\nexport interface TransactionStatePattern {\n major: TransactionMajorState | TransactionStateWildcard;\n minor?: TransactionMinorState | TransactionStateWildcard;\n}\n\nexport interface TestingWaitTransactionRequest {\n transactionId: TransactionIdStr;\n\n /**\n * Additional identifier that is used in the logs\n * to easily find the status of the particular wait\n * request.\n */\n logId?: string;\n\n /**\n * After the timeout has passed, give up on\n * waiting for the desired state and raise\n * an error instead.\n */\n timeout?: DurationUnitSpec;\n\n /**\n * If set to true, wait until the desired state\n * is reached with an error.\n */\n requireError?: boolean;\n\n txState: TransactionStatePattern | TransactionStatePattern[] | number;\n}\n\nexport interface TestingGetReserveHistoryRequest {\n reservePub: string;\n exchangeBaseUrl: string;\n}\n\nexport const codecForTestingGetReserveHistoryRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"reservePub\", codecForString())\n .property(\"exchangeBaseUrl\", codecForString())\n .build(\"TestingGetReserveHistoryRequest\");\n\nexport interface TestingGetDenomStatsRequest {\n exchangeBaseUrl: string;\n}\n\nexport interface TestingGetDenomStatsResponse {\n numKnown: number;\n numOffered: number;\n numLost: number;\n}\n\nexport interface TestingGetDiagnosticsResponse {\n version: 0;\n /**\n * Statistics about the size of object stores.\n */\n idbObjectStoreCounts?: Record;\n exchangeEntries: {\n exchangeBaseUrl: string;\n numDenoms: number;\n numWithdrawableDenoms: number;\n numCandidateWithdrawableDenoms: number;\n }[];\n}\n\nexport interface TestingGetFlightRecordsResponse {\n flightRecords: FlightRecordEntry[];\n}\n\nexport const codecForTestingGetDenomStatsRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .build(\"TestingGetDenomStatsRequest\");\n\nexport interface RunFixupRequest {\n id: string;\n}\n\nexport const codecForRunFixupRequest = (): Codec =>\n buildCodecForObject()\n .property(\"id\", codecForString())\n .build(\"RunFixupRequest\");\n\nexport interface WithdrawalExchangeAccountDetails {\n /**\n * Payto URI to credit the exchange.\n *\n * Depending on whether the (manual!) withdrawal is accepted or just\n * being checked, this already includes the subject with the\n * reserve public key.\n */\n paytoUri: string;\n\n /**\n * Status that indicates whether the account can be used\n * by the user to send funds for a withdrawal.\n *\n * ok: account should be shown to the user\n * error: account should not be shown to the user, UIs might render the error (in conversionError),\n * especially in dev mode.\n */\n status: \"ok\" | \"error\";\n\n /**\n * Transfer amount. Might be in a different currency than the requested\n * amount for withdrawal.\n *\n * Absent if this is a conversion account and the conversion failed.\n */\n transferAmount?: AmountString;\n\n /**\n * Currency specification for the external currency.\n *\n * Only included if this account requires a currency conversion.\n */\n currencySpecification?: CurrencySpecification;\n\n /**\n * Further restrictions for sending money to the\n * exchange.\n */\n creditRestrictions?: AccountRestriction[];\n\n /**\n * Label given to the account or the account's bank by the exchange.\n */\n bankLabel?: string;\n\n /*\n * Display priority assigned to this bank account by the exchange.\n */\n priority?: number;\n\n /**\n * Error that happened when attempting to request the conversion rate.\n */\n conversionError?: TalerErrorDetail;\n}\n\nexport interface PrepareWithdrawExchangeRequest {\n /**\n * A taler://withdraw-exchange URI.\n */\n talerUri: string;\n}\n\nexport const codecForPrepareWithdrawExchangeRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"talerUri\", codecForString())\n .build(\"PrepareWithdrawExchangeRequest\");\n\nexport interface PrepareWithdrawExchangeResponse {\n /**\n * Base URL of the exchange that already existed\n * or was ephemerally added as an exchange entry to\n * the wallet.\n */\n exchangeBaseUrl: string;\n\n /**\n * Amount from the taler://withdraw-exchange URI.\n * Only present if specified in the URI.\n */\n amount?: AmountString;\n}\n\nexport interface ExchangeEntryState {\n tosStatus: ExchangeTosStatus;\n exchangeEntryStatus: ExchangeEntryStatus;\n exchangeUpdateStatus: ExchangeUpdateStatus;\n}\n\nexport interface ListGlobalCurrencyAuditorsResponse {\n auditors: {\n currency: string;\n auditorBaseUrl: string;\n auditorPub: string;\n }[];\n}\n\nexport interface ListGlobalCurrencyExchangesResponse {\n exchanges: {\n currency: string;\n exchangeBaseUrl: string;\n exchangeMasterPub: string;\n }[];\n}\n\nexport interface AddGlobalCurrencyExchangeRequest {\n currency: string;\n exchangeBaseUrl: string;\n exchangeMasterPub: string;\n}\n\nexport const codecForAddGlobalCurrencyExchangeRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"exchangeMasterPub\", codecForString())\n .build(\"AddGlobalCurrencyExchangeRequest\");\n\nexport interface RemoveGlobalCurrencyExchangeRequest {\n currency: string;\n exchangeBaseUrl: string;\n exchangeMasterPub: string;\n}\n\nexport const codecForRemoveGlobalCurrencyExchangeRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"exchangeBaseUrl\", codecForCanonBaseUrl())\n .property(\"exchangeMasterPub\", codecForString())\n .build(\"RemoveGlobalCurrencyExchangeRequest\");\n\nexport interface AddGlobalCurrencyAuditorRequest {\n currency: string;\n auditorBaseUrl: string;\n auditorPub: string;\n}\n\nexport const codecForAddGlobalCurrencyAuditorRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"auditorBaseUrl\", codecForCanonBaseUrl())\n .property(\"auditorPub\", codecForString())\n .build(\"AddGlobalCurrencyAuditorRequest\");\n\nexport interface RemoveGlobalCurrencyAuditorRequest {\n currency: string;\n auditorBaseUrl: string;\n auditorPub: string;\n}\n\nexport const codecForRemoveGlobalCurrencyAuditorRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"auditorBaseUrl\", codecForCanonBaseUrl())\n .property(\"auditorPub\", codecForString())\n .build(\"RemoveGlobalCurrencyAuditorRequest\");\n\nexport interface HintNetworkAvailabilityRequest {\n isNetworkAvailable: boolean;\n}\n\nexport const codecForHintNetworkAvailabilityRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"isNetworkAvailable\", codecForBoolean())\n .build(\"HintNetworkAvailabilityRequest\");\n\nexport interface GetDepositWireTypesRequest {\n currency?: string;\n /**\n * Optional scope info to further restrict the result.\n * Currency must match the currency field.\n */\n scopeInfo?: ScopeInfo;\n}\n\nexport const codecForGetDepositWireTypesRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecOptional(codecForString()))\n .property(\"scopeInfo\", codecOptional(codecForScopeInfo()))\n .build(\"GetDepositWireTypesRequest\");\n\nexport interface GetDepositWireTypesResponse {\n /**\n * Details for each wire type.\n */\n wireTypeDetails: WireTypeDetails[];\n}\n\nexport interface GetDepositWireTypesForCurrencyRequest {\n currency: string;\n /**\n * Optional scope info to further restrict the result.\n * Currency must match the currency field.\n */\n scopeInfo?: ScopeInfo;\n}\n\nexport const codecForGetDepositWireTypesForCurrencyRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"scopeInfo\", codecOptional(codecForScopeInfo()))\n .build(\"GetDepositWireTypesForCurrencyRequest\");\n\n/**\n * Response with wire types that are supported for a deposit.\n *\n * In the future, we might surface more information here, such as debit restrictions\n * by the exchange, which then can be shown by UIs to the user before they\n * enter their payment information.\n */\nexport interface GetDepositWireTypesForCurrencyResponse {\n /**\n * @deprecated, use wireTypeDetails instead.\n */\n wireTypes: string[];\n\n /**\n * Details for each wire type.\n */\n wireTypeDetails: WireTypeDetails[];\n}\n\nexport interface WireTypeDetails {\n paymentTargetType: string;\n\n /**\n * Only applicable for payment target type IBAN.\n *\n * Specifies whether the user wants to preferably\n * enter their bank account details as an IBAN\n * or as a BBAN.\n *\n * Mandatory for paymentTargetType=\"iban\".\n */\n preferredEntryType?: \"iban\" | \"bban\";\n\n /**\n * Allowed hostnames for the deposit payto URI.\n * Only applicable to x-taler-bank.\n */\n talerBankHostnames?: string[];\n}\n\nexport interface GetQrCodesForPaytoRequest {\n paytoUri: string;\n}\n\nexport const codecForGetQrCodesForPaytoRequest = () =>\n buildCodecForObject()\n .property(\"paytoUri\", codecForString())\n .build(\"GetQrCodesForPaytoRequest\");\n\nexport interface GetQrCodesForPaytoResponse {\n codes: QrCodeSpec[];\n}\n\nexport interface GetBankingChoicesForPaytoRequest {\n paytoUri: string;\n}\n\nexport const codecForGetBankingChoicesForPaytoRequest = () =>\n buildCodecForObject()\n .property(\"paytoUri\", codecForString())\n .build(\"GetBankingChoicesForPaytoRequest\");\n\nexport interface ConvertIbanAccountFieldToPaytoRequest {\n value: string;\n currency: string;\n}\n\nexport const codecForConvertIbanAccountFieldToPaytoRequest = () =>\n buildCodecForObject()\n .property(\"value\", codecForString())\n .property(\"currency\", codecForString())\n .build(\"ConvertIbanAccountFieldToPaytoRequest\");\n\nexport interface ConvertIbanPaytoToAccountFieldRequest {\n paytoUri: string;\n}\n\nexport const codecForConvertIbanPaytoToAccountFieldRequest = () =>\n buildCodecForObject()\n .property(\"paytoUri\", codecForString())\n .build(\"ConvertIbanPaytoToAccountFieldRequest\");\n\nexport interface ConvertIbanPaytoToAccountFieldResponse {\n type: \"iban\" | \"bban\";\n value: string;\n}\n\nexport type ConvertIbanAccountFieldToPaytoResponse =\n | { ok: true; type: \"iban\" | \"bban\"; paytoUri: string }\n | { ok: false };\n\nexport interface BankingChoiceSpec {\n label: string;\n // FIXME: In the future, we might also have some way to return intents here?\n type: \"link\";\n uri: string;\n}\n\nexport interface GetBankingChoicesForPaytoResponse {\n choices: BankingChoiceSpec[];\n}\n\nexport interface GetPerformanceStatsRequest {\n /**\n * Limit to N largest average performance stats of each table.\n *\n * When undefined, all performance stats will be returned.\n */\n limit?: number;\n}\n\nexport const codecForGetPerformanceStatsRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"limit\", codecOptional(codecForNumber()))\n .build(\"GetPerformanceStatsRequest\");\n\nexport interface GetPerformanceStatsResponse {\n stats: PerformanceTable;\n}\n\nexport type EmptyObject = Record;\n\nexport const codecForEmptyObject = (): Codec =>\n buildCodecForObject().build(\"EmptyObject\");\n\nexport interface TestingWaitWalletKycRequest {\n exchangeBaseUrl: string;\n amount: AmountString;\n /**\n * Do we wait for the KYC to be passed (true),\n * or do we already return if legitimization is\n * required (false).\n */\n passed: boolean;\n}\n\nexport const codecForTestingWaitWalletKycRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForString())\n .property(\"amount\", codecForAmountString())\n .property(\"passed\", codecForBoolean())\n .build(\"TestingWaitWalletKycRequest\");\n\nexport interface TestingPlanMigrateExchangeBaseUrlRequest {\n oldExchangeBaseUrl: string;\n newExchangeBaseUrl: string;\n}\n\nexport const codecForTestingPlanMigrateExchangeBaseUrlRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"oldExchangeBaseUrl\", codecForString())\n .property(\"newExchangeBaseUrl\", codecForString())\n .build(\"TestingMigrateExchangeBaseUrlRequest\");\n\nexport interface StartExchangeWalletKycRequest {\n exchangeBaseUrl: string;\n amount: AmountString;\n}\n\nexport const codecForStartExchangeWalletKycRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchangeBaseUrl\", codecForString())\n .property(\"amount\", codecForAmountString())\n .build(\"StartExchangeWalletKycRequest\");\n\nexport interface ExportDbToFileRequest {\n /**\n * Directory that the DB should be exported into.\n */\n directory: string;\n\n /**\n * Stem of the exported DB filename.\n *\n * The final name will be ${directory}/${stem}.${extension},\n * where the extension depends on the used DB backend.\n */\n stem: string;\n\n /**\n * Force the format of the export.\n *\n * Currently only \"json\" is supported as a forced\n * export format.\n */\n forceFormat?: string;\n}\n\nexport const codecForExportDbToFileRequest = (): Codec =>\n buildCodecForObject()\n .property(\"directory\", codecForString())\n .property(\"stem\", codecForString())\n .property(\"forceFormat\", codecOptional(codecForString()))\n .build(\"ExportDbToFileRequest\");\n\nexport interface ExportDbToFileResponse {\n /**\n * Full path to the backup.\n */\n path: string;\n}\n\nexport interface ImportDbFromFileRequest {\n /**\n * Full path to the backup.\n */\n path: string;\n}\n\nexport const codecForImportDbFromFileRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"path\", codecForString())\n .build(\"ImportDbFromFileRequest\");\n\nexport interface CompleteBaseUrlRequest {\n url: string;\n}\n\nexport const codecForCompleteBaseUrlRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"url\", codecForString())\n .build(\"CompleteBaseUrlRequest\");\n\nexport type CompleteBaseUrlResult =\n | {\n /**\n * ok: completion is a proper exchange\n */\n status: \"ok\";\n /** Completed exchange base URL, if completion was possible */\n completion: string;\n }\n | {\n /**\n * bad-syntax: url is so badly malformed, it can't be completed\n * bad-network: syntax okay, but exchange can't be reached\n * bad-exchange: syntax and network okay, but not talking to an exchange\n */\n status: \"bad-syntax\" | \"bad-network\" | \"bad-exchange\";\n /** Error details in case status is not \"ok\" */\n error: TalerErrorDetail;\n };\n\nexport interface SetDonauRequest {\n donauBaseUrl: string;\n taxPayerId: string;\n}\n\nexport const codecForSetDonauRequest = (): Codec =>\n buildCodecForObject()\n .property(\"donauBaseUrl\", codecForString())\n .property(\"taxPayerId\", codecForString())\n .build(\"SetDonauRequest\");\n\nexport interface DonauStatementItem {\n total: AmountString;\n year: number;\n legalDomain: string;\n uri: string;\n donationStatementSig: EddsaSignatureString;\n donauPub: EddsaPublicKeyString;\n}\n\nexport interface GetDonauStatementsRequest {\n donauBaseUrl?: string;\n}\n\nexport interface GetDonauStatementsResponse {\n statements: DonauStatementItem[];\n}\n\nexport interface GetDonauResponse {\n currentDonauInfo:\n | {\n donauBaseUrl: string;\n taxPayerId: string;\n }\n | undefined;\n}\n\nexport const codecForGetDonauStatementsRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"donauBaseUrl\", codecOptional(codecForString()))\n .build(\"GetDonauStatementsRequest\");\n\nexport interface FlightRecordEntry {\n timestamp: TalerPreciseTimestamp;\n target: string;\n event: FlightRecordEvent;\n}\n\nexport enum FlightRecordEvent {\n MeltGone = \"melt-gone\",\n WithdrawalRedenominate = \"withdrawal-redenominate\",\n}\n\nexport interface GetDefaultExchangesResponse {\n defaultExchanges: {\n /**\n * A taler://withdraw-exchange URI for the\n * exchange.\n */\n talerUri: string;\n /**\n * Currency offered by the exchange.\n */\n currency: string;\n /**\n * Currency spec for the currency offered\n * by the exchange.\n */\n currencySpec: CurrencySpecification;\n }[];\n}\n\nexport interface TestingCorruptWithdrawalCoinSelRequest {\n transactionId: TransactionIdStr;\n}\n\nexport const codecForTestingCorruptWithdrawalCoinSelRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForTransactionIdStr())\n .build(\"TestingCorruptWithdrawalCoinSelRequest\");\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n Codec,\n buildCodecForObject,\n codecForAny,\n codecForBoolean,\n codecForList,\n codecForNumber,\n codecForString,\n codecOptional,\n} from \"./codec.js\";\nimport {\n AccessToken,\n AccountLimit,\n CancellationToken,\n DenomKeyType,\n ExchangeWireAccount,\n ObjectCodec,\n PaytoString,\n TalerPreciseTimestamp,\n UnblindedDenominationSignature,\n assertUnreachable,\n buildCodecForUnion,\n codecForAccountLimit,\n codecForConstNumber,\n codecForConstString,\n codecForEither,\n codecForExchangeWireAccount,\n codecForMap,\n codecForPaytoString,\n codecForPreciseTimestamp,\n codecForStringURL,\n codecForTalerUriString,\n codecOptionalDefault,\n} from \"./index.js\";\nimport {\n AbsoluteTime,\n Duration,\n TalerProtocolDuration,\n TalerProtocolTimestamp,\n codecForDuration,\n codecForTimestamp,\n} from \"./time.js\";\nimport {\n AmountString,\n Base32String,\n ClaimToken,\n CoinPublicKey,\n Cs25519Point,\n Cs25519Scalar,\n CurrencySpecification,\n EddsaPublicKey,\n EddsaPublicKeyString,\n EddsaSignatureString,\n HashCode,\n HashCodeString,\n ImageDataUrl,\n Integer,\n InternationalizedString,\n RelativeTime,\n RsaPublicKey,\n RsaSignature,\n Timestamp,\n WireTransferIdentifierRawP,\n codecForAccessToken,\n codecForCurrencySpecificiation,\n codecForEddsaPublicKey,\n codecForEddsaSignature,\n codecForInternationalizedString,\n codecForURLString,\n} from \"./types-taler-common.js\";\nimport { codecForCanonBaseUrl, PayWalletData } from \"./types-taler-wallet.js\";\n\n/**\n * Proposal returned from the contract URL.\n *\n * Doc name: api-merchant/ClaimResponse.\n */\nexport interface MerchantClaimResponse {\n /**\n * Contract terms for the propoal.\n * Raw, un-decoded JSON object.\n */\n contract_terms: any;\n\n /**\n * Signature over contract, made by the merchant. The public key used for signing\n * must be contract_terms.merchant_pub.\n */\n sig: string;\n}\n\nexport type TokenEnvelope = TokenEnvelopeRsa | TokenEnvelopeCs;\n\nexport interface TokenEnvelopeRsa {\n cipher: DenomKeyType.Rsa;\n rsa_blinded_planchet: string;\n}\n\nexport interface TokenEnvelopeCs {\n cipher: DenomKeyType.ClauseSchnorr;\n cs_nonce: string;\n cs_blinded_c0: string; // Crockford base32 encoded\n cs_blinded_c1: string; // Crockford base32 encoded\n}\n\nexport interface SignedTokenEnvelope {\n blind_sig: TokenIssueBlindSig;\n}\n\nexport type TokenIssueBlindSig = RSATokenIssueBlindSig | CSTokenIssueBlindSig;\n\nexport interface RSATokenIssueBlindSig {\n cipher: DenomKeyType.Rsa;\n blinded_rsa_signature: string;\n}\n\nexport interface CSTokenIssueBlindSig {\n cipher: DenomKeyType.ClauseSchnorr;\n b: Integer;\n s: Cs25519Scalar;\n}\n\nexport interface TokenUseSig {\n token_sig: EddsaSignatureString;\n token_pub: EddsaPublicKeyString;\n ub_sig: UnblindedDenominationSignature;\n h_issue: string;\n}\n\nexport interface MerchantPayResponse {\n // Signature on TALER_PaymentResponsePS with the public\n // key of the merchant instance.\n sig: EddsaSignatureString;\n\n // Text to be shown to the point-of-sale staff as a proof of\n // payment.\n pos_confirmation?: string;\n\n // Signed tokens. Returned in the same order as the\n // token envelopes were provided in the request. Specifically,\n // the order will follow the order of the outputs from the\n // contract terms, and then within each output follow the\n // order in which the wallet_data contained the respective\n // blinded envelopes. The donation tokens will be present\n // at the offset matching the place where a donation receipt\n // was indicated in the outputs array, and of course be skipped\n // if the PayWalletData did not have a donau field.\n // @since protocol **v21**\n token_sigs?: SignedTokenEnvelope[];\n}\ninterface MerchantOrderStatusPaid {\n // Was the payment refunded (even partially, via refund or abort)?\n refunded: boolean;\n\n // Is any amount of the refund still waiting to be picked up (even partially)?\n refund_pending: boolean;\n\n // Amount that was refunded in total.\n refund_amount: AmountString;\n\n // Amount that already taken by the wallet.\n refund_taken: AmountString;\n}\n\ninterface MerchantOrderRefundResponse {\n /**\n * Amount that was refunded in total.\n */\n refund_amount: AmountString;\n\n /**\n * Successful refunds for this payment, empty array for none.\n */\n refunds: MerchantCoinRefundStatus[];\n\n /**\n * Public key of the merchant.\n */\n merchant_pub: EddsaPublicKeyString;\n}\n\n/**\n * Response from the internal merchant API.\n */\nexport class CheckPaymentResponse {\n order_status: string;\n refunded: boolean | undefined;\n refunded_amount: string | undefined;\n contract_terms: any | undefined;\n taler_pay_uri: string | undefined;\n contract_url: string | undefined;\n}\n\nexport const codecForMerchantRefundPermission =\n (): Codec =>\n buildCodecForObject()\n .property(\"refund_amount\", codecForAmountString())\n .property(\"refund_fee\", codecForAmountString())\n .property(\"coin_pub\", codecForString())\n .property(\"rtransaction_id\", codecForNumber())\n .property(\"exchange_http_status\", codecForNumber())\n .property(\"exchange_code\", codecOptional(codecForNumber()))\n .property(\"exchange_reply\", codecOptional(codecForAny()))\n .property(\"exchange_sig\", codecOptional(codecForString()))\n .property(\"exchange_pub\", codecOptional(codecForString()))\n .build(\"MerchantRefundPermission\");\n\nexport const codecForMerchantClaimResponse = (): Codec =>\n buildCodecForObject()\n .property(\"contract_terms\", codecForMerchantContractTerms())\n .property(\"sig\", codecForString())\n .build(\"MerchantClaimResponse\");\n\nexport const codecForCheckPaymentResponse = (): Codec =>\n buildCodecForObject()\n .property(\"order_status\", codecForString())\n .property(\"refunded\", codecOptional(codecForBoolean()))\n .property(\"refunded_amount\", codecOptional(codecForString()))\n .property(\"contract_terms\", codecOptional(codecForAny()))\n .property(\"taler_pay_uri\", codecOptional(codecForString()))\n .property(\"contract_url\", codecOptional(codecForString()))\n .build(\"CheckPaymentResponse\");\n\nexport type MerchantCoinRefundStatus =\n | MerchantCoinRefundSuccessStatus\n | MerchantCoinRefundFailureStatus;\n\nexport interface MerchantCoinRefundSuccessStatus {\n type: \"success\";\n\n // HTTP status of the exchange request, 200 (integer) required for refund confirmations.\n exchange_status: 200;\n\n // the EdDSA :ref:signature (binary-only) with purpose\n // TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND using a current signing key of the\n // exchange affirming the successful refund\n exchange_sig: EddsaSignatureString;\n\n // public EdDSA key of the exchange that was used to generate the signature.\n // Should match one of the exchange's signing keys from /keys. It is given\n // explicitly as the client might otherwise be confused by clock skew as to\n // which signing key was used.\n exchange_pub: EddsaPublicKeyString;\n\n // Refund transaction ID.\n rtransaction_id: number;\n\n // public key of a coin that was refunded\n coin_pub: EddsaPublicKeyString;\n\n // Amount that was refunded, including refund fee charged by the exchange\n // to the customer.\n refund_amount: AmountString;\n\n execution_time: TalerProtocolTimestamp;\n}\n\nexport interface MerchantCoinRefundFailureStatus {\n type: \"failure\";\n\n // HTTP status of the exchange request, must NOT be 200.\n exchange_status: number;\n\n // Taler error code from the exchange reply, if available.\n exchange_code?: number;\n\n // If available, HTTP reply from the exchange.\n exchange_reply?: any;\n\n // Refund transaction ID.\n rtransaction_id: number;\n\n // public key of a coin that was refunded\n coin_pub: EddsaPublicKeyString;\n\n // Amount that was refunded, including refund fee charged by the exchange\n // to the customer.\n refund_amount: AmountString;\n\n execution_time: TalerProtocolTimestamp;\n}\n\nexport interface MerchantOrderStatusUnpaid {\n /**\n * URI that the wallet must process to complete the payment.\n */\n taler_pay_uri: string;\n\n /**\n * Alternative order ID which was paid for already in the same session.\n *\n * Only given if the same product was purchased before in the same session.\n */\n already_paid_order_id?: string;\n}\n\nexport const codecForMerchantPayResponse = (): Codec =>\n buildCodecForObject()\n .property(\"sig\", codecForString())\n .property(\"pos_confirmation\", codecOptional(codecForString()))\n .property(\n \"token_sigs\",\n codecOptional(codecForList(codecForSignedTokenEnvelope())),\n )\n .build(\"MerchantPayResponse\");\n\nexport const codecForSignedTokenEnvelope = (): Codec =>\n buildCodecForObject()\n .property(\"blind_sig\", codecForTokenIssueBlindSig())\n .build(\"SignedTokenEnvelope\");\n\nexport const codecForTokenIssueBlindSig = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"cipher\")\n .alternative(DenomKeyType.Rsa, codecForRSATokenIssueBlindSig())\n .alternative(DenomKeyType.ClauseSchnorr, codecForCsTokenIssueBlindSig())\n .build(\"TokenIssueBlindSig\");\n\nexport const codecForRSATokenIssueBlindSig = (): Codec =>\n buildCodecForObject()\n .property(\"cipher\", codecForConstString(DenomKeyType.Rsa))\n .property(\"blinded_rsa_signature\", codecForString())\n .build(\"RSATokenIssueBlindSig\");\n\nexport const codecForCsTokenIssueBlindSig = (): Codec =>\n buildCodecForObject()\n .property(\"cipher\", codecForConstString(DenomKeyType.ClauseSchnorr))\n .property(\"b\", codecForNumber())\n .property(\"s\", codecForString())\n .build(\"CSTokenIssueBlindSig\");\n\nexport const codecForMerchantOrderStatusPaid =\n (): Codec =>\n buildCodecForObject()\n .property(\"refund_amount\", codecForAmountString())\n .property(\"refund_taken\", codecForAmountString())\n .property(\"refund_pending\", codecForBoolean())\n .property(\"refunded\", codecForBoolean())\n .build(\"MerchantOrderStatusPaid\");\n\nexport const codecForMerchantOrderStatusUnpaid =\n (): Codec =>\n buildCodecForObject()\n .property(\"taler_pay_uri\", codecForString())\n .property(\"already_paid_order_id\", codecOptional(codecForString()))\n .build(\"MerchantOrderStatusUnpaid\");\n\nexport interface AbortRequest {\n // hash of the order's contract terms (this is used to authenticate the\n // wallet/customer in case $ORDER_ID is guessable).\n h_contract: string;\n\n // List of coins the wallet would like to see refunds for.\n // (Should be limited to the coins for which the original\n // payment succeeded, as far as the wallet knows.)\n coins: AbortingCoin[];\n}\n\nexport interface AbortingCoin {\n // Public key of a coin for which the wallet is requesting an abort-related refund.\n coin_pub: EddsaPublicKeyString;\n\n // URL of the exchange this coin was withdrawn from.\n exchange_url: string;\n}\n\nexport interface AbortResponse {\n // List of refund responses about the coins that the wallet\n // requested an abort for. In the same order as the 'coins'\n // from the original request.\n // The rtransaction_id is implied to be 0.\n refunds: MerchantAbortPayRefundStatus[];\n}\n\nexport type MerchantAbortPayRefundStatus =\n | MerchantAbortPayRefundSuccessStatus\n | MerchantAbortPayRefundFailureStatus\n | MerchantAbortPayRefundUndepositedStatus;\n\nexport interface MerchantAbortPayRefundUndepositedStatus {\n // Used as tag for the sum type RefundStatus sum type.\n type: \"undeposited\";\n}\n\n// Details about why a refund failed.\nexport interface MerchantAbortPayRefundFailureStatus {\n // Used as tag for the sum type RefundStatus sum type.\n type: \"failure\";\n\n // HTTP status of the exchange request, must NOT be 200.\n exchange_status: number;\n\n // Taler error code from the exchange reply, if available.\n exchange_code?: number;\n\n // If available, HTTP reply from the exchange.\n exchange_reply?: unknown;\n}\n\n// Additional details needed to verify the refund confirmation signature\n// (h_contract_terms and merchant_pub) are already known\n// to the wallet and thus not included.\nexport interface MerchantAbortPayRefundSuccessStatus {\n // Used as tag for the sum type MerchantCoinRefundStatus sum type.\n type: \"success\";\n\n // HTTP status of the exchange request, 200 (integer) required for refund confirmations.\n exchange_status: 200;\n\n // the EdDSA :ref:signature (binary-only) with purpose\n // TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND using a current signing key of the\n // exchange affirming the successful refund\n exchange_sig: string;\n\n // public EdDSA key of the exchange that was used to generate the signature.\n // Should match one of the exchange's signing keys from /keys. It is given\n // explicitly as the client might otherwise be confused by clock skew as to\n // which signing key was used.\n exchange_pub: string;\n}\n\nexport interface AuditorHandle {\n /**\n * Official name of the auditor.\n */\n name: string;\n\n /**\n * Master public signing key of the auditor.\n */\n auditor_pub: EddsaPublicKeyString;\n\n /**\n * Base URL of the auditor.\n */\n url: string;\n}\n\n// Delivery location, loosely modeled as a subset of\n// ISO20022's PostalAddress25.\nexport interface Location {\n // Nation with its own government.\n country?: string;\n\n // Identifies a subdivision of a country such as state, region, county.\n country_subdivision?: string;\n\n // Identifies a subdivision within a country sub-division.\n district?: string;\n\n // Name of a built-up area, with defined boundaries, and a local government.\n town?: string;\n\n // Specific location name within the town.\n town_location?: string;\n\n // Identifier consisting of a group of letters and/or numbers that\n // is added to a postal address to assist the sorting of mail.\n post_code?: string;\n\n // Name of a street or thoroughfare.\n street?: string;\n\n // Name of the building or house.\n building_name?: string;\n\n // Number that identifies the position of a building on a street.\n building_number?: string;\n\n // Free-form address lines, should not exceed 7 elements.\n address_lines?: string[];\n}\n\nexport interface MerchantInfo {\n // The merchant's legal name of business.\n name: string;\n\n // Label for a location with the business address of the merchant.\n email?: string;\n\n // Label for a location with the business address of the merchant.\n website?: string;\n\n // An optional base64-encoded product image.\n logo?: ImageDataUrl;\n\n // Label for a location with the business address of the merchant.\n address?: Location;\n\n // Label for a location that denotes the jurisdiction for disputes.\n // Some of the typical fields for a location (such as a street address) may be absent.\n jurisdiction?: Location;\n}\n\nexport interface Tax {\n // the name of the tax\n name: string;\n\n // amount paid in tax\n tax: AmountString;\n}\n\n// export interface Product {\n// // merchant-internal identifier for the product.\n// product_id?: string;\n\n// // Human-readable product description.\n// description: string;\n\n// // Map from IETF BCP 47 language tags to localized descriptions\n// description_i18n?: InternationalizedString;\n\n// // The number of units of the product to deliver to the customer.\n// quantity?: Integer;\n\n// // The unit in which the product is measured (liters, kilograms, packages, etc.)\n// unit?: string;\n\n// // The price of the product; this is the total price for quantity times unit of this product.\n// price?: AmountString;\n\n// // An optional base64-encoded product image\n// image?: ImageDataUrl;\n\n// // a list of taxes paid by the merchant for this product. Can be empty.\n// taxes?: Tax[];\n\n// // time indicating when this product should be delivered\n// delivery_date?: TalerProtocolTimestamp;\n// }\n\n/**\n * Contract terms from a merchant.\n */\ninterface MerchantContractTermsCommon {\n // The hash of the merchant instance's wire details.\n h_wire: string;\n\n // Specifies for how long the wallet should try to get an\n // automatic refund for the purchase. If this field is\n // present, the wallet should wait for a few seconds after\n // the purchase and then automatically attempt to obtain\n // a refund. The wallet should probe until \"delay\"\n // after the payment was successful (i.e. via long polling\n // or via explicit requests with exponential back-off).\n //\n // In particular, if the wallet is offline\n // at that time, it MUST repeat the request until it gets\n // one response from the merchant after the delay has expired.\n // If the refund is granted, the wallet MUST automatically\n // recover the payment. This is used in case a merchant\n // knows that it might be unable to satisfy the contract and\n // desires for the wallet to attempt to get the refund without any\n // customer interaction. Note that it is NOT an error if the\n // merchant does not grant a refund.\n auto_refund?: TalerProtocolDuration;\n\n // Wire transfer method identifier for the wire method associated with h_wire.\n // The wallet may only select exchanges via a matching auditor if the\n // exchange also supports this wire method.\n // The wire transfer fees must be added based on this wire transfer method.\n wire_method: string;\n\n // Human-readable description of the whole purchase.\n summary: string;\n\n // Map from IETF BCP 47 language tags to localized summaries.\n summary_i18n?: InternationalizedString;\n\n // Unique, free-form identifier for the proposal.\n // Must be unique within a merchant instance.\n // For merchants that do not store proposals in their DB\n // before the customer paid for them, the order_id can be used\n // by the frontend to restore a proposal from the information\n // encoded in it (such as a short product identifier and timestamp).\n order_id: string;\n\n // Nonce generated by the wallet and echoed by the merchant\n // in this field when the proposal is generated.\n nonce: string;\n\n // After this deadline, the merchant won't accept payments for the contract.\n pay_deadline: TalerProtocolTimestamp;\n\n // More info about the merchant, see below.\n merchant: MerchantInfo;\n\n // Merchant's public key used to sign this proposal; this information\n // is typically added by the backend. Note that this can be an ephemeral key.\n merchant_pub: string;\n\n // Time indicating when the order should be delivered.\n // May be overwritten by individual products.\n delivery_date?: TalerProtocolTimestamp;\n\n // Delivery location for (all!) products.\n delivery_location?: Location;\n\n // Exchanges that the merchant accepts even if it does not accept any auditors that audit them.\n exchanges: Exchange[];\n\n // List of products that are part of the purchase (see Product).\n products?: ProductSold[];\n\n // After this deadline has passed, no refunds will be accepted.\n refund_deadline: TalerProtocolTimestamp;\n\n // Transfer deadline for the exchange. Must be in the\n // deposit permissions of coins used to pay for this order.\n wire_transfer_deadline: TalerProtocolTimestamp;\n\n // Time when this contract was generated.\n timestamp: TalerProtocolTimestamp;\n\n // Base URL of the (public!) merchant backend API.\n // Must be an absolute URL that ends with a slash.\n merchant_base_url: string;\n\n // URL that will show that the order was successful after\n // it has been paid for. Optional, but either fulfillment_url\n // or fulfillment_message must be specified in every\n // contract terms.\n //\n // If a non-unique fulfillment URL is used, a customer can only\n // buy the order once and will be redirected to a previous purchase\n // when trying to buy an order with the same fulfillment URL a second\n // time. This is useful for digital goods that a customer only needs\n // to buy once but should be able to repeatedly download.\n //\n // For orders where the customer is expected to be able to make\n // repeated purchases (for equivalent goods), the fulfillment URL\n // should be made unique for every order. The easiest way to do\n // this is to include a unique order ID in the fulfillment URL.\n //\n // When POSTing to the merchant, the placeholder text \"${ORDER_ID}\"\n // is be replaced with the actual order ID (useful if the\n // order ID is generated server-side and needs to be\n // in the URL). Note that this placeholder can only be used once.\n // Front-ends may use other means to generate a unique fulfillment URL.\n fulfillment_url?: string;\n\n // URL where the same contract could be ordered again (if\n // available). Returned also at the public order endpoint\n // for people other than the actual buyer (hence public,\n // in case order IDs are guessable).\n public_reorder_url?: string;\n\n // Message shown to the customer after paying for the order.\n // Either fulfillment_url or fulfillment_message must be specified.\n fulfillment_message?: string;\n\n // Map from IETF BCP 47 language tags to localized fulfillment\n // messages.\n fulfillment_message_i18n?: InternationalizedString;\n\n // Extra data that is only interpreted by the merchant frontend.\n // Useful when the merchant needs to store extra information on a\n // contract without storing it separately in their database.\n // Must really be an Object (not a string, integer, float or array).\n extra?: any;\n\n // Minimum age the buyer must have (in years). Default is 0.\n // This value is at least as large as the maximum over all\n // minimum age requirements of the products in this contract.\n // It might also be set independent of any product, due to\n // legal requirements.\n minimum_age?: Integer;\n\n // Default money pot to use for this product, applies to the\n // amount remaining that was not claimed by money pots of\n // products or taxes. Not useful to wallets, only for\n // merchant-internal accounting. If not given, the remaining\n // account is simply not accounted for in any money pot.\n // Since **v25**.\n default_money_pot?: Integer;\n}\n\nexport enum MerchantContractVersion {\n V0 = 0,\n V1 = 1,\n}\n\nexport interface MerchantContractTermsV0 extends MerchantContractTermsCommon {\n version?: MerchantContractVersion.V0;\n\n // Total price for the transaction.\n // The exchange will subtract deposit fees from that amount\n // before transferring it to the merchant.\n amount: AmountString;\n\n // Maximum total deposit fee accepted by the merchant for this contract.\n // Overrides defaults of the merchant instance.\n max_fee: AmountString;\n}\n\nexport interface MerchantContractTermsV1 extends MerchantContractTermsCommon {\n version: MerchantContractVersion.V1;\n\n // List of contract choices that the customer can select from.\n // @since protocol **vSUBSCRIBE**\n choices: MerchantContractChoice[];\n\n // Map of storing metadata and issue keys of\n // token families referenced in this contract.\n // @since protocol **vSUBSCRIBE**\n token_families: { [token_family_slug: string]: MerchantContractTokenFamily };\n}\n\nexport type MerchantContractTerms =\n | MerchantContractTermsV0\n | MerchantContractTermsV1;\n\nexport interface MerchantContractChoice {\n // Price to be paid for this choice. Could be 0.\n // The price is in addition to other instruments,\n // such as rations and tokens.\n // The exchange will subtract deposit fees from that amount\n // before transferring it to the merchant.\n amount: AmountString;\n\n // Human readable description of the semantics of the choice\n // within the contract to be shown to the user at payment.\n description?: string;\n\n // Map from IETF 47 language tags to localized descriptions.\n description_i18n?: InternationalizedString;\n\n // List of inputs the wallet must provision (all of them) to\n // satisfy the conditions for the contract.\n inputs: MerchantContractInput[];\n\n // List of outputs the merchant promises to yield (all of them)\n // once the contract is paid.\n outputs: MerchantContractOutput[];\n\n // Maximum total deposit fee accepted by the merchant for this contract.\n max_fee: AmountString;\n}\n\nexport enum MerchantContractInputType {\n Token = \"token\",\n}\n\nexport type MerchantContractInput = MerchantContractInputToken;\n\nexport interface MerchantContractInputToken {\n type: MerchantContractInputType.Token;\n\n // Slug of the token family in the\n // token_families map on the order.\n token_family_slug: string;\n\n // Number of tokens of this type required.\n // Defaults to one if the field is not provided.\n count?: Integer;\n}\n\nexport enum MerchantContractOutputType {\n Token = \"token\",\n TaxReceipt = \"tax-receipt\",\n}\n\nexport type MerchantContractOutput =\n | MerchantContractOutputToken\n | MerchantContractOutputTaxReceipt;\n\nexport interface MerchantContractOutputToken {\n type: MerchantContractOutputType.Token;\n\n // Slug of the token family in the\n // 'token_families' map on the top-level.\n token_family_slug: string;\n\n // Number of tokens to be issued.\n // Defaults to one if the field is not provided.\n count?: Integer;\n\n // Index of the public key for this output token\n // in the ContractTokenFamily keys array.\n key_index: Integer;\n}\n\nexport interface MerchantContractOutputTaxReceipt {\n type: MerchantContractOutputType.TaxReceipt;\n\n // Array of base URLs of donation authorities that can be\n // used to issue the tax receipts. The client must select one.\n donau_urls: string[];\n\n // Total amount that will be on the tax receipt.\n // Optional, if missing the full amount will be on the receipt.\n amount?: AmountString;\n}\n\nexport interface MerchantContractTokenFamily {\n // Human readable name of the token family.\n name: string;\n\n // Human-readable description of the semantics of\n // this token family (for display).\n description: string;\n\n // Map from IETF BCP 47 language tags to localized descriptions.\n description_i18n?: { [lang_tag: string]: string };\n\n // Public keys used to validate tokens issued by this token family.\n keys: TokenIssuePublicKey[];\n\n // Kind-specific information of the token\n details: MerchantContractTokenDetails;\n\n // Must a wallet understand this token type to\n // process contracts that use or issue it?\n critical: boolean;\n}\n\nexport type TokenIssuePublicKey =\n | TokenIssueRsaPublicKey\n | TokenIssueCsPublicKey;\n\nexport interface TokenIssueRsaPublicKey {\n cipher: \"RSA\";\n\n // RSA public key.\n rsa_pub: RsaPublicKey;\n\n // Start time of this key's signatures validity period.\n signature_validity_start: Timestamp;\n\n // End time of this key's signatures validity period.\n signature_validity_end: Timestamp;\n}\n\nexport interface TokenIssueCsPublicKey {\n cipher: \"CS\";\n\n // CS public key.\n cs_pub: Cs25519Point;\n\n // Start time of this key's signatures validity period.\n signature_validity_start: Timestamp;\n\n // End time of this key's signatures validity period.\n signature_validity_end: Timestamp;\n}\n\nexport enum MerchantContractTokenKind {\n Subscription = \"subscription\",\n Discount = \"discount\",\n}\n\nexport type MerchantContractTokenDetails =\n | MerchantContractSubscriptionTokenDetails\n | MerchantContractDiscountTokenDetails;\n\nexport interface MerchantContractSubscriptionTokenDetails {\n class: MerchantContractTokenKind.Subscription;\n\n // Array of domain names where this subscription\n // can be safely used (e.g. the issuer warrants that\n // these sites will re-issue tokens of this type\n // if the respective contract says so). May contain\n // \"*\" for any domain or subdomain.\n trusted_domains: string[];\n}\n\nexport interface MerchantContractDiscountTokenDetails {\n class: MerchantContractTokenKind.Discount;\n\n // Array of domain names where this discount token\n // is intended to be used. May contain \"*\" for any\n // domain or subdomain. Users should be warned about\n // sites proposing to consume discount tokens of this\n // type that are not in this list that the merchant\n // is accepting a coupon from a competitor and thus\n // may be attaching different semantics (like get 20%\n // discount for my competitors 30% discount token).\n expected_domains: string[];\n}\n\n/**\n * Refund permission in the format that the merchant gives it to us.\n */\nexport interface MerchantAbortPayRefundDetails {\n /**\n * Amount to be refunded.\n */\n refund_amount: string;\n\n /**\n * Fee for the refund.\n */\n refund_fee: string;\n\n /**\n * Public key of the coin being refunded.\n */\n coin_pub: string;\n\n /**\n * Refund transaction ID between merchant and exchange.\n */\n rtransaction_id: number;\n\n /**\n * Exchange's key used for the signature.\n */\n exchange_pub?: string;\n\n /**\n * Exchange's signature to confirm the refund.\n */\n exchange_sig?: string;\n\n /**\n * Error replay from the exchange (if any).\n */\n exchange_reply?: any;\n\n /**\n * Error code from the exchange (if any).\n */\n exchange_code?: number;\n\n /**\n * HTTP status code of the exchange's response\n * to the merchant's refund request.\n */\n exchange_http_status: number;\n}\n\n/**\n * Reserve signature, defined as separate class to facilitate\n * schema validation.\n */\nexport interface MerchantBlindSigWrapperV1 {\n /**\n * Reserve signature.\n */\n blind_sig: string;\n}\n\nexport const codecForAuditorHandle = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"auditor_pub\", codecForEddsaPublicKey())\n .property(\"url\", codecForString())\n .build(\"AuditorHandle\");\n\nexport const codecForLocation = (): Codec =>\n buildCodecForObject()\n .property(\"country\", codecOptional(codecForString()))\n .property(\"country_subdivision\", codecOptional(codecForString()))\n .property(\"building_name\", codecOptional(codecForString()))\n .property(\"building_number\", codecOptional(codecForString()))\n .property(\"district\", codecOptional(codecForString()))\n .property(\"street\", codecOptional(codecForString()))\n .property(\"post_code\", codecOptional(codecForString()))\n .property(\"town\", codecOptional(codecForString()))\n .property(\"town_location\", codecOptional(codecForString()))\n .property(\"address_lines\", codecOptional(codecForList(codecForString())))\n .build(\"Location\");\n\nexport const codecForMerchantInfo = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"address\", codecOptional(codecForLocation()))\n .property(\"jurisdiction\", codecOptional(codecForLocation()))\n .build(\"MerchantInfo\");\n\nconst codecForMerchantContractTermsCommon =\n (): ObjectCodec =>\n buildCodecForObject()\n .property(\"order_id\", codecForString())\n .property(\"fulfillment_url\", codecOptional(codecForString()))\n .property(\"fulfillment_message\", codecOptional(codecForString()))\n .property(\n \"fulfillment_message_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"public_reorder_url\", codecOptional(codecForString()))\n .property(\"merchant_base_url\", codecForString())\n .property(\"h_wire\", codecForString())\n .property(\"auto_refund\", codecOptional(codecForDuration))\n .property(\"wire_method\", codecForString())\n .property(\"summary\", codecForString())\n .property(\n \"summary_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"nonce\", codecForString())\n .property(\"pay_deadline\", codecForTimestamp)\n .property(\"refund_deadline\", codecForTimestamp)\n .property(\"wire_transfer_deadline\", codecForTimestamp)\n .property(\"timestamp\", codecForTimestamp)\n .property(\"delivery_location\", codecOptional(codecForLocation()))\n .property(\"delivery_date\", codecOptional(codecForTimestamp))\n .property(\"merchant\", codecForMerchantInfo())\n .property(\"merchant_pub\", codecForString())\n .property(\"exchanges\", codecForList(codecForExchange()))\n .property(\"products\", codecOptional(codecForList(codecForProductSold())))\n .property(\"extra\", codecForAny())\n .property(\"minimum_age\", codecOptional(codecForNumber()))\n .property(\"default_money_pot\", codecOptional(codecForNumber()))\n .build(\"TalerMerchantApi.ContractTermsCommon\");\n\nexport const codecForMerchantContractTermsV0 =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"version\",\n codecOptional(codecForConstNumber(MerchantContractVersion.V0)),\n )\n .property(\"amount\", codecForAmountString())\n .property(\"max_fee\", codecForAmountString())\n .mixin(codecForMerchantContractTermsCommon())\n .build(\"TalerMerchantApi.ContractTermsV0\");\n\nexport const codecForMerchantContractTermsV1 =\n (): Codec =>\n buildCodecForObject()\n .property(\"version\", codecForConstNumber(MerchantContractVersion.V1))\n .property(\"choices\", codecForList(codecForMerchantContractChoice()))\n .property(\n \"token_families\",\n codecForMap(codecForMerchantContractTokenFamily()),\n )\n .mixin(codecForMerchantContractTermsCommon())\n .build(\"TalerMerchantApi.ContractTermsV1\");\n\nexport const codecForMerchantContractTerms = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"version\")\n .alternative(undefined, codecForMerchantContractTermsV0())\n .alternative(MerchantContractVersion.V0, codecForMerchantContractTermsV0())\n .alternative(MerchantContractVersion.V1, codecForMerchantContractTermsV1())\n .build(\"TalerMerchantApi.ContractTerms\");\n\nexport const codecForMerchantContractChoice =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"description\", codecOptional(codecForString()))\n .property(\n \"description_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"inputs\", codecForList(codecForMerchantContractInput()))\n .property(\"outputs\", codecForList(codecForMerchantContractOutput()))\n .property(\"max_fee\", codecForAmountString())\n .build(\"TalerMerchantApi.ContractChoice\");\n\nexport const codecForMerchantContractInput = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\n MerchantContractInputType.Token,\n codecForMerchantContractInputToken(),\n )\n .build(\"TalerMerchantApi.ContractInput\");\n\nexport const codecForMerchantContractInputToken =\n (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(MerchantContractInputType.Token))\n .property(\"token_family_slug\", codecForString())\n .property(\"count\", codecOptional(codecForNumber()))\n .build(\"TalerMerchantApi.ContractInputToken\");\n\nexport const codecForMerchantContractOutput =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\n MerchantContractOutputType.Token,\n codecForMerchantContractOutputToken(),\n )\n .alternative(\n MerchantContractOutputType.TaxReceipt,\n codecForMerchantContractOutputTaxReceipt(),\n )\n .build(\"TalerMerchantApi.ContractOutput\");\n\nexport const codecForMerchantContractOutputToken =\n (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(MerchantContractOutputType.Token))\n .property(\"token_family_slug\", codecForString())\n .property(\"count\", codecOptional(codecForNumber()))\n .property(\"key_index\", codecForNumber())\n .build(\"TalerMerchantApi.ContractOutputToken\");\n\nexport const codecForMerchantContractOutputTaxReceipt =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"type\",\n codecForConstString(MerchantContractOutputType.TaxReceipt),\n )\n .property(\"donau_urls\", codecForList(codecForString()))\n .property(\"amount\", codecOptional(codecForAmountString()))\n .build(\"TalerMerchantApi.ContractOutputTaxReceipt\");\n\nexport const codecForMerchantContractTokenFamily =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"description\", codecForString())\n .property(\n \"description_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"keys\", codecForList(codecForTokenIssuePublicKey()))\n .property(\"details\", codecForMerchantContractTokenDetails())\n .property(\"critical\", codecForBoolean())\n .build(\"TalerMerchantApi.ContractTokenFamily\");\n\nexport const codecForTokenIssuePublicKey = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"cipher\")\n .alternative(\"RSA\", codecForTokenIssueRsaPublicKey())\n .alternative(\"CS\", codecForTokenIssueCsPublicKey())\n .build(\"TalerMerchantApi.TokenIssuePublicKey\");\n\nexport const codecForTokenIssueRsaPublicKey =\n (): Codec =>\n buildCodecForObject()\n .property(\"cipher\", codecForConstString(\"RSA\"))\n .property(\"rsa_pub\", codecForString())\n .property(\"signature_validity_start\", codecForTimestamp)\n .property(\"signature_validity_end\", codecForTimestamp)\n .build(\"TalerMerchantApi.TokenIssueRsaPublicKey\");\n\nexport const codecForTokenIssueCsPublicKey = (): Codec =>\n buildCodecForObject()\n .property(\"cipher\", codecForConstString(\"CS\"))\n .property(\"cs_pub\", codecForString())\n .property(\"signature_validity_start\", codecForTimestamp)\n .property(\"signature_validity_end\", codecForTimestamp)\n .build(\"TalerMerchantApi.TokenIssueRsaPublicKey\");\n\nexport const codecForMerchantContractTokenDetails =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"class\")\n .alternative(\n MerchantContractTokenKind.Subscription,\n codecForMerchantContractSubscriptionTokenDetails(),\n )\n .alternative(\n MerchantContractTokenKind.Discount,\n codecForMerchantContractDiscountTokenDetails(),\n )\n .build(\"TalerMerchantApi.ContractTokenDetails\");\n\nexport const codecForMerchantContractSubscriptionTokenDetails =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"class\",\n codecForConstString(MerchantContractTokenKind.Subscription),\n )\n .property(\"trusted_domains\", codecForList(codecForString()))\n .build(\"TalerMerchantApi.ContractSubscriptionTokenDetails\");\n\nexport const codecForMerchantContractDiscountTokenDetails =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"class\",\n codecForConstString(MerchantContractTokenKind.Discount),\n )\n .property(\"expected_domains\", codecForList(codecForString()))\n .build(\"TalerMerchantApi.ContractDiscountTokenDetails\");\n\nexport type MerchantPersona =\n | \"tester\"\n | \"expert\"\n | \"offline-vending-machine\"\n | \"point-of-sale\"\n | \"digital-publishing\"\n | \"e-commerce\";\n\nexport interface MerchantVersionResponse {\n // libtool-style representation of the Merchant protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Name of the protocol.\n name: \"taler-merchant\";\n\n // URN of the implementation (needed to interpret 'revision' in version).\n // @since **v8**, may become mandatory in the future.\n implementation?: string;\n\n // Default (!) currency supported by this backend.\n // This is the currency that the backend should\n // suggest by default to the user when entering\n // amounts. See currencies for a list of\n // supported currencies and how to render them.\n currency: string;\n\n // Which Persona should be used by default by new clients in the SPA.\n // Can be changed locally per browser under \"Personalization\".\n // Possible values include \"expert\", \"offline-vending-machine\",\n // \"point-of-sale\", \"digital-publishing\", \"e-commerce\" and \"developer\".\n // @since **v23**.\n default_persona: MerchantPersona;\n\n // How services should render currencies supported\n // by this backend. Maps\n // currency codes (e.g. \"EUR\" or \"KUDOS\") to\n // the respective currency specification.\n // All currencies in this map are supported by\n // the backend. Note that the actual currency\n // specifications are a *hint* for applications\n // that would like *advice* on how to render amounts.\n // Applications *may* ignore the currency specification\n // if they know how to render currencies that they are\n // used with.\n currencies: { [currency: string]: CurrencySpecification };\n\n // Maps available report generator configuration section names\n // to descriptions of the respective report generator.\n // Since **v25**.\n report_generators: string[];\n\n // Posix regular expression for allowed phone numbers;\n // applies when creating or patching an instance.\n // Optional, can be NULL for no restrictions.\n // Since **v26**.\n phone_regex?: string;\n\n // Array of exchanges trusted by the merchant.\n // Since protocol **v6**.\n exchanges: ExchangeConfigInfo[];\n\n // Set when the merchant supports\n // self-provisioning instances.\n // Since protocol **v21**\n have_self_provisioning?: boolean;\n\n // True if this merchant backend supports the Donau\n // extension and can thus issue donation receipts.\n // Should primarily be used to control the SPA's CRUD\n // functionality for Donau.\n // @since **v21**\n have_donau: boolean;\n\n // Tan channels that are required\n // to be confirmed for an instance to\n // be usable.\n // @since **v21**\n mandatory_tan_channels: TanChannel[];\n\n // Space-separated list of enabled payment target types.\n // Useful if the SPA should not show allow adding other\n // types of bank accounts. \"*\" is used to represent no\n // restriction.\n // @since **v22**\n payment_target_types: string;\n\n // Regular expression representing further restrictions\n // on allowed payment targets. Any \"payto://\"-URI supplied\n // for a bank account must match the given regular expression.\n // For example, \"payto://iban/CH.*\" would restrict the system\n // to only Swiss bank accounts.\n // Optional, no restrictions are imposed if the field is\n // absent.\n // @since **v22**\n // CAUTION: Likely to be removed/deprecated,\n // as we'll want an array of restrictions with the\n // same format as the exchange uses, as this allows\n // proper i18n and spec/code reuse.\n payment_target_regex?: string;\n\n // Default wire transfer delay for new instances.\n // This is the default to use for new instances, see the instance value for\n // the instance-specific default.\n // @since **v22**\n default_wire_transfer_delay?: RelativeTime;\n\n // Default payment delay for new instances.\n // This is the default to use for new instances, see the instance value for\n // the instance-specific default.\n // @since **v22**\n default_pay_delay?: RelativeTime;\n\n // If the frontend does NOT specify a refund deadline, how long should\n // refunds be allowed by default?\n // This is the default to use for new instances, see the instance value for\n // the instance-specific default.\n // @since **v22**\n default_refund_delay?: RelativeTime;\n\n // Default interval to which wire deadlines computed by\n // adding the wire_transfer_delay on top of the refund\n // deadline should be rounded up to.\n // @since **v23**\n default_wire_transfer_rounding_interval?: RoundingInterval;\n}\n\nexport enum RoundingInterval {\n NONE = \"NONE\",\n SECOND = \"SECOND\",\n MINUTE = \"MINUTE\",\n HOUR = \"HOUR\",\n DAY = \"DAY\",\n WEEK = \"WEEK\",\n MONTH = \"MONTH\",\n QUARTER = \"QUARTER\",\n YEAR = \"YEAR\",\n}\n\nexport interface ExchangeConfigInfo {\n // Base URL of the exchange REST API.\n base_url: string;\n\n // Currency for which the merchant is configured\n // to trust the exchange.\n // May not be the one the exchange actually uses,\n // but is the only one we would trust this exchange for.\n currency: string;\n\n // Offline master public key of the exchange. The\n // /keys data must be signed with this public\n // key for us to trust it.\n master_pub: EddsaPublicKey;\n}\n\nexport interface ClaimRequest {\n // Nonce to identify the wallet that claimed the order.\n nonce: string;\n\n // Token that authorizes the wallet to claim the order.\n // *Optional* as the merchant may not have required it\n // (create_token set to false in PostOrderRequest).\n token?: ClaimToken;\n}\n\nexport interface ClaimResponse {\n // Contract terms of the claimed order\n contract_terms: any;\n\n // Signature by the merchant over the contract terms.\n sig: EddsaSignatureString;\n}\n\nexport interface PaymentResponse {\n // Signature on TALER_PaymentResponsePS with the public\n // key of the merchant instance.\n sig: EddsaSignatureString;\n\n // Text to be shown to the point-of-sale staff as a proof of\n // payment.\n pos_confirmation?: string;\n}\nexport interface PaymentDeniedLegallyResponse {\n // Base URL of the exchanges that denied the payment.\n // The wallet should refresh the coins from these\n // exchanges, but may try to pay with coins from\n // other exchanges.\n exchange_base_urls: string[];\n}\n\nexport interface PaymentStatusRequestParams {\n // Hash of the order\u2019s contract terms (this is used to\n // authenticate the wallet/customer in case\n // $ORDER_ID is guessable).\n // Required once an order was claimed.\n contractTermHash?: string;\n // Authorizes the request via the claim token that\n // was returned in the PostOrderResponse. Used with\n // unclaimed orders only. Whether token authorization is\n // required is determined by the merchant when the\n // frontend creates the order.\n claimToken?: string;\n // Session ID that the payment must be bound to.\n // If not specified, the payment is not session-bound.\n sessionId?: string;\n // If specified, the merchant backend will wait up to\n // timeout_ms milliseconds for completion of the payment\n // before sending the HTTP response. A client must never\n // rely on this behavior, as the merchant backend may return\n // a response immediately.\n timeout?: number;\n // If set to \u201Cyes\u201D, poll for the order\u2019s pending refunds\n // to be picked up. timeout_ms specifies how long we\n // will wait for the refund.\n awaitRefundObtained?: boolean;\n // Indicates that we are polling for a refund above the\n // given AMOUNT. timeout_ms will specify how long we\n // will wait for the refund.\n refund?: AmountString;\n // Since protocol v9 refunded orders are only returned\n // under \u201Calready_paid_order_id\u201D if this flag is set\n // explicitly to \u201CYES\u201D.\n allowRefundedForRepurchase?: boolean;\n}\n\n/**\n * @deprecated use KycLongPollingReason\n */\nexport enum KycStatusLongPollingReason {\n /**\n * Waiting for an account to receive the wire transfer\n */\n AUTH_TRANSFER = 1,\n /**\n * Waiting for an account on aml investigation to be completed\n */\n AML_INVESTIGATION = 2,\n /**\n * Waiting for an account to be ready to be used\n */\n TO_BE_OK = 3,\n}\n\nexport type KycLongPollingReason =\n | KycLongPollingReasonWaitForStateEnter\n | KycLongPollingReasonWaitForStateExit\n | KycLongPollingReasonWaitForStateChange;\n\nexport type KycEtag = string;\n\nexport type KycLongPollingReasonWaitForStateEnter = {\n type: \"state-enter\";\n status: MerchantAccountKycStatus;\n // FIXME: Unit!\n timeout: number;\n};\nexport type KycLongPollingReasonWaitForStateExit = {\n type: \"state-exit\";\n status: MerchantAccountKycStatus;\n // FIXME: Unit!\n timeout: number;\n};\nexport type KycLongPollingReasonWaitForStateChange = {\n type: \"state-change\";\n etag: KycEtag;\n // FIXME: Unit!\n timeout: number;\n};\n\nexport interface GetKycStatusRequestParams {\n // If specified, the KYC check should return\n // the KYC status only for this wire account.\n // Otherwise, for all wire accounts.\n wireHash?: string;\n // If specified, the KYC check should return\n // the KYC status only for the given exchange.\n // Otherwise, for all exchanges we interacted with.\n exchangeURL?: string;\n /**\n * @deprecated use longpoll\n * If specified, the merchant will wait up to\n * timeout_ms milliseconds for the exchanges to\n * confirm completion of the KYC process(es).\n */\n timeout?: number;\n\n /**\n * @deprecated use longpoll\n * Specifies what status change we are long-polling for.\n * Use 1 to wait for the KYC auth transfer (access token available),\n * 2 to wait for an AML investigation to be done,\n * and 3 to wait for the KYC status to be OK. If multiple accounts\n * or exchanges match the query, any account reaching the TARGET\n * state will cause the response to be returned.\n */\n reason?: KycStatusLongPollingReason;\n\n /**\n *\n */\n longpoll?: KycLongPollingReason;\n\n ct?: CancellationToken;\n}\nexport type OrderDetailLongPollingReason = {\n etag: string;\n timeout: number;\n};\nexport interface GetOtpDeviceRequestParams {\n // Timestamp in seconds to use when calculating\n // the current OTP code of the device. Since protocol v10.\n faketime?: number;\n // Price to use when calculating the current OTP\n // code of the device. Since protocol v10.\n price?: AmountString;\n}\nexport interface GetOrderRequestParams {\n // Session ID that the payment must be bound to.\n // If not specified, the payment is not session-bound.\n sessionId?: string;\n /**\n * @deprecated use longpoll\n * Timeout in milliseconds to wait for a payment if\n * the answer would otherwise be negative (long polling).\n */\n timeout?: number;\n\n /**\n *\n */\n longpoll?: OrderDetailLongPollingReason;\n\n // Since protocol v9 refunded orders are only returned\n // under \u201Calready_paid_order_id\u201D if this flag is set\n // explicitly to \u201CYES\u201D.\n allowRefundedForRepurchase?: boolean;\n\n ct?: CancellationToken;\n}\nexport interface ListConfirmedWireTransferRequestParams {\n /**\n * Filter for transfers to the given bank account\n * (subject and amount MUST NOT be given in the payto URI).\n */\n paytoURI?: string;\n /**\n * Filter for transfers executed before the given timestamp.\n */\n before?: number;\n /**\n * Filter for transfers executed after the given timestamp.\n */\n after?: number;\n /**\n * At most return the given number of results. Negative for\n * descending in execution time, positive for ascending in\n * execution time. Default is -20.\n */\n limit?: number;\n /**\n *\n */\n order?: \"asc\" | \"dec\";\n /**\n * Starting transfer_serial_id for an iteration.\n */\n offset?: string;\n /**\n * Filter transfers that we expected to receive.\n */\n expected?: boolean;\n}\nexport interface ListIncomingWireTransferRequestParams {\n /**\n * Filter for transfers to the given bank account\n * (subject and amount MUST NOT be given in the payto URI).\n */\n paytoURI?: string;\n /**\n * Filter for transfers executed before the given timestamp.\n */\n before?: number;\n /**\n * Filter for transfers executed after the given timestamp.\n */\n after?: number;\n /**\n * At most return the given number of results. Negative for\n * descending in execution time, positive for ascending in\n * execution time. Default is -20.\n */\n limit?: number;\n /**\n *\n */\n order?: \"asc\" | \"dec\";\n /**\n * Starting transfer_serial_id for an iteration.\n */\n offset?: string;\n /**\n * Filter transfers by verification status.\n */\n verified?: boolean;\n /**\n * Filter transfers that were confirmed\n */\n confirmed?: boolean;\n}\n\nexport interface ListOrdersRequestParams {\n /**\n * If set to yes, only return paid orders, if no only\n * unpaid orders. Do not give (or use \u201Call\u201D) to see all\n * orders regardless of payment status.\n */\n paid?: boolean;\n /**\n * If set to yes, only return refunded orders, if no only\n * unrefunded orders. Do not give (or use \u201Call\u201D) to see\n * all orders regardless of refund status.\n */\n refunded?: boolean;\n /**\n * If set to yes, only return wired orders, if no only\n * orders with missing wire transfers. Do not give (or\n * use \u201Call\u201D) to see all orders regardless of wire transfer\n * status.\n */\n wired?: boolean;\n /**\n * At most return the given number of results. Negative\n * for descending by row ID, positive for ascending by\n * row ID. Default is 20. Since protocol v12.\n */\n limit?: number;\n /**\n * Non-negative date in seconds after the UNIX Epoc, see delta\n * for its interpretation. If not specified, we default to the\n * oldest or most recent entry, depending on delta.\n */\n date?: AbsoluteTime;\n /**\n * Relative time. Only return orders younger than the specified\n * age. Only applicable if delta is positive. If both max_age\n * and date_s are given, the larger of the two applies\n */\n maxAge?: Duration;\n /**\n * Starting product_serial_id for an iteration.\n * Since protocol v12.\n */\n offset?: string;\n /**\n * Timeout in milliseconds to wait for additional orders if the\n * answer would otherwise be negative (long polling). Only useful\n * if delta is positive. Note that the merchant MAY still return\n * a response that contains fewer than delta orders.\n */\n timeout?: number;\n /**\n * Filters by session ID.\n */\n sessionId?: string;\n /**\n * Filters by fulfillment URL.\n */\n fulfillmentUrl?: string;\n /**\n * Only returns orders where the summary contains the given text as a substring. Matching is case-insensitive\n */\n summary?: string;\n order?: \"asc\" | \"dec\";\n\n ct?: CancellationToken;\n}\n\nexport interface GetStatisticsRequestParams {\n // Optional. If set to \u201CBUCKET\u201D, only statistics by bucket will\n // be returned. If set to \u201CINTERVAL\u201D, only statistics kept by\n // interval will be returned.\n // If not set or set to \u201CANY\u201D, both will be returned.\n by?: \"INTERVAL\" | \"BUCKET\" | undefined;\n}\n\nexport interface GetStatisticsReportParams {\n granularity?: StatisticBucketRange;\n count?: number;\n}\n\nexport interface PayRequest {\n // The coins used to make the payment.\n coins: CoinPaySig[];\n\n // Input tokens required by choice indicated by choice_index.\n // @since protocol **v21**\n tokens?: TokenUseSig[];\n\n // Custom inputs from the wallet for the contract.\n wallet_data?: PayWalletData;\n\n // The session for which the payment is made (or replayed).\n // Only set for session-based payments.\n session_id?: string;\n}\n\nexport interface CoinPaySig {\n // Signature by the coin.\n coin_sig: EddsaSignatureString;\n\n // Public key of the coin being spent.\n coin_pub: EddsaPublicKey;\n\n // Signature made by the denomination public key.\n ub_sig: RsaSignature;\n\n // The hash of the denomination public key associated with this coin.\n h_denom: HashCodeString;\n\n // The amount that is subtracted from this coin with this payment.\n contribution: AmountString;\n\n // URL of the exchange this coin was withdrawn from.\n exchange_url: string;\n}\n\nexport interface StatusPaid {\n type: \"paid\";\n\n // Was the payment refunded (even partially, via refund or abort)?\n refunded: boolean;\n\n // Is any amount of the refund still waiting to be picked up (even partially)?\n refund_pending: boolean;\n\n // Amount that was refunded in total.\n refund_amount: AmountString;\n\n // Amount that already taken by the wallet.\n refund_taken: AmountString;\n}\nexport interface StatusGotoResponse {\n type: \"goto\";\n // The client should go to the reorder URL, there a fresh\n // order might be created as this one is taken by another\n // customer or wallet (or repurchase detection logic may\n // apply).\n public_reorder_url: string;\n}\nexport interface StatusUnpaidResponse {\n type: \"unpaid\";\n // URI that the wallet must process to complete the payment.\n taler_pay_uri: string;\n\n // Status URL, can be used as a redirect target for the browser\n // to show the order QR code / trigger the wallet.\n fulfillment_url?: string;\n\n // Alternative order ID which was paid for already in the same session.\n // Only given if the same product was purchased before in the same session.\n already_paid_order_id?: string;\n}\n\nexport interface PaidRefundStatusResponse {\n // Text to be shown to the point-of-sale staff as a proof of\n // payment (present only if reusable OTP algorithm is used).\n pos_confirmation?: string;\n\n // True if the order has been subjected to\n // refunds. False if it was simply paid.\n refunded: boolean;\n}\n\nexport interface PaidRequest {\n // Signature on TALER_PaymentResponsePS with the public\n // key of the merchant instance.\n sig: EddsaSignatureString;\n\n // Hash of the order's contract terms (this is used to authenticate the\n // wallet/customer and to enable signature verification without\n // database access).\n h_contract: HashCodeString;\n\n // Hash over custom inputs from the wallet for the contract.\n wallet_data_hash?: HashCodeString;\n\n // Session id for which the payment is proven.\n session_id: string;\n}\n\nexport interface AbortRequest {\n // Hash of the order's contract terms (this is used to authenticate the\n // wallet/customer in case $ORDER_ID is guessable).\n h_contract: HashCodeString;\n\n // List of coins the wallet would like to see refunds for.\n // (Should be limited to the coins for which the original\n // payment succeeded, as far as the wallet knows.)\n coins: AbortingCoin[];\n}\n\nexport interface AbortResponse {\n // List of refund responses about the coins that the wallet\n // requested an abort for. In the same order as the coins\n // from the original request.\n // The rtransaction_id is implied to be 0.\n refunds: MerchantAbortPayRefundStatus[];\n}\n\nexport interface WalletRefundRequest {\n // Hash of the order's contract terms (this is used to authenticate the\n // wallet/customer).\n h_contract: HashCodeString;\n}\n\nexport interface WalletRefundResponse {\n // Amount that was refunded in total.\n refund_amount: AmountString;\n\n // Successful refunds for this payment, empty array for none.\n refunds: MerchantCoinRefundStatus[];\n\n // Public key of the merchant.\n merchant_pub: EddsaPublicKey;\n}\n\n// Additional details needed to verify the refund confirmation signature\n// (h_contract_terms and merchant_pub) are already known\n// to the wallet and thus not included.\nexport interface MerchantCoinRefundSuccessStatus {\n // Used as tag for the sum type MerchantCoinRefundStatus sum type.\n type: \"success\";\n\n // HTTP status of the exchange request, 200 (integer) required for refund confirmations.\n exchange_status: 200;\n\n // The EdDSA :ref:signature (binary-only) with purpose\n // TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND using a current signing key of the\n // exchange affirming the successful refund.\n exchange_sig: EddsaSignatureString;\n\n // Public EdDSA key of the exchange that was used to generate the signature.\n // Should match one of the exchange's signing keys from /keys. It is given\n // explicitly as the client might otherwise be confused by clock skew as to\n // which signing key was used.\n exchange_pub: EddsaPublicKey;\n\n // Refund transaction ID.\n rtransaction_id: Integer;\n\n // Public key of a coin that was refunded.\n coin_pub: EddsaPublicKey;\n\n // Amount that was refunded, including refund fee charged by the exchange\n // to the customer.\n refund_amount: AmountString;\n\n // Timestamp when the merchant approved the refund.\n // Useful for grouping refunds.\n execution_time: Timestamp;\n}\n\nexport interface InstanceConfigurationMessage {\n // Name of the merchant instance to create (will become $INSTANCE).\n // Must match the regex ^[A-Za-z0-9][A-Za-z0-9_.@-]+$.\n id: string;\n\n // Merchant name corresponding to this instance.\n name: string;\n\n // Merchant email for customer contact.\n email?: string;\n\n // Merchant phone number for password reset (2-FA)\n // @since **v21**.\n phone_number?: string;\n\n // Merchant public website.\n website?: string;\n\n // Merchant logo.\n logo?: ImageDataUrl;\n\n // Authentication settings for this instance\n auth: InstanceAuthConfigurationMessage;\n\n // The merchant's physical address (to be put into contracts).\n address: Location;\n\n // The jurisdiction under which the merchant conducts its business\n // (to be put into contracts).\n jurisdiction: Location;\n\n // Use STEFAN curves to determine default fees?\n // If false, no fees are allowed by default.\n // Can always be overridden by the frontend on a per-order basis.\n use_stefan: boolean;\n\n // If the frontend does NOT specify a payment deadline, how long should\n // offers we make be valid by default?\n // Optional @since **v22** (before the setting was mandatory).\n // If not provided, the global merchant default will be used.\n default_pay_delay?: RelativeTime;\n\n // If the frontend does NOT specify a refund deadline, how long should\n // refunds be allowed by default? Added on top of the\n // payment deadline.\n // @since **v22**\n default_refund_delay?: RelativeTime;\n\n // If the frontend does NOT specify an execution date, how long should\n // we tell the exchange to wait to aggregate transactions before\n // executing the wire transfer? This delay is added on top of\n // the refund deadline and afterwards subject to rounding\n // via the default_wire_transfer_rounding_interval.\n // Optional @since **v22** (before the setting was mandatory).\n // If not provided, the global merchant default will be used.\n default_wire_transfer_delay?: RelativeTime;\n\n // How far should the wire deadline (if computed with the help of\n // the default_wire_transfer_delay) be rounded up to compute\n // the ultimate wire deadline?\n // @since **v22**, defaults to no rounding if not given.\n default_wire_transfer_rounding_interval?: RoundingInterval;\n}\n\nexport interface InstanceAuthConfigurationMessage {\n // Type of authentication.\n method: MerchantAuthMethod;\n\n // Since **v19**: For method \"token\", this field is mandatory.\n // Authentication against the /private/token endpoint\n // is done using basic authentication with the configured password\n // in the \"password\" field. Tokens are passed to other endpoints for\n // authorization using RFC 8959 bearer tokens.\n password: string;\n}\n\nexport enum LoginTokenScope {\n ReadOnly = \"readonly\",\n All = \"all\",\n Spa = \"spa\",\n OrderSimple = \"order-simple\",\n OrderPos = \"order-pos\",\n OrderManagement = \"order-mgmt\",\n OrderFull = \"order-full\",\n ReadOnly_Refreshable = \"readonly:refreshable\",\n All_Refreshable = \"all:refreshable\",\n Spa_Refreshable = \"spa:refreshable\",\n OrderSimple_Refreshable = \"order-simple:refreshable\",\n OrderPos_Refreshable = \"order-pos:refreshable\",\n OrderManagement_Refreshable = \"order-mgmt:refreshable\",\n OrderFull_Refreshable = \"order-full:refreshable\",\n}\n\nexport interface LoginTokenRequest {\n // Scope of the token (which kinds of operations it will allow)\n scope: LoginTokenScope;\n\n // Server may impose its own upper bound\n // on the token validity duration\n duration?: RelativeTime;\n\n // Optional token description\n description?: string;\n}\n\nexport interface LoginTokenSuccessResponse {\n // @deprecated since v19. See access_token\n // token: string;\n\n // The login token that can be used to access resources\n // that are in scope for some time. Must be prefixed\n // with \"Bearer \" when used in the \"Authorization\" HTTP header.\n // Will already begin with the RFC 8959 prefix.\n // **Since v19**\n access_token: AccessToken;\n\n // Scope of the token (which kinds of operations it will allow)\n scope: LoginTokenScope;\n\n // Server may impose its own upper bound\n // on the token validity duration\n expiration: Timestamp;\n\n // Can this token be refreshed?\n refreshable: boolean;\n}\n\nexport interface InstanceReconfigurationMessage {\n // Merchant name corresponding to this instance.\n name: string;\n\n // Merchant email for customer contact.\n email?: string;\n\n // Merchant phone number for password reset (2-FA)\n // @since **v21**.\n phone_number?: string;\n\n // Merchant public website.\n website?: string;\n\n // Merchant logo.\n logo?: ImageDataUrl;\n\n // The merchant's physical address (to be put into contracts).\n address: Location;\n\n // The jurisdiction under which the merchant conducts its business\n // (to be put into contracts).\n jurisdiction: Location;\n\n // Use STEFAN curves to determine default fees?\n // If false, no fees are allowed by default.\n // Can always be overridden by the frontend on a per-order basis.\n use_stefan: boolean;\n\n // If the frontend does NOT specify a payment deadline, how long should\n // offers we make be valid by default?\n // Optional @since **v22** (before the setting was mandatory).\n // If not provided, the previous setting will now simply be preserved.\n default_pay_delay?: RelativeTime;\n\n // If the frontend does NOT specify a refund deadline, how long should\n // refunds be allowed by default? Added on top of the payment deadline.\n // @since **v22**\n default_refund_delay?: RelativeTime;\n\n // If the frontend does NOT specify an execution date, how long should\n // we tell the exchange to wait to aggregate transactions before\n // executing the wire transfer? This delay is added on top of\n // the refund deadline and afterwards subject to rounding\n // via the default_wire_transfer_rounding_interval.\n // Optional @since **v22** (before the setting was mandatory).\n // If not provided, the previous setting will now simply be preserved.\n default_wire_transfer_delay?: RelativeTime;\n\n // How far should the wire deadline (if computed with the help of\n // the default_wire_transfer_delay) be rounded up to compute\n // the ultimate wire deadline?\n // @since **v22**, defaults to no rounding if not given.\n default_wire_transfer_rounding_interval?: RoundingInterval;\n}\n\nexport interface InstancesResponse {\n // List of instances that are present in the backend (see Instance).\n instances: Instance[];\n}\n\nexport interface Instance {\n // Merchant name corresponding to this instance.\n name: string;\n\n // Merchant public website.\n website?: string;\n\n // Merchant logo.\n logo?: ImageDataUrl;\n\n // Merchant instance this response is about ($INSTANCE).\n id: string;\n\n // Public key of the merchant/instance, in Crockford Base32 encoding.\n merchant_pub: EddsaPublicKey;\n\n // List of the payment targets supported by this instance. Clients can\n // specify the desired payment target in /order requests. Note that\n // front-ends do not have to support wallets selecting payment targets.\n payment_targets: string[];\n\n // Has this instance been deleted (but not purged)?\n deleted: boolean;\n}\n\nexport interface QueryInstancesResponse {\n // Merchant name corresponding to this instance.\n name: string;\n\n // Merchant email for customer contact.\n email?: string;\n\n // True if the email address was validated.\n // @since **v21**.\n email_validated?: boolean;\n\n // Merchant phone number for password reset (2-FA)\n // @since **v21**.\n phone_number?: string;\n\n // True if the email address was validated.\n // @since **v21**.\n phone_validated?: boolean;\n\n // Merchant public website.\n website?: string;\n\n // Merchant logo.\n logo?: ImageDataUrl;\n\n // Public key of the merchant/instance, in Crockford Base32 encoding.\n merchant_pub: EddsaPublicKey;\n\n // The merchant's physical address (to be put into contracts).\n address: Location;\n\n // The jurisdiction under which the merchant conducts its business\n // (to be put into contracts).\n jurisdiction: Location;\n\n // Use STEFAN curves to determine default fees?\n // If false, no fees are allowed by default.\n // Can always be overridden by the frontend on a per-order basis.\n use_stefan: boolean;\n\n // If the frontend does NOT specify a payment deadline, how long should\n // offers we make be valid by default? Added to the order creation\n // time.\n default_pay_delay: RelativeTime;\n\n // If the frontend does NOT specify a refund deadline, how long should\n // refunds be allowed by default? Added to the payment deadline.\n // @since **v22**\n default_refund_delay: RelativeTime;\n\n // If the frontend does NOT specify an execution date, how long should\n // we tell the exchange to wait to aggregate transactions before\n // executing the wire transfer? This delay is added to the\n // refund deadline and subject to rounding to the\n // default_wire_transfer_rounding_interval.\n default_wire_transfer_delay: RelativeTime;\n\n // Default interval to which wire deadlines computed by\n // adding the wire_transfer_delay on top of the refund\n // deadline should be rounded up to.\n // @since **v23**\n default_wire_transfer_rounding_interval?: RoundingInterval;\n\n // Authentication configuration.\n // Does not contain the token when token auth is configured.\n auth: {\n method: MerchantAuthMethod;\n };\n}\n\n// Type of authentication.\n// \"external\": The mechant backend does not do\n// any authentication checks. Instead an API\n// gateway must do the authentication.\n// \"token\": The merchant checks an auth token.\n// See \"token\" for details.\nexport enum MerchantAuthMethod {\n TOKEN = \"token\",\n // EXTERNAL = \"external\",\n // PASSWORD = \"password\",\n}\n\nexport interface MerchantAccountKycRedirectsResponse {\n // Array of KYC status information for\n // the exchanges and bank accounts selected\n // by the query.\n kyc_data: MerchantAccountKycRedirect[];\n}\n\nexport enum MerchantAccountKycStatus {\n NO_EXCHANGE_KEY = \"no-exchange-keys\",\n UNSUPPORTED_ACCOUNT = \"unsupported-account\",\n KYC_WIRE_IMPOSSIBLE = \"kyc-wire-impossible\",\n KYC_WIRE_REQUIRED = \"kyc-wire-required\",\n KYC_REQUIRED = \"kyc-required\",\n AWAITING_AML_REVIEW = \"awaiting-aml-review\",\n READY = \"ready\",\n LOGIC_BUG = \"logic-bug\",\n MERCHANT_INTERNAL_ERROR = \"merchant-internal-error\",\n EXCHANGE_INTERNAL_ERROR = \"exchange-internal-error\",\n EXCHANGE_GATEWAY_TIMEOUT = \"exchange-gateway-timeout\",\n EXCHANGE_UNREACHABLE = \"exchange-unreachable\",\n EXCHANGE_STATUS_INVALID = \"exchange-status-invalid\",\n}\n\n/**\n * Higher is more important\n */\nexport enum MerchantAccountKycStatusSimplified {\n OK = 0,\n ACTION_REQUIRED = 100,\n WARNING = 200,\n ERROR = 300,\n}\n\nexport function getMerchantAccountKycStatusSimplified(\n st: MerchantAccountKycStatus,\n): MerchantAccountKycStatusSimplified {\n switch (st) {\n case MerchantAccountKycStatus.AWAITING_AML_REVIEW:\n case MerchantAccountKycStatus.READY:\n return MerchantAccountKycStatusSimplified.OK;\n case MerchantAccountKycStatus.KYC_WIRE_REQUIRED:\n case MerchantAccountKycStatus.KYC_REQUIRED:\n return MerchantAccountKycStatusSimplified.ACTION_REQUIRED;\n case MerchantAccountKycStatus.NO_EXCHANGE_KEY:\n case MerchantAccountKycStatus.MERCHANT_INTERNAL_ERROR:\n case MerchantAccountKycStatus.EXCHANGE_INTERNAL_ERROR:\n case MerchantAccountKycStatus.EXCHANGE_GATEWAY_TIMEOUT:\n case MerchantAccountKycStatus.EXCHANGE_UNREACHABLE:\n return MerchantAccountKycStatusSimplified.WARNING;\n case MerchantAccountKycStatus.KYC_WIRE_IMPOSSIBLE:\n case MerchantAccountKycStatus.LOGIC_BUG:\n case MerchantAccountKycStatus.EXCHANGE_STATUS_INVALID:\n case MerchantAccountKycStatus.UNSUPPORTED_ACCOUNT:\n return MerchantAccountKycStatusSimplified.ERROR;\n default:\n assertUnreachable(st);\n }\n}\n\nexport interface MerchantAccountKycRedirect {\n // Summary of the status of the KYC process. Possible values are:\n //\n // o \"no-exchange-keys\": we do not (yet) have the /keys of the exchange\n // - \"kyc-wire-impossible\": KYC auth transfer needed but not possible\n // @ \"kyc-wire-required\": KYC auth transfer still needed and possible\n // @ \"kyc-required\": merchant must supply KYC data to proceed\n // + \"awaiting-aml-review\": account under review by payment provider\n // + \"ready\": everything is fine, account can be fully used\n // - \"logic-bug\": merchant backend logic bug\n // o \"merchant-internal-error\": merchant had an internal error\n // o \"exchange-internal-error\": exchange had an internal error\n // o \"exchange-gateway-timeout\": network timeout at gateway\n // o \"exchange-unreachable\": exchange did not respond at all\n // - \"exchange-status-invalid\": exchange violated protocol in reply\n //\n // \"+\" are perfectly normal states, \"@\" are states where the user\n // must performn an action (show link!); \"o\" are reasonable transient\n // states that could happen and are we are expected to likely recover\n // from automatically but that we should inform the user about\n // (show in yellow?), \"-\" are hard error states from which\n // there is likely no good automatic recovery from (show in red?).\n status: MerchantAccountKycStatus;\n\n // Our bank wire account this is about.\n payto_uri: PaytoString;\n\n // Hash of the salted payto://-URI of our\n // bank wire account this is about.\n // Since protocol **v17**.\n h_wire: string;\n\n // Base URL of the exchange this is about.\n exchange_url: string;\n\n // Currency used by the exchange.\n // @since protocol **v25**.\n exchange_currency?: string;\n\n // HTTP status code returned by the exchange when we asked for\n // information about the KYC status.\n // Since protocol **v17**.\n exchange_http_status: number;\n\n // Set to true if we did not get a /keys response from\n // the exchange and thus cannot do certain checks, such as\n // determining default account limits or account eligibility.\n no_keys: boolean;\n\n // Set to true if the given account cannot to KYC at the\n // given exchange because no wire method exists that could\n // be used to do the KYC auth wire transfer.\n auth_conflict: boolean;\n\n // Numeric error code indicating errors the exchange\n // returned, or TALER_EC_INVALID for none.\n // Optional (as there may not always have\n // been an error code). Since protocol **v17**.\n exchange_code?: number;\n\n // Access token needed to open the KYC SPA and/or\n // access the /kyc-info/ endpoint.\n access_token?: AccessToken;\n\n // Array with limitations that currently apply to this\n // account and that may be increased or lifted if the\n // KYC check is passed.\n // Note that additional limits *may* exist and not be\n // communicated to the client. If such limits are\n // reached, this *may* be indicated by the account\n // going into aml_review state. However, it is\n // also possible that the exchange may legally have\n // to deny operations without being allowed to provide\n // any justification.\n // The limits should be used by the client to\n // possibly structure their operations (e.g. withdraw\n // what is possible below the limit, ask the user to\n // pass KYC checks or withdraw the rest after the time\n // limit is passed, warn the user to not withdraw too\n // much or even prevent the user from generating a\n // request that would cause it to exceed hard limits).\n limits?: AccountLimit[];\n\n // Array of wire transfer instructions (including\n // optional amount and subject) for a KYC auth wire\n // transfer. Set only if this is required\n // to get the given exchange working.\n // Array because the exchange may have multiple\n // bank accounts, in which case any of these\n // accounts will do.\n // Optional. Since protocol **v17**.\n payto_kycauths?: string[];\n}\n\nexport interface ExchangeKycTimeout {\n // Base URL of the exchange this is about.\n exchange_url: string;\n\n // Numeric error code indicating errors the exchange\n // returned, or TALER_EC_INVALID for none.\n exchange_code: number;\n\n // HTTP status code returned by the exchange when we asked for\n // information about the KYC status.\n // 0 if there was no response at all.\n exchange_http_status: number;\n}\n\nexport interface AccountAddDetails {\n // payto:// URI of the account.\n payto_uri: PaytoString;\n\n // URL from where the merchant can download information\n // about incoming wire transfers to this account.\n credit_facade_url?: string;\n\n // Credentials to use when accessing the credit facade.\n // Never returned on a GET (as this may be somewhat\n // sensitive data). Can be set in POST\n // or PATCH requests to update (or delete) credentials.\n // To really delete credentials, set them to the type: \"none\".\n credit_facade_credentials?: FacadeCredentials;\n\n // Additional text to include in the wire transfer subject when\n // settling the payment. Note that the merchant MUST use this\n // consistently for the same merchant_pub and merchant_payto_uri\n // as during aggregation *any* of these values may be selected\n // for the actual aggregated wire transfer. If a merchant wants\n // to use different extra_subject values for the same IBAN,\n // it should thus create multiple instances (with different\n // merchant_pub values). When changing the extra_subject,\n // the change may thus not be immediately reflected in the\n // settlements.\n //\n // Must match [a-zA-Z0-9-.:]{1, 40}\n //\n // Optional. Since **v27**.\n extra_wire_subject_metadata?: string;\n}\n\n// Fixed-point decimal string in the form \"[.]\".\n// Fractional part has up to six digits.\n// \"-1\" is only valid for fields that explicitly allow \"infinity\".\n// Since protocol **v25**; used in template selection since **v25**.\nexport type DecimalQuantity = string;\n\nexport type FacadeCredentials =\n | NoFacadeCredentials\n | BasicAuthFacadeCredentials\n | BearerAuthFacadeCredentials;\n\nexport interface NoFacadeCredentials {\n type: \"none\";\n}\n\nexport interface BasicAuthFacadeCredentials {\n type: \"basic\";\n\n // Username to use to authenticate\n username: string;\n\n // Password to use to authenticate\n password: string;\n}\n\nexport interface BearerAuthFacadeCredentials {\n type: \"bearer\";\n\n // token to use to authenticate\n token: string;\n}\n\nexport interface AccountAddResponse {\n // Hash over the wire details (including over the salt).\n h_wire: HashCode;\n\n // Salt used to compute h_wire.\n salt: HashCode;\n}\n\nexport interface AccountPatchDetails {\n // URL from where the merchant can download information\n // about incoming wire transfers to this account.\n credit_facade_url?: string;\n\n // Credentials to use when accessing the credit facade.\n // Never returned on a GET (as this may be somewhat\n // sensitive data). Can be set in POST\n // or PATCH requests to update (or delete) credentials.\n // To really delete credentials, set them to the type: \"none\".\n // If the argument is omitted, the old credentials\n // are simply preserved.\n credit_facade_credentials?: FacadeCredentials;\n\n // Additional text to include in the wire transfer subject when\n // settling the payment. Note that the merchant MUST use this\n // consistently for the same merchant_pub and merchant_payto_uri\n // as during aggregation *any* of these values may be selected\n // for the actual aggregated wire transfer. If a merchant wants\n // to use different extra_subject values for the same IBAN,\n // it should thus create multiple instances (with different\n // merchant_pub values). When changing the extra_subject,\n // the change may thus not be immediately reflected in the\n // settlements.\n //\n // Must match [a-zA-Z0-9-.:]{1, 40}\n //\n // Optional. Since **v27**.\n extra_wire_subject_metadata?: string;\n}\n\nexport interface AccountsSummaryResponse {\n // List of accounts that are known for the instance.\n accounts: BankAccountEntry[];\n}\n\n// TODO: missing in docs\nexport interface BankAccountEntry {\n // payto:// URI of the account.\n payto_uri: PaytoString;\n\n // Hash over the wire details (including over the salt).\n h_wire: HashCode;\n\n // true if this account is active,\n // false if it is historic.\n active?: boolean;\n}\nexport interface BankAccountDetail {\n // payto:// URI of the account.\n payto_uri: PaytoString;\n\n // Hash over the wire details (including over the salt).\n h_wire: HashCode;\n\n // Salt used to compute h_wire.\n salt: HashCode;\n\n // URL from where the merchant can download information\n // about incoming wire transfers to this account.\n credit_facade_url?: string;\n\n // true if this account is active,\n // false if it is historic.\n active?: boolean;\n\n // Additional text to include in the wire transfer subject when\n // settling the payment. Note that the merchant MUST use this\n // consistently for the same merchant_pub and merchant_payto_uri\n // as during aggregation *any* of these values may be selected\n // for the actual aggregated wire transfer. If a merchant wants\n // to use different extra_subject values for the same IBAN,\n // it should thus create multiple instances (with different\n // merchant_pub values). When changing the extra_subject,\n // the change may thus not be immediately reflected in the\n // settlements.\n //\n // Must match [a-zA-Z0-9-.:]{1, 40}\n //\n // Optional. Since **v27**.\n extra_wire_subject_metadata?: string;\n}\n\nexport interface CategoryListResponse {\n // Array with all of the categories we know.\n categories: CategoryListEntry[];\n}\n\nexport interface CategoryListEntry {\n // Unique number for the category.\n category_id: Integer;\n\n // Name of the category.\n name: string;\n\n // Translations of the name into various\n // languages.\n name_i18n?: { [lang_tag: string]: string };\n\n // Number of products in this category.\n // A product can be in more than one category.\n product_count: Integer;\n}\n\nexport interface CategoryProductList {\n // Name of the category.\n name: string;\n\n // Translations of the name into various\n // languages.\n name_i18n?: { [lang_tag: string]: string };\n\n // The products in this category.\n products: CategoryProductSummary[];\n}\n\nexport interface CategoryProductSummary {\n // Product ID to use.\n product_id: string;\n}\n\nexport interface CategoryCreateRequest {\n // Name of the category.\n name: string;\n\n // Translations of the name into various\n // languages.\n name_i18n?: { [lang_tag: string]: string };\n}\n\nexport interface CategoryCreatedResponse {\n // Number of the newly created category.\n category_id: Integer;\n}\n\nexport interface ProductAddDetailRequest {\n // Product ID to use.\n product_id: string;\n\n // Human-readable product name.\n // Since API version **v20**. Optional only for\n // backwards-compatibility, should be considered mandatory\n // moving forward!\n product_name?: string;\n\n // Human-readable product description.\n description: string;\n\n // Map from IETF BCP 47 language tags to localized descriptions.\n description_i18n?: { [lang_tag: string]: string };\n\n // Categories into which the product belongs.\n // Used in the POS-endpoint.\n // Since API version **v16**.\n categories?: Integer[];\n\n // Unit in which the product is measured (liters, kilograms, packages, etc.).\n unit: string;\n\n // Legacy price field.\n // Deprecated since **v25**;\n // when present it must match the first element of unit_price.\n price: AmountString;\n\n // An optional base64-encoded product image.\n image?: ImageDataUrl;\n\n // A list of taxes paid by the merchant for one unit of this product.\n taxes?: Tax[];\n\n // Number of units of the product in stock in sum in total,\n // including all existing sales ever. Given in product-specific\n // units.\n // A value of -1 indicates \"infinite\" (i.e. for \"electronic\" books).\n total_stock: Integer;\n\n // Preferred way to express the per-unit price of the product. Supply at least one entry;\n // the first entry must match price.\n // The price given MUST include applicable taxes if price_is_net\n // is false, and MUST exclude applicable taxes if price_is_net\n // is true.\n // Zero implies that the product is not sold separately or that the price must be supplied\n // by the frontend.\n // Each entry must use a distinct currency.\n // Since API version **v25**.\n // Currency uniqueness enforced since protocol **v25**.\n unit_price?: AmountString[];\n\n // Identifies where the product is in stock.\n address?: Location;\n\n // Identifies when we expect the next restocking to happen.\n next_restock?: Timestamp;\n\n // Minimum age buyer must have (in years). Default is 0.\n minimum_age?: Integer;\n\n // Product group the product belongs to. 0 and missing both\n // means default.\n // Since **v25**.\n product_group_id?: Integer;\n\n // Money pot revenue on the product should be accounted in.\n // 0 and missing both mean no money pot (revenue accounted\n // in money pot of the overall order or not at all).\n // Since **v25**.\n money_pot_id?: Integer;\n}\n\nexport interface ProductPatchDetailRequest {\n // Human-readable product name.\n // Since API version **v20**. Optional only for\n // backwards-compatibility, should be considered mandatory\n // moving forward!\n product_name?: string;\n\n // Human-readable product description.\n description: string;\n\n // Map from IETF BCP 47 language tags to localized descriptions.\n description_i18n?: { [lang_tag: string]: string };\n\n // Categories into which the product belongs.\n // Used in the POS-endpoint.\n // Since API version **v16**.\n categories?: Integer[];\n\n // Unit in which the product is measured (liters, kilograms, packages, etc.).\n unit: string;\n\n // The price for one unit of the product. Zero is used\n // to imply that this product is not sold separately, or\n // that the price is not fixed, and must be supplied by the\n // front-end. If non-zero, this price MUST include applicable\n // taxes.\n price: AmountString;\n\n // An optional base64-encoded product image.\n image?: ImageDataUrl;\n\n // A list of taxes paid by the merchant for one unit of this product.\n taxes?: Tax[];\n\n // Number of units of the product in stock in sum in total,\n // including all existing sales ever. Given in product-specific\n // units.\n // A value of -1 indicates \"infinite\" (i.e. for \"electronic\" books).\n total_stock: Integer;\n\n // Number of units of the product that have already been sold.\n total_sold: Integer;\n\n // Number of units of the product that were lost (spoiled, stolen, etc.).\n total_lost?: Integer;\n\n // Identifies where the product is in stock.\n address?: Location;\n\n // Identifies when we expect the next restocking to happen.\n next_restock?: Timestamp;\n\n // Minimum age buyer must have (in years). Default is 0.\n minimum_age?: Integer;\n\n // Product group the product belongs to. 0 and missing both\n // means default.\n // Since **v25**.\n product_group_id?: Integer;\n\n // Money pot revenue on the product should be accounted in.\n // 0 and missing both mean no money pot (revenue accounted\n // in money pot of the overall order or not at all).\n // Since **v25**.\n money_pot_id?: Integer;\n}\n\nexport interface InventorySummaryResponse {\n // List of products that are present in the inventory.\n products: InventoryEntry[];\n}\n\nexport interface InventoryEntry {\n // Product identifier, as found in the product.\n product_id: string;\n // product_serial_id of the product in the database.\n product_serial: Integer;\n}\n\nexport interface FullInventoryDetailsResponse {\n // List of products that are present in the inventory.\n products: MerchantPosProductDetail[];\n\n // List of categories in the inventory.\n categories: MerchantCategory[];\n}\n\nexport interface MerchantPosProductDetail {\n // A unique numeric ID of the product\n product_serial: number;\n\n // A merchant-internal unique identifier for the product\n product_id?: string;\n\n // Human-readable product name.\n // Since API version **v20**.\n product_name?: string;\n\n // A list of category IDs this product belongs to.\n // Typically, a product only belongs to one category, but more than one is supported.\n categories: number[];\n\n // Human-readable product description.\n description: string;\n\n // Map from IETF BCP 47 language tags to localized descriptions.\n description_i18n: { [lang_tag: string]: string };\n\n // Unit in which the product is measured (liters, kilograms, packages, etc.).\n unit: string;\n\n // The price for one unit of the product. Zero is used\n // to imply that this product is not sold separately, or\n // that the price is not fixed, and must be supplied by the\n // front-end. If non-zero, this price MUST include applicable\n // taxes.\n price: AmountString;\n\n // An optional base64-encoded product image.\n image?: ImageDataUrl;\n\n // A list of taxes paid by the merchant for one unit of this product.\n taxes?: Tax[];\n\n // Number of units of the product in stock in sum in total,\n // including all existing sales ever. Given in product-specific\n // units.\n // Optional, if missing treat as \"infinite\".\n total_stock?: Integer;\n\n // Minimum age buyer must have (in years).\n minimum_age?: Integer;\n}\n\nexport interface MerchantCategory {\n // A unique numeric ID of the category\n id: number;\n\n // The name of the category. This will be shown to users and used in the order summary.\n name: string;\n\n // Map from IETF BCP 47 language tags to localized names\n name_i18n?: { [lang_tag: string]: string };\n}\n\nexport interface ProductDetailResponse {\n // Human-readable product name.\n // Since API version **v20**.\n product_name?: string;\n\n // Human-readable product description.\n description: string;\n\n // Map from IETF BCP 47 language tags to localized descriptions.\n description_i18n: { [lang_tag: string]: string };\n\n // Unit in which the product is measured (liters, kilograms, packages, etc.).\n unit: string;\n\n // Categories into which the product belongs.\n // Since API version **v16**.\n categories: Integer[];\n\n // The price for one unit of the product. Zero is used\n // to imply that this product is not sold separately, or\n // that the price is not fixed, and must be supplied by the\n // front-end. If non-zero, this price MUST include applicable\n // taxes.\n price: AmountString;\n\n // An optional base64-encoded product image.\n image: ImageDataUrl;\n\n // A list of taxes paid by the merchant for one unit of this product.\n taxes?: Tax[];\n\n // Number of units of the product in stock in sum in total,\n // including all existing sales ever. Given in product-specific\n // units.\n // A value of -1 indicates \"infinite\" (i.e. for \"electronic\" books).\n total_stock: Integer;\n\n // Number of units of the product that have already been sold.\n total_sold: Integer;\n\n // Number of units of the product that were lost (spoiled, stolen, etc.).\n total_lost: Integer;\n\n // Identifies where the product is in stock.\n address?: Location;\n\n // Identifies when we expect the next restocking to happen.\n next_restock?: Timestamp;\n\n // Minimum age buyer must have (in years).\n minimum_age?: Integer;\n\n // Product group the product belongs to. Missing means default.\n // Since **v25**.\n product_group_id?: Integer;\n\n // Money pot revenue on the product should be accounted in.\n // Missing means no money pot (revenue accounted\n // in money pot of the overall order or not at all).\n // Since **v25**.\n money_pot_id?: Integer;\n}\nexport interface LockRequest {\n // UUID that identifies the frontend performing the lock\n // Must be unique for the lifetime of the lock.\n lock_uuid: string;\n\n // How long does the frontend intend to hold the lock?\n duration: RelativeTime;\n\n // How many units should be locked?\n quantity: Integer;\n}\n\nexport interface PostOrderRequest {\n // The order must at least contain the minimal\n // order detail, but can override all.\n order: Order;\n\n // If set, the backend will then set the refund deadline to the current\n // time plus the specified delay. If it's not set, refunds will not be\n // possible.\n refund_delay?: RelativeTime;\n\n // Specifies the payment target preferred by the client. Can be used\n // to select among the various (active) wire methods supported by the instance.\n payment_target?: string;\n\n // Specifies that some products are to be included in the\n // order from the inventory. For these inventory management\n // is performed (so the products must be in stock) and\n // details are completed from the product data of the backend.\n inventory_products?: MinimalInventoryProduct[];\n\n // Specifies a lock identifier that was used to\n // lock a product in the inventory. Only useful if\n // inventory_products is set. Used in case a frontend\n // reserved quantities of the individual products while\n // the shopping cart was being built. Multiple UUIDs can\n // be used in case different UUIDs were used for different\n // products (i.e. in case the user started with multiple\n // shopping sessions that were combined during checkout).\n lock_uuids?: string[];\n\n // Should a token for claiming the order be generated?\n // False can make sense if the ORDER_ID is sufficiently\n // high entropy to prevent adversarial claims (like it is\n // if the backend auto-generates one). Default is 'true'.\n create_token?: boolean;\n\n // OTP device ID to associate with the order.\n // This parameter is optional.\n otp_id?: string;\n}\n\nexport type Order = OrderV0 | OrderV1;\n\nexport interface MinimalOrderDetail {\n // Amount to be paid by the customer.\n amount: AmountString;\n\n // Short summary of the order.\n summary: string;\n\n // See documentation of fulfillment_url in ContractTerms.\n // Either fulfillment_url or fulfillment_message must be specified.\n // When creating an order, the fulfillment URL can\n // contain ${ORDER_ID} which will be substituted with the\n // order ID of the newly created order.\n fulfillment_url?: string;\n\n // See documentation of fulfillment_message in ContractTerms.\n // Either fulfillment_url or fulfillment_message must be specified.\n fulfillment_message?: string;\n}\n\nexport interface MinimalInventoryProduct {\n // Which product is requested (here mandatory!).\n product_id: string;\n\n // How many units of the product are requested.\n quantity: Integer;\n\n // Money pot to use for this product, overrides value from\n // the inventory if given.\n // Since **v25**.\n product_money_pot?: Integer;\n}\n\nexport interface PostOrderResponse {\n // Order ID of the response that was just created.\n order_id: string;\n\n // Deadline when the offer expires; the customer must pay before.\n // @since protocol **v21**.\n pay_deadline?: Timestamp;\n\n // Token that authorizes the wallet to claim the order.\n // Provided only if \"create_token\" was set to 'true'\n // in the request.\n token?: ClaimToken;\n}\nexport interface OutOfStockResponse {\n // Product ID of an out-of-stock item.\n product_id: string;\n\n // Legacy integer quantity requested. Deprecated; see unit_requested_quantity.\n requested_quantity: Integer;\n\n // Requested quantity using \"[.]\" syntax with up to six fractional digits.\n unit_requested_quantity: string;\n\n // Legacy integer availability (must be below requested_quantity).\n available_quantity: Integer;\n\n // Available quantity using \"[.]\" syntax with up to six fractional digits.\n unit_available_quantity: string;\n\n // When do we expect the product to be again in stock?\n // Optional, not given if unknown.\n restock_expected?: Timestamp;\n}\nexport interface OrderHistory {\n // Timestamp-sorted array of all orders matching the query.\n // The order of the sorting depends on the sign of delta.\n orders: OrderHistoryEntry[];\n}\n\nexport interface OrderHistoryEntry {\n // Order ID of the transaction related to this entry.\n order_id: string;\n\n // Row ID of the order in the database.\n row_id: number;\n\n // When the order was created.\n timestamp: Timestamp;\n\n // The amount of money the order is for.\n amount: AmountString;\n\n // The total amount of refunds granted by the merchant.\n // Includes refunds that the wallet did not yet pick up.\n // Only available if the order was paid.\n // Since **v24**.\n refund_amount?: AmountString;\n\n // The amount of refunds the customer's wallet did not yet\n // pick up. Only available if the order was paid.\n // Since **v24**.\n pending_refund_amount?: AmountString;\n\n // The summary of the order.\n summary: string;\n\n // Whether some part of the order is refundable,\n // that is the refund deadline has not yet expired\n // and the total amount refunded so far is below\n // the value of the original transaction.\n refundable: boolean;\n\n // Whether the order has been paid or not.\n paid: boolean;\n}\n\nexport type MerchantOrderStatusResponse =\n | CheckPaymentPaidResponse\n | CheckPaymentClaimedResponse\n | CheckPaymentUnpaidResponse;\n\nexport interface CheckPaymentPaidResponse {\n // The customer paid for this contract.\n order_status: \"paid\";\n\n // Was the payment refunded (even partially)?\n refunded: boolean;\n\n // True if there are any approved refunds that the wallet has\n // not yet obtained.\n refund_pending: boolean;\n\n // Did the exchange wire us the funds?\n wired: boolean;\n\n // Total amount the exchange deposited into our bank account\n // for this contract, excluding fees.\n deposit_total: AmountString;\n\n // Numeric error code indicating errors the exchange\n // encountered tracking the wire transfer for this purchase (before\n // we even got to specific coin issues).\n // 0 if there were no issues.\n exchange_code: number;\n\n // HTTP status code returned by the exchange when we asked for\n // information to track the wire transfer for this purchase.\n // 0 if there were no issues.\n exchange_http_status: number;\n\n // Total amount that was refunded, 0 if refunded is false.\n refund_amount: AmountString;\n\n // Contract terms.\n // FIXME: support for contract v1\n contract_terms: MerchantContractTerms;\n\n // Index of the selected choice within the choices array of\n // contract terms.\n // @since protocol **v21**\n choice_index?: Integer;\n\n // If the order is paid, set to the last time when a payment\n // was made to pay for this order. @since **v14**.\n last_payment: Timestamp;\n\n // The wire transfer status from the exchange for this order if\n // available, otherwise empty array.\n wire_details: TransactionWireTransfer[];\n\n // Reports about trouble obtaining wire transfer details,\n // empty array if no trouble were encountered.\n wire_reports: TransactionWireReport[];\n\n // The refund details for this order. One entry per\n // refunded coin; empty array if there are no refunds.\n refund_details: RefundDetails[];\n\n // Status URL, can be used as a redirect target for the browser\n // to show the order QR code / trigger the wallet.\n order_status_url: string;\n}\n\nexport interface CheckPaymentClaimedResponse {\n // A wallet claimed the order, but did not yet pay for the contract.\n order_status: \"claimed\";\n\n // Contract terms.\n contract_terms: MerchantContractTerms;\n\n // Status URL, can be used as a redirect target for the browser\n // to show the order QR code / trigger the wallet.\n // Since protocol **v19**.\n order_status_url: string;\n}\n\nexport interface CheckPaymentUnpaidResponse {\n // The order was neither claimed nor paid.\n order_status: \"unpaid\";\n\n // URI that the wallet must process to complete the payment.\n taler_pay_uri: string;\n\n // Time when the order was created.\n creation_time: Timestamp;\n\n // Deadline when the offer expires; the customer must pay before.\n // @since protocol **v21**.\n pay_deadline?: Timestamp;\n\n // Order summary text.\n summary: string;\n\n // Total amount of the order (to be paid by the customer).\n // Optional for v1 contracts.\n total_amount?: AmountString;\n\n // Alternative order ID which was paid for already in the same session.\n // Only given if the same product was purchased before in the same session.\n already_paid_order_id?: string;\n\n // Fulfillment URL of an already paid order. Only given if under this\n // session an already paid order with a fulfillment URL exists.\n already_paid_fulfillment_url?: string;\n\n // Status URL, can be used as a redirect target for the browser\n // to show the order QR code / trigger the wallet.\n order_status_url: string;\n\n // We do we NOT return the contract terms here because they may not\n // exist in case the wallet did not yet claim them.\n}\nexport interface RefundDetails {\n // Reason given for the refund.\n reason: string;\n\n // Set to true if a refund is still available for the wallet for this payment.\n pending: boolean;\n\n // When was the refund approved.\n timestamp: Timestamp;\n\n // Total amount that was refunded (minus a refund fee).\n amount: AmountString;\n}\n\nexport interface TransactionWireTransfer {\n // Responsible exchange.\n exchange_url: string;\n\n // 32-byte wire transfer identifier.\n wtid: Base32String;\n\n // Execution time of the wire transfer.\n execution_time: Timestamp;\n\n // Total amount that has been wire transferred\n // to the merchant.\n amount: AmountString;\n\n // Deposit fees to be paid to the\n // exchange for this order.\n // Since **v26**.\n deposit_fee: AmountString;\n\n // Was this transfer confirmed by the merchant via the\n // POST /transfers API, or is it merely claimed by the exchange?\n confirmed: boolean;\n\n // Transfer serial ID of this wire transfer, useful as\n // ``offset`` for the GET ``/private/incoming`` endpoint.\n // Since **v25**.\n expected_transfer_serial_id?: Integer;\n}\n\nexport interface TransactionWireReport {\n // Numerical error code.\n code: number;\n\n // Human-readable error description.\n hint: string;\n\n // Numerical error code from the exchange.\n exchange_code: number;\n\n // HTTP status code received from the exchange.\n exchange_http_status: number;\n\n // Public key of the coin for which we got the exchange error.\n coin_pub: CoinPublicKey;\n}\n\nexport interface ForgetRequest {\n // Array of valid JSON paths to forgettable fields in the order's\n // contract terms.\n fields: string[];\n}\n\nexport interface RefundRequest {\n // Amount to be refunded.\n refund: AmountString;\n\n // Human-readable refund justification.\n reason: string;\n}\nexport interface MerchantRefundResponse {\n // URL (handled by the backend) that the wallet should access to\n // trigger refund processing.\n // taler://refund/...\n taler_refund_uri: string;\n\n // Contract hash that a client may need to authenticate an\n // HTTP request to obtain the above URI in a wallet-friendly way.\n h_contract: HashCode;\n}\n\nexport interface TransferInformation {\n // How much was wired to the merchant (minus fees).\n credit_amount: AmountString;\n\n // Raw wire transfer identifier identifying the wire transfer (a base32-encoded value).\n wtid: WireTransferIdentifierRawP;\n\n // Target account that received the wire transfer.\n payto_uri: PaytoString;\n\n // Base URL of the exchange that made the wire transfer.\n exchange_url: string;\n}\n\nexport interface TransferList {\n // List of all the transfers that fit the filter that we know.\n transfers: TransferDetails[];\n}\n\nexport interface ExpectedTransferList {\n incoming: ExpectedTransferEntry[];\n}\n\nexport interface TransferDetails {\n // How much was wired to the merchant (minus fees).\n credit_amount: AmountString;\n\n // Raw wire transfer identifier identifying the wire transfer (a base32-encoded value).\n wtid: WireTransferIdentifierRawP;\n\n // Target account that received the wire transfer.\n payto_uri: PaytoString;\n\n // Base URL of the exchange that made the wire transfer.\n exchange_url: string;\n\n // Serial number identifying the transfer in the merchant backend.\n // Used for filtering via offset.\n transfer_serial_id: number;\n\n // Time of the execution of the wire transfer.\n // Missing if unknown in protocol **v25**.\n execution_time?: Timestamp;\n\n // True if this wire transfer was expected.\n // (a matching \"/private/incoming\" record exists).\n // Since protocol **v20**.\n expected?: boolean;\n}\n\nexport interface ExpectedTransferEntry {\n // How much was wired to the merchant (minus fees).\n expected_credit_amount?: AmountString;\n\n // Raw wire transfer identifier identifying the wire transfer (a base32-encoded value).\n wtid: WireTransferIdentifierRawP;\n\n // Target account that received the wire transfer.\n payto_uri: PaytoString;\n\n // Base URL of the exchange that made the wire transfer.\n exchange_url: string;\n\n // Serial number identifying the transfer in the merchant backend.\n // Used for filtering via offset.\n expected_transfer_serial_id?: number;\n\n // Time of the execution of the wire transfer by the exchange, according to the exchange\n // Only provided if we did get an answer from the exchange.\n execution_time?: Timestamp;\n\n // True if we checked the exchange's answer and are happy with\n // the reconciation data.\n // False if we have an answer and are unhappy, missing if we\n // do not have an answer from the exchange.\n // Does not imply that the wire transfer was settled (for\n // that, see confirmed).\n validated: boolean;\n\n // True if the merchant uses the POST /transfers API to confirm\n // that this wire transfer took place (and it is thus not\n // something merely claimed by the exchange).\n // (a matching entry exists in /private/transfers)\n confirmed: boolean;\n\n // Last HTTP status we received from the exchange, 0 for\n // none (incl. timeout)\n last_http_status: Integer;\n\n // Last Taler error code we got from the exchange.\n last_ec: number;\n\n // Last error detail we got back from the exchange.\n last_error_detail?: string;\n}\n\nexport interface ExpectedTransferDetails {\n // List of orders that are settled by this wire\n // transfer according to the exchange. Only\n // available if last_http_status is 200.\n reconciliation_details?: ExchangeTransferReconciliationDetails[];\n\n // Wire fee paid by the merchant. Only\n // available if last_http_status is 200.\n // Not present if the backend was unable to obtain the\n // wire fee for the execution_time from the exchange.\n // (If missing, this is thus indicative of a minor error.)\n wire_fee?: AmountString;\n}\n\nexport interface ExchangeTransferReconciliationDetails {\n // ID of the order for which these are the\n // reconciliation details.\n order_id: string;\n\n // Remaining deposit total to be paid,\n // that is the total amount of the order\n // minus any refunds that were granted.\n // The actual amount to be wired is this\n // amount minus deposit_fee and (overall)\n // minus the wire_fee of the transfer.\n remaining_deposit: AmountString;\n\n // Deposit fees paid to the exchange for this order.\n deposit_fee: AmountString;\n}\n\nexport interface OtpDeviceAddDetails {\n // Device ID to use.\n otp_device_id: string;\n\n // Human-readable description for the device.\n otp_device_description: string;\n\n // A key encoded with RFC 3548 Base32.\n // IMPORTANT: This is not using the typical\n // Taler base32-crockford encoding.\n // Instead it uses the RFC 3548 encoding to\n // be compatible with the TOTP standard.\n otp_key: string;\n\n // Algorithm for computing the POS confirmation.\n // \"NONE\" or 0: No algorithm (no pos confirmation will be generated)\n // \"TOTP_WITHOUT_PRICE\" or 1: Without amounts (typical OTP device)\n // \"TOTP_WITH_PRICE\" or 2: With amounts (special-purpose OTP device)\n // The \"String\" variants are supported @since protocol **v7**.\n otp_algorithm: Integer | string;\n\n // Counter for counter-based OTP devices.\n otp_ctr?: Integer;\n}\n\nexport interface OtpDevicePatchDetails {\n // Human-readable description for the device.\n otp_device_description: string;\n\n // A key encoded with RFC 3548 Base32.\n // IMPORTANT: This is not using the typical\n // Taler base32-crockford encoding.\n // Instead it uses the RFC 3548 encoding to\n // be compatible with the TOTP standard.\n otp_key: string;\n\n // Algorithm for computing the POS confirmation.\n otp_algorithm: Integer;\n\n // Counter for counter-based OTP devices.\n otp_ctr?: Integer;\n}\n\nexport interface OtpDeviceSummaryResponse {\n // Array of devices that are present in our backend.\n otp_devices: OtpDeviceEntry[];\n}\nexport interface OtpDeviceEntry {\n // Device identifier.\n otp_device_id: string;\n\n // Human-readable description for the device.\n device_description: string;\n}\n\nexport interface OtpDeviceDetails {\n // Human-readable description for the device.\n device_description: string;\n\n // Algorithm for computing the POS confirmation.\n //\n // Currently, the following numbers are defined:\n // 0: None\n // 1: TOTP without price\n // 2: TOTP with price\n otp_algorithm: Integer;\n\n // Counter for counter-based OTP devices.\n otp_ctr?: Integer;\n\n // Current time for time-based OTP devices.\n // Will match the faketime argument of the\n // query if one was present, otherwise the current\n // time at the backend.\n //\n // Available since protocol **v10**.\n otp_timestamp: Integer;\n\n // Current OTP confirmation string of the device.\n // Matches exactly the string that would be returned\n // as part of a payment confirmation for the given\n // amount and time (so may contain multiple OTP codes).\n //\n // If the otp_algorithm is time-based, the code is\n // returned for the current time, or for the faketime\n // if a TIMESTAMP query argument was provided by the client.\n //\n // When using OTP with counters, the counter is **NOT**\n // increased merely because this endpoint created\n // an OTP code (this is a GET request, after all!).\n //\n // If the otp_algorithm requires an amount, the\n // amount argument must be specified in the\n // query, otherwise the otp_code is not\n // generated.\n //\n // This field is *optional* in the response, as it is\n // only provided if we could compute it based on the\n // otp_algorithm and matching client query arguments.\n //\n // Available since protocol **v10**.\n otp_code?: string;\n}\nexport interface TemplateAddDetails {\n // Template ID to use.\n template_id: string;\n\n // Human-readable description for the template.\n template_description: string;\n\n // OTP device ID.\n // This parameter is optional.\n otp_id?: string;\n\n // Additional information in a separate template.\n template_contract: TemplateContractDetails;\n\n // Key-value pairs matching a subset of the\n // fields from template_contract that are\n // user-editable defaults for this template.\n // Since protocol **v13**.\n editable_defaults?: TemplateContractDetailsDefaults;\n}\n\nexport type TemplateContractDetails =\n | TemplateContractFixedOrder\n | TemplateContractInventoryCart\n | TemplateContractPaivana;\n\nexport enum TemplateType {\n FIXED_ORDER = \"fixed-order\",\n INVENTORY_CART = \"inventory-cart\",\n PAIVANA = \"paivana\",\n}\nexport interface TemplateContractCommon {\n // Template type to apply. Defaults to \"fixed-order\" if omitted.\n // Prescribes which interface has to be followed\n // Since protocol **v25**.\n template_type: TemplateType;\n\n // Human-readable summary for the template.\n summary?: string;\n\n // Required currency for payments to the template.\n // This parameter is optional and should not be present\n // if \"amount\" is given.\n currency?: string;\n\n // The time the customer need to pay before his order will be deleted.\n // It is deleted if the customer did not pay and if the duration is over.\n pay_duration?: RelativeTime;\n\n // How long will customers have to access / read / pick-up\n // the resource they are buying? Will turn into\n // max_pickup_time in the contract. Optional, if not given\n // the duration is forever.\n // Since protocol **v29**.\n max_pickup_duration?: RelativeTime;\n\n // Minimum age buyer must have (in years). Default is 0.\n minimum_age?: Integer;\n\n // Inventory-cart: request a tip during instantiation.\n // Since protocol **v25**.\n request_tip?: boolean;\n}\n\nexport interface TemplateContractFixedOrder extends TemplateContractCommon {\n template_type: TemplateType.FIXED_ORDER;\n\n // The price is imposed by the merchant and cannot be changed by the customer.\n // This parameter is optional.\n amount?: AmountString;\n}\n\nexport interface TemplateContractPaivana extends TemplateContractCommon {\n template_type: TemplateType.PAIVANA;\n // Regular expression over URLs for which\n // this template is valid.\n // Optional, if not given all URLs are accepted.\n // Since protocol **v25**.\n website_regex?: string;\n\n // Methods to pay for the contract.\n choices: OrderChoice[];\n}\n\nexport interface TemplateContractInventoryCart extends TemplateContractCommon {\n template_type: TemplateType.INVENTORY_CART;\n\n // Inventory-cart: allow any inventory item to be selected.\n // Since protocol **v25**.\n selected_all?: boolean;\n\n // Inventory-cart: only products in these categories are selectable.\n // Since protocol **v25**.\n selected_categories?: Integer[];\n\n // Inventory-cart: only these products are selectable.\n // Since protocol **v25**.\n selected_products?: string[];\n\n // Inventory-cart: require exactly one selection entry.\n // Since protocol **v25**.\n choose_one?: boolean;\n\n // Inventory-cart: backend-provided payload with selectable data.\n // Only present in GET /templates/$TEMPLATE_ID responses.\n // Since protocol **v25**.\n inventory_payload?: InventoryPayload;\n}\n\nexport interface InventoryPayload {\n // Inventory products available for selection.\n // Since protocol **v25**.\n products: InventoryPayloadProduct[];\n\n // Categories referenced by the payload products.\n // Since protocol **v25**.\n categories: InventoryPayloadCategory[];\n\n // Custom units referenced by the payload products.\n // Since protocol **v25**.\n units: InventoryPayloadUnit[];\n}\n\nexport interface InventoryPayloadProduct {\n // Product identifier.\n // Since protocol **v25**.\n product_id: string;\n\n // Human-readable product name.\n // Since protocol **v25**.\n product_name: string;\n\n // Human-readable product description.\n // Since protocol **v25**.\n description: string;\n\n // Localized product descriptions.\n // Since protocol **v25**.\n description_i18n?: { [lang_tag: string]: string };\n\n // Unit identifier for the product.\n // Since protocol **v25**.\n unit: string;\n\n // Price tiers for the product.\n // Since protocol **v25**.\n unit_prices: AmountString[];\n\n // Whether fractional quantities are allowed for this unit.\n // Since protocol **v25**.\n unit_allow_fraction: boolean;\n\n // Maximum fractional precision (0-6) enforced for this unit.\n // Since protocol **v25**.\n unit_precision_level: Integer;\n\n // Remaining stock available for selection.\n // Since protocol **v25**.\n remaining_stock: DecimalQuantity;\n\n // Category identifiers associated with this product.\n // Since protocol **v25**.\n categories: Integer[];\n\n // Taxes applied to the product.\n // Since protocol **v25**.\n taxes?: Tax[];\n\n // Hash of the product image (if any).\n // Since protocol **v25**.\n image_hash?: string;\n}\n\nexport interface InventoryPayloadCategory {\n // Category identifier.\n // Since protocol **v25**.\n category_id: Integer;\n\n // Human-readable category name.\n // Since protocol **v25**.\n category_name: string;\n\n // Localized category names.\n // Since protocol **v25**.\n category_name_i18n?: { [lang_tag: string]: string };\n}\n\nexport interface InventoryPayloadUnit {\n // Unit identifier.\n // Since protocol **v25**.\n unit: string;\n\n // Human-readable long label.\n // Since protocol **v25**.\n unit_name_long: string;\n\n // Localized long labels.\n // Since protocol **v25**.\n unit_name_long_i18n?: { [lang_tag: string]: string };\n\n // Human-readable short label.\n // Since protocol **v25**.\n unit_name_short: string;\n\n // Localized short labels.\n // Since protocol **v25**.\n unit_name_short_i18n?: { [lang_tag: string]: string };\n\n // Whether fractional quantities are allowed for this unit.\n // Since protocol **v25**.\n unit_allow_fraction: boolean;\n\n // Maximum fractional precision (0-6) enforced for this unit.\n // Since protocol **v25**.\n unit_precision_level: Integer;\n}\n\n/**\n * Key-value pairs matching a subset of the\n * fields from template_contract that are\n * user-editable defaults for this template.\n * Since protocol **v13**.\n */\nexport interface TemplateContractDetailsDefaults {\n summary?: string;\n\n currency?: string;\n\n /**\n * Amount *or* a plain currency string.\n */\n amount?: string;\n}\n\nexport interface TemplatePatchDetails {\n // Human-readable description for the template.\n template_description: string;\n\n // OTP device ID.\n // This parameter is optional.\n otp_id?: string;\n\n // Additional information in a separate template.\n template_contract: TemplateContractDetails;\n\n // Key-value pairs matching a subset of the\n // fields from template_contract that are\n // user-editable defaults for this template.\n // Since protocol **v13**.\n editable_defaults?: TemplateContractDetailsDefaults;\n}\n\nexport interface TemplateSummaryResponse {\n // List of templates that are present in our backend.\n templates: TemplateEntry[];\n}\n\nexport interface TemplateEntry {\n // Template identifier, as found in the template.\n template_id: string;\n\n // Human-readable description for the template.\n template_description: string;\n}\n\nexport interface WalletTemplateDetailsResponse {\n // Hard-coded information about the contract terms\n // for this template.\n template_contract: TemplateContractDetails;\n\n // Key-value pairs matching a subset of the\n // fields from template_contract that are\n // user-editable defaults for this template.\n // Since protocol **v13**.\n editable_defaults?: TemplateContractDetailsDefaults;\n\n // Required currency for payments. Useful if no\n // amount is specified in the template_contract\n // but the user should be required to pay in a\n // particular currency anyway. Merchant backends\n // may reject requests if the template_contract\n // or editable_defaults do\n // specify an amount in a different currency.\n // This parameter is optional.\n // Since protocol **v13**.\n required_currency?: string;\n}\n\nexport interface TemplateDetails {\n // Human-readable description for the template.\n template_description: string;\n\n // OTP device ID.\n // This parameter is optional.\n otp_id?: string;\n\n // Additional information in a separate template.\n template_contract: TemplateContractDetails;\n\n // Key-value pairs matching a subset of the\n // fields from template_contract that are\n // user-editable defaults for this template.\n // Since protocol **v13**.\n editable_defaults?: TemplateContractDetailsDefaults;\n\n // Required currency for payments. Useful if no\n // amount is specified in the template_contract\n // but the user should be required to pay in a\n // particular currency anyway. Merchant backends\n // may reject requests if the template_contract\n // or editable_defaults do\n // specify an amount in a different currency.\n // This parameter is optional.\n // Since protocol **v13**.\n required_currency?: string;\n}\n\nexport type UsingTemplateDetailsRequest = (\n | UsingTemplateFixedOrderRequest\n | UsingTemplateInventoryCartRequest\n | UsingTemplatePaivanaRequest\n) &\n UsingTemplateCommonRequest;\n\nexport interface UsingTemplateCommonRequest {\n // Type of the template being instantiated.\n // Possible values include \"fixed-order\",\n // \"inventory-cart\" and \"paivana\".\n // Since protocol **v25**.\n // Defaults to \"fixed-order\" while supporting previous\n // protocol versions.\n template_type: string;\n\n // Summary to use in the contract. Only if\n // not already specified by the template.\n summary?: string;\n\n // The amount to be paid, including tip.\n amount?: AmountString;\n\n // Optional tip amount. Must match the currency of amount or the\n // fixed template currency.\n // Since protocol **v25**.\n tip?: AmountString;\n}\n\nexport interface UsingTemplateFixedOrderRequest {\n template_type: TemplateType.FIXED_ORDER;\n}\n\nexport interface UsingTemplateInventoryCartRequest {\n template_type: TemplateType.INVENTORY_CART;\n\n // Inventory-cart: selected products and quantities.\n // Since protocol **v25**.\n inventory_selection?: InventorySelectionEntry[];\n}\n\nexport interface InventorySelectionEntry {\n // Inventory product to add.\n product_id: string;\n\n // Quantity in \"[.]\" form using the product unit rules.\n quantity: DecimalQuantity;\n}\n\nexport interface UsingTemplatePaivanaRequest {\n template_type: TemplateType.PAIVANA;\n\n // Website to which access is being sold.\n // Will become the fulfillment URL in the contract.\n website: string;\n\n // Client Paivana ID to grant access to.\n // This becomes the \"session_id\" for session-based\n // access control.\n paivana_id: string;\n}\n\nexport interface WebhookAddDetails {\n // Webhook ID to use.\n webhook_id: string;\n\n // The event of the webhook: why the webhook is used.\n event_type: string;\n\n // URL of the webhook where the customer will be redirected.\n url: string;\n\n // Method used by the webhook\n http_method: string;\n\n // Header template of the webhook\n header_template?: string;\n\n // Body template by the webhook\n body_template?: string;\n}\n\nexport interface WebhookPatchDetails {\n // The event of the webhook: why the webhook is used.\n event_type: string;\n\n // URL of the webhook where the customer will be redirected.\n url: string;\n\n // Method used by the webhook\n http_method: string;\n\n // Header template of the webhook\n header_template?: string;\n\n // Body template by the webhook\n body_template?: string;\n}\n\nexport interface WebhookSummaryResponse {\n // Return webhooks that are present in our backend.\n webhooks: WebhookEntry[];\n}\n\nexport interface WebhookEntry {\n // Webhook identifier, as found in the webhook.\n webhook_id: string;\n\n // The event of the webhook: why the webhook is used.\n event_type: string;\n}\n\nexport interface WebhookDetails {\n // The event of the webhook: why the webhook is used.\n event_type: string;\n\n // URL of the webhook where the customer will be redirected.\n url: string;\n\n // Method used by the webhook\n http_method: string;\n\n // Header template of the webhook\n header_template?: string;\n\n // Body template by the webhook\n body_template?: string;\n}\n\nexport interface TokenFamilyCreateRequest {\n // Identifier for the token family consisting of unreserved characters\n // according to RFC 3986.\n slug: string;\n\n // Human-readable name for the token family.\n name: string;\n\n // Human-readable description for the token family.\n description: string;\n\n // Optional map from IETF BCP 47 language tags to localized descriptions.\n description_i18n?: { [lang_tag: string]: string };\n\n // Start time of the token family's validity period.\n // If not specified, merchant backend will use the current time.\n valid_after?: Timestamp;\n\n // End time of the token family's validity period.\n valid_before: Timestamp;\n\n // Validity duration of an issued token.\n duration: RelativeTime;\n\n // Rounding granularity for the start validity of keys.\n // The desired time is rounded down to a multiple of this\n // granularity and then the start_offset is added to\n // compute the actual start time of the token keys' validity.\n // The end is then computed by adding the duration.\n // Must be 1 minute, 1 hour, 1 day, 1 week, 30 days, 90 days\n // or 365 days (1 year).\n validity_granularity: RelativeTime;\n\n // Offset to add to the start time rounded to validity_granularity\n // to compute the actual start time for a key.\n // Default is zero.\n start_offset?: Integer;\n\n // Kind of the token family.\n kind: TokenFamilyKind;\n}\n\nexport enum TokenFamilyKind {\n Discount = \"discount\",\n Subscription = \"subscription\",\n}\n\nexport interface TokenFamilyUpdateRequest {\n // Human-readable name for the token family.\n name: string;\n\n // Human-readable description for the token family.\n description: string;\n\n // Optional map from IETF BCP 47 language tags to localized descriptions.\n description_i18n: { [lang_tag: string]: string };\n\n // Start time of the token family's validity period.\n valid_after: Timestamp;\n\n // End time of the token family's validity period.\n valid_before: Timestamp;\n\n // Validity duration of an issued token.\n duration: RelativeTime;\n}\n\nexport interface TokenFamiliesList {\n // All configured token families of this instance.\n token_families: TokenFamilySummary[];\n}\n\nexport interface TokenFamilySummary {\n // Identifier for the token family consisting of unreserved characters\n // according to RFC 3986.\n slug: string;\n\n // Human-readable name for the token family.\n name: string;\n\n // Human-readable description for the token family.\n // @since protocol **v23**.\n description: string;\n\n // Optional map from IETF BCP 47 language tags to localized descriptions.\n // @since protocol **v23**.\n description_i18n?: { [lang_tag: string]: string };\n\n // Start time of the token family's validity period.\n valid_after: Timestamp;\n\n // End time of the token family's validity period.\n valid_before: Timestamp;\n\n // Kind of the token family.\n kind: TokenFamilyKind;\n}\n\nexport interface TokenFamilyDetails {\n // Identifier for the token family consisting of unreserved characters\n // according to RFC 3986.\n slug: string;\n\n // Human-readable name for the token family.\n name: string;\n\n // Human-readable description for the token family.\n description: string;\n\n // Optional map from IETF BCP 47 language tags to localized descriptions.\n description_i18n?: { [lang_tag: string]: string };\n\n // Start time of the token family's validity period.\n valid_after: Timestamp;\n\n // End time of the token family's validity period.\n valid_before: Timestamp;\n\n // Validity duration of an issued token.\n duration: RelativeTime;\n\n // Kind of the token family.\n kind: TokenFamilyKind;\n\n // How many tokens have been issued for this family.\n issued: Integer;\n\n // How many tokens have been used for this family.\n used: Integer;\n}\n\nexport enum StatisticBucketRange {\n Hour = \"hour\",\n Day = \"day\",\n Week = \"week\",\n Month = \"month\",\n Quarter = \"quarter\",\n Year = \"year\",\n}\n\nexport interface StatisticAmountByBucket {\n // Start time of the bucket (inclusive)\n start_time: Timestamp;\n\n // End time of the bucket (exclusive)\n end_time: Timestamp;\n\n // Range of the bucket\n range: StatisticBucketRange;\n\n // Sum of all amounts falling under the given\n // SLUG within this timeframe.\n cumulative_amounts: AmountString[];\n}\n\nexport interface StatisticAmountByInterval {\n // Start time of the interval.\n // The interval always ends at the response\n // generation time.\n start_time: Timestamp;\n\n // Sum of all amounts falling under the given\n // SLUG within this timeframe.\n cumulative_amounts: AmountString[];\n}\n\nexport interface StatisticsAmount {\n // Statistics kept for a particular fixed time window.\n buckets: StatisticAmountByBucket[];\n\n // Human-readable bucket statistic description.\n // Unset if no buckets returned\n buckets_description?: string;\n\n // Statistics kept for a particular sliding interval.\n intervals: StatisticAmountByInterval[];\n\n // Human-readable interval statistic description.\n // Unset if no buckets returned\n intervals_description?: string;\n}\n\nexport interface StatisticCounterByBucket {\n // Start time of the bucket (inclusive)\n start_time: Timestamp;\n\n // End time of the bucket (exclusive)\n end_time: Timestamp;\n\n // Range of the bucket\n range: string; //StatisticBucketRange;\n\n // Sum of all counters falling under the given\n // SLUG within this timeframe.\n cumulative_counter: number;\n}\n\nexport interface StatisticCounterByInterval {\n // Start time of the interval.\n // The interval always ends at the response\n // generation time.\n start_time: Timestamp;\n\n // Sum of all counters falling under the given\n // SLUG within this timeframe.\n cumulative_counter: number;\n}\n\nexport interface StatisticsCounter {\n // Statistics kept for a particular fixed time window.\n buckets: StatisticCounterByBucket[];\n\n // Human-readable bucket statistic description.\n // Unset if no buckets returned\n buckets_description?: string;\n\n // Statistics kept for a particular sliding interval.\n intervals: StatisticCounterByInterval[];\n\n // Human-readable interval statistic description.\n // Unset if no intervals returned\n intervals_description?: string;\n}\n\nexport interface OrderChoice {\n // Total price for the choice. The exchange will subtract deposit\n // fees from that amount before transferring it to the merchant.\n amount: AmountString;\n\n // Human readable description of the semantics of the choice\n // within the contract to be shown to the user at payment.\n description?: string;\n\n // Map from IETF 47 language tags to localized descriptions.\n description_i18n?: InternationalizedString;\n\n // Inputs that must be provided by the customer, if this choice is selected.\n // Defaults to empty array if not specified.\n inputs?: OrderInput[];\n\n // Outputs provided by the merchant, if this choice is selected.\n // Defaults to empty array if not specified.\n outputs?: OrderOutput[];\n\n // Maximum total deposit fee accepted by the merchant for this contract.\n // Overrides defaults of the merchant instance.\n max_fee?: AmountString;\n}\n\nexport enum OrderInputType {\n Token = \"token\",\n}\n\nexport type OrderInput = OrderInputToken;\n\nexport interface OrderInputToken {\n // Token input.\n type: OrderInputType.Token;\n\n // Token family slug as configured in the merchant backend. Slug is unique\n // across all configured tokens of a merchant.\n token_family_slug: string;\n\n // How many units of the input are required.\n // Defaults to 1 if not specified. Output with count == 0 are ignored by\n // the merchant backend.\n count?: Integer;\n}\n\nexport enum OrderOutputType {\n Token = \"token\",\n TaxReceipt = \"tax-receipt\",\n}\n\nexport type OrderOutput = OrderOutputToken | OrderOutputTaxReceipt;\n\nexport interface OrderOutputToken {\n type: OrderOutputType.Token;\n\n // Token family slug as configured in the merchant backend. Slug is unique\n // across all configured tokens of a merchant.\n token_family_slug: string;\n\n // How many units of the output are issued by the merchant.\n // Defaults to 1 if not specified. Output with count == 0 are ignored by\n // the merchant backend.\n count?: Integer;\n\n // When should the output token be valid. Can be specified if the\n // desired validity period should be in the future (like selling\n // a subscription for the next month). Optional. If not given,\n // the validity is supposed to be \"now\" (time of order creation).\n valid_at?: TalerPreciseTimestamp;\n}\n\nexport interface OrderOutputTaxReceipt {\n type: OrderOutputType.TaxReceipt;\n\n // Total amount that will be on the tax receipt.\n // Optional, if missing the full amount will be on the receipt.\n amount?: AmountString;\n\n donau_urls: string[];\n}\n\nexport interface OrderCommon {\n // Human-readable description of the whole purchase.\n summary: string;\n\n // Map from IETF BCP 47 language tags to localized summaries.\n summary_i18n?: { [lang_tag: string]: string };\n\n // Unique, free-form identifier for the proposal.\n // Must be unique within a merchant instance.\n // For merchants that do not store proposals in their DB\n // before the customer paid for them, the order_id can be used\n // by the frontend to restore a proposal from the information\n // encoded in it (such as a short product identifier and timestamp).\n order_id?: string;\n\n // URL where the same contract could be ordered again (if\n // available). Returned also at the public order endpoint\n // for people other than the actual buyer (hence public,\n // in case order IDs are guessable).\n public_reorder_url?: string;\n\n // URL that will show that the order was successful after\n // it has been paid for. Optional. When POSTing to the\n // merchant, the placeholder \"${ORDER_ID}\" will be\n // replaced with the actual order ID (useful if the\n // order ID is generated server-side and needs to be\n // in the URL).\n // Note that this placeholder can only be used once.\n // Either fulfillment_url or fulfillment_message must be specified.\n fulfillment_url?: string;\n\n // Message shown to the customer after paying for the order.\n // Either fulfillment_url or fulfillment_message must be specified.\n fulfillment_message?: string;\n\n // Map from IETF BCP 47 language tags to localized fulfillment\n // messages.\n fulfillment_message_i18n?: { [lang_tag: string]: string };\n\n // List of products that are part of the purchase (see Product).\n products?: ProductSold[];\n\n // Time when this contract was generated.\n timestamp?: Timestamp;\n\n // After this deadline has passed, no refunds will be accepted.\n refund_deadline?: Timestamp;\n\n // After this deadline, the merchant won't accept payments for the contract.\n pay_deadline?: Timestamp;\n\n // Transfer deadline for the exchange. Must be in the\n // deposit permissions of coins used to pay for this order.\n wire_transfer_deadline?: Timestamp;\n\n // Base URL of the (public!) merchant backend API.\n // Must be an absolute URL that ends with a slash.\n merchant_base_url?: string;\n\n // Wire transfer method identifier for the wire method associated with h_wire.\n // The wallet may only select exchanges via a matching auditor if the\n // exchange also supports this wire method.\n // The wire transfer fees must be added based on this wire transfer method.\n wire_method?: string;\n\n // Delivery location for (all!) products.\n delivery_location?: Location;\n\n // Time indicating when the order should be delivered.\n // May be overwritten by individual products.\n delivery_date?: Timestamp;\n\n // Specifies for how long the wallet should try to get an\n // automatic refund for the purchase. If this field is\n // present, the wallet should wait for a few seconds after\n // the purchase and then automatically attempt to obtain\n // a refund. The wallet should probe until \"delay\"\n // after the payment was successful (i.e. via long polling\n // or via explicit requests with exponential back-off).\n //\n // In particular, if the wallet is offline\n // at that time, it MUST repeat the request until it gets\n // one response from the merchant after the delay has expired.\n // If the refund is granted, the wallet MUST automatically\n // recover the payment. This is used in case a merchant\n // knows that it might be unable to satisfy the contract and\n // desires for the wallet to attempt to get the refund without any\n // customer interaction. Note that it is NOT an error if the\n // merchant does not grant a refund.\n auto_refund?: RelativeTime;\n\n // Extra data that is only interpreted by the merchant frontend.\n // Useful when the merchant needs to store extra information on a\n // contract without storing it separately in their database.\n extra?: any;\n\n // Minimum age buyer must have (in years). Default is 0.\n minimum_age?: Integer;\n\n // Money pot to increment for whatever order payment amount\n // is not yet assigned to a pot via the ProductSold.\n // Not useful to wallets, only for\n // merchant-internal accounting.\n // Since protocol **v25**.\n order_default_money_pot?: Integer;\n}\n\nexport enum OrderVersion {\n V0 = 0,\n V1 = 1,\n}\n\nexport interface OrderV0 extends OrderCommon {\n // Optional, defaults to 0 if not set.\n version?: OrderVersion.V0;\n\n // Total price for the transaction. The exchange will subtract deposit\n // fees from that amount before transferring it to the merchant.\n amount: AmountString;\n\n // Maximum total deposit fee accepted by the merchant for this contract.\n // Overrides defaults of the merchant instance.\n max_fee?: AmountString;\n}\n\nexport interface OrderV1 extends OrderCommon {\n // Version 1 order support discounts and subscriptions.\n // https://docs.taler.net/design-documents/046-mumimo-contracts.html\n // @since protocol **v21**\n version: OrderVersion.V1;\n\n // List of contract choices that the customer can select from.\n // @since protocol **v21**\n choices?: OrderChoice[];\n}\n\nexport interface ProductSold {\n // Merchant-internal identifier for the product.\n product_id?: string;\n\n // Name of the product.\n // Since API version **v20**. Optional only for\n // backwards-compatibility, should be considered mandatory\n // moving forward!\n product_name?: string;\n\n // Human-readable product description.\n description: string;\n\n // Map from IETF BCP 47 language tags to localized descriptions.\n description_i18n?: { [lang_tag: string]: string };\n\n // The number of units of the product to deliver to the customer.\n quantity?: Integer;\n\n // Unit in which the product is measured (liters, kilograms, packages, etc.).\n unit?: string;\n\n // The price of the product; this is the total price for quantity times unit of this product.\n price?: AmountString;\n\n // An optional base64-encoded product image.\n image?: ImageDataUrl;\n\n // A list of taxes paid by the merchant for this product. Can be empty.\n taxes?: Tax[];\n\n // Time indicating when this product should be delivered.\n delivery_date?: Timestamp;\n\n // Money pot to use for this product, overrides value from\n // the inventory if given. Not useful to wallets, only for\n // merchant-internal accounting.\n // Since **v25**.\n product_money_pot?: Integer;\n}\n\nexport interface Tax {\n // The name of the tax.\n name: string;\n\n // Amount paid in tax.\n tax: AmountString;\n}\n\nexport interface Merchant {\n // The merchant's legal name of business.\n name: string;\n\n // Label for a location with the business address of the merchant.\n email?: string;\n\n // Label for a location with the business address of the merchant.\n website?: string;\n\n // An optional base64-encoded product image.\n logo?: ImageDataUrl;\n\n // Label for a location with the business address of the merchant.\n address?: Location;\n\n // Label for a location that denotes the jurisdiction for disputes.\n // Some of the typical fields for a location (such as a street address) may be absent.\n jurisdiction?: Location;\n}\n\n// Delivery location, loosely modeled as a subset of\n// ISO20022's PostalAddress25.\nexport interface Location {\n // Nation with its own government.\n country?: string;\n\n // Identifies a subdivision of a country such as state, region, county.\n country_subdivision?: string;\n\n // Identifies a subdivision within a country sub-division.\n district?: string;\n\n // Name of a built-up area, with defined boundaries, and a local government.\n town?: string;\n\n // Specific location name within the town.\n town_location?: string;\n\n // Identifier consisting of a group of letters and/or numbers that\n // is added to a postal address to assist the sorting of mail.\n post_code?: string;\n\n // Name of a street or thoroughfare.\n street?: string;\n\n // Name of the building or house.\n building_name?: string;\n\n // Number that identifies the position of a building on a street.\n building_number?: string;\n\n // Free-form address lines, should not exceed 7 elements.\n address_lines?: string[];\n}\n\nexport interface Exchange {\n // The exchange's base URL.\n url: string;\n\n // How much would the merchant like to use this exchange.\n // The wallet should use a suitable exchange with high\n // priority. The following priority values are used, but\n // it should be noted that they are NOT in any way normative.\n //\n // 0: likely it will not work (recently seen with account\n // restriction that would be bad for this merchant)\n // 512: merchant does not know, might be down (merchant\n // did not yet get /wire response).\n // 1024: good choice (recently confirmed working)\n priority: Integer;\n\n // Master public key of the exchange.\n master_pub: EddsaPublicKey;\n\n // Maximum amount that the merchant could be paid\n // using this exchange (due to legal limits).\n // New in protocol **v17**.\n // Optional, no limit if missing.\n max_contribution?: AmountString;\n}\n\nexport interface MerchantReserveCreateConfirmation {\n // Public key identifying the reserve.\n reserve_pub: EddsaPublicKey;\n\n // Wire accounts of the exchange where to transfer the funds.\n accounts: ExchangeWireAccount[];\n}\n\nexport interface TemplateEditableDetails {\n // Human-readable summary for the template.\n summary?: string;\n\n // Required currency for payments to the template.\n // The user may specify any amount, but it must be\n // in this currency.\n // This parameter is optional and should not be present\n // if \"amount\" is given.\n currency?: string;\n\n // The price is imposed by the merchant and cannot be changed by the customer.\n // This parameter is optional.\n amount?: AmountString;\n}\n\nexport interface MerchantTemplateContractDetails {\n // Human-readable summary for the template.\n summary?: string;\n\n // The price is imposed by the merchant and cannot be changed by the customer.\n // This parameter is optional.\n amount?: string;\n\n // Minimum age buyer must have (in years). Default is 0.\n minimum_age: number;\n\n // The time the customer need to pay before his order will be deleted.\n // It is deleted if the customer did not pay and if the duration is over.\n pay_duration: TalerProtocolDuration;\n}\n\nexport interface MerchantTemplateAddDetails {\n // Template ID to use.\n template_id: string;\n\n // Human-readable description for the template.\n template_description: string;\n\n // A base64-encoded image selected by the merchant.\n // This parameter is optional.\n // We are not sure about it.\n image?: string;\n\n editable_defaults?: TemplateEditableDetails;\n\n // Additional information in a separate template.\n template_contract: MerchantTemplateContractDetails;\n\n // OTP device ID.\n // This parameter is optional.\n otp_id?: string;\n}\n\nexport interface ExchangeStatusResponse {\n exchanges: ExchangeStatusDetail[];\n}\n\nexport interface ExchangeStatusDetail {\n // Base URL of the exchange this is about.\n exchange_url: string;\n\n // Time when the backend will download /keys next.\n next_download: Timestamp;\n\n // Time when the current /keys response is expected to\n // expire. Missing if we do not have one.\n keys_expiration?: Timestamp;\n\n // HTTP status code returned by the exchange when we asked for\n // /keys. 0 if we did not receive an HTTP status code.\n // Usually 200 for success.\n keys_http_status: Integer;\n\n // Numeric error code indicating an\n // error we had processing the /keys response.\n keys_ec: Integer;\n\n // Human-readable error description matching keys_ec.\n keys_hint: string;\n}\n\nexport const codecForExchangeStatusResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchanges\", codecForList(codecForExchangeStatusDetail()))\n .build(\"TalerMerchantApi.ExchangeStatusResponse\");\n\nexport const codecForExchangeStatusDetail = (): Codec =>\n buildCodecForObject()\n .property(\"exchange_url\", codecForCanonBaseUrl())\n .property(\"next_download\", codecForTimestamp)\n .property(\"keys_expiration\", codecOptional(codecForTimestamp))\n .property(\"keys_http_status\", codecForNumber())\n .property(\"keys_ec\", codecForNumber())\n .property(\"keys_hint\", codecForString())\n .build(\"TalerMerchantApi.ExchangeStatusDetail\");\n\nconst codecForExchangeConfigInfo = (): Codec =>\n buildCodecForObject()\n .property(\"base_url\", codecForString())\n .property(\"currency\", codecForString())\n .property(\"master_pub\", codecForEddsaPublicKey())\n .build(\"TalerMerchantApi.ExchangeConfigInfo\");\n\nexport const codecForTalerMerchantConfigResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForConstString(\"taler-merchant\"))\n .property(\"currency\", codecForString())\n .property(\n \"default_persona\",\n codecOptionalDefault(\n codecForEither(\n codecForConstString(\"expert\"),\n codecForConstString(\"offline-vending-machine\"),\n codecForConstString(\"point-of-sale\"),\n codecForConstString(\"digital-publishing\"),\n codecForConstString(\"e-commerce\"),\n ),\n \"expert\",\n ),\n )\n .property(\"version\", codecForString())\n .property(\"currencies\", codecForMap(codecForCurrencySpecificiation()))\n .property(\n \"report_generators\",\n codecOptionalDefault(codecForList(codecForString()), []),\n )\n .property(\"phone_regex\", codecOptional(codecForString()))\n .property(\"exchanges\", codecForList(codecForExchangeConfigInfo()))\n .property(\"implementation\", codecOptional(codecForString()))\n .property(\n \"have_self_provisioning\",\n codecOptionalDefault(codecForBoolean(), false),\n )\n .property(\"have_donau\", codecOptionalDefault(codecForBoolean(), false))\n .property(\n \"mandatory_tan_channels\",\n codecOptionalDefault(\n codecForList(\n codecForEither(\n codecForConstString(TanChannel.SMS),\n codecForConstString(TanChannel.EMAIL),\n ),\n ),\n [],\n ),\n )\n .property(\"default_pay_delay\", codecOptional(codecForDuration))\n .property(\"default_refund_delay\", codecOptional(codecForDuration))\n .property(\"default_wire_transfer_delay\", codecOptional(codecForDuration))\n .property(\n \"payment_target_regex\",\n codecOptionalDefault(codecForString(), \"*\"),\n )\n .property(\n \"payment_target_types\",\n codecOptionalDefault(codecForString(), \"*\"),\n )\n .property(\n \"default_wire_transfer_rounding_interval\",\n codecOptional(codecForRoundingInterval),\n )\n .build(\"TalerMerchantApi.VersionResponse\");\n\nexport const codecForRoundingInterval = codecForEither(\n codecForConstString(RoundingInterval.NONE),\n codecForConstString(RoundingInterval.SECOND),\n codecForConstString(RoundingInterval.MINUTE),\n codecForConstString(RoundingInterval.HOUR),\n codecForConstString(RoundingInterval.DAY),\n codecForConstString(RoundingInterval.WEEK),\n codecForConstString(RoundingInterval.MONTH),\n codecForConstString(RoundingInterval.QUARTER),\n codecForConstString(RoundingInterval.YEAR),\n);\n\nexport const codecForClaimResponse = (): Codec =>\n buildCodecForObject()\n // Must be 'any', otherwise, contract terms won't match.\n .property(\"contract_terms\", codecForAny())\n .property(\"sig\", codecForEddsaSignature())\n .build(\"TalerMerchantApi.ClaimResponse\");\n\nexport const codecForPaymentResponse = (): Codec =>\n buildCodecForObject()\n .property(\"pos_confirmation\", codecOptional(codecForString()))\n .property(\"sig\", codecForEddsaSignature())\n .build(\"TalerMerchantApi.PaymentResponse\");\n\nexport const codecForPaymentDeniedLegallyResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"exchange_base_urls\",\n codecOptionalDefault(codecForList(codecForString()), []),\n )\n .build(\"TalerMerchantApi.PaymentDeniedLegallyResponse\");\n\nexport const codecForStatusPaid = (): Codec =>\n buildCodecForObject()\n .property(\"refund_amount\", codecForAmountString())\n .property(\"refund_pending\", codecForBoolean())\n .property(\"refund_taken\", codecForAmountString())\n .property(\"refunded\", codecForBoolean())\n .property(\"type\", codecForConstString(\"paid\"))\n .build(\"TalerMerchantApi.StatusPaid\");\n\nexport const codecForStatusGoto = (): Codec =>\n buildCodecForObject()\n .property(\"public_reorder_url\", codecForURLString())\n .property(\"type\", codecForConstString(\"goto\"))\n .build(\"TalerMerchantApi.StatusGotoResponse\");\n\nexport const codecForStatusStatusUnpaid = (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"unpaid\"))\n .property(\"already_paid_order_id\", codecOptional(codecForString()))\n .property(\"fulfillment_url\", codecOptional(codecForString()))\n .property(\"taler_pay_uri\", codecForTalerUriString())\n .build(\"TalerMerchantApi.PaymentResponse\");\n\nexport const codecForPaidRefundStatusResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"pos_confirmation\", codecOptional(codecForString()))\n .property(\"refunded\", codecForBoolean())\n .build(\"TalerMerchantApi.PaidRefundStatusResponse\");\n\nexport const codecForMerchantAbortPayRefundSuccessStatus =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchange_pub\", codecForString())\n .property(\"exchange_sig\", codecForString())\n .property(\"exchange_status\", codecForConstNumber(200))\n .property(\"type\", codecForConstString(\"success\"))\n .build(\"TalerMerchantApi.MerchantAbortPayRefundSuccessStatus\");\n\nexport const codecForMerchantAbortPayRefundFailureStatus =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchange_code\", codecForNumber())\n .property(\"exchange_reply\", codecForAny())\n .property(\"exchange_status\", codecForNumber())\n .property(\"type\", codecForConstString(\"failure\"))\n .build(\"TalerMerchantApi.MerchantAbortPayRefundFailureStatus\");\n\nexport const codecForMerchantAbortPayRefundUndepositedStatus =\n (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"undeposited\"))\n .build(\"TalerMerchantApi.MerchantAbortPayRefundUndepositedStatus\");\n\nexport const codecForMerchantAbortPayRefundStatus =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\"success\", codecForMerchantAbortPayRefundSuccessStatus())\n .alternative(\"failure\", codecForMerchantAbortPayRefundFailureStatus())\n .alternative(\n \"undeposited\",\n codecForMerchantAbortPayRefundUndepositedStatus(),\n )\n .build(\"TalerMerchantApi.MerchantAbortPayRefundStatus\");\n\nexport const codecForAbortResponse = (): Codec =>\n buildCodecForObject()\n .property(\"refunds\", codecForList(codecForMerchantAbortPayRefundStatus()))\n .build(\"TalerMerchantApi.AbortResponse\");\n\nexport const codecForWalletRefundResponse = (): Codec =>\n buildCodecForObject()\n .property(\"merchant_pub\", codecForEddsaPublicKey())\n .property(\"refund_amount\", codecForAmountString())\n .property(\"refunds\", codecForList(codecForMerchantCoinRefundStatus()))\n .build(\"TalerMerchantApi.AbortResponse\");\n\nexport const codecForMerchantCoinRefundSuccessStatus =\n (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"success\"))\n .property(\"coin_pub\", codecForEddsaPublicKey())\n .property(\"exchange_status\", codecForConstNumber(200))\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"rtransaction_id\", codecForNumber())\n .property(\"refund_amount\", codecForAmountString())\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .property(\"execution_time\", codecForTimestamp)\n .build(\"TalerMerchantApi.MerchantCoinRefundSuccessStatus\");\n\nexport const codecForMerchantCoinRefundFailureStatus =\n (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"failure\"))\n .property(\"coin_pub\", codecForEddsaPublicKey())\n .property(\"exchange_status\", codecForNumber())\n .property(\"rtransaction_id\", codecForNumber())\n .property(\"refund_amount\", codecForAmountString())\n .property(\"exchange_code\", codecOptional(codecForNumber()))\n .property(\"exchange_reply\", codecOptional(codecForAny()))\n .property(\"execution_time\", codecForTimestamp)\n .build(\"TalerMerchantApi.MerchantCoinRefundFailureStatus\");\n\nexport const codecForMerchantCoinRefundStatus =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\"success\", codecForMerchantCoinRefundSuccessStatus())\n .alternative(\"failure\", codecForMerchantCoinRefundFailureStatus())\n .build(\"TalerMerchantApi.MerchantCoinRefundStatus\");\n\nexport const codecForMerchantAuthMethod = codecForEither(\n codecForConstString(MerchantAuthMethod.TOKEN),\n);\n\nexport const codecForQueryInstancesResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"email\", codecOptional(codecForString()))\n .property(\"phone_number\", codecOptional(codecForString()))\n .property(\"website\", codecOptional(codecForString()))\n .property(\"email_validated\", codecOptional(codecForBoolean()))\n .property(\"phone_validated\", codecOptional(codecForBoolean()))\n .property(\"logo\", codecOptional(codecForString()))\n .property(\"merchant_pub\", codecForEddsaPublicKey())\n .property(\"address\", codecForLocation())\n .property(\"jurisdiction\", codecForLocation())\n .property(\"use_stefan\", codecForBoolean())\n .property(\"default_wire_transfer_delay\", codecForDuration)\n .property(\"default_pay_delay\", codecForDuration)\n .property(\"default_refund_delay\", codecForDuration)\n .property(\n \"default_wire_transfer_rounding_interval\",\n codecOptional(codecForRoundingInterval),\n )\n .property(\n \"auth\",\n buildCodecForObject<{\n method: MerchantAuthMethod.TOKEN;\n }>()\n .property(\"method\", codecForMerchantAuthMethod)\n .build(\"TalerMerchantApi.QueryInstancesResponse.auth\"),\n )\n .build(\"TalerMerchantApi.QueryInstancesResponse\");\n\nexport const codecForAccountKycRedirects =\n (): Codec =>\n buildCodecForObject()\n .property(\"kyc_data\", codecForList(codecForMerchantAccountKycRedirect()))\n\n .build(\"TalerMerchantApi.MerchantAccountKycRedirectsResponse\");\n\nexport const codecForMerchantAccountKycStatus = codecForEither(\n codecForConstString(MerchantAccountKycStatus.AWAITING_AML_REVIEW),\n codecForConstString(MerchantAccountKycStatus.UNSUPPORTED_ACCOUNT),\n codecForConstString(MerchantAccountKycStatus.EXCHANGE_GATEWAY_TIMEOUT),\n codecForConstString(MerchantAccountKycStatus.EXCHANGE_INTERNAL_ERROR),\n codecForConstString(MerchantAccountKycStatus.EXCHANGE_STATUS_INVALID),\n codecForConstString(MerchantAccountKycStatus.EXCHANGE_UNREACHABLE),\n codecForConstString(MerchantAccountKycStatus.KYC_REQUIRED),\n codecForConstString(MerchantAccountKycStatus.KYC_WIRE_IMPOSSIBLE),\n codecForConstString(MerchantAccountKycStatus.KYC_WIRE_REQUIRED),\n codecForConstString(MerchantAccountKycStatus.LOGIC_BUG),\n codecForConstString(MerchantAccountKycStatus.NO_EXCHANGE_KEY),\n codecForConstString(MerchantAccountKycStatus.READY),\n);\n\nexport const codecForMerchantAccountKycRedirect =\n (): Codec =>\n buildCodecForObject()\n .property(\"status\", codecForMerchantAccountKycStatus)\n .property(\"h_wire\", codecForString())\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"exchange_url\", codecForURLString())\n .property(\"exchange_currency\", codecOptional(codecForString()))\n .property(\"exchange_http_status\", codecForNumber())\n .property(\"no_keys\", codecForBoolean())\n .property(\"auth_conflict\", codecForBoolean())\n .property(\"exchange_code\", codecOptional(codecForNumber()))\n .property(\"access_token\", codecOptional(codecForAccessToken()))\n .property(\"limits\", codecOptional(codecForList(codecForAccountLimit())))\n .property(\"payto_kycauths\", codecOptional(codecForList(codecForString())))\n .build(\"TalerMerchantApi.MerchantAccountKycRedirect\");\n\nexport const codecForTokenScope = codecForEither(\n codecForConstString(LoginTokenScope.All),\n codecForConstString(LoginTokenScope.Spa),\n codecForConstString(LoginTokenScope.OrderFull),\n codecForConstString(LoginTokenScope.OrderManagement),\n codecForConstString(LoginTokenScope.OrderPos),\n codecForConstString(LoginTokenScope.OrderSimple),\n codecForConstString(LoginTokenScope.ReadOnly),\n codecForConstString(LoginTokenScope.All_Refreshable),\n codecForConstString(LoginTokenScope.Spa_Refreshable),\n codecForConstString(LoginTokenScope.OrderFull_Refreshable),\n codecForConstString(LoginTokenScope.OrderManagement_Refreshable),\n codecForConstString(LoginTokenScope.OrderPos_Refreshable),\n codecForConstString(LoginTokenScope.OrderSimple_Refreshable),\n codecForConstString(LoginTokenScope.ReadOnly_Refreshable),\n);\n\nexport const codecForLoginTokenSuccessResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"scope\", codecForTokenScope)\n .property(\"access_token\", codecForAccessToken())\n .property(\"expiration\", codecForTimestamp)\n .property(\"refreshable\", codecForBoolean())\n .build(\"TalerMerchantApi.LoginTokenSuccessResponse\");\n\nexport const codecForExchangeKycTimeout = (): Codec =>\n buildCodecForObject()\n .property(\"exchange_url\", codecForURLString())\n .property(\"exchange_code\", codecForNumber())\n .property(\"exchange_http_status\", codecForNumber())\n .build(\"TalerMerchantApi.ExchangeKycTimeout\");\n\nexport const codecForAccountAddResponse = (): Codec =>\n buildCodecForObject()\n .property(\"h_wire\", codecForString())\n .property(\"salt\", codecForString())\n .build(\"TalerMerchantApi.AccountAddResponse\");\n\nexport const codecForAccountsSummaryResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"accounts\", codecForList(codecForBankAccountEntry()))\n .build(\"TalerMerchantApi.AccountsSummaryResponse\");\n\nexport const codecForBankAccountEntry = (): Codec =>\n buildCodecForObject()\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"h_wire\", codecForString())\n .property(\"active\", codecOptional(codecForBoolean()))\n .build(\"TalerMerchantApi.BankAccountEntry\");\n\nexport const codecForBankAccountDetail = (): Codec =>\n buildCodecForObject()\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"h_wire\", codecForString())\n .property(\"extra_wire_subject_metadata\", codecOptional(codecForString()))\n .property(\"salt\", codecForString())\n .property(\"credit_facade_url\", codecOptional(codecForURLString()))\n .property(\"active\", codecOptional(codecForBoolean()))\n .build(\"TalerMerchantApi.BankAccountEntry\");\n\nexport const codecForCategoryListResponse = (): Codec =>\n buildCodecForObject()\n .property(\"categories\", codecForList(codecForCategoryListEntry()))\n .build(\"TalerMerchantApi.CategoryListResponse\");\n\nexport const codecForCategoryListEntry = (): Codec =>\n buildCodecForObject()\n .property(\"category_id\", codecForNumber())\n .property(\"name\", codecForString())\n .property(\"name_i18n\", codecForInternationalizedString())\n .property(\"product_count\", codecForNumber())\n .build(\"TalerMerchantApi.CategoryListEntry\");\n\nexport const codecForCategoryProductList = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"name_i18n\", codecForInternationalizedString())\n .property(\"products\", codecForList(codecForProductSummary()))\n .build(\"TalerMerchantApi.CategoryProductList\");\n\nexport const codecForProductSummary = (): Codec =>\n buildCodecForObject()\n .property(\"product_id\", codecForString())\n .build(\"TalerMerchantApi.CategoryProductSummary\");\n\nexport const codecForInventorySummaryResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"products\", codecForList(codecForInventoryEntry()))\n .build(\"TalerMerchantApi.InventorySummaryResponse\");\n\nexport const codecForInventoryEntry = (): Codec =>\n buildCodecForObject()\n .property(\"product_id\", codecForString())\n .property(\"product_serial\", codecForNumber())\n .build(\"TalerMerchantApi.InventoryEntry\");\n\nexport const codecForMerchantPosProductDetail =\n (): Codec =>\n buildCodecForObject()\n .property(\"product_serial\", codecForNumber())\n .property(\"product_id\", codecOptional(codecForString()))\n .property(\"product_name\", codecOptional(codecForString()))\n .property(\"categories\", codecForList(codecForNumber()))\n .property(\"description\", codecForString())\n .property(\"description_i18n\", codecForInternationalizedString())\n .property(\"unit\", codecForString())\n .property(\"price\", codecForAmountString())\n .property(\"image\", codecForString())\n .property(\"taxes\", codecOptional(codecForList(codecForTax())))\n .property(\"total_stock\", codecForNumber())\n .property(\"minimum_age\", codecOptional(codecForNumber()))\n .build(\"TalerMerchantApi.MerchantPosProductDetail\");\n\nexport const codecForMerchantCategory = (): Codec =>\n buildCodecForObject()\n .property(\"id\", codecForNumber())\n .property(\"name\", codecForString())\n .property(\"name_i18n\", codecForInternationalizedString())\n .build(\"TalerMerchantApi.MerchantCategory\");\n\nexport const codecForFullInventoryDetailsResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"categories\", codecForList(codecForMerchantCategory()))\n .property(\"products\", codecForList(codecForMerchantPosProductDetail()))\n .build(\"TalerMerchantApi.FullInventoryDetailsResponse\");\n\nexport const codecForProductDetailResponse = (): Codec =>\n buildCodecForObject()\n .property(\"description\", codecForString())\n .property(\"description_i18n\", codecForInternationalizedString())\n .property(\"unit\", codecForString())\n .property(\"product_name\", codecOptional(codecForString()))\n .property(\"price\", codecForAmountString())\n .property(\"image\", codecForString())\n .property(\"categories\", codecForList(codecForNumber()))\n .property(\"taxes\", codecOptional(codecForList(codecForTax())))\n .property(\"address\", codecOptional(codecForLocation()))\n .property(\"next_restock\", codecOptional(codecForTimestamp))\n .property(\"total_stock\", codecForNumber())\n .property(\"total_sold\", codecForNumber())\n .property(\"total_lost\", codecForNumber())\n .property(\"minimum_age\", codecOptional(codecForNumber()))\n .property(\"money_pot_id\", codecOptional(codecForNumber()))\n .property(\"product_group_id\", codecOptional(codecForNumber()))\n .build(\"TalerMerchantApi.ProductDetailResponse\");\n\nexport const codecForTax = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"tax\", codecForAmountString())\n .build(\"TalerMerchantApi.Tax\");\n\nexport const codecForPostOrderResponse = (): Codec =>\n buildCodecForObject()\n .property(\"order_id\", codecForString())\n .property(\"pay_deadline\", codecOptional(codecForTimestamp))\n .property(\"token\", codecOptional(codecForString()))\n .build(\"TalerMerchantApi.PostOrderResponse\");\n\nexport const codecForOutOfStockResponse = (): Codec =>\n buildCodecForObject()\n .property(\"product_id\", codecForString())\n .property(\"available_quantity\", codecForNumber())\n .property(\"requested_quantity\", codecForNumber())\n .property(\"unit_available_quantity\", codecForString())\n .property(\"unit_requested_quantity\", codecForString())\n .property(\"restock_expected\", codecOptional(codecForTimestamp))\n .build(\"TalerMerchantApi.OutOfStockResponse\");\n\nexport const codecForOrderHistory = (): Codec =>\n buildCodecForObject()\n .property(\"orders\", codecForList(codecForOrderHistoryEntry()))\n .build(\"TalerMerchantApi.OrderHistory\");\n\nexport const codecForOrderHistoryEntry = (): Codec =>\n buildCodecForObject()\n .property(\"order_id\", codecForString())\n .property(\"row_id\", codecForNumber())\n .property(\"timestamp\", codecForTimestamp)\n .property(\"amount\", codecForAmountString())\n .property(\"refund_amount\", codecOptional(codecForAmountString()))\n .property(\"pending_refund_amount\", codecOptional(codecForAmountString()))\n .property(\"summary\", codecForString())\n .property(\"refundable\", codecForBoolean())\n .property(\"paid\", codecForBoolean())\n .build(\"TalerMerchantApi.OrderHistoryEntry\");\n\nexport const codecForMerchant = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"email\", codecOptional(codecForString()))\n .property(\"logo\", codecOptional(codecForString()))\n .property(\"website\", codecOptional(codecForString()))\n .property(\"address\", codecOptional(codecForLocation()))\n .property(\"jurisdiction\", codecOptional(codecForLocation()))\n .build(\"TalerMerchantApi.MerchantInfo\");\n\nexport const codecForExchange = (): Codec =>\n buildCodecForObject()\n .property(\"master_pub\", codecForEddsaPublicKey())\n .property(\"priority\", codecForNumber())\n .property(\"url\", codecForString())\n .property(\"max_contribution\", codecOptional(codecForAmountString()))\n .build(\"TalerMerchantApi.Exchange\");\n\nconst codecForOrderCommon = (): ObjectCodec =>\n buildCodecForObject()\n .property(\"order_id\", codecOptional(codecForString()))\n .property(\"public_reorder_url\", codecOptional(codecForString()))\n .property(\"fulfillment_url\", codecOptional(codecForString()))\n .property(\"fulfillment_message\", codecOptional(codecForString()))\n .property(\n \"fulfillment_message_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"merchant_base_url\", codecOptional(codecForString()))\n .property(\"auto_refund\", codecOptional(codecForDuration))\n .property(\"summary\", codecForString())\n .property(\"summary_i18n\", codecOptional(codecForInternationalizedString()))\n .property(\"pay_deadline\", codecOptional(codecForTimestamp))\n .property(\"refund_deadline\", codecOptional(codecForTimestamp))\n .property(\"wire_transfer_deadline\", codecOptional(codecForTimestamp))\n .property(\"timestamp\", codecOptional(codecForTimestamp))\n .property(\"delivery_location\", codecOptional(codecForLocation()))\n .property(\"delivery_date\", codecOptional(codecForTimestamp))\n .property(\"products\", codecOptional(codecForList(codecForProductSold())))\n .property(\"extra\", codecOptional(codecForAny()))\n .property(\"order_default_money_pot\", codecOptional(codecForNumber()))\n .build(\"TalerMerchantApi.Order\");\n\nexport const codecForOrderV0 = (): Codec =>\n buildCodecForObject()\n .property(\"version\", codecOptional(codecForConstNumber(OrderVersion.V0)))\n .property(\"amount\", codecForAmountString())\n .property(\"max_fee\", codecOptional(codecForAmountString()))\n .mixin(codecForOrderCommon())\n .build(\"TalerMerchantApi.OrderV0\");\n\nexport const codecForOrderV1 = (): Codec =>\n buildCodecForObject()\n .property(\"version\", codecForConstNumber(OrderVersion.V1))\n .property(\"choices\", codecForList(codecForOrderChoice()))\n .mixin(codecForOrderCommon())\n .build(\"TalerMerchantApi.OrderV1\");\n\nexport const codecForOrder = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"version\")\n .alternative(undefined, codecForOrderV0())\n .alternative(OrderVersion.V0, codecForOrderV0())\n .alternative(OrderVersion.V1, codecForOrderV1())\n .build(\"TalerMerchantApi.Order\");\n\nexport const codecForOrderChoice = (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"description\", codecOptional(codecForString()))\n .property(\n \"description_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"max_fee\", codecOptional(codecForAmountString()))\n .property(\"inputs\", codecOptional(codecForList(codecForOrderInput())))\n .property(\"outputs\", codecOptional(codecForList(codecForOrderOutput())))\n .build(\"TalerMerchantApi.OrderChoice\");\n\nexport const codecForOrderInput = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(OrderInputType.Token, codecForOrderInputToken())\n .build(\"TalerMerchantApi.OrderInput\");\n\nexport const codecForOrderInputToken = (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(OrderInputType.Token))\n .property(\"token_family_slug\", codecForString())\n .property(\"count\", codecOptional(codecForNumber()))\n .build(\"TalerMerchantApi.OrderInputToken\");\n\nexport const codecForOrderOutput = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(OrderOutputType.Token, codecForOrderOutputToken())\n .alternative(OrderOutputType.TaxReceipt, codecForOrderOutputTaxReceipt())\n .build(\"TalerMerchantApi.OrderOutput\");\n\nexport const codecForOrderOutputToken = (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(OrderOutputType.Token))\n .property(\"token_family_slug\", codecForString())\n .property(\"count\", codecOptional(codecForNumber()))\n .property(\"valid_at\", codecOptional(codecForPreciseTimestamp))\n .build(\"TalerMerchantApi.OrderOutputToken\");\n\nexport const codecForOrderOutputTaxReceipt = (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(OrderOutputType.TaxReceipt))\n .property(\"amount\", codecOptional(codecForAmountString()))\n .property(\"donau_urls\", codecForList(codecForStringURL()))\n .build(\"TalerMerchantApi.OrderOutputTaxReceipt\");\n\nexport const codecForProductSold = (): Codec =>\n buildCodecForObject()\n .property(\"product_id\", codecOptional(codecForString()))\n .property(\"product_name\", codecOptional(codecForString()))\n .property(\"description\", codecForString())\n .property(\n \"description_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"quantity\", codecOptional(codecForNumber()))\n .property(\"unit\", codecOptional(codecForString()))\n .property(\"price\", codecOptional(codecForAmountString()))\n .property(\"image\", codecOptional(codecForString()))\n .property(\"taxes\", codecOptional(codecForList(codecForTax())))\n .property(\"delivery_date\", codecOptional(codecForTimestamp))\n .property(\"product_money_pot\", codecOptional(codecForNumber()))\n .build(\"TalerMerchantApi.Product\");\n\nexport const codecForCheckPaymentPaidResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"order_status\", codecForConstString(\"paid\"))\n .property(\"refunded\", codecForBoolean())\n .property(\"refund_pending\", codecForBoolean())\n .property(\"wired\", codecForBoolean())\n .property(\"deposit_total\", codecForAmountString())\n .property(\"exchange_code\", codecForNumber())\n .property(\"exchange_http_status\", codecForNumber())\n .property(\"refund_amount\", codecForAmountString())\n .property(\"contract_terms\", codecForMerchantContractTerms())\n .property(\"choice_index\", codecOptional(codecForNumber()))\n .property(\"last_payment\", codecForTimestamp)\n .property(\"wire_reports\", codecForList(codecForTransactionWireReport()))\n .property(\"wire_details\", codecForList(codecForTransactionWireTransfer()))\n .property(\"refund_details\", codecForList(codecForRefundDetails()))\n .property(\"order_status_url\", codecForURLString())\n .build(\"TalerMerchantApi.CheckPaymentPaidResponse\");\n\nexport const codecForCheckPaymentUnpaidResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"order_status\", codecForConstString(\"unpaid\"))\n .property(\"taler_pay_uri\", codecForTalerUriString())\n .property(\"creation_time\", codecForTimestamp)\n .property(\"pay_deadline\", codecOptional(codecForTimestamp))\n .property(\"summary\", codecForString())\n .property(\"total_amount\", codecOptional(codecForAmountString()))\n .property(\"already_paid_order_id\", codecOptional(codecForString()))\n .property(\"already_paid_fulfillment_url\", codecOptional(codecForString()))\n .property(\"order_status_url\", codecForString())\n .build(\"TalerMerchantApi.CheckPaymentUnpaidResponse\");\n\nexport const codecForCheckPaymentClaimedResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"order_status\", codecForConstString(\"claimed\"))\n .property(\"contract_terms\", codecForMerchantContractTerms())\n .property(\"order_status_url\", codecForString())\n .build(\"TalerMerchantApi.CheckPaymentClaimedResponse\");\n\nexport const codecForMerchantOrderPrivateStatusResponse =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"order_status\")\n .alternative(\"paid\", codecForCheckPaymentPaidResponse())\n .alternative(\"unpaid\", codecForCheckPaymentUnpaidResponse())\n .alternative(\"claimed\", codecForCheckPaymentClaimedResponse())\n .build(\"TalerMerchantApi.MerchantOrderStatusResponse\");\n\nexport interface GetSessionStatusPaidResponse {\n // Order ID of the paid order.\n order_id: string;\n}\nexport const codecForGetSessionStatusPaidResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"order_id\", codecForString())\n .build(\"TalerMerchantApi.GetSessionStatusPaidResponse\");\n\nexport interface GetSessionStatusUnpaidResponse {\n // Order ID of the unpaid order.\n order_id: string;\n}\nexport const codecForGetSessionStatusUnpaidResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"order_id\", codecForString())\n .build(\"TalerMerchantApi.GetSessionStatusUnpaidResponse\");\n\nexport const codecForRefundDetails = (): Codec =>\n buildCodecForObject()\n .property(\"reason\", codecForString())\n .property(\"pending\", codecForBoolean())\n .property(\"timestamp\", codecForTimestamp)\n .property(\"amount\", codecForAmountString())\n .build(\"TalerMerchantApi.RefundDetails\");\n\nexport const codecForTransactionWireTransfer =\n (): Codec =>\n buildCodecForObject()\n .property(\"exchange_url\", codecForURLString())\n .property(\"wtid\", codecForString())\n .property(\"execution_time\", codecForTimestamp)\n .property(\"amount\", codecForAmountString())\n .property(\"deposit_fee\", codecForAmountString())\n .property(\"confirmed\", codecForBoolean())\n .property(\"expected_transfer_serial_id\", codecOptional(codecForNumber()))\n .build(\"TalerMerchantApi.TransactionWireTransfer\");\n\nexport const codecForTransactionWireReport = (): Codec =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"hint\", codecForString())\n .property(\"exchange_code\", codecForNumber())\n .property(\"exchange_http_status\", codecForNumber())\n .property(\"coin_pub\", codecForEddsaPublicKey())\n .build(\"TalerMerchantApi.TransactionWireReport\");\n\nexport const codecForMerchantRefundResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"taler_refund_uri\", codecForTalerUriString())\n .property(\"h_contract\", codecForString())\n .build(\"TalerMerchantApi.MerchantRefundResponse\");\n\nexport const codecForTansferList = (): Codec =>\n buildCodecForObject()\n .property(\"transfers\", codecForList(codecForTransferDetails()))\n .build(\"TalerMerchantApi.TransferList\");\n\nexport const codecForExpectedTansferList = (): Codec =>\n buildCodecForObject()\n .property(\"incoming\", codecForList(codecForExpectedTransferEntry()))\n .build(\"TalerMerchantApi.ExpectedTransferList\");\n\nexport const codecForExchangeTransferReconciliationDetails =\n (): Codec =>\n buildCodecForObject()\n .property(\"deposit_fee\", codecForAmountString())\n .property(\"order_id\", codecForString())\n .property(\"remaining_deposit\", codecForAmountString())\n .build(\"TalerMerchantApi.ExchangeTransferReconciliationDetails\");\n\nexport const codecForExpectedTransferDetails =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"reconciliation_details\",\n codecForList(codecForExchangeTransferReconciliationDetails()),\n )\n .property(\"wire_fee\", codecForAmountString())\n .build(\"TalerMerchantApi.ExpectedTransferDetails\");\n\nexport const codecForTransferDetails = (): Codec =>\n buildCodecForObject()\n .property(\"credit_amount\", codecForAmountString())\n .property(\"wtid\", codecForString())\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"exchange_url\", codecForURLString())\n .property(\"transfer_serial_id\", codecForNumber())\n .property(\"execution_time\", codecOptional(codecForTimestamp))\n .property(\"expected\", codecOptional(codecForBoolean()))\n .build(\"TalerMerchantApi.TransferDetails\");\n\nexport const codecForExpectedTransferEntry = (): Codec =>\n buildCodecForObject()\n .property(\"expected_credit_amount\", codecOptional(codecForAmountString()))\n .property(\"wtid\", codecForString())\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"exchange_url\", codecForURLString())\n .property(\"expected_transfer_serial_id\", codecOptional(codecForNumber()))\n .property(\"execution_time\", codecOptional(codecForTimestamp))\n .property(\"validated\", codecForBoolean())\n .property(\"confirmed\", codecForBoolean())\n .property(\"last_http_status\", codecForNumber())\n .property(\"last_ec\", codecForNumber())\n .property(\"last_error_detail\", codecOptional(codecForAny()))\n .build(\"TalerMerchantApi.ExpectedTransferDetails\");\n\nexport const codecForOtpDeviceSummaryResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"otp_devices\", codecForList(codecForOtpDeviceEntry()))\n .build(\"TalerMerchantApi.OtpDeviceSummaryResponse\");\n\nexport const codecForOtpDeviceEntry = (): Codec =>\n buildCodecForObject()\n .property(\"otp_device_id\", codecForString())\n .property(\"device_description\", codecForString())\n .build(\"TalerMerchantApi.OtpDeviceEntry\");\n\nexport const codecForOtpDeviceDetails = (): Codec =>\n buildCodecForObject()\n .property(\"device_description\", codecForString())\n .property(\"otp_algorithm\", codecForNumber())\n .property(\"otp_ctr\", codecOptional(codecForNumber()))\n .property(\"otp_timestamp\", codecForNumber())\n .property(\"otp_code\", codecOptional(codecForString()))\n .build(\"TalerMerchantApi.OtpDeviceDetails\");\n\nexport const codecForTemplateSummaryResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"templates\", codecForList(codecForTemplateEntry()))\n .build(\"TalerMerchantApi.TemplateSummaryResponse\");\n\nexport const codecForTemplateEntry = (): Codec =>\n buildCodecForObject()\n .property(\"template_id\", codecForString())\n .property(\"template_description\", codecForString())\n .build(\"TalerMerchantApi.TemplateEntry\");\n\nexport const codecForTemplateDetails = (): Codec =>\n buildCodecForObject()\n .property(\"template_description\", codecForString())\n .property(\"otp_id\", codecOptional(codecForString()))\n .property(\"template_contract\", codecForTemplateContractDetails())\n .property(\n \"editable_defaults\",\n codecOptional(codecForTemplateContractDetailsDefaults()),\n )\n .build(\"TalerMerchantApi.TemplateDetails\");\n\nexport const codecForTemplateContractPaivana =\n (): Codec =>\n buildCodecForObject()\n .property(\"choices\", codecForList(codecForOrderChoice()))\n .property(\"website_regex\", codecOptional(codecForString()))\n\n .property(\"currency\", codecOptional(codecForString()))\n .property(\"max_pickup_duration\", codecOptional(codecForDuration))\n .property(\"minimum_age\", codecOptional(codecForNumber()))\n .property(\"pay_duration\", codecOptional(codecForDuration))\n .property(\"request_tip\", codecOptional(codecForBoolean()))\n .property(\"summary\", codecOptional(codecForString()))\n .property(\"template_type\", codecForConstString(TemplateType.PAIVANA))\n .build(\"TalerMerchantApi.TemplateContractPaivana\");\n\nexport const codecForTemplateContractInventoryCart =\n (): Codec =>\n buildCodecForObject()\n .property(\"choose_one\", codecOptional(codecForBoolean()))\n .property(\"selected_all\", codecOptional(codecForBoolean()))\n .property(\n \"selected_categories\",\n codecOptionalDefault(codecForList(codecForNumber()), []),\n )\n .property(\n \"selected_products\",\n codecOptionalDefault(codecForList(codecForString()), []),\n )\n .property(\"inventory_payload\", codecOptional(codecForAny())) // FIXME: validate\n\n .property(\"currency\", codecOptional(codecForString()))\n .property(\"max_pickup_duration\", codecOptional(codecForDuration))\n .property(\"minimum_age\", codecOptional(codecForNumber()))\n .property(\"pay_duration\", codecOptional(codecForDuration))\n .property(\"request_tip\", codecOptional(codecForBoolean()))\n .property(\"summary\", codecOptional(codecForString()))\n .property(\n \"template_type\",\n codecOptionalDefault(\n codecForConstString(TemplateType.INVENTORY_CART),\n TemplateType.INVENTORY_CART,\n ),\n )\n .build(\"TalerMerchantApi.TemplateContractInventoryCart\");\nexport const codecForTemplateContractFixedOrder =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecOptional(codecForAmountString()))\n\n .property(\"currency\", codecOptional(codecForString()))\n .property(\"max_pickup_duration\", codecOptional(codecForDuration))\n .property(\"minimum_age\", codecOptional(codecForNumber()))\n .property(\"pay_duration\", codecOptional(codecForDuration))\n .property(\"request_tip\", codecOptional(codecForBoolean()))\n .property(\"summary\", codecOptional(codecForString()))\n .property(\n \"template_type\",\n codecOptionalDefault(\n codecForConstString(TemplateType.FIXED_ORDER),\n TemplateType.FIXED_ORDER,\n ),\n )\n .build(\"TalerMerchantApi.TemplateContractFixedOrder\");\n\nexport const codecForTemplateContractDetails =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"template_type\")\n .alternative(\n TemplateType.FIXED_ORDER,\n codecForTemplateContractFixedOrder(),\n )\n .alternative(\n TemplateType.INVENTORY_CART,\n codecForTemplateContractInventoryCart(),\n )\n .alternative(TemplateType.PAIVANA, codecForTemplateContractPaivana())\n .alternativeOnMissing(\n TemplateType.FIXED_ORDER,\n codecForTemplateContractFixedOrder(),\n )\n .build(\"TalerMerchantApi.TemplateContractDetails\");\n\nexport const codecForTemplateContractDetailsDefaults =\n (): Codec =>\n buildCodecForObject()\n .property(\"summary\", codecOptional(codecForString()))\n .property(\"currency\", codecOptional(codecForString()))\n .property(\"amount\", codecOptional(codecForAmountString()))\n .allowExtra()\n .build(\"TalerMerchantApi.TemplateContractDetailsDefaults\");\n\nexport const codecForWalletTemplateDetails =\n (): Codec =>\n buildCodecForObject()\n .property(\"template_contract\", codecForTemplateContractDetails())\n .property(\n \"editable_defaults\",\n codecOptional(codecForTemplateContractDetailsDefaults()),\n )\n .build(\"TalerMerchantApi.WalletTemplateDetails\");\n\nexport const codecForWebhookSummaryResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"webhooks\", codecForList(codecForWebhookEntry()))\n .build(\"TalerMerchantApi.WebhookSummaryResponse\");\n\nexport const codecForWebhookEntry = (): Codec =>\n buildCodecForObject()\n .property(\"webhook_id\", codecForString())\n .property(\"event_type\", codecForString())\n .build(\"TalerMerchantApi.WebhookEntry\");\n\nexport const codecForWebhookDetails = (): Codec =>\n buildCodecForObject()\n .property(\"event_type\", codecForString())\n .property(\"url\", codecForString())\n .property(\"http_method\", codecForString())\n .property(\"header_template\", codecOptional(codecForString()))\n .property(\"body_template\", codecOptional(codecForString()))\n .build(\"TalerMerchantApi.WebhookDetails\");\n\nexport const codecForTokenFamilyKind = codecForEither(\n codecForConstString(TokenFamilyKind.Discount),\n codecForConstString(TokenFamilyKind.Subscription),\n);\n\nexport const codecForTokenFamilyDetails = (): Codec =>\n buildCodecForObject()\n .property(\"slug\", codecForString())\n .property(\"name\", codecForString())\n .property(\"description\", codecForString())\n .property(\n \"description_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"valid_after\", codecForTimestamp)\n .property(\"valid_before\", codecForTimestamp)\n .property(\"duration\", codecForDuration)\n .property(\"kind\", codecForTokenFamilyKind)\n .property(\"issued\", codecForNumber())\n .property(\"used\", codecForNumber())\n .build(\"TalerMerchantApi.TokenFamilyDetails\");\n\nexport const codecForTokenFamiliesList = (): Codec =>\n buildCodecForObject()\n .property(\"token_families\", codecForList(codecForTokenFamilySummary()))\n .build(\"TalerMerchantApi.TokenFamiliesList\");\n\nexport const codecForTokenFamilySummary = (): Codec =>\n buildCodecForObject()\n .property(\"slug\", codecForString())\n .property(\"name\", codecForString())\n .property(\"description\", codecForString())\n .property(\"description_i18n\", codecForInternationalizedString())\n .property(\"valid_after\", codecForTimestamp)\n .property(\"valid_before\", codecForTimestamp)\n .property(\"kind\", codecForTokenFamilyKind)\n .build(\"TalerMerchantApi.TokenFamilySummary\");\n\nexport const codecForStatisticBucketRange = codecForEither(\n codecForConstString(StatisticBucketRange.Day),\n codecForConstString(StatisticBucketRange.Hour),\n codecForConstString(StatisticBucketRange.Day),\n codecForConstString(StatisticBucketRange.Week),\n codecForConstString(StatisticBucketRange.Month),\n codecForConstString(StatisticBucketRange.Quarter),\n codecForConstString(StatisticBucketRange.Year),\n);\n\nexport const codecForStatisticsAmountBucket =\n (): Codec =>\n buildCodecForObject()\n .property(\"start_time\", codecForTimestamp)\n .property(\"end_time\", codecForTimestamp)\n .property(\"range\", codecForStatisticBucketRange) // FIXME Bucket range string to be specific\n .property(\"cumulative_amounts\", codecForList(codecForAmountString()))\n .build(\"TalerMerchantApi.StatisticsAmountBucket\");\n\nexport const codecForStatisticsAmountInterval =\n (): Codec =>\n buildCodecForObject()\n .property(\"start_time\", codecForTimestamp)\n .property(\"cumulative_amounts\", codecForList(codecForAmountString()))\n .build(\"TalerMerchantApi.StatisticsAmountInterval\");\n\nexport const codecForStatisticsAmountResponse = (): Codec =>\n buildCodecForObject()\n .property(\"buckets\", codecForList(codecForStatisticsAmountBucket()))\n .property(\"buckets_description\", codecOptional(codecForString()))\n .property(\"intervals\", codecForList(codecForStatisticsAmountInterval()))\n .property(\"intervals_description\", codecOptional(codecForString()))\n .build(\"TalerMerchantApi.StatisticsAmountResponse\");\n\nexport const codecForStatisticsCounterBucket =\n (): Codec =>\n buildCodecForObject()\n .property(\"start_time\", codecForTimestamp)\n .property(\"end_time\", codecForTimestamp)\n .property(\"range\", codecForString()) // FIXME Bucket range string to be specific\n .property(\"cumulative_counter\", codecForNumber())\n .build(\"TalerMerchantApi.StatisticsCounterBucket\");\n\nexport const codecForStatisticsCounterInterval =\n (): Codec =>\n buildCodecForObject()\n .property(\"start_time\", codecForTimestamp)\n .property(\"cumulative_counter\", codecForNumber())\n .build(\"TalerMerchantApi.StatisticsCounterInterval\");\n\nexport const codecForStatisticsCounterResponse = (): Codec =>\n buildCodecForObject()\n .property(\"buckets\", codecForList(codecForStatisticsCounterBucket()))\n .property(\"buckets_description\", codecOptional(codecForString()))\n .property(\"intervals\", codecForList(codecForStatisticsCounterInterval()))\n .property(\"intervals_description\", codecOptional(codecForString()))\n .build(\"TalerMerchantApi.StatisticsCounterResponse\");\n\nexport const codecForInstancesResponse = (): Codec =>\n buildCodecForObject()\n .property(\"instances\", codecForList(codecForInstance()))\n .build(\"TalerMerchantApi.InstancesResponse\");\n\nexport const codecForInstance = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"website\", codecOptional(codecForString()))\n .property(\"logo\", codecOptional(codecForString()))\n .property(\"id\", codecForString())\n .property(\"merchant_pub\", codecForEddsaPublicKey())\n .property(\"payment_targets\", codecForList(codecForString()))\n .property(\"deleted\", codecForBoolean())\n .build(\"TalerMerchantApi.Instance\");\n\nexport const codecForTemplateEditableDetails =\n (): Codec =>\n buildCodecForObject()\n .property(\"summary\", codecOptional(codecForString()))\n .property(\"currency\", codecOptional(codecForString()))\n .property(\"amount\", codecOptional(codecForAmountString()))\n .build(\"TemplateEditableDetails\");\n\nexport const codecForMerchantReserveCreateConfirmation =\n (): Codec =>\n buildCodecForObject()\n .property(\"accounts\", codecForList(codecForExchangeWireAccount()))\n .property(\"reserve_pub\", codecForEddsaPublicKey())\n .build(\"MerchantReserveCreateConfirmation\");\n\nexport interface ChallengeResponse {\n // List of challenge IDs that must be solved before the\n // client may proceed.\n challenges: Challenge[];\n\n // True if **all** challenges must be solved (AND), false if\n // it is sufficient to solve one of them (OR).\n combi_and: boolean;\n}\nexport interface Challenge {\n // Unique identifier of the challenge to solve to run this protected\n // operation.\n challenge_id: string;\n\n // Channel of the last successful transmission of the TAN challenge.\n tan_channel: TanChannel;\n\n // Info of the last successful transmission of the TAN challenge.\n // Hint to show to the user as to where the challenge was\n // sent or what to use to solve the challenge. May not\n // contain the full address for privacy.\n tan_info: string;\n}\n\nexport enum TanChannel {\n SMS = \"sms\",\n EMAIL = \"email\",\n}\n\nexport const codecForChallenge = (): Codec =>\n buildCodecForObject()\n .property(\"challenge_id\", codecForString())\n .property(\n \"tan_channel\",\n codecForEither(\n codecForConstString(TanChannel.SMS),\n codecForConstString(TanChannel.EMAIL),\n ),\n )\n .property(\"tan_info\", codecForString())\n .build(\"MFA.Challenge\");\n\nexport const codecForChallengeResponse = (): Codec =>\n buildCodecForObject()\n .property(\"challenges\", codecForList(codecForChallenge()))\n .property(\"combi_and\", codecForBoolean())\n .build(\"MFA.ChallengeResponse\");\n\nexport interface ChallengeRequestResponse {\n // FIXME: this response fields are mandatory but\n // put it optional from the client side to\n // handle server that doesn't support this response.\n // Remove it when all server has been upgraded\n\n /**\n * How long does the client have to solve the challenge.\n */\n solve_expiration?: Timestamp;\n\n /**\n * What is the earliest time at which the client may request a new challenge to be transmitted?\n */\n earliest_retransmission?: Timestamp;\n}\n\nexport const codecForChallengeRequestResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"solve_expiration\", codecOptional(codecForTimestamp))\n .property(\"earliest_retransmission\", codecOptional(codecForTimestamp))\n .build(\"MFA.ChallengeRequestResponse\");\n\nexport interface ChallengeSolveRequest {\n // The TAN code that solves $CHALLENGE_ID.\n tan: string;\n}\n\nexport interface MerchantPostDonauBody {\n donau_url: string;\n charity_id: number;\n}\n\nexport interface MerchantStatisticsReportResponse {\n // Name of the business for which the report is generated.\n business_name: string;\n\n // Starting date for the report.\n start_date: Timestamp;\n\n // End date for the report.\n end_date: Timestamp;\n\n // Period of time covered by each bucket (aka granularity).\n bucket_period: RelativeTime;\n\n // Charts to include in the report.\n charts: MerchantReportChart[];\n}\n\nexport const codecForMerchantStatisticsReportResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"business_name\", codecForString())\n .property(\"start_date\", codecForTimestamp)\n .property(\"end_date\", codecForTimestamp)\n .property(\"bucket_period\", codecForDuration)\n .property(\"charts\", codecForList(codecForMerchantReportChart()))\n .build(\"TalerMerchantApi.MerchantStatisticsReportResponse\");\n\nexport interface MerchantReportChart {\n // Name of the chart.\n chart_name: string;\n\n // Label to use for the y-axis of the chart.\n // (x-axis is always time).\n y_label: string;\n\n // Statistical values for the respective time windows,\n // one entry per bucket_period in between start_date\n // and end_date.\n data_groups: BucketDataGroup[];\n\n // Human-readable labels for the values in each of the\n // data_groups. Length of the array must match the\n // length of the values arrays.\n labels: string[];\n\n // Should the values in each of the data_groups\n // be rendered cumulatively or using a grouped representation?\n cumulative: boolean;\n}\n\nexport const codecForMerchantReportChart = (): Codec =>\n buildCodecForObject()\n .property(\"chart_name\", codecForString())\n .property(\"y_label\", codecForString())\n .property(\"data_groups\", codecForList(codecForBucketDataGroup()))\n .property(\"labels\", codecForList(codecForString()))\n .property(\"cumulative\", codecForBoolean())\n .build(\"TalerMerchantApi.MerchantReportChart\");\n\nexport interface BucketDataGroup {\n // Starting data for this group\n start_date: Timestamp;\n\n // Values in the data group.\n values: number[];\n}\nexport const codecForBucketDataGroup = (): Codec =>\n buildCodecForObject()\n .property(\"start_date\", codecForTimestamp)\n .property(\"values\", codecForList(codecForNumber()))\n .build(\"TalerMerchantApi.BucketDataGroup\");\n\nexport interface ReportGenerationRequest {\n // Report token authorizing the report generation.\n report_token: string;\n}\n\nexport interface ReportAddRequest {\n // Description of the report. Possibly included\n // in the report message.\n description: string;\n\n // Merchant backend configuration section specifying\n // the program to use to transmit the report\n program_section: string;\n\n // Mime-type to request from the data source.\n mime_type: string;\n\n // Base URL to request the data from.\n data_source: string;\n\n // Address where the report program should send\n // the report.\n target_address: string;\n\n // Report frequency\n report_frequency: RelativeTime;\n\n // Report frequency shift. Defaults to zero if missing.\n report_frequency_shift?: RelativeTime;\n}\n\nexport interface ReportAddedResponse {\n // Unique ID for the report.\n report_serial_id: Integer;\n}\n\nexport const codecForReportAddedResponse = (): Codec =>\n buildCodecForObject()\n .property(\"report_serial_id\", codecForNumber())\n .build(\"TalerMerchantApi.ReportAddedResponse\");\n\nexport interface ReportDetailResponse {\n // Report identifier\n report_serial: Integer;\n\n // Description of the report. Possibly included\n // in the report message.\n description: string;\n\n // Merchant backend configuration section specifying\n // the program to use to transmit the report\n program_section: string;\n\n // Mime-type to request from the data source.\n mime_type: string;\n\n // Base URL to request the data from.\n data_source: string;\n\n // Address where the report program should send\n // the report.\n target_address: string;\n\n // Report frequency\n report_frequency: RelativeTime;\n\n // Report frequency shift\n report_frequency_shift: RelativeTime;\n\n // Numeric error code unique to the\n // error encountered in generating the latest report.\n // Absent if there was no error.\n last_error_code?: Integer;\n\n // Details about any error encountered\n // in generating the latest report.\n last_error_detail?: string;\n}\n\nexport const codecForReportDetailResponse = (): Codec =>\n buildCodecForObject()\n .property(\"report_serial\", codecForNumber())\n .property(\"description\", codecForString())\n .property(\"program_section\", codecForString())\n .property(\"mime_type\", codecForString())\n .property(\"data_source\", codecForString())\n .property(\"target_address\", codecForString())\n .property(\"report_frequency\", codecForDuration)\n .property(\"report_frequency_shift\", codecForDuration)\n .property(\"last_error_code\", codecOptional(codecForNumber()))\n .property(\"last_error_detail\", codecOptional(codecForString()))\n .build(\"TalerMerchantApi.ReportDetailResponse\");\n\nexport interface ReportsSummaryResponse {\n // Return reports that are present in our backend.\n reports: ReportEntry[];\n}\n\nexport const codecForReportsSummaryResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"reports\", codecForList(codecForReportEntry()))\n .build(\"TalerMerchantApi.ReportsSummaryResponse\");\n\nexport interface ReportEntry {\n // Report identifier\n report_serial: Integer;\n\n // Description for the report.\n description: string;\n\n // Frequency for the report.\n report_frequency: RelativeTime;\n}\n\nexport const codecForReportEntry = (): Codec =>\n buildCodecForObject()\n .property(\"report_serial\", codecForNumber())\n .property(\"description\", codecForString())\n .property(\"report_frequency\", codecForDuration)\n .build(\"TalerMerchantApi.ReportEntry\");\n\nexport interface GroupsSummaryResponse {\n // Return groups that are present in our backend.\n groups: GroupEntry[];\n}\n\nexport interface GroupEntry {\n // Group identifier\n group_serial: Integer;\n\n // Unique name for the group (unique per instance).\n group_name: string;\n\n // Description for the group.\n description: string;\n}\n\nexport const codecForGroupsSummaryResponse = (): Codec =>\n buildCodecForObject()\n .property(\"groups\", codecForList(codecForGroupEntry()))\n .build(\"TalerMerchantApi.GroupsSummaryResponse\");\n\nexport const codecForGroupEntry = (): Codec =>\n buildCodecForObject()\n .property(\"group_name\", codecForString())\n .property(\"group_serial\", codecForNumber())\n .property(\"description\", codecForString())\n .build(\"TalerMerchantApi.GroupEntry\");\n\nexport interface GroupAddRequest {\n // Unique name for the group (unique per instance).\n group_name: string;\n\n // Description of the group.\n description: string;\n}\n\nexport interface GroupAddedResponse {\n // Unique ID for the group.\n group_serial_id: Integer;\n}\n\nexport const codecForGroupAddedResponse = (): Codec =>\n buildCodecForObject()\n .property(\"group_serial_id\", codecForNumber())\n .build(\"TalerMerchantApi.GroupAddedResponse\");\n\nexport interface PotAddRequest {\n // Description of the pot. Possibly included\n // in the pot message.\n description: string;\n\n // Name of the pot. Must be unique per instance.\n pot_name: string;\n}\n\nexport interface PotAddedResponse {\n // Unique ID for the pot.\n pot_serial_id: Integer;\n}\n\nexport const codecForPotAddedResponse = (): Codec =>\n buildCodecForObject()\n .property(\"pot_serial_id\", codecForNumber())\n .build(\"TalerMerchantApi.PotAddedResponse\");\n\nexport interface PotModifyRequest {\n // Description of the pot. Possibly included\n // in the pot message.\n description: string;\n\n // Name of the pot. Must be unique per instance.\n pot_name: string;\n\n // Expected current totals amount in the pot.\n // Should be given if new_pot_total is specified\n // as this allows checking that the pot total did\n // not change in the meantime. However, this is\n // not enforced server-side, the client may choose\n // to not use this safety-measure.\n expected_pot_totals?: AmountString[];\n\n // Expected new total amounts to store in the pot.\n // Does **not** have to be in the same currencies as\n // the existing amounts in the pot. Used to reset\n // the pot and/or change the amounts.\n new_pot_totals?: AmountString[];\n}\n\nexport interface PotsSummaryResponse {\n // Return pots that are present in our backend.\n pots: PotEntry[];\n}\n\nexport interface PotEntry {\n // Pot identifier\n pot_serial: Integer;\n // Name of the pot. Must be unique per instance.\n pot_name: string;\n // Current total amounts in the pot.\n pot_totals: AmountString[];\n}\n\nexport const codecForPotsSummaryResponse = (): Codec =>\n buildCodecForObject()\n .property(\"pots\", codecForList(codecForPotEntry()))\n .build(\"TalerMerchantApi.PotsSummaryResponse\");\n\nexport const codecForPotEntry = (): Codec =>\n buildCodecForObject()\n .property(\"pot_serial\", codecForNumber())\n .property(\"pot_name\", codecForString())\n .property(\"pot_totals\", codecForList(codecForAmountString()))\n .build(\"TalerMerchantApi.PotEntry\");\n\nexport interface PotDetailResponse {\n // Description of the pot. Possibly included\n // in the pot message.\n description: string;\n // Name of the pot. Must be unique per instance.\n pot_name: string;\n // Current total amount in the pot.\n pot_totals: AmountString[];\n}\n\nexport const codecForPotDetailResponse = (): Codec =>\n buildCodecForObject()\n .property(\"description\", codecForString())\n .property(\"pot_name\", codecForString())\n .property(\"pot_totals\", codecForList(codecForAmountString()))\n .build(\"TalerMerchantApi.PotDetailResponse\");\n", "/*\n This file is part of GNU Taler\n (C) 2021 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { assertUnreachable } from \"./errors.js\";\nimport { canonicalJson } from \"./helpers.js\";\nimport { Logger } from \"./logging.js\";\nimport {\n decodeCrock,\n encodeCrock,\n getRandomBytes,\n hash,\n kdf,\n stringToBytes,\n} from \"./taler-crypto.js\";\nimport { AmountString, Integer } from \"./types-taler-common.js\";\nimport {\n MerchantContractTerms,\n MerchantContractTermsV0,\n MerchantContractTermsV1,\n MerchantContractTokenKind,\n MerchantContractVersion,\n} from \"./types-taler-merchant.js\";\n\nconst logger = new Logger(\"contractTerms.ts\");\n\nexport namespace ContractTermsUtil {\n export function forgetAllImpl(\n anyJson: any,\n path: string[],\n pred: PathPredicate,\n ): any {\n const dup = JSON.parse(JSON.stringify(anyJson));\n if (Array.isArray(dup)) {\n for (let i = 0; i < dup.length; i++) {\n dup[i] = forgetAllImpl(dup[i], [...path, `${i}`], pred);\n }\n } else if (typeof dup === \"object\" && dup != null) {\n if (typeof dup.$forgettable === \"object\") {\n for (const x of Object.keys(dup.$forgettable)) {\n if (!pred([...path, x])) {\n continue;\n }\n if (!dup.$forgotten) {\n dup.$forgotten = {};\n }\n if (!dup.$forgotten[x]) {\n const membValCanon = stringToBytes(\n canonicalJson(scrub(dup[x])) + \"\\0\",\n );\n const membSalt = stringToBytes(dup.$forgettable[x] + \"\\0\");\n const h = kdf(64, membValCanon, membSalt, new Uint8Array([]));\n dup.$forgotten[x] = encodeCrock(h);\n }\n delete dup[x];\n delete dup.$forgettable[x];\n }\n if (Object.keys(dup.$forgettable).length === 0) {\n delete dup.$forgettable;\n }\n }\n for (const x of Object.keys(dup)) {\n if (x.startsWith(\"$\")) {\n continue;\n }\n dup[x] = forgetAllImpl(dup[x], [...path, x], pred);\n }\n }\n return dup;\n }\n\n export type PathPredicate = (path: string[]) => boolean;\n\n /**\n * Scrub all forgettable members from an object.\n */\n export function scrub(anyJson: any): any {\n return forgetAllImpl(anyJson, [], () => true);\n }\n\n /**\n * Recursively forget all forgettable members of an object,\n * where the path matches a predicate.\n */\n export function forgetAll(anyJson: any, pred: PathPredicate): any {\n return forgetAllImpl(anyJson, [], pred);\n }\n\n /**\n * Generate a salt for all members marked as forgettable,\n * but which don't have an actual salt yet.\n */\n export function saltForgettable(anyJson: any): any {\n const dup = JSON.parse(JSON.stringify(anyJson));\n if (Array.isArray(dup)) {\n for (let i = 0; i < dup.length; i++) {\n dup[i] = saltForgettable(dup[i]);\n }\n } else if (typeof dup === \"object\" && dup !== null) {\n if (typeof dup.$forgettable === \"object\") {\n for (const k of Object.keys(dup.$forgettable)) {\n if (dup.$forgettable[k] === true) {\n dup.$forgettable[k] = encodeCrock(getRandomBytes(32));\n }\n }\n }\n for (const x of Object.keys(dup)) {\n if (x.startsWith(\"$\")) {\n continue;\n }\n dup[x] = saltForgettable(dup[x]);\n }\n }\n return dup;\n }\n\n const nameRegex = /^[0-9A-Za-z_]+$/;\n\n /**\n * Check that the given JSON object is well-formed with regards\n * to forgettable fields and other restrictions for forgettable JSON.\n */\n export function validateForgettable(anyJson: any): boolean {\n if (anyJson === undefined) {\n return true;\n }\n if (typeof anyJson === \"string\") {\n return true;\n }\n if (typeof anyJson === \"number\") {\n return (\n Number.isInteger(anyJson) &&\n anyJson >= Number.MIN_SAFE_INTEGER &&\n anyJson <= Number.MAX_SAFE_INTEGER\n );\n }\n if (typeof anyJson === \"boolean\") {\n return true;\n }\n if (anyJson === null) {\n return true;\n }\n if (Array.isArray(anyJson)) {\n return anyJson.every((x) => validateForgettable(x));\n }\n if (typeof anyJson === \"object\") {\n for (const k of Object.keys(anyJson)) {\n if (k.match(nameRegex)) {\n if (validateForgettable(anyJson[k])) {\n continue;\n } else {\n return false;\n }\n }\n if (k === \"$forgettable\") {\n const fga = anyJson.$forgettable;\n if (!fga || typeof fga !== \"object\") {\n return false;\n }\n for (const fk of Object.keys(fga)) {\n if (!fk.match(nameRegex)) {\n return false;\n }\n if (!(fk in anyJson)) {\n return false;\n }\n const fv = anyJson.$forgettable[fk];\n if (typeof fv !== \"string\") {\n return false;\n }\n }\n } else if (k === \"$forgotten\") {\n const fgo = anyJson.$forgotten;\n if (!fgo || typeof fgo !== \"object\") {\n return false;\n }\n for (const fk of Object.keys(fgo)) {\n if (!fk.match(nameRegex)) {\n return false;\n }\n // Check that the value has actually been forgotten.\n if (fk in anyJson) {\n return false;\n }\n const fv = anyJson.$forgotten[fk];\n if (typeof fv !== \"string\") {\n return false;\n }\n try {\n const decFv = decodeCrock(fv);\n if (decFv.length != 64) {\n return false;\n }\n } catch (e) {\n return false;\n }\n // Check that salt has been deleted after forgetting.\n if (anyJson.$forgettable?.[k] !== undefined) {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n return true;\n }\n return false;\n }\n\n /**\n * Check that no forgettable information has been forgotten.\n *\n * Must only be called on an object already validated with validateForgettable.\n */\n export function validateNothingForgotten(contractTerms: any): boolean {\n throw Error(\"not implemented yet\");\n }\n\n export function validateParsed(\n contractTerms: MerchantContractTerms,\n ): boolean {\n // validate trusted/expected domains\n if (contractTerms.version === MerchantContractVersion.V1) {\n const regex = new RegExp(\"^(\\\\*\\\\.)?([\\\\w\\\\d]+\\\\.)+[\\\\w\\\\d]+$\");\n for (const slug in contractTerms.token_families) {\n const family = contractTerms.token_families[slug];\n var domains: string[] = [];\n switch (family.details.class) {\n case MerchantContractTokenKind.Subscription:\n domains.push(...family.details.trusted_domains);\n break;\n case MerchantContractTokenKind.Discount:\n domains.push(...family.details.expected_domains);\n break;\n default:\n assertUnreachable(family.details);\n }\n\n for (const domain in domains) {\n if (domain !== \"*\" && !regex.test(domain)) {\n return false;\n }\n }\n }\n }\n\n return true;\n }\n\n /**\n * Hash a contract terms object. Forgettable fields\n * are scrubbed and JSON canonicalization is applied\n * before hashing.\n */\n export function hashContractTerms(contractTerms: unknown): string {\n const cleaned = scrub(contractTerms);\n const canon = canonicalJson(cleaned) + \"\\0\";\n const bytes = stringToBytes(canon);\n return encodeCrock(hash(bytes));\n }\n\n /**\n * Extract raw amount and max fee.\n */\n export function extractAmounts(\n contractTerms: MerchantContractTerms,\n choiceIndex: Integer | undefined,\n ):\n | {\n available: true;\n amountRaw: AmountString;\n maxFee: AmountString;\n }\n | {\n available: false;\n amountRaw: undefined;\n maxFee: undefined;\n } {\n let amountRaw: AmountString;\n let maxFee: AmountString;\n switch (contractTerms.version) {\n case undefined:\n case MerchantContractVersion.V0:\n amountRaw = contractTerms.amount;\n maxFee = contractTerms.max_fee;\n break;\n case MerchantContractVersion.V1:\n if (choiceIndex === undefined) {\n logger.trace(\"choice index not specified for contract v1\");\n return {\n available: false,\n amountRaw: undefined,\n maxFee: undefined,\n };\n }\n if (contractTerms.choices[choiceIndex] === undefined)\n throw Error(`invalid choice index ${choiceIndex}`);\n amountRaw = contractTerms.choices[choiceIndex].amount;\n maxFee = contractTerms.choices[choiceIndex].max_fee;\n break;\n default:\n assertUnreachable(contractTerms);\n }\n\n return {\n available: true,\n amountRaw,\n maxFee,\n };\n }\n\n export function getV0CompatChoiceIndex(\n terms: MerchantContractTermsV1,\n ): number | undefined {\n // Select the first choice that doesn't have\n // and non-currency inputs.\n let firstGood: number | undefined = undefined;\n for (let i = 0; i < terms.choices.length; i++) {\n if (terms.choices[i].inputs.length == 0) {\n firstGood = i;\n break;\n }\n }\n if (firstGood != null) {\n return firstGood;\n }\n return undefined;\n }\n\n /**\n * Try to downgrade contract terms in the v1 format to the v0 format.\n * Returns undefined if downgrading is not possible. This can happen\n * when the contract only offers token payments.\n */\n export function downgradeContractTerms(\n terms: MerchantContractTerms,\n ): MerchantContractTermsV0 | undefined {\n if (terms.version == MerchantContractVersion.V0) {\n return terms;\n }\n if (terms.version !== MerchantContractVersion.V1) {\n return undefined;\n }\n const firstGood = getV0CompatChoiceIndex(terms);\n if (firstGood == null) {\n return undefined;\n }\n return {\n amount: terms.choices[firstGood].amount,\n exchanges: terms.exchanges,\n h_wire: terms.h_wire,\n max_fee: terms.choices[firstGood].max_fee,\n merchant: terms.merchant,\n merchant_base_url: terms.merchant_base_url,\n merchant_pub: terms.merchant_pub,\n nonce: terms.nonce,\n order_id: terms.order_id,\n pay_deadline: terms.pay_deadline,\n refund_deadline: terms.refund_deadline,\n summary: terms.summary,\n timestamp: terms.timestamp,\n wire_method: terms.wire_method,\n wire_transfer_deadline: terms.wire_transfer_deadline,\n auto_refund: terms.auto_refund,\n delivery_date: terms.delivery_date,\n delivery_location: terms.delivery_location,\n extra: terms.extra,\n fulfillment_message: terms.fulfillment_message,\n fulfillment_message_i18n: terms.fulfillment_message_i18n,\n fulfillment_url: terms.fulfillment_url,\n minimum_age: terms.minimum_age,\n products: terms.products,\n public_reorder_url: terms.public_reorder_url,\n summary_i18n: terms.summary_i18n,\n version: MerchantContractVersion.V0,\n };\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2021 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Functional programming utilities.\n */\nexport namespace fnutil {\n export function all(arr: T[], f: (x: T) => boolean): boolean {\n for (const x of arr) {\n if (!f(x)) {\n return false;\n }\n }\n return true;\n }\n\n export function any(arr: T[], f: (x: T) => boolean): boolean {\n for (const x of arr) {\n if (f(x)) {\n return true;\n }\n }\n return false;\n }\n}\n", "/**\n * Hypertext Transfer Protocol (HTTP) response status codes.\n *\n * @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes}\n */\nexport enum HttpStatusCode {\n /**\n * The server has received the request headers and the client should proceed to send the request body\n * (in the case of a request for which a body needs to be sent; for example, a POST request).\n * Sending a large request body to a server after a request has been rejected for inappropriate headers would be inefficient.\n * To have a server check the request's headers, a client must send Expect: 100-continue as a header in its initial request\n * and receive a 100 Continue status code in response before sending the body. The response 417 Expectation Failed indicates the request should not be continued.\n */\n Continue = 100,\n\n /**\n * The requester has asked the server to switch protocols and the server has agreed to do so.\n */\n SwitchingProtocols = 101,\n\n /**\n * A WebDAV request may contain many sub-requests involving file operations, requiring a long time to complete the request.\n * This code indicates that the server has received and is processing the request, but no response is available yet.\n * This prevents the client from timing out and assuming the request was lost.\n */\n Processing = 102,\n\n /**\n * Standard response for successful HTTP requests.\n * The actual response will depend on the request method used.\n * In a GET request, the response will contain an entity corresponding to the requested resource.\n * In a POST request, the response will contain an entity describing or containing the result of the action.\n */\n Ok = 200,\n\n /**\n * The request has been fulfilled, resulting in the creation of a new resource.\n */\n Created = 201,\n\n /**\n * The request has been accepted for processing, but the processing has not been completed.\n * The request might or might not be eventually acted upon, and may be disallowed when processing occurs.\n */\n Accepted = 202,\n\n /**\n * SINCE HTTP/1.1\n * The server is a transforming proxy that received a 200 OK from its origin,\n * but is returning a modified version of the origin's response.\n */\n NonAuthoritativeInformation = 203,\n\n /**\n * The server successfully processed the request and is not returning any content.\n */\n NoContent = 204,\n\n /**\n * The server successfully processed the request, but is not returning any content.\n * Unlike a 204 response, this response requires that the requester reset the document view.\n */\n ResetContent = 205,\n\n /**\n * The server is delivering only part of the resource (byte serving) due to a range header sent by the client.\n * The range header is used by HTTP clients to enable resuming of interrupted downloads,\n * or split a download into multiple simultaneous streams.\n */\n PartialContent = 206,\n\n /**\n * The message body that follows is an XML message and can contain a number of separate response codes,\n * depending on how many sub-requests were made.\n */\n MultiStatus = 207,\n\n /**\n * The members of a DAV binding have already been enumerated in a preceding part of the (multistatus) response,\n * and are not being included again.\n */\n AlreadyReported = 208,\n\n /**\n * The server has fulfilled a request for the resource,\n * and the response is a representation of the result of one or more instance-manipulations applied to the current instance.\n */\n ImUsed = 226,\n\n /**\n * Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation).\n * For example, this code could be used to present multiple video format options,\n * to list files with different filename extensions, or to suggest word-sense disambiguation.\n */\n MultipleChoices = 300,\n\n /**\n * This and all future requests should be directed to the given URI.\n */\n MovedPermanently = 301,\n\n /**\n * This is an example of industry practice contradicting the standard.\n * The HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect\n * (the original describing phrase was \"Moved Temporarily\"), but popular browsers implemented 302\n * with the functionality of a 303 See Other. Therefore, HTTP/1.1 added status codes 303 and 307\n * to distinguish between the two behaviours. However, some Web applications and frameworks\n * use the 302 status code as if it were the 303.\n */\n Found = 302,\n\n /**\n * SINCE HTTP/1.1\n * The response to the request can be found under another URI using a GET method.\n * When received in response to a POST (or PUT/DELETE), the client should presume that\n * the server has received the data and should issue a redirect with a separate GET message.\n */\n SeeOther = 303,\n\n /**\n * Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match.\n * In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy.\n */\n NotModified = 304,\n\n /**\n * SINCE HTTP/1.1\n * The requested resource is available only through a proxy, the address for which is provided in the response.\n * Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status code, primarily for security reasons.\n */\n UseProxy = 305,\n\n /**\n * No longer used. Originally meant \"Subsequent requests should use the specified proxy.\"\n */\n SwitchProxy = 306,\n\n /**\n * SINCE HTTP/1.1\n * In this case, the request should be repeated with another URI; however, future requests should still use the original URI.\n * In contrast to how 302 was historically implemented, the request method is not allowed to be changed when reissuing the original request.\n * For example, a POST request should be repeated using another POST request.\n */\n TemporaryRedirect = 307,\n\n /**\n * The request and all future requests should be repeated using another URI.\n * 307 and 308 parallel the behaviors of 302 and 301, but do not allow the HTTP method to change.\n * So, for example, submitting a form to a permanently redirected resource may continue smoothly.\n */\n PermanentRedirect = 308,\n\n /**\n * The server cannot or will not process the request due to an apparent client error\n * (e.g., malformed request syntax, too large size, invalid request message framing, or deceptive request routing).\n */\n BadRequest = 400,\n\n /**\n * Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet\n * been provided. The response must include a WWW-Authenticate header field containing a challenge applicable to the\n * requested resource. See Basic access authentication and Digest access authentication. 401 semantically means\n * \"unauthenticated\",i.e. the user does not have the necessary credentials.\n */\n Unauthorized = 401,\n\n /**\n * Reserved for future use. The original intention was that this code might be used as part of some form of digital\n * cash or micro payment scheme, but that has not happened, and this code is not usually used.\n * Google Developers API uses this status if a particular developer has exceeded the daily limit on requests.\n */\n PaymentRequired = 402,\n\n /**\n * The request was valid, but the server is refusing action.\n * The user might not have the necessary permissions for a resource.\n */\n Forbidden = 403,\n\n /**\n * The requested resource could not be found but may be available in the future.\n * Subsequent requests by the client are permissible.\n */\n NotFound = 404,\n\n /**\n * A request method is not supported for the requested resource;\n * for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource.\n */\n MethodNotAllowed = 405,\n\n /**\n * The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.\n */\n NotAcceptable = 406,\n\n /**\n * The client must first authenticate itself with the proxy.\n */\n ProxyAuthenticationRequired = 407,\n\n /**\n * The server timed out waiting for the request.\n * According to HTTP specifications:\n * \"The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time.\"\n */\n RequestTimeout = 408,\n\n /**\n * Indicates that the request could not be processed because of conflict in the request,\n * such as an edit conflict between multiple simultaneous updates.\n */\n Conflict = 409,\n\n /**\n * Indicates that the resource requested is no longer available and will not be available again.\n * This should be used when a resource has been intentionally removed and the resource should be purged.\n * Upon receiving a 410 status code, the client should not request the resource in the future.\n * Clients such as search engines should remove the resource from their indices.\n * Most use cases do not require clients and search engines to purge the resource, and a \"404 Not Found\" may be used instead.\n */\n Gone = 410,\n\n /**\n * The request did not specify the length of its content, which is required by the requested resource.\n */\n LengthRequired = 411,\n\n /**\n * The server does not meet one of the preconditions that the requester put on the request.\n */\n PreconditionFailed = 412,\n\n /**\n * The request is larger than the server is willing or able to process. Previously called \"Request Entity Too Large\".\n */\n PayloadTooLarge = 413,\n\n /**\n * The URI provided was too long for the server to process. Often the result of too much data being encoded as a query-string of a GET request,\n * in which case it should be converted to a POST request.\n * Called \"Request-URI Too Long\" previously.\n */\n UriTooLong = 414,\n\n /**\n * The request entity has a media type which the server or resource does not support.\n * For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format.\n */\n UnsupportedMediaType = 415,\n\n /**\n * The client has asked for a portion of the file (byte serving), but the server cannot supply that portion.\n * For example, if the client asked for a part of the file that lies beyond the end of the file.\n * Called \"Requested Range Not Satisfiable\" previously.\n */\n RangeNotSatisfiable = 416,\n\n /**\n * The server cannot meet the requirements of the Expect request-header field.\n */\n ExpectationFailed = 417,\n\n /**\n * This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol,\n * and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by\n * teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including Google.com.\n */\n IAmATeapot = 418,\n\n /**\n * The request was directed at a server that is not able to produce a response (for example because a connection reuse).\n */\n MisdirectedRequest = 421,\n\n /**\n * The request was well-formed but was unable to be followed due to semantic errors.\n */\n UnprocessableEntity = 422,\n\n /**\n * The resource that is being accessed is locked.\n */\n Locked = 423,\n\n /**\n * The request failed due to failure of a previous request (e.g., a PROPPATCH).\n */\n FailedDependency = 424,\n\n /**\n * Indicates that the server is unwilling to risk processing a request that might be replayed.\n */\n TooEarly = 425,\n\n /**\n * The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field.\n */\n UpgradeRequired = 426,\n\n /**\n * The origin server requires the request to be conditional.\n * Intended to prevent \"the 'lost update' problem, where a client\n * GETs a resource's state, modifies it, and PUTs it back to the server,\n * when meanwhile a third party has modified the state on the server, leading to a conflict.\"\n */\n PreconditionRequired = 428,\n\n /**\n * The user has sent too many requests in a given amount of time. Intended for use with rate-limiting schemes.\n */\n TooManyRequests = 429,\n\n /**\n * The server is unwilling to process the request because either an individual header field,\n * or all the header fields collectively, are too large.\n */\n RequestHeaderFieldsTooLarge = 431,\n\n /**\n * A server operator has received a legal demand to deny access to a resource or to a set of resources\n * that includes the requested resource. The code 451 was chosen as a reference to the novel Fahrenheit 451.\n */\n UnavailableForLegalReasons = 451,\n\n /**\n * A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.\n */\n InternalServerError = 500,\n\n /**\n * The server either does not recognize the request method, or it lacks the ability to fulfill the request.\n * Usually this implies future availability (e.g., a new feature of a web-service API).\n */\n NotImplemented = 501,\n\n /**\n * The server was acting as a gateway or proxy and received an invalid response from the upstream server.\n */\n BadGateway = 502,\n\n /**\n * The server is currently unavailable (because it is overloaded or down for maintenance).\n * Generally, this is a temporary state.\n */\n ServiceUnavailable = 503,\n\n /**\n * The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.\n */\n GatewayTimeout = 504,\n\n /**\n * The server does not support the HTTP protocol version used in the request\n */\n HttpVersionNotSupported = 505,\n\n /**\n * Transparent content negotiation for the request results in a circular reference.\n */\n VariantAlsoNegotiates = 506,\n\n /**\n * The server is unable to store the representation needed to complete the request.\n */\n InsufficientStorage = 507,\n\n /**\n * The server detected an infinite loop while processing the request.\n */\n LoopDetected = 508,\n\n /**\n * Further extensions to the request are required for the server to fulfill it.\n */\n NotExtended = 510,\n\n /**\n * The client needs to authenticate to gain network access.\n * Intended for use by intercepting proxies used to control access to the network (e.g., \"captive portals\" used\n * to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot).\n */\n NetworkAuthenticationRequired = 511,\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n Codec,\n buildCodecForObject,\n codecForConstString,\n codecForEither,\n codecForString,\n} from \"./codec.js\";\nimport {\n AmountString,\n CurrencySpecification,\n DecimalNumber,\n codecForCurrencySpecificiation,\n codecForDecimalNumber,\n} from \"./types-taler-common.js\";\n\n// export interface ConversionInfo {\n// // Exchange rate to buy regional currency from fiat\n// cashin_ratio: DecimalNumber;\n\n// // Exchange rate to sell regional currency for fiat\n// cashout_ratio: DecimalNumber;\n\n// // Fee to subtract after applying the cashin ratio.\n// cashin_fee: AmountString;\n\n// // Fee to subtract after applying the cashout ratio.\n// cashout_fee: AmountString;\n\n// // Minimum amount authorised for cashin, in fiat before conversion\n// cashin_min_amount: AmountString;\n\n// // Minimum amount authorised for cashout, in regional before conversion\n// cashout_min_amount: AmountString;\n\n// // Smallest possible regional amount, converted amount is rounded to this amount\n// cashin_tiny_amount: AmountString;\n\n// // Smallest possible fiat amount, converted amount is rounded to this amount\n// cashout_tiny_amount: AmountString;\n\n// // Rounding mode used during cashin conversion\n// cashin_rounding_mode: RoundingMode;\n\n// // Rounding mode used during cashout conversion\n// cashout_rounding_mode: RoundingMode;\n// }\n\nexport interface TalerConversionInfoConfig {\n // libtool-style representation of the Bank protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Name of the API.\n name: \"taler-conversion-info\";\n\n // URN of the implementation (needed to interpret 'revision' in version).\n // @since v4, may become mandatory in the future.\n implementation?: string;\n\n // Currency used by this bank.\n regional_currency: string;\n\n // How the bank SPA should render this currency.\n regional_currency_specification: CurrencySpecification;\n\n // External currency used during conversion.\n fiat_currency: string;\n\n // How the bank SPA should render this currency.\n fiat_currency_specification: CurrencySpecification;\n\n // Global exchange rate between the regional currency and the fiat\n // currency of the banking system. Use /rate to get the user specific\n // rate.\n // FIXME spec: changed on v2, breaking change insteand of deprecating\n conversion_rate: ConversionRate;\n}\n\nexport interface CashinConversionResponse {\n // Amount that the user will get deducted from their fiat\n // bank account, according to the 'amount_credit' value.\n amount_debit: AmountString;\n // Amount that the user will receive in their regional\n // bank account, according to 'amount_debit'.\n amount_credit: AmountString;\n}\n\nexport interface CashoutConversionResponse {\n // Amount that the user will get deducted from their regional\n // bank account, according to the 'amount_credit' value.\n amount_debit: AmountString;\n // Amount that the user will receive in their fiat\n // bank account, according to 'amount_debit'.\n amount_credit: AmountString;\n}\n\nexport type RoundingMode = \"zero\" | \"up\" | \"nearest\";\n\nexport interface ConversionRate {\n // Minimum amount authorised for cashin, in fiat before conversion\n cashin_min_amount: AmountString;\n\n // Exchange rate to buy regional currency from fiat\n cashin_ratio: DecimalNumber;\n\n // Fee to subtract after applying the cashin ratio.\n cashin_fee: AmountString;\n\n // Rounding mode used during cashin conversion\n cashin_rounding_mode: RoundingMode;\n\n // Smallest possible regional amount, converted amount is rounded to this amount\n cashin_tiny_amount: AmountString;\n\n // Minimum amount authorised for cashout, in regional before conversion\n cashout_min_amount: AmountString;\n\n // Exchange rate to sell regional currency for fiat\n cashout_ratio: DecimalNumber;\n\n // Fee to subtract after applying the cashout ratio.\n cashout_fee: AmountString;\n\n // Rounding mode used during cashout conversion\n cashout_rounding_mode: RoundingMode;\n\n // Smallest possible fiat amount, converted amount is rounded to this amount\n cashout_tiny_amount: AmountString;\n}\n\nexport const codecForCashoutConversionResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount_credit\", codecForAmountString())\n .property(\"amount_debit\", codecForAmountString())\n .build(\"TalerCorebankApi.CashoutConversionResponse\");\n\nexport const codecForCashinConversionResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount_credit\", codecForAmountString())\n .property(\"amount_debit\", codecForAmountString())\n .build(\"TalerCorebankApi.CashinConversionResponse\");\n\nexport const codecForConversionRate = (): Codec =>\n buildCodecForObject()\n .property(\"cashin_fee\", codecForAmountString())\n .property(\"cashin_min_amount\", codecForAmountString())\n .property(\"cashin_ratio\", codecForDecimalNumber())\n .property(\n \"cashin_rounding_mode\",\n codecForEither(\n codecForConstString(\"zero\"),\n codecForConstString(\"up\"),\n codecForConstString(\"nearest\"),\n ),\n )\n .property(\"cashin_tiny_amount\", codecForAmountString())\n .property(\"cashout_fee\", codecForAmountString())\n .property(\"cashout_min_amount\", codecForAmountString())\n .property(\"cashout_ratio\", codecForDecimalNumber())\n .property(\n \"cashout_rounding_mode\",\n codecForEither(\n codecForConstString(\"zero\"),\n codecForConstString(\"up\"),\n codecForConstString(\"nearest\"),\n ),\n )\n .property(\"cashout_tiny_amount\", codecForAmountString())\n .build(\"ConversionBankConfig.ConversionInfo\");\n\nexport const codecForConversionBankConfig =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForConstString(\"taler-conversion-info\"))\n .property(\"version\", codecForString())\n .property(\"regional_currency\", codecForString())\n .property(\n \"regional_currency_specification\",\n codecForCurrencySpecificiation(),\n )\n .property(\"fiat_currency\", codecForString())\n .property(\"fiat_currency_specification\", codecForCurrencySpecificiation())\n\n .property(\"conversion_rate\", codecForConversionRate())\n .build(\"ConversionBankConfig.IntegrationConfig\");\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Imports.\n */\nimport { AmountJson, Amounts } from \"../amounts.js\";\nimport { HttpRequestLibrary } from \"../http-common.js\";\nimport { HttpStatusCode } from \"../http-status-codes.js\";\nimport { createPlatformHttpLib } from \"../http.js\";\nimport { LibtoolVersion } from \"../libtool-version.js\";\nimport {\n FailCasesByMethod,\n ResultByMethod,\n carefullyParseConfig,\n opEmptySuccess,\n opKnownHttpFailure,\n opKnownTalerFailure,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n} from \"../operation.js\";\nimport { TalerErrorCode } from \"../taler-error-codes.js\";\nimport {\n ConversionRate,\n codecForCashinConversionResponse,\n codecForCashoutConversionResponse,\n codecForConversionBankConfig,\n codecForConversionRate,\n} from \"../types-taler-bank-conversion.js\";\nimport { codecForTalerErrorDetail } from \"../types-taler-wallet.js\";\nimport {\n authHeaders,\n BasicOrTokenAuth,\n CacheEvictor,\n nullEvictor,\n TokenAuth,\n} from \"./utils.js\";\n\nexport type TalerBankConversionResultByMethod<\n prop extends keyof TalerBankConversionHttpClient,\n> = ResultByMethod;\nexport type TalerBankConversionErrorsByMethod<\n prop extends keyof TalerBankConversionHttpClient,\n> = FailCasesByMethod;\n\nexport enum TalerBankConversionCacheEviction {\n UPDATE_RATE,\n}\n\n/**\n * The API is used by the wallets.\n */\nexport class TalerBankConversionHttpClient {\n public static readonly PROTOCOL_VERSION = \"0:0:0\";\n\n httpLib: HttpRequestLibrary;\n cacheEvictor: CacheEvictor;\n\n constructor(\n readonly baseUrl: string,\n httpClient?: HttpRequestLibrary,\n cacheEvictor?: CacheEvictor,\n ) {\n this.httpLib = httpClient ?? createPlatformHttpLib();\n this.cacheEvictor = cacheEvictor ?? nullEvictor;\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version);\n return compare?.compatible ?? false;\n }\n\n /**\n * https://docs.taler.net/core/api-bank-conversion-info.html#get--config\n *\n */\n async getConfig() {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-conversion-info\",\n TalerBankConversionHttpClient.PROTOCOL_VERSION,\n resp,\n codecForConversionBankConfig(),\n );\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-conversion-info.html#get--rate\n *\n */\n async getRate(auth: TokenAuth | undefined) {\n const url = new URL(`rate`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForConversionRate());\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-conversion-info.html#get--cashin-rate\n *\n */\n async getCashinRate(\n auth: TokenAuth | undefined,\n conversion: { debit?: AmountJson; credit?: AmountJson },\n ) {\n const url = new URL(`cashin-rate`, this.baseUrl);\n if (conversion.debit) {\n url.searchParams.set(\"amount_debit\", Amounts.stringify(conversion.debit));\n }\n if (conversion.credit) {\n url.searchParams.set(\n \"amount_credit\",\n Amounts.stringify(conversion.credit),\n );\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForCashinConversionResponse());\n case HttpStatusCode.BadRequest: {\n const body = await resp.json();\n const details = codecForTalerErrorDetail().decode(body);\n switch (details.code) {\n case TalerErrorCode.GENERIC_PARAMETER_MISSING:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.GENERIC_PARAMETER_MALFORMED:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.GENERIC_CURRENCY_MISMATCH:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-conversion-info.html#get--cashout-rate\n *\n */\n async getCashoutRate(\n auth: TokenAuth | undefined,\n conversion: {\n debit?: AmountJson;\n credit?: AmountJson;\n },\n ) {\n const url = new URL(`cashout-rate`, this.baseUrl);\n if (conversion.debit) {\n url.searchParams.set(\"amount_debit\", Amounts.stringify(conversion.debit));\n }\n if (conversion.credit) {\n url.searchParams.set(\n \"amount_credit\",\n Amounts.stringify(conversion.credit),\n );\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForCashoutConversionResponse());\n case HttpStatusCode.BadRequest: {\n const body = await resp.json();\n const details = codecForTalerErrorDetail().decode(body);\n switch (details.code) {\n case TalerErrorCode.GENERIC_PARAMETER_MISSING:\n return opKnownHttpFailure(resp.status, resp);\n case TalerErrorCode.GENERIC_PARAMETER_MALFORMED:\n return opKnownHttpFailure(resp.status, resp);\n case TalerErrorCode.GENERIC_CURRENCY_MISMATCH:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-conversion-info.html#post--conversion-rate\n *\n */\n async updateConversionRate(\n auth: BasicOrTokenAuth | undefined,\n body: ConversionRate,\n ) {\n const url = new URL(`conversion-rate`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: authHeaders(auth),\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerBankConversionCacheEviction.UPDATE_RATE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n Codec,\n buildCodecForObject,\n buildCodecForUnion,\n codecForBoolean,\n codecForConstString,\n codecForEither,\n codecForList,\n codecForNumber,\n codecForString,\n codecOptional,\n codecOptionalDefault,\n} from \"./codec.js\";\nimport { PaytoString, codecForPaytoString } from \"./payto.js\";\nimport { codecForTalerUriString, TalerUriString } from \"./taleruri.js\";\nimport { codecForTimestamp } from \"./time.js\";\nimport {\n codecForConversionRate,\n ConversionRate,\n RoundingMode,\n} from \"./types-taler-bank-conversion.js\";\nimport { WithdrawalOperationStatusFlag } from \"./types-taler-bank-integration.js\";\nimport {\n AmountString,\n CurrencySpecification,\n DecimalNumber,\n Integer,\n ShortHashCode,\n Timestamp,\n codecForCurrencySpecificiation,\n codecForDecimalNumber,\n} from \"./types-taler-common.js\";\nimport { TanChannel } from \"./types-taler-merchant.js\";\n\nexport interface IntegrationConfig {\n // libtool-style representation of the Bank protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n currency: string;\n\n // How the bank SPA should render this currency.\n currency_specification: CurrencySpecification;\n\n // Name of the API.\n name: \"taler-bank-integration\";\n\n implementation?: string;\n}\n\nexport interface TalerCorebankConfigResponse {\n /**\n * Name of this API, always \"taler-corebank\".\n *\n * For legacy reasons, libeufin-bank will also be accepted for some time.\n */\n name: \"libeufin-bank\" | \"taler-corebank\";\n\n // API version in the form $n:$n:$n\n version: string;\n\n // Bank display name to be used in user interfaces.\n // For consistency use \"Taler Bank\" if missing.\n // @since v4, will become mandatory in the next version.\n bank_name?: string;\n\n // Advertised base URL to use when you sharing an URL with another\n // program.\n // @since v4.\n base_url?: string;\n\n // If 'true' the server provides local currency conversion support\n // If 'false' some parts of the API are not supported and return 501\n allow_conversion?: boolean;\n\n // If 'true' anyone can register\n // If 'false' only the admin can\n allow_registrations?: boolean;\n\n // If 'true' account can delete themselves\n // If 'false' only the admin can delete accounts\n allow_deletions?: boolean;\n\n // If 'true' anyone can edit their name\n // If 'false' only admin can\n allow_edit_name?: boolean;\n\n // If 'true' anyone can edit their cashout account\n // If 'false' only the admin\n allow_edit_cashout_payto_uri?: boolean;\n\n // Default debt limit for newly created accounts\n default_debit_threshold?: AmountString;\n\n // Currency used by this bank.\n currency: string;\n\n // How the bank SPA should render this currency.\n currency_specification: CurrencySpecification;\n\n // TAN channels supported by the server\n supported_tan_channels?: TanChannel[];\n\n // Wire transfer type supported by the bank.\n // Default to 'iban' is missing\n // @since v4, may become mandatory in the future.\n wire_type?: string;\n\n // Wire transfer execution fees.\n // @since v4, will become mandatory in the next version.\n wire_transfer_fees?: AmountString;\n\n // Minimum wire transfer amount allowed. Only applies to bank transactions and withdrawals.\n // @since **v4**, will become mandatory in the next version.\n min_wire_transfer_amount?: AmountString;\n\n // Maximum wire transfer amount allowed. Only applies to bank transactions and withdrawals.\n // @since **v4**, will become mandatory in the next version.\n max_wire_transfer_amount?: AmountString;\n}\n\nexport interface BankAccountCreateWithdrawalRequest {\n // Amount to withdraw. If given, the wallet\n // cannot change the amount.\n // Optional since **vC2EC**.\n amount?: AmountString;\n\n // Suggested amount to withdraw. The wallet can\n // still change the suggestion.\n // @since **vC2EC**\n suggested_amount?: AmountString;\n\n // If true, tell the wallet not to allow the user to\n // specify an amount to withdraw and to not provide\n // any amount when registering with the withdrawal\n // operation. The amount to withdraw will be set\n // by the final /withdrawals/$WITHDRAWAL_ID/confirm step.\n // @since **v8**\n no_amount_to_wallet?: boolean;\n}\n\nexport interface BankAccountConfirmWithdrawalRequest {\n // Selected amount to be transferred. Optional if the\n // backend already knows the amount.\n // @since **v6**\n amount?: AmountString;\n}\n\nexport interface BankAccountCreateWithdrawalResponse {\n // ID of the withdrawal, can be used to view/modify the withdrawal operation.\n withdrawal_id: string;\n\n // URI that can be passed to the wallet to initiate the withdrawal.\n taler_withdraw_uri: TalerUriString;\n}\n\nexport interface WithdrawalPublicInfo {\n // Current status of the operation\n // pending: the operation is pending parameters selection (exchange and reserve public key)\n // selected: the operations has been selected and is pending confirmation\n // aborted: the operation has been aborted\n // confirmed: the transfer has been confirmed and registered by the bank\n status: WithdrawalOperationStatusFlag;\n\n // Amount that will be withdrawn with this operation\n // (raw amount without fee considerations).\n amount?: AmountString;\n\n // Suggestion for the amount to be withdrawn with this\n // operation. Given if a suggestion was made but the\n // user may still change the amount.\n // Optional since **vC2EC**.\n suggested_amount?: AmountString;\n\n // Account username\n username: string;\n\n // Reserve public key selected by the exchange,\n // only non-null if status is selected or confirmed.\n selected_reserve_pub?: string;\n\n // Exchange account selected by the wallet\n // only non-null if status is selected or confirmed.\n selected_exchange_account?: PaytoString;\n\n // If true, the wallet must not allow the user to\n // specify an amount to withdraw and to not provide\n // any amount when registering with the withdrawal\n // operation. The amount to withdraw will be set\n // by the final /withdrawals/$WITHDRAWAL_ID/confirm step.\n // @since **v8**\n no_amount_to_wallet?: boolean;\n}\n\nexport interface BankAccountTransactionsResponse {\n transactions: BankAccountTransactionInfo[];\n}\n\nexport interface BankAccountTransactionInfo {\n creditor_payto_uri: PaytoString;\n debtor_payto_uri: PaytoString;\n\n amount: AmountString;\n direction: \"debit\" | \"credit\";\n\n subject: string;\n\n // Transaction unique ID. Matches\n // $transaction_id from the URI.\n row_id: number;\n date: Timestamp;\n}\n\nexport interface CreateTransactionRequest {\n // Address in the Payto format of the wire transfer receiver.\n // It needs at least the 'message' query string parameter.\n payto_uri: PaytoString;\n\n // Transaction amount (in the $currency:x.y format), optional.\n // However, when not given, its value must occupy the 'amount'\n // query string parameter of the 'payto' field. In case it\n // is given in both places, the paytoUri's takes the precedence.\n amount?: AmountString;\n\n // Nonce to make the request idempotent. Requests with the same\n // request_uid that differ in any of the other fields\n // are rejected.\n // @since v4, will become mandatory in the next version.\n request_uid?: ShortHashCode;\n}\n\nexport interface CreateTransactionResponse {\n // ID identifying the transaction being created\n row_id: Integer;\n}\n\nexport interface RegisterAccountResponse {\n // Internal payto URI of this bank account.\n internal_payto_uri: PaytoString;\n}\n\nexport interface RegisterAccountRequest {\n // Username\n // Must match [a-zA-Z0-9\\-\\._~]{1, 126}\n username: string;\n\n // Password.\n password: string;\n\n // Legal name of the account owner\n name: string;\n\n // Make this account visible to anyone?\n // Defaults to false.\n is_public?: boolean;\n\n // Is this a taler exchange account?\n // If true:\n // - incoming transactions to the account that do not\n // have a valid reserve public key are automatically\n // - the account provides the taler-wire-gateway-api endpoints\n // Defaults to false.\n is_taler_exchange?: boolean;\n\n // Addresses where to send the TAN for transactions.\n contact_data?: ChallengeContactData;\n\n // 'payto' address of a fiat bank account.\n // Payments will be sent to this bank account\n // when the user wants to convert the regional currency\n // back to fiat currency outside bank.\n cashout_payto_uri?: PaytoString;\n\n // Internal payto URI of this bank account.\n // Used mostly for testing.\n payto_uri?: PaytoString;\n\n // If present, set the max debit allowed for this user\n // Only admin can set this property.\n debit_threshold?: AmountString;\n\n // If present, set the user conversion rate class\n // Only admin can set this property.\n // @since **v9**\n conversion_rate_class_id?: Integer;\n\n // If present, enables 2FA and set the TAN channel used for challenges\n // Only admin can set this property, other user can reconfig their account\n // after creation.\n tan_channel?: TanChannel;\n\n // @deprecated in **v9**, use conversion_rate_class_id instead\n // min_cashout?: Amount;\n}\n\nexport type EmailAddress = string;\nexport type PhoneNumber = string;\n\nexport interface ChallengeContactData {\n // E-Mail address\n email?: EmailAddress;\n\n // Phone number.\n phone?: PhoneNumber;\n}\n\nexport interface AccountReconfiguration {\n // Addresses where to send the TAN for transactions.\n // Currently only used for cashouts.\n // If missing, cashouts will fail.\n // In the future, might be used for other transactions\n // as well.\n // Only admin can change this property.\n contact_data?: ChallengeContactData;\n\n // 'payto' URI of a fiat bank account.\n // Payments will be sent to this bank account\n // when the user wants to convert the regional currency\n // back to fiat currency outside bank.\n // Only admin can change this property if not allowed in config\n cashout_payto_uri?: PaytoString | null;\n\n // If present, change the legal name associated with $username.\n // Only admin can change this property if not allowed in config\n name?: string;\n\n // Make this account visible to anyone?\n is_public?: boolean;\n\n // If present, change the max debit allowed for this user\n // Only admin can change this property.\n debit_threshold?: AmountString;\n\n // If present, set the user conversion rate class\n // Only admin can set this property.\n // @since **v9**\n conversion_rate_class_id?: Integer | null;\n\n // If present, enables 2FA and set the TAN channel used for challenges\n tan_channel?: TanChannel | null;\n\n // @deprecated in **v9**, user conversion rate classes instead\n // min_cashout?: Amount;\n}\n\nexport interface AccountPasswordChange {\n // New password.\n new_password: string;\n // Old password. If present, check that the old password matches.\n // Optional for admin account.\n old_password?: string;\n}\n\nexport interface PublicAccountsResponse {\n public_accounts: PublicAccount[];\n}\nexport interface PublicAccount {\n // Username of the account\n username: string;\n\n // Internal payto URI of this bank account.\n payto_uri: string;\n\n // Current balance of the account\n balance: Balance;\n\n // Is this a taler exchange account?\n is_taler_exchange: boolean;\n\n // Opaque unique ID used for pagination.\n // @since v4, will become mandatory in the future.\n row_id?: Integer;\n}\n\nexport interface ListBankAccountsResponse {\n accounts: AccountMinimalData[];\n}\n\nexport interface GetBankAccountByIdResponse {\n account: AccountMinimalData;\n}\n\nexport interface Balance {\n amount: AmountString;\n credit_debit_indicator: \"credit\" | \"debit\";\n}\n\nexport interface AccountMinimalData {\n // Username\n username: string;\n\n // Legal name of the account owner.\n name: string;\n\n // Internal payto URI of this bank account.\n payto_uri: PaytoString;\n\n // current balance of the account\n balance: Balance;\n\n // Number indicating the max debit allowed for the requesting user.\n debit_threshold: AmountString;\n\n // Custom minimum cashout amount for this account.\n // If null or absent, the global conversion fee is used.\n // @since v6\n // @deprecated in **v9**, use conversion_rate_class_id instead\n // min_cashout?: AmountString;\n\n // Is this account visible to anyone?\n is_public: boolean;\n\n // Is this a taler exchange account?\n is_taler_exchange: boolean;\n\n // Opaque unique ID used for pagination.\n // @since v4, will become mandatory in the future.\n row_id?: Integer;\n\n // Is the account locked.\n // Defaults to false.\n // @deprecated since **v7**\n // is_locked?: boolean;\n\n // Current status of the account\n // active: the account can be used\n // locked: the account can be used but cannot create new tokens\n // @since **v7**\n // deleted: the account has been deleted but is retained for compliance\n // reasons, only the administrator can access it\n // Defaults to 'active' is missing\n // @since **v4**, will become mandatory in the next version.\n status?: AccountStatus;\n\n // Conversion rate class of the user\n conversion_rate_class_id?: Integer;\n\n // Applied conversion rate\n conversion_rate?: ConversionRate;\n}\n\nexport type AccountStatus = \"active\" | \"locked\" | \"deleted\";\n\nexport interface ConversionRateClass {\n // The name of this class\n name: string;\n\n // A description of the class\n description?: string;\n\n // Class unique ID\n conversion_rate_class_id: Integer;\n\n // Number of users affected to this class\n num_users: Integer;\n\n // Minimum fiat amount authorised for cashin before conversion\n cashin_min_amount?: AmountString;\n\n // Exchange rate to buy regional currency from fiat\n cashin_ratio?: DecimalNumber;\n\n // Regional amount fee to subtract after applying the cashin ratio.\n cashin_fee?: AmountString;\n\n // Rounding mode used during cashin conversion\n cashin_rounding_mode?: RoundingMode;\n\n // Minimum regional amount authorised for cashout before conversion\n cashout_min_amount?: AmountString;\n\n // Exchange rate to sell regional currency for fiat\n cashout_ratio?: DecimalNumber;\n\n // Fiat amount fee to subtract after applying the cashout ratio.\n cashout_fee?: AmountString;\n\n // Rounding mode used during cashout conversion\n cashout_rounding_mode?: RoundingMode;\n}\n\nexport interface ConversionRateClasses {\n classes: ConversionRateClass[];\n}\n\nexport interface AccountConversionRateClass {\n // Class unique ID\n conversion_rate_class_id: Integer;\n\n // Minimum fiat amount authorised for cashin before conversion\n cashin_min_amount?: AmountString;\n\n // Exchange rate to buy regional currency from fiat\n cashin_ratio?: DecimalNumber;\n\n // Regional amount fee to subtract after applying the cashin ratio.\n cashin_fee?: AmountString;\n\n // Rounding mode used during cashin conversion\n cashin_rounding_mode?: RoundingMode;\n\n // Minimum regional amount authorised for cashout before conversion\n cashout_min_amount?: AmountString;\n\n // Exchange rate to sell regional currency for fiat\n cashout_ratio?: DecimalNumber;\n\n // Fiat amount fee to subtract after applying the cashout ratio.\n cashout_fee?: AmountString;\n\n // Rounding mode used during cashout conversion\n cashout_rounding_mode?: RoundingMode;\n}\n\nexport interface ConversionRateClassInput {\n // The name of this class\n name: string;\n\n // A description of the class\n description?: string;\n\n // Minimum fiat amount authorised for cashin before conversion\n cashin_min_amount?: AmountString;\n\n // Exchange rate to buy regional currency from fiat\n cashin_ratio?: DecimalNumber;\n\n // Regional amount fee to subtract after applying the cashin ratio.\n cashin_fee?: AmountString;\n\n // Rounding mode used during cashin conversion\n cashin_rounding_mode?: RoundingMode;\n\n // Minimum regional amount authorised for cashout before conversion\n cashout_min_amount?: AmountString;\n\n // Exchange rate to sell regional currency for fiat\n cashout_ratio?: DecimalNumber;\n\n // Fiat amount fee to subtract after applying the cashout ratio.\n cashout_fee?: AmountString;\n\n // Rounding mode used during cashout conversion\n cashout_rounding_mode?: RoundingMode;\n}\n\nexport interface ConversionRateClassResponse {\n // ID identifying the conversion rate class being created\n conversion_rate_class_id: Integer;\n}\n\nexport interface AccountData {\n // Legal name of the account owner.\n name: string;\n\n // Available balance on the account.\n balance: Balance;\n\n // payto://-URI of the account.\n payto_uri: PaytoString;\n\n // Number indicating the max debit allowed for the requesting user.\n debit_threshold: AmountString;\n\n // Custom minimum cashout amount for this account.\n // If null or absent, the global conversion fee is used.\n // @since v6\n // @deprecated in **v9**, use conversion_rate_class_id instead\n // min_cashout?: AmountString;\n\n // Addresses where to send the TAN for transactions.\n // Currently only used for cashouts.\n // If missing, cashouts will fail.\n // In the future, might be used for other transactions\n // as well.\n contact_data?: ChallengeContactData;\n\n // Full 'payto' URI of a fiat bank account where to send cashouts with\n // ``name`` as the 'receiver-name'.\n // This field is optional\n // because not all the accounts are required to participate\n // in the merchants' circuit. One example is the exchange:\n // that never cashouts. Registering these accounts can\n // be done via the access API.\n cashout_payto_uri?: PaytoString;\n\n // Is this account visible to anyone?\n is_public: boolean;\n\n // Is this a taler exchange account?\n is_taler_exchange: boolean;\n\n // Is the account locked.\n // Defaults to false.\n // @deprecated since **v7**\n // is_locked?: boolean;\n\n // Is 2FA enabled and what channel is used for challenges?\n tan_channel?: TanChannel;\n\n // Current status of the account\n // active: the account can be used\n // locked: the account can be used but cannot create new tokens\n // @since **v7**\n // deleted: the account has been deleted but is retained for compliance\n // reasons, only the administrator can access it\n // Defaults to 'active' is missing\n // @since **v4**, will become mandatory in the next version.\n status?: AccountStatus;\n\n // Conversion rate class of the user\n conversion_rate_class_id?: Integer;\n}\n\nexport interface CashoutRequest {\n // Nonce to make the request idempotent. Requests with the same\n // request_uid that differ in any of the other fields\n // are rejected.\n request_uid: ShortHashCode;\n\n // Optional subject to associate to the\n // cashout operation. This data will appear\n // as the incoming wire transfer subject in\n // the user's fiat bank account.\n subject?: string;\n\n // That is the plain amount that the user specified\n // to cashout. Its $currency is the (regional) currency of the\n // bank instance.\n amount_debit: AmountString;\n\n // That is the amount that will effectively be\n // transferred by the bank to the user's bank\n // account, that is external to the regional currency.\n // It is expressed in the fiat currency and\n // is calculated after the cashout fee and the\n // exchange rate. See the /cashout-rates call.\n // The client needs to calculate this amount\n // correctly based on the amount_debit and the cashout rate,\n // otherwise the request will fail.\n amount_credit: AmountString;\n}\n\nexport interface CashoutResponse {\n // ID identifying the operation being created\n cashout_id: number;\n}\n\n/**\n * @deprecated since 4, use 2fa\n */\nexport interface CashoutConfirmRequest {\n // the TAN that confirms $CASHOUT_ID.\n tan: string;\n}\n\nexport interface Cashouts {\n // Every string represents a cash-out operation ID.\n cashouts: CashoutInfo[];\n}\n\nexport interface CashoutInfo {\n cashout_id: number;\n}\nexport interface GlobalCashouts {\n // Every string represents a cash-out operation ID.\n cashouts: GlobalCashoutInfo[];\n}\nexport interface GlobalCashoutInfo {\n cashout_id: number;\n username: string;\n}\n\nexport interface CashoutStatusResponse {\n // Amount debited to the internal\n // regional currency bank account.\n amount_debit: AmountString;\n\n // Amount credited to the external bank account.\n amount_credit: AmountString;\n\n // Transaction subject.\n subject: string;\n\n // Time when the cashout was created.\n creation_time: Timestamp;\n}\n\nexport interface ConversionRatesResponse {\n // Exchange rate to buy the local currency from the external one\n buy_at_ratio: DecimalNumber;\n\n // Exchange rate to sell the local currency for the external one\n sell_at_ratio: DecimalNumber;\n\n // Fee to subtract after applying the buy ratio.\n buy_in_fee: DecimalNumber;\n\n // Fee to subtract after applying the sell ratio.\n sell_out_fee: DecimalNumber;\n}\n\nexport enum MonitorTimeframeParam {\n hour,\n day,\n month,\n year,\n decade,\n}\n\nexport type MonitorResponse = MonitorNoConversion | MonitorWithConversion;\n\n// Monitoring stats when conversion is not supported\nexport interface MonitorNoConversion {\n type: \"no-conversions\";\n\n // How many payments were made to a Taler exchange by another\n // bank account.\n talerInCount: number;\n\n // Overall volume that has been paid to a Taler\n // exchange by another bank account.\n talerInVolume: AmountString;\n\n // How many payments were made by a Taler exchange to another\n // bank account.\n talerOutCount: number;\n\n // Overall volume that has been paid by a Taler\n // exchange to another bank account.\n talerOutVolume: AmountString;\n}\n\n// Monitoring stats when conversion is supported\nexport interface MonitorWithConversion {\n type: \"with-conversions\";\n\n // How many cashin operations were confirmed by a\n // wallet owner. Note: wallet owners\n // are NOT required to be customers of the libeufin-bank.\n cashinCount: number;\n\n // Overall regional currency that has been paid by the regional admin account\n // to regional bank accounts to fulfill all the confirmed cashin operations.\n cashinRegionalVolume: AmountString;\n\n // Overall fiat currency that has been paid to the fiat admin account\n // by fiat bank accounts to fulfill all the confirmed cashin operations.\n cashinFiatVolume: AmountString;\n\n // How many cashout operations were confirmed.\n cashoutCount: number;\n\n // Overall regional currency that has been paid to the regional admin account\n // by fiat bank accounts to fulfill all the confirmed cashout operations.\n cashoutRegionalVolume: AmountString;\n\n // Overall fiat currency that has been paid by the fiat admin account\n // to fiat bank accounts to fulfill all the confirmed cashout operations.\n cashoutFiatVolume: AmountString;\n\n // How many payments were made to a Taler exchange by another\n // bank account.\n talerInCount: number;\n\n // Overall volume that has been paid to a Taler\n // exchange by another bank account.\n talerInVolume: AmountString;\n\n // How many payments were made by a Taler exchange to another\n // bank account.\n talerOutCount: number;\n\n // Overall volume that has been paid by a Taler\n // exchange to another bank account.\n talerOutVolume: AmountString;\n}\n\nexport const codecForIntegrationBankConfig = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForConstString(\"taler-bank-integration\"))\n .property(\"version\", codecForString())\n .property(\"currency\", codecForString())\n .property(\"currency_specification\", codecForCurrencySpecificiation())\n .property(\"implementation\", codecOptional(codecForString()))\n .build(\"TalerCorebankApi.IntegrationConfig\");\n\nexport const codecForCoreBankConfig = (): Codec =>\n buildCodecForObject()\n .property(\n \"name\",\n codecForEither(\n codecForConstString(\"taler-corebank\"),\n codecForConstString(\"libeufin-bank\"),\n ),\n )\n .property(\"version\", codecForString())\n .property(\"bank_name\", codecOptional(codecForString()))\n .property(\"base_url\", codecOptional(codecForString()))\n .property(\"allow_conversion\", codecOptional(codecForBoolean()))\n .property(\"allow_registrations\", codecOptional(codecForBoolean()))\n .property(\"allow_deletions\", codecOptional(codecForBoolean()))\n .property(\"allow_edit_name\", codecOptional(codecForBoolean()))\n .property(\"allow_edit_cashout_payto_uri\", codecOptional(codecForBoolean()))\n .property(\"default_debit_threshold\", codecOptional(codecForAmountString()))\n .property(\"currency\", codecForString())\n .property(\"currency_specification\", codecForCurrencySpecificiation())\n .property(\n \"supported_tan_channels\",\n codecOptional(\n codecForList(\n codecForEither(\n codecForConstString(TanChannel.SMS),\n codecForConstString(TanChannel.EMAIL),\n ),\n ),\n ),\n )\n .property(\"wire_type\", codecOptionalDefault(codecForString(), \"iban\"))\n .property(\"wire_transfer_fees\", codecOptional(codecForAmountString()))\n .property(\"min_wire_transfer_amount\", codecOptional(codecForAmountString()))\n .property(\"max_wire_transfer_amount\", codecOptional(codecForAmountString()))\n .build(\"TalerCorebankApi.Config\");\n\nconst codecForBalance = (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\n \"credit_debit_indicator\",\n codecForEither(\n codecForConstString(\"credit\"),\n codecForConstString(\"debit\"),\n ),\n )\n .build(\"TalerCorebankApi.Balance\");\n\nconst codecForPublicAccount = (): Codec =>\n buildCodecForObject()\n .property(\"username\", codecForString())\n .property(\"balance\", codecForBalance())\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"is_taler_exchange\", codecForBoolean())\n .property(\"row_id\", codecOptional(codecForNumber()))\n .build(\"TalerCorebankApi.PublicAccount\");\n\nexport const codecForPublicAccountsResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"public_accounts\", codecForList(codecForPublicAccount()))\n .build(\"TalerCorebankApi.PublicAccountsResponse\");\n\nexport const codecForAccountMinimalData = (): Codec =>\n buildCodecForObject()\n .property(\"username\", codecForString())\n .property(\"name\", codecForString())\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"balance\", codecForBalance())\n .property(\"row_id\", codecForNumber())\n .property(\"debit_threshold\", codecForAmountString())\n .property(\"is_public\", codecForBoolean())\n .property(\"is_taler_exchange\", codecForBoolean())\n .property(\n \"status\",\n codecOptional(\n codecForEither(\n codecForConstString(\"active\"),\n codecForConstString(\"locked\"),\n codecForConstString(\"deleted\"),\n ),\n ),\n )\n .property(\"conversion_rate_class_id\", codecOptional(codecForNumber()))\n .property(\"conversion_rate\", codecOptional(codecForConversionRate()))\n .build(\"TalerCorebankApi.AccountMinimalData\");\n\nexport const codecForListBankAccountsResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"accounts\", codecForList(codecForAccountMinimalData()))\n .build(\"TalerCorebankApi.ListBankAccountsResponse\");\n\nexport const codecForAccountData = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForString())\n .property(\"balance\", codecForBalance())\n .property(\"payto_uri\", codecForPaytoString())\n .property(\"debit_threshold\", codecForAmountString())\n .property(\"contact_data\", codecOptional(codecForChallengeContactData()))\n .property(\"cashout_payto_uri\", codecOptional(codecForPaytoString()))\n .property(\"is_public\", codecForBoolean())\n .property(\"is_taler_exchange\", codecForBoolean())\n .property(\"conversion_rate_class_id\", codecOptional(codecForNumber()))\n .property(\n \"tan_channel\",\n codecOptional(\n codecForEither(\n codecForConstString(TanChannel.SMS),\n codecForConstString(TanChannel.EMAIL),\n ),\n ),\n )\n .property(\n \"status\",\n codecOptional(\n codecForEither(\n codecForConstString(\"active\"),\n codecForConstString(\"locked\"),\n codecForConstString(\"deleted\"),\n ),\n ),\n )\n .build(\"TalerCorebankApi.AccountData\");\n\nexport const codecForConversionRateClassResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"conversion_rate_class_id\", codecForNumber())\n .build(\"TalerCorebankApi.ConversionRateClassResponse\");\n\nexport const codecForConversionRateClass = (): Codec =>\n buildCodecForObject()\n .property(\"cashin_fee\", codecOptional(codecForAmountString()))\n .property(\"cashin_min_amount\", codecOptional(codecForAmountString()))\n .property(\"cashin_ratio\", codecOptional(codecForDecimalNumber()))\n .property(\n \"cashin_rounding_mode\",\n codecOptional(\n codecForEither(\n codecForConstString(\"zero\"),\n codecForConstString(\"up\"),\n codecForConstString(\"nearest\"),\n ),\n ),\n )\n .property(\"cashout_fee\", codecOptional(codecForAmountString()))\n .property(\"cashout_min_amount\", codecOptional(codecForAmountString()))\n .property(\"cashout_ratio\", codecOptional(codecForDecimalNumber()))\n .property(\n \"cashout_rounding_mode\",\n codecOptional(\n codecForEither(\n codecForConstString(\"zero\"),\n codecForConstString(\"up\"),\n codecForConstString(\"nearest\"),\n ),\n ),\n )\n .property(\"conversion_rate_class_id\", codecForNumber())\n .property(\"description\", codecOptional(codecForString()))\n .property(\"name\", codecForString())\n .property(\"num_users\", codecForNumber())\n .build(\"TalerCorebankApi.ConversionRateClass\");\n\nexport const codecForConversionRateClasses = (): Codec =>\n buildCodecForObject()\n .property(\"classes\", codecForList(codecForConversionRateClass()))\n .build(\"TalerCorebankApi.ConversionRateClasses\");\n\nexport const codecForChallengeContactData = (): Codec =>\n buildCodecForObject()\n .property(\"email\", codecOptional(codecForString()))\n .property(\"phone\", codecOptional(codecForString()))\n .build(\"TalerCorebankApi.ChallengeContactData\");\n\nexport const codecForWithdrawalPublicInfo = (): Codec =>\n buildCodecForObject()\n .property(\n \"status\",\n codecForEither(\n codecForConstString(\"pending\"),\n codecForConstString(\"selected\"),\n codecForConstString(\"aborted\"),\n codecForConstString(\"confirmed\"),\n ),\n )\n .property(\"amount\", codecOptional(codecForAmountString()))\n .property(\"suggested_amount\", codecOptional(codecForAmountString()))\n .property(\"username\", codecForString())\n .property(\"selected_reserve_pub\", codecOptional(codecForString()))\n .property(\"selected_exchange_account\", codecOptional(codecForPaytoString()))\n .property(\"no_amount_to_wallet\", codecOptional(codecForBoolean()))\n .build(\"TalerCorebankApi.WithdrawalPublicInfo\");\n\nexport const codecForBankAccountTransactionsResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"transactions\",\n codecForList(codecForBankAccountTransactionInfo()),\n )\n .build(\"TalerCorebankApi.BankAccountTransactionsResponse\");\n\nexport const codecForBankAccountTransactionInfo =\n (): Codec =>\n buildCodecForObject()\n .property(\"creditor_payto_uri\", codecForPaytoString())\n .property(\"debtor_payto_uri\", codecForPaytoString())\n .property(\"amount\", codecForAmountString())\n .property(\n \"direction\",\n codecForEither(\n codecForConstString(\"debit\"),\n codecForConstString(\"credit\"),\n ),\n )\n .property(\"subject\", codecForString())\n .property(\"row_id\", codecForNumber())\n .property(\"date\", codecForTimestamp)\n .build(\"TalerCorebankApi.BankAccountTransactionInfo\");\n\nexport const codecForCreateTransactionResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"row_id\", codecForNumber())\n .build(\"TalerCorebankApi.CreateTransactionResponse\");\n\nexport const codecForRegisterAccountResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"internal_payto_uri\", codecForPaytoString())\n .build(\"TalerCorebankApi.RegisterAccountResponse\");\n\nexport const codecForBankAccountCreateWithdrawalResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"taler_withdraw_uri\", codecForTalerUriString())\n .property(\"withdrawal_id\", codecForString())\n .build(\"TalerCorebankApi.BankAccountCreateWithdrawalResponse\");\n\nexport const codecForCashoutPending = (): Codec =>\n buildCodecForObject()\n .property(\"cashout_id\", codecForNumber())\n .build(\"TalerCorebankApi.CashoutPending\");\n\nexport const codecForCashouts = (): Codec =>\n buildCodecForObject()\n .property(\"cashouts\", codecForList(codecForCashoutInfo()))\n .build(\"TalerCorebankApi.Cashouts\");\n\nexport const codecForCashoutInfo = (): Codec =>\n buildCodecForObject()\n .property(\"cashout_id\", codecForNumber())\n .build(\"TalerCorebankApi.CashoutInfo\");\n\nexport const codecForGlobalCashouts = (): Codec =>\n buildCodecForObject()\n .property(\"cashouts\", codecForList(codecForGlobalCashoutInfo()))\n .build(\"TalerCorebankApi.GlobalCashouts\");\n\nexport const codecForGlobalCashoutInfo = (): Codec =>\n buildCodecForObject()\n .property(\"cashout_id\", codecForNumber())\n .property(\"username\", codecForString())\n .build(\"TalerCorebankApi.GlobalCashoutInfo\");\n\nexport const codecForCashoutStatusResponse = (): Codec =>\n buildCodecForObject()\n .property(\"amount_debit\", codecForAmountString())\n .property(\"amount_credit\", codecForAmountString())\n .property(\"subject\", codecForString())\n .property(\"creation_time\", codecForTimestamp)\n .build(\"TalerCorebankApi.CashoutStatusResponse\");\n\nexport const codecForConversionRatesResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"buy_at_ratio\", codecForDecimalNumber())\n .property(\"buy_in_fee\", codecForDecimalNumber())\n .property(\"sell_at_ratio\", codecForDecimalNumber())\n .property(\"sell_out_fee\", codecForDecimalNumber())\n .build(\"TalerCorebankApi.ConversionRatesResponse\");\n\nexport const codecForMonitorResponse = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\"no-conversions\", codecForMonitorNoConversion())\n .alternative(\"with-conversions\", codecForMonitorWithCashout())\n .build(\"TalerWireGatewayApi.IncomingBankTransaction\");\n\nexport const codecForMonitorNoConversion = (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"no-conversions\"))\n .property(\"talerInCount\", codecForNumber())\n .property(\"talerInVolume\", codecForAmountString())\n .property(\"talerOutCount\", codecForNumber())\n .property(\"talerOutVolume\", codecForAmountString())\n .build(\"TalerCorebankApi.MonitorJustPayouts\");\n\nexport const codecForMonitorWithCashout = (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"with-conversions\"))\n .property(\"cashinCount\", codecForNumber())\n .property(\"cashinFiatVolume\", codecForAmountString())\n .property(\"cashinRegionalVolume\", codecForAmountString())\n .property(\"cashoutCount\", codecForNumber())\n .property(\"cashoutFiatVolume\", codecForAmountString())\n .property(\"cashoutRegionalVolume\", codecForAmountString())\n .property(\"talerInCount\", codecForNumber())\n .property(\"talerInVolume\", codecForAmountString())\n .property(\"talerOutCount\", codecForNumber())\n .property(\"talerOutVolume\", codecForAmountString())\n .build(\"TalerCorebankApi.MonitorWithCashout\");\n", "/*\n This file is part of GNU Taler\n (C) 2019-2020 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * @fileoverview\n * Construction and parsing of taler:// URIs.\n * Specification: https://lsd.gnunet.org/lsd0006/\n */\n\n/**\n * Imports.\n */\nimport { Amounts } from \"./amounts.js\";\nimport { Codec, Context, DecodingError, renderContext } from \"./codec.js\";\nimport { assertUnreachable } from \"./errors.js\";\nimport { HostPortPath, Paytos } from \"./payto.js\";\nimport { Result, ResultError, ResultOk } from \"./result.js\";\nimport { TalerErrorCode } from \"./taler-error-codes.js\";\nimport { AmountString, HashCodeString } from \"./types-taler-common.js\";\nimport { URL, URLSearchParams } from \"./url.js\";\n/**\n * A parsed taler URI.\n */\nexport type TalerUri =\n | PayUriResult\n | PayTemplateUriResult\n | DevExperimentUri\n | PayPullUriResult\n | PayPushUriResult\n | BackupRestoreUri\n | RefundUriResult\n | WithdrawUriResult\n | WithdrawExchangeUri\n | AddExchangeUri\n | WithdrawalTransferResultUri\n | AddContactUri;\n\ndeclare const __action_str: unique symbol;\nexport type TalerUriString = string & { [__action_str]: true };\n\nexport function codecForTalerUriString(): Codec {\n return {\n decode(x: any, c?: Context): TalerUriString {\n if (typeof x !== \"string\") {\n throw new DecodingError(\n `expected string at ${renderContext(c)} but got ${typeof x}`,\n );\n }\n if (parseTalerUri(x) === undefined) {\n throw new DecodingError(\n `invalid taler URI at ${renderContext(c)} but got \"${x}\"`,\n );\n }\n return x as TalerUriString;\n },\n };\n}\n\nconst TALER_PREFIX = \"taler://\";\nconst TALER_HTTP_PREFIX = \"taler+http://\";\n\nexport enum TalerUriParseError {\n /**\n * URI should start with taler:// or taler+http://\n */\n WRONG_PREFIX,\n /**\n * URI should have a / after the target type\n */\n INCOMPLETE,\n /**\n * URI type is not in the list of supported types\n */\n UNSUPPORTED,\n /**\n * The quantity of components is wrong based on the target type\n */\n COMPONENTS_LENGTH,\n /**\n * The validation of one path component failed\n */\n INVALID_TARGET_PATH,\n /**\n * The validation of one parameter component failed\n */\n INVALID_PARAMETER,\n}\n\nexport namespace TalerUris {\n export type URI = TalerUri;\n\n const supported_targets: Record = {\n \"add-contact\": true,\n \"add-exchange\": true,\n \"dev-experiment\": true,\n pay: true,\n \"pay-pull\": true,\n \"pay-template\": true,\n \"pay-push\": true,\n \"withdraw-exchange\": true,\n refund: true,\n restore: true,\n withdraw: true,\n \"withdrawal-transfer-result\": true,\n };\n\n export function createTalerPay(\n merchantBaseUrl: HostPortPath,\n orderId: string,\n sessionId: string,\n opts: {\n claimToken?: string;\n noncePriv?: string;\n } = {},\n ): PayUriResult {\n return {\n type: TalerUriAction.Pay,\n merchantBaseUrl,\n orderId,\n sessionId,\n ...opts,\n };\n }\n export function createTalerWithdraw(\n bankIntegrationApiBaseUrl: HostPortPath,\n withdrawalOperationId: string,\n opts: {\n externalConfirmation?: boolean;\n } = {},\n ): WithdrawUriResult {\n return {\n type: TalerUriAction.Withdraw,\n bankIntegrationApiBaseUrl,\n withdrawalOperationId,\n ...opts,\n };\n }\n export function createTalerRefund(\n merchantBaseUrl: HostPortPath,\n orderId: string,\n ): RefundUriResult {\n return {\n type: TalerUriAction.Refund,\n merchantBaseUrl,\n orderId,\n };\n }\n export function createTalerPayPull(\n exchangeBaseUrl: HostPortPath,\n contractPriv: string,\n ): PayPullUriResult {\n return {\n type: TalerUriAction.PayPull,\n exchangeBaseUrl,\n contractPriv,\n };\n }\n export function createTalerPayPush(\n exchangeBaseUrl: HostPortPath,\n contractPriv: string,\n ): PayPushUriResult {\n return {\n type: TalerUriAction.PayPush,\n exchangeBaseUrl,\n contractPriv,\n };\n }\n export function createTalerPayTemplate(\n merchantBaseUrl: HostPortPath,\n templateId: string,\n opts: {\n sessionId?: string;\n fulfillmenURL?: string;\n } = {},\n ): PayTemplateUriResult {\n return {\n type: TalerUriAction.PayTemplate,\n merchantBaseUrl,\n templateId,\n fulfillmentUrl: opts.fulfillmenURL,\n sessionId: opts.sessionId,\n };\n }\n export function createTalerRestore(\n walletRootPriv: string,\n providers: HostPortPath[],\n ): BackupRestoreUri {\n return {\n type: TalerUriAction.Restore,\n providers,\n walletRootPriv,\n };\n }\n export function createTalerDevExperiment(\n devExperimentId: string,\n // params: Record,\n query: URLSearchParams, // FIXME: Wrong type it should be Record\n ): DevExperimentUri {\n return {\n type: TalerUriAction.DevExperiment,\n devExperimentId,\n query,\n };\n }\n export function createTalerWithdrawExchange(\n exchangeBaseUrl: HostPortPath,\n opts: {\n amount?: AmountString;\n } = {},\n ): WithdrawExchangeUri {\n return {\n type: TalerUriAction.WithdrawExchange,\n exchangeBaseUrl,\n ...opts,\n };\n }\n export function createTalerAddExchange(\n exchangeBaseUrl: HostPortPath,\n ): AddExchangeUri {\n return {\n type: TalerUriAction.AddExchange,\n exchangeBaseUrl,\n };\n }\n export function createTalerAddContact(\n aliasType: string,\n alias: string,\n mailboxUri: string,\n mailboxIdentity: string,\n sourceBaseUrl: string,\n ): AddContactUri {\n return {\n type: TalerUriAction.AddContact,\n alias: alias,\n aliasType: aliasType,\n mailboxBaseUri: mailboxUri,\n mailboxIdentity: mailboxIdentity,\n sourceBaseUrl: sourceBaseUrl,\n };\n }\n export function createTalerWithdrawalTransferResult(\n ref: string,\n opts: {\n status?: \"success\" | \"aborted\";\n } = {},\n ): WithdrawalTransferResultUri {\n return {\n type: TalerUriAction.WithdrawalTransferResult,\n ref,\n ...opts,\n };\n }\n function asHost(s: HostPortPath): string {\n const b = new URL(s);\n // if (b.port) {\n // return `${b.host}:${b.port}${b.pathname}`;\n // }\n return `${b.host}${b.pathname}`;\n }\n\n function getTalerParamList(p: URI): [string, string][] {\n const result: [string, string][] = [];\n switch (p.type) {\n case TalerUriAction.Withdraw: {\n if (p.externalConfirmation) result.push([\"external-confirmation\", \"1\"]);\n return result;\n }\n case TalerUriAction.Pay: {\n if (p.claimToken) result.push([\"c\", p.claimToken]);\n if (p.noncePriv) result.push([\"n\", p.noncePriv]);\n return result;\n }\n case TalerUriAction.WithdrawExchange: {\n if (p.amount) result.push([\"a\", p.amount]);\n return result;\n }\n case TalerUriAction.WithdrawalTransferResult: {\n result.push([\"ref\", p.ref]);\n if (p.status) result.push([\"status\", p.status]);\n return result;\n }\n case TalerUriAction.AddContact: {\n if (p.sourceBaseUrl) result.push([\"sourceBaseUrl\", p.sourceBaseUrl]);\n return result;\n }\n case TalerUriAction.PayTemplate: {\n if (p.fulfillmentUrl)\n result.push([\"fulfillment_url\", p.fulfillmentUrl]);\n if (p.sessionId) result.push([\"session_id\", p.sessionId]);\n return result;\n }\n case TalerUriAction.Refund:\n case TalerUriAction.PayPush:\n case TalerUriAction.PayPull:\n case TalerUriAction.Restore:\n case TalerUriAction.DevExperiment:\n case TalerUriAction.AddExchange: {\n return result;\n }\n default: {\n assertUnreachable(p);\n }\n }\n }\n\n function getTalerPrefix(p: URI): string {\n switch (p.type) {\n case TalerUriAction.Withdraw:\n return p.bankIntegrationApiBaseUrl.startsWith(\"http://\")\n ? TALER_HTTP_PREFIX\n : TALER_PREFIX;\n case TalerUriAction.Pay:\n case TalerUriAction.Refund:\n case TalerUriAction.PayTemplate:\n return p.merchantBaseUrl.startsWith(\"http://\")\n ? TALER_HTTP_PREFIX\n : TALER_PREFIX;\n case TalerUriAction.PayPush:\n case TalerUriAction.PayPull:\n case TalerUriAction.AddExchange:\n case TalerUriAction.WithdrawExchange:\n return p.exchangeBaseUrl.startsWith(\"http://\")\n ? TALER_HTTP_PREFIX\n : TALER_PREFIX;\n case TalerUriAction.Restore:\n case TalerUriAction.DevExperiment:\n case TalerUriAction.WithdrawalTransferResult:\n case TalerUriAction.AddContact:\n return TALER_PREFIX;\n default:\n assertUnreachable(p);\n }\n }\n\n function getTalerPath(p: URI): string {\n /**\n * After the host we should not add a / since the href\n * already adds one\n */\n switch (p.type) {\n case TalerUriAction.Withdraw:\n return `/${asHost(p.bankIntegrationApiBaseUrl)}${p.withdrawalOperationId}`;\n case TalerUriAction.Pay:\n return `/${asHost(p.merchantBaseUrl)}${p.orderId}/${p.sessionId}`;\n case TalerUriAction.Refund:\n // refund should end with a /\n return `/${asHost(p.merchantBaseUrl)}${p.orderId}/`;\n case TalerUriAction.PayTemplate:\n return `/${asHost(p.merchantBaseUrl)}${p.templateId}`;\n case TalerUriAction.PayPush:\n return `/${asHost(p.exchangeBaseUrl)}${p.contractPriv}`;\n case TalerUriAction.PayPull:\n return `/${asHost(p.exchangeBaseUrl)}${p.contractPriv}`;\n case TalerUriAction.AddExchange:\n return `/${asHost(p.exchangeBaseUrl)}`;\n case TalerUriAction.WithdrawExchange:\n return `/${asHost(p.exchangeBaseUrl)}`;\n case TalerUriAction.Restore:\n return `/${p.walletRootPriv}/${p.providers\n .map((d) => encodeURIComponent(d))\n .join(\",\")}`;\n case TalerUriAction.DevExperiment:\n return `/${p.devExperimentId}`;\n case TalerUriAction.WithdrawalTransferResult:\n return `/`;\n case TalerUriAction.AddContact:\n return `/${p.aliasType}/${p.alias}/${asHost(\n p.mailboxBaseUri as HostPortPath,\n )}/${p.mailboxIdentity}`;\n default:\n assertUnreachable(p);\n }\n }\n\n export function toString(p: URI): TalerUriString {\n const prefix = getTalerPrefix(p);\n const path = getTalerPath(p);\n const paramList = getTalerParamList(p);\n const url = new URL(`${prefix}${p.type}${path}`);\n url.search = createSearchParams(paramList);\n return url.href as TalerUriString;\n }\n\n export interface PaytoParseOptions {\n /**\n * do not check path component format\n */\n ignoreComponentError?: boolean;\n /**\n * tolerate upper-case on taler:// and\n * target action.\n * Userful for user input\n */\n ignoreUppercase?: boolean;\n }\n\n export type InvalidTargetPathDetail =\n | {\n uriType: TalerUriAction.Pay;\n }\n | {\n uriType: TalerUriAction.Withdraw;\n }\n | {\n uriType: TalerUriAction.Refund;\n pos: 0;\n }\n | {\n uriType: TalerUriAction.Refund;\n pos: 1;\n }\n | {\n uriType: TalerUriAction.PayPull;\n pos: 0;\n }\n | {\n uriType: TalerUriAction.PayPush;\n pos: 0;\n }\n | {\n uriType: TalerUriAction.PayTemplate;\n pos: 0;\n }\n | {\n uriType: TalerUriAction.WithdrawExchange;\n pos: 0;\n }\n | {\n uriType: TalerUriAction.WithdrawExchange;\n pos: 1;\n }\n | {\n uriType: TalerUriAction.AddExchange;\n pos: 0;\n }\n | {\n uriType: TalerUriAction.AddContact;\n pos: 0;\n };\n\n export function fromString(\n s: string,\n opts: PaytoParseOptions = {},\n ):\n | ResultOk\n | ResultError\n | ResultError\n | ResultError\n | ResultError<\n TalerUriParseError.COMPONENTS_LENGTH,\n { uriType: TalerUriAction }\n >\n | ResultError<\n TalerUriParseError.INVALID_TARGET_PATH,\n InvalidTargetPathDetail\n >\n | ResultError<\n TalerUriParseError.INVALID_PARAMETER,\n { uriType: TalerUriAction; name: string }\n > {\n // check prefix\n let isHttp = false;\n const prefixCheck = opts.ignoreUppercase ? s.toLowerCase() : s;\n if (\n !prefixCheck.startsWith(TALER_PREFIX) &&\n !(isHttp = prefixCheck.startsWith(TALER_HTTP_PREFIX))\n ) {\n return Result.error(TalerUriParseError.WRONG_PREFIX);\n }\n const scheme = isHttp ? (\"http\" as const) : (\"https\" as const);\n\n // get path and search\n const [path, search] = s\n .slice((isHttp ? TALER_HTTP_PREFIX : TALER_PREFIX).length)\n .split(\"?\", 2);\n\n // check if supported\n const firstSlashPos = path.indexOf(\"/\");\n const uriTypeUncased = (\n firstSlashPos === -1 ? path : path.slice(0, firstSlashPos)\n ) as TalerUriAction;\n\n const uriType = opts.ignoreUppercase\n ? (uriTypeUncased.toLowerCase() as TalerUriAction)\n : uriTypeUncased;\n\n if (!supported_targets[uriType]) {\n return Result.errorWithDetail(TalerUriParseError.UNSUPPORTED, {\n uriType,\n });\n }\n\n const targetPath = path.slice(firstSlashPos + 1);\n if (firstSlashPos === -1 || !targetPath) {\n return Result.errorWithDetail(TalerUriParseError.INCOMPLETE, {\n uriType,\n });\n }\n\n // parse params\n const params: { [k: string]: string } = {};\n if (search) {\n const searchParams = new URLSearchParams(search);\n searchParams.forEach((v, k) => {\n // URLSearchParams already decodes uri components\n params[k] = v;\n });\n }\n\n // get URI components\n const cs = targetPath.split(\"/\");\n switch (uriType) {\n case TalerUriAction.Pay: {\n // check number of segments\n if (cs.length < 3) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n // get merchant host\n const merchant = Paytos.parseHostPortPath2(\n cs[0],\n cs.slice(1, -2).join(\"/\"),\n scheme,\n );\n if (!opts.ignoreComponentError && !merchant) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: merchant,\n },\n );\n }\n\n // get order\n const orderId = cs[cs.length - 2];\n // get session\n const sessionId = cs[cs.length - 1];\n\n return Result.of(\n createTalerPay(\n merchant ?? (cs[0] as HostPortPath),\n orderId,\n sessionId,\n {\n claimToken: params[\"c\"],\n noncePriv: params[\"n\"],\n },\n ),\n );\n }\n case TalerUriAction.Withdraw: {\n // check number of segments\n if (cs.length < 2) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n // get bank host\n const bank = Paytos.parseHostPortPath2(\n cs[0],\n cs.slice(1, -1).join(\"/\"),\n scheme,\n );\n if (!opts.ignoreComponentError && !bank) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: bank,\n },\n );\n }\n\n // get operation id\n const operationId = cs[cs.length - 1];\n // get external confirmation\n const externalConfirmation = !params[\"external-confirmation\"]\n ? undefined\n : params[\"external-confirmation\"] === \"1\";\n\n return Result.of(\n createTalerWithdraw(bank ?? (cs[0] as HostPortPath), operationId, {\n externalConfirmation,\n }),\n );\n }\n case TalerUriAction.Refund: {\n // check number of segments\n if (cs.length < 3) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n if (cs[cs.length - 1]) {\n // last must be empty\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 1 as const,\n uriType,\n },\n );\n }\n\n // get merchant host\n const merchant = Paytos.parseHostPortPath2(\n cs[0],\n cs.slice(1, -2).join(\"/\"),\n scheme,\n );\n if (!opts.ignoreComponentError && !merchant) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: merchant,\n },\n );\n }\n\n // get order id\n const orderId = cs[cs.length - 2];\n return Result.of(\n createTalerRefund(merchant ?? (cs[0] as HostPortPath), orderId),\n );\n }\n case TalerUriAction.PayPull: {\n // check number of segments\n if (cs.length < 2) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n // get exchange host\n const exchange = Paytos.parseHostPortPath2(\n cs[0],\n cs.slice(1, -1).join(\"/\"),\n scheme,\n );\n if (!opts.ignoreComponentError && !exchange) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: exchange,\n },\n );\n }\n // get contract priv\n const contractPriv = cs[cs.length - 1]; // FIXME: validate private key\n\n return Result.of(\n createTalerPayPull(exchange ?? (cs[0] as HostPortPath), contractPriv),\n );\n }\n case TalerUriAction.PayPush: {\n // check number of segments\n if (cs.length < 2) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n // get exchange host\n const exchange = Paytos.parseHostPortPath2(\n cs[0],\n cs.slice(1, -1).join(\"/\"),\n scheme,\n );\n if (!opts.ignoreComponentError && !exchange) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: exchange,\n },\n );\n }\n\n // get contract priv\n const contractPriv = cs[cs.length - 1]; // FIXME: validate private key\n\n return Result.of(\n createTalerPayPush(exchange ?? (cs[0] as HostPortPath), contractPriv),\n );\n }\n case TalerUriAction.PayTemplate: {\n // check number of segments\n if (cs.length < 2) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n // get merchant host\n const merchant = Paytos.parseHostPortPath2(\n cs[0],\n cs.slice(1, -1).join(\"/\"),\n scheme,\n );\n if (!opts.ignoreComponentError && !merchant) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: merchant,\n },\n );\n }\n\n // get contract priv\n const contractPriv = cs[cs.length - 1]; // FIXME: validate private key\n\n return Result.of(\n createTalerPayTemplate(\n merchant ?? (cs[0] as HostPortPath),\n contractPriv,\n ),\n );\n }\n case TalerUriAction.Restore: {\n // check number of segments\n if (cs.length !== 2) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n const walletPriv = cs[0]; // FIXME: validate private key\n const providers: Array = [];\n // const providers = new Array();\n cs[1].split(\",\").map((name) => {\n const url = decodeURIComponent(name);\n\n let isHttp = false;\n const withoutScheme = url.startsWith(\"https://\")\n ? url.substring(8)\n : (isHttp = url.startsWith(\"http://\"))\n ? url.substring(7)\n : url;\n\n // Check resolution of this issue https://bugs.gnunet.org/view.php?id=10466\n const thisScheme =\n url === withoutScheme ? scheme : isHttp ? \"http\" : \"https\";\n\n const [hostname, path] = withoutScheme.split(\"/\", 1);\n const host = Paytos.parseHostPortPath2(hostname, path, thisScheme)!;\n providers.push(host);\n });\n\n return Result.of(\n createTalerRestore(walletPriv ?? (cs[0] as HostPortPath), providers),\n );\n }\n case TalerUriAction.DevExperiment: {\n // check number of segments\n if (cs.length !== 1) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n const experimentId = cs[0];\n const query = new URLSearchParams(search);\n\n return Result.of(createTalerDevExperiment(experimentId, query));\n }\n case TalerUriAction.WithdrawExchange: {\n // check number of segments\n if (cs.length < 1) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n // FIXME: https://bugs.gnunet.org/view.php?id=10466\n // if (cs[cs.length-1]) {\n if (cs.length > 1 && cs[cs.length - 1]) {\n // last must be empty\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 1 as const,\n uriType,\n },\n );\n }\n\n // get exchange host\n const exchange = Paytos.parseHostPortPath2(\n cs[0],\n cs.slice(1, -1).join(\"/\"),\n scheme,\n );\n if (!opts.ignoreComponentError && !exchange) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: exchange,\n },\n );\n }\n\n // get amount param\n const amountRes = !params[\"a\"]\n ? undefined\n : Amounts.parseWithError(params[\"a\"]);\n if (\n !opts.ignoreComponentError &&\n amountRes &&\n amountRes.type === \"fail\"\n ) {\n return Result.errorWithDetail(TalerUriParseError.INVALID_PARAMETER, {\n name: \"a\" as const,\n uriType,\n error: amountRes,\n });\n }\n const amount =\n amountRes && amountRes.type === \"ok\"\n ? Amounts.stringify(amountRes.body)\n : undefined;\n\n return Result.of(\n createTalerWithdrawExchange(exchange ?? (cs[0] as HostPortPath), {\n amount,\n }),\n );\n }\n case TalerUriAction.AddExchange: {\n // check number of segments\n if (cs.length === 1) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n // get exchange host\n const exchange = Paytos.parseHostPortPath2(\n cs[0],\n cs.slice(1).join(\"/\"),\n scheme,\n );\n if (!opts.ignoreComponentError && !exchange) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: exchange,\n },\n );\n }\n\n return Result.of(\n createTalerAddExchange(exchange ?? (cs[0] as HostPortPath)),\n );\n }\n case TalerUriAction.WithdrawalTransferResult: {\n if (cs.length === 0) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n const ref = params[\"ref\"];\n const status =\n params[\"status\"] !== \"aborted\" && params[\"status\"] !== \"success\"\n ? undefined\n : params[\"status\"];\n\n return Result.of(\n createTalerWithdrawalTransferResult(ref, {\n status,\n }),\n );\n }\n case TalerUriAction.AddContact: {\n // check number of segments\n if (cs.length < 4) {\n return Result.errorWithDetail(TalerUriParseError.COMPONENTS_LENGTH, {\n uriType,\n });\n }\n\n const mailboxBaseUri = Paytos.parseHostPortPath2(\n cs[2],\n cs.slice(2, cs.length - 2).join(\"/\"),\n scheme,\n );\n if (!mailboxBaseUri) {\n return Result.errorWithDetail(\n TalerUriParseError.INVALID_TARGET_PATH,\n {\n pos: 0 as const,\n uriType,\n error: mailboxBaseUri,\n },\n );\n }\n const mailboxIdentity = cs[cs.length - 1];\n\n return Result.of(\n createTalerAddContact(\n cs[0],\n cs[1],\n mailboxBaseUri,\n mailboxIdentity,\n params[\"sourceBaseUrl\"],\n ),\n );\n }\n default: {\n assertUnreachable(uriType);\n }\n }\n }\n}\n\n/**\n *\n */\nexport interface PayUriResult {\n type: TalerUriAction.Pay;\n merchantBaseUrl: HostPortPath;\n orderId: string;\n sessionId: string;\n claimToken?: string;\n /**\n * Nonce priv, only present in the\n * \"continue on mobile\" payment flow.\n */\n noncePriv?: string;\n}\n\nexport type TemplateParams = {\n amount?: string;\n summary?: string;\n};\n\nexport interface PayTemplateUriResult {\n type: TalerUriAction.PayTemplate;\n merchantBaseUrl: HostPortPath;\n templateId: string;\n sessionId?: string;\n fulfillmentUrl?: string;\n}\n\nexport interface WithdrawUriResult {\n type: TalerUriAction.Withdraw;\n bankIntegrationApiBaseUrl: HostPortPath;\n withdrawalOperationId: string;\n externalConfirmation?: boolean;\n}\n\nexport interface RefundUriResult {\n type: TalerUriAction.Refund;\n merchantBaseUrl: HostPortPath;\n orderId: string;\n}\n\nexport interface PayPushUriResult {\n type: TalerUriAction.PayPush;\n exchangeBaseUrl: HostPortPath;\n contractPriv: string;\n}\n\nexport interface PayPullUriResult {\n type: TalerUriAction.PayPull;\n exchangeBaseUrl: HostPortPath;\n contractPriv: string;\n}\n\nexport interface DevExperimentUri {\n type: TalerUriAction.DevExperiment;\n devExperimentId: string;\n query?: URLSearchParams; // FIXME: Wrong type it should be Record\n}\n\nexport interface BackupRestoreUri {\n type: TalerUriAction.Restore;\n walletRootPriv: string;\n providers: Array;\n}\n\nexport interface WithdrawExchangeUri {\n type: TalerUriAction.WithdrawExchange;\n exchangeBaseUrl: HostPortPath;\n amount?: AmountString;\n}\n\nexport interface AddExchangeUri {\n type: TalerUriAction.AddExchange;\n exchangeBaseUrl: HostPortPath;\n}\nexport interface WithdrawalTransferResultUri {\n type: TalerUriAction.WithdrawalTransferResult;\n ref: string;\n status?: \"success\" | \"aborted\";\n}\n\nexport interface AddContactUri {\n type: TalerUriAction.AddContact;\n alias: string;\n aliasType: string;\n mailboxBaseUri: string;\n mailboxIdentity: HashCodeString;\n sourceBaseUrl: string;\n}\n\n/**\n * Parse a taler[+http]://withdraw URI.\n * Return undefined if not passed a valid URI.\n */\nexport function parseWithdrawUriWithError(s: string) {\n const pi = parseProtoInfoWithError(s, \"withdraw\");\n if (pi.tag === \"error\") {\n return pi;\n }\n\n const c = pi.value.rest.split(\"?\", 2);\n const path = c[0];\n const q = new URLSearchParams(c[1] ?? \"\");\n\n const parts = path.split(\"/\");\n\n if (parts.length < 2) {\n return Result.error(TalerErrorCode.WALLET_TALER_URI_MALFORMED);\n }\n\n const host = parts[0].toLowerCase();\n const pathSegments = parts.slice(1, parts.length - 1);\n /**\n * The statement below does not tolerate a slash-ended URI.\n * This results in (1) the withdrawalId being passed as the\n * empty string, and (2) the bankIntegrationApi ending with the\n * actual withdrawal operation ID. That can be fixed by\n * trimming the parts-list. FIXME\n */\n const withdrawId = parts[parts.length - 1];\n // const p = [host, ...pathSegments].join(\"/\");\n\n const result: WithdrawUriResult = {\n type: TalerUriAction.Withdraw,\n bankIntegrationApiBaseUrl: Paytos.parseHostPortPath2(\n host,\n pathSegments.join(\"/\"),\n pi.value.innerProto,\n )!,\n withdrawalOperationId: withdrawId,\n externalConfirmation: q.get(\"external-confirmation\") == \"1\",\n };\n return Result.of(result);\n}\n\n/**\n *\n * @deprecated use parseWithdrawUriWithError\n */\nexport function parseWithdrawUri(s: string): WithdrawUriResult | undefined {\n const r = parseWithdrawUriWithError(s);\n if (r.tag === \"error\") return undefined;\n return r.value;\n}\n\n/**\n * Parse a taler[+http]://withdraw URI.\n * Return undefined if not passed a valid URI.\n */\nexport function parseAddExchangeUriWithError(s: string) {\n const pi = parseProtoInfoWithError(s, \"add-exchange\");\n if (pi.tag === \"error\") {\n return pi;\n }\n const parts = pi.value.rest.split(\"/\");\n\n if (parts.length < 2) {\n return Result.error(TalerErrorCode.WALLET_TALER_URI_MALFORMED);\n }\n\n const host = parts[0].toLowerCase();\n const pathSegments = parts.slice(1, parts.length - 1);\n /**\n * The statement below does not tolerate a slash-ended URI.\n * This results in (1) the withdrawalId being passed as the\n * empty string, and (2) the bankIntegrationApi ending with the\n * actual withdrawal operation ID. That can be fixed by\n * trimming the parts-list. FIXME\n */\n // const p = [host, ...pathSegments].join(\"/\");\n\n const result: AddExchangeUri = {\n type: TalerUriAction.AddExchange,\n exchangeBaseUrl: Paytos.parseHostPortPath2(\n host,\n pathSegments.join(\"/\"),\n pi.value.innerProto,\n )!,\n };\n return Result.of(result);\n}\n\n/**\n * Parse a taler[+http]://add-contact URI.\n * Return undefined if not passed a valid URI.\n */\nexport function parseAddContactUriWithError(s: string) {\n const pi = parseProtoInfoWithError(s, \"add-contact\");\n if (pi.tag === \"error\") {\n return pi;\n }\n const parts = pi.value.rest.split(\"/\");\n\n if (parts.length < 4) {\n return Result.error(TalerErrorCode.WALLET_TALER_URI_MALFORMED);\n }\n const mailboxBaseUri = parts[2];\n const pathSegments = parts.slice(3, parts.length - 2);\n const lastPart = parts[parts.length - 1];\n const q = new URLSearchParams(lastPart ?? \"\");\n const mailboxIdentity = lastPart.split(\"?\")[0];\n const sourceBaseUrl = q.get(\"sourceBaseUrl\") ?? \"\";\n const mailboxHostPort = Paytos.parseHostPortPath2(\n mailboxBaseUri,\n pathSegments.join(\"/\"),\n pi.value.innerProto,\n );\n const result: AddContactUri = {\n type: TalerUriAction.AddContact,\n aliasType: parts[0],\n alias: parts[1],\n mailboxBaseUri: mailboxHostPort!,\n mailboxIdentity: mailboxIdentity,\n sourceBaseUrl: sourceBaseUrl,\n };\n return Result.of(result);\n}\n\n/**\n *\n * @deprecated use parseWithdrawUriWithError\n */\nexport function parseAddExchangeUri(s: string): AddExchangeUri | undefined {\n const r = parseAddExchangeUriWithError(s);\n if (r.tag === \"error\") return undefined;\n return r.value;\n}\n\n/**\n *\n * @deprecated use parseWithdrawUriWithError\n */\nexport function parseAddContactUri(s: string): AddContactUri | undefined {\n const r = parseAddContactUriWithError(s);\n if (r.tag === \"error\") return undefined;\n return r.value;\n}\n\nexport enum TalerUriAction {\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.1\n */\n Withdraw = \"withdraw\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.2\n */\n Pay = \"pay\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.3\n */\n Refund = \"refund\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.4\n */\n PayPush = \"pay-push\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.5\n */\n PayPull = \"pay-pull\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.6\n */\n PayTemplate = \"pay-template\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.7\n */\n Restore = \"restore\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.8\n */\n DevExperiment = \"dev-experiment\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.9\n */\n AddExchange = \"add-exchange\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.10\n */\n WithdrawExchange = \"withdraw-exchange\",\n /**\n * https://lsd.gnunet.org/lsd0006/#section-5.11\n */\n WithdrawalTransferResult = \"withdrawal-transfer-result\",\n /**\n * FIXME: LSD\n * Add a contact to the wallet\n */\n AddContact = \"add-contact\",\n}\n\ninterface TalerUriProtoInfo {\n innerProto: \"http\" | \"https\";\n rest: string;\n}\n\nfunction parseProtoInfo(\n s: string,\n action: string,\n): TalerUriProtoInfo | undefined {\n const pfxPlain = `taler://${action}/`;\n const pfxHttp = `taler+http://${action}/`;\n if (s.toLowerCase().startsWith(pfxPlain)) {\n return {\n innerProto: \"https\",\n rest: s.substring(pfxPlain.length),\n };\n } else if (s.toLowerCase().startsWith(pfxHttp)) {\n return {\n innerProto: \"http\",\n rest: s.substring(pfxHttp.length),\n };\n } else {\n return undefined;\n }\n}\n\ninterface ProtoInfo {\n innerProto: \"http\" | \"https\";\n rest: string;\n}\n\n/**\n * @deprecated\n *\n * @param s\n * @param action\n * @returns\n */\nfunction parseProtoInfoWithError(\n s: string,\n action: string,\n): Result {\n if (\n !s.toLowerCase().startsWith(\"taler://\") &&\n !s.toLowerCase().startsWith(\"taler+http://\")\n ) {\n return Result.error(TalerErrorCode.WALLET_TALER_URI_MALFORMED);\n }\n const pfxPlain = `taler://${action}/`;\n const pfxHttp = `taler+http://${action}/`;\n if (s.toLowerCase().startsWith(pfxPlain)) {\n return Result.of({\n innerProto: \"https\",\n rest: s.substring(pfxPlain.length),\n });\n } else if (s.toLowerCase().startsWith(pfxHttp)) {\n return Result.of({\n innerProto: \"http\",\n rest: s.substring(pfxHttp.length),\n });\n } else {\n return Result.error(TalerErrorCode.WALLET_TALER_URI_MALFORMED);\n }\n}\n\ntype Parser = (s: string) => TalerUri | undefined;\nconst parsers: { [A in TalerUriAction]: Parser } = {\n [TalerUriAction.Pay]: parsePayUri,\n [TalerUriAction.PayPull]: parsePayPullUri,\n [TalerUriAction.PayPush]: parsePayPushUri,\n [TalerUriAction.PayTemplate]: parsePayTemplateUri,\n [TalerUriAction.Restore]: parseRestoreUri,\n [TalerUriAction.Refund]: parseRefundUri,\n [TalerUriAction.Withdraw]: parseWithdrawUri,\n [TalerUriAction.DevExperiment]: parseDevExperimentUri,\n [TalerUriAction.WithdrawExchange]: parseWithdrawExchangeUri,\n [TalerUriAction.AddExchange]: parseAddExchangeUri,\n [TalerUriAction.AddContact]: parseAddContactUri,\n [TalerUriAction.WithdrawalTransferResult]: () => {\n throw new Error(\"not supported\");\n },\n};\n\n/**\n * @deprecated\n *\n * @param string\n * @returns\n */\nexport function parseTalerUri(string: string): TalerUri | undefined {\n const https = string.startsWith(\"taler://\");\n const http = string.startsWith(\"taler+http://\");\n if (!https && !http) return undefined;\n const actionStart = https ? 8 : 13;\n const actionEnd = string.indexOf(\"/\", actionStart + 1);\n const action = string.substring(actionStart, actionEnd);\n const found = Object.values(TalerUriAction).find((x) => x === action);\n if (!found) return undefined;\n return parsers[found](string);\n}\n\n/**\n * @deprecated\n *\n * @param uri\n * @returns\n */\nexport function stringifyTalerUri(uri: TalerUri): string {\n switch (uri.type) {\n case TalerUriAction.DevExperiment: {\n return stringifyDevExperimentUri(uri);\n }\n case TalerUriAction.Pay: {\n return stringifyPayUri(uri);\n }\n case TalerUriAction.PayPull: {\n return stringifyPayPullUri(uri);\n }\n case TalerUriAction.PayPush: {\n return stringifyPayPushUri(uri);\n }\n case TalerUriAction.PayTemplate: {\n return stringifyPayTemplateUri(uri);\n }\n case TalerUriAction.Restore: {\n return stringifyRestoreUri(uri);\n }\n case TalerUriAction.Refund: {\n return stringifyRefundUri(uri);\n }\n case TalerUriAction.Withdraw: {\n return stringifyWithdrawUri(uri);\n }\n case TalerUriAction.WithdrawExchange: {\n return stringifyWithdrawExchange(uri);\n }\n case TalerUriAction.AddExchange: {\n return stringifyAddExchange(uri);\n }\n case TalerUriAction.AddContact: {\n return stringifyAddContact(uri);\n }\n case TalerUriAction.WithdrawalTransferResult: {\n throw Error(\"not supported\");\n }\n }\n}\n\n/**\n * @deprecated\n *\n * Parse a taler[+http]://pay URI.\n * Return undefined if not passed a valid URI.\n */\nexport function parsePayUri(s: string): PayUriResult | undefined {\n const pi = parseProtoInfo(s, \"pay\");\n if (!pi) {\n return undefined;\n }\n const c = pi?.rest.split(\"?\");\n const q = new URLSearchParams(c[1] ?? \"\");\n const claimToken = q.get(\"c\") ?? undefined;\n const noncePriv = q.get(\"n\") ?? undefined;\n const parts = c[0].split(\"/\");\n if (parts.length < 3) {\n return undefined;\n }\n const host = parts[0].toLowerCase();\n const sessionId = parts[parts.length - 1];\n const orderId = parts[parts.length - 2];\n const pathSegments = parts.slice(1, parts.length - 2);\n // const p = [host, ...pathSegments].join(\"/\");\n const merchantBaseUrl = Paytos.parseHostPortPath2(\n host,\n pathSegments.join(\"/\"),\n pi.innerProto,\n )!;\n\n return {\n type: TalerUriAction.Pay,\n merchantBaseUrl,\n orderId,\n sessionId,\n claimToken,\n noncePriv,\n };\n}\n\n/**\n * @deprecated\n *\n * @param s\n * @returns\n */\nexport function parsePayTemplateUri(\n uriString: string,\n): PayTemplateUriResult | undefined {\n const pi = parseProtoInfo(uriString, TalerUriAction.PayTemplate);\n if (!pi) {\n return undefined;\n }\n const c = pi.rest.split(\"?\");\n\n const parts = c[0].split(\"/\");\n if (parts.length < 2) {\n return undefined;\n }\n\n const q = new URLSearchParams(c[1] ?? \"\");\n const params: Record = {};\n q.forEach((v, k) => {\n params[k] = v;\n });\n\n const host = parts[0].toLowerCase();\n const templateId = parts[parts.length - 1];\n const pathSegments = parts.slice(1, parts.length - 1);\n const hostAndSegments = [host, ...pathSegments].join(\"/\");\n // const merchantBaseUrl = canonicalizeBaseUrl(\n // `${pi.innerProto}://${hostAndSegments}/`,\n // );\n\n const merchantBaseUrl = Paytos.parseHostPortPath2(\n host,\n pathSegments.join(\"/\"),\n pi.innerProto,\n )!;\n return {\n type: TalerUriAction.PayTemplate,\n merchantBaseUrl,\n templateId,\n fulfillmentUrl: q.get(\"fulfillment_url\") ?? undefined,\n sessionId: q.get(\"session_id\") ?? undefined,\n };\n}\n\n/**\n * @deprecated\n *\n * @param s\n * @returns\n */\nexport function parsePayPushUri(s: string): PayPushUriResult | undefined {\n const pi = parseProtoInfo(s, TalerUriAction.PayPush);\n if (!pi) {\n return undefined;\n }\n const c = pi?.rest.split(\"?\");\n const parts = c[0].split(\"/\");\n if (parts.length < 2) {\n return undefined;\n }\n const host = parts[0].toLowerCase();\n const contractPriv = parts[parts.length - 1];\n const pathSegments = parts.slice(1, parts.length - 1);\n const hostAndSegments = [host, ...pathSegments].join(\"/\");\n // const exchangeBaseUrl = canonicalizeBaseUrl(\n // `${pi.innerProto}://${hostAndSegments}/`,\n // );\n const exchangeBaseUrl = Paytos.parseHostPortPath2(\n host,\n pathSegments.join(\"/\"),\n pi.innerProto,\n )!;\n\n return {\n type: TalerUriAction.PayPush,\n exchangeBaseUrl,\n contractPriv,\n };\n}\n\n/**\n * @deprecated\n *\n * @param s\n * @returns\n */\nexport function parsePayPullUri(s: string): PayPullUriResult | undefined {\n const pi = parseProtoInfo(s, TalerUriAction.PayPull);\n if (!pi) {\n return undefined;\n }\n const c = pi?.rest.split(\"?\");\n const parts = c[0].split(\"/\");\n if (parts.length < 2) {\n return undefined;\n }\n const host = parts[0].toLowerCase();\n const contractPriv = parts[parts.length - 1];\n const pathSegments = parts.slice(1, parts.length - 1);\n const hostAndSegments = [host, ...pathSegments].join(\"/\");\n // const exchangeBaseUrl = canonicalizeBaseUrl(\n // `${pi.innerProto}://${hostAndSegments}/`,\n // );\n const exchangeBaseUrl = Paytos.parseHostPortPath2(\n host,\n pathSegments.join(\"/\"),\n pi.innerProto,\n )!;\n\n return {\n type: TalerUriAction.PayPull,\n exchangeBaseUrl,\n contractPriv,\n };\n}\n\n/**\n * @deprecaed\n *\n * @param s\n * @returns\n */\nexport function parseWithdrawExchangeUri(\n s: string,\n): WithdrawExchangeUri | undefined {\n const pi = parseProtoInfo(s, \"withdraw-exchange\");\n if (!pi) {\n return undefined;\n }\n const c = pi?.rest.split(\"?\");\n const parts = c[0].split(\"/\");\n if (parts.length < 1) {\n return undefined;\n }\n const host = parts[0].toLowerCase();\n // Used to be the reserve public key, now it's empty!\n const lastPathComponent =\n parts.length > 1 ? parts[parts.length - 1] : undefined;\n\n if (lastPathComponent) {\n // invalid taler://withdraw-exchange URI, must end with a slash\n return undefined;\n }\n const pathSegments = parts.slice(1, parts.length - 1);\n const hostAndSegments = [host, ...pathSegments].join(\"/\");\n // const exchangeBaseUrl = canonicalizeBaseUrl(\n // `${pi.innerProto}://${hostAndSegments}/`,\n // );\n const exchangeBaseUrl = Paytos.parseHostPortPath2(\n host,\n pathSegments.join(\"/\"),\n pi.innerProto,\n )!;\n\n const q = new URLSearchParams(c[1] ?? \"\");\n const amount = (q.get(\"a\") ?? undefined) as AmountString | undefined;\n\n return {\n type: TalerUriAction.WithdrawExchange,\n exchangeBaseUrl,\n amount,\n };\n}\n\n/**\n * @deprecated\n * Parse a taler[+http]://refund URI.\n * Return undefined if not passed a valid URI.\n */\nexport function parseRefundUri(s: string): RefundUriResult | undefined {\n const pi = parseProtoInfo(s, \"refund\");\n if (!pi) {\n return undefined;\n }\n const c = pi?.rest.split(\"?\");\n const parts = c[0].split(\"/\");\n if (parts.length < 3) {\n return undefined;\n }\n const host = parts[0].toLowerCase();\n const sessionId = parts[parts.length - 1];\n const orderId = parts[parts.length - 2];\n const pathSegments = parts.slice(1, parts.length - 2);\n const hostAndSegments = [host, ...pathSegments].join(\"/\");\n // const merchantBaseUrl = canonicalizeBaseUrl(\n // `${pi.innerProto}://${hostAndSegments}/`,\n // );\n const merchantBaseUrl = Paytos.parseHostPortPath2(\n host,\n pathSegments.join(\"/\"),\n pi.innerProto,\n )!;\n\n return {\n type: TalerUriAction.Refund,\n merchantBaseUrl,\n orderId,\n };\n}\n\n/**\n * @deprecated\n *\n * @param s\n * @returns\n */\nexport function parseDevExperimentUri(s: string): DevExperimentUri | undefined {\n const pi = parseProtoInfo(s, \"dev-experiment\");\n const c = pi?.rest.split(\"?\");\n if (!c) {\n return undefined;\n }\n const parts = c[0].split(\"/\");\n return {\n type: TalerUriAction.DevExperiment,\n devExperimentId: parts[0],\n query: new URLSearchParams(c[1] ?? \"\"),\n };\n}\n\n/**\n * @deprecated\n *\n * @param s\n * @returns\n */\nexport function parseRestoreUri(uri: string): BackupRestoreUri | undefined {\n const pi = parseProtoInfo(uri, \"restore\");\n if (!pi) {\n return undefined;\n }\n const c = pi.rest.split(\"?\");\n const parts = c[0].split(\"/\");\n if (parts.length < 2) {\n return undefined;\n }\n\n const walletRootPriv = parts[0];\n if (!walletRootPriv) return undefined;\n const providers = new Array();\n parts[1].split(\",\").map((name) => {\n const url = decodeURIComponent(name);\n let isHttp = false;\n const withoutScheme = url.startsWith(\"https://\")\n ? url.substring(8)\n : (isHttp = url.startsWith(\"http://\"))\n ? url.substring(7)\n : url;\n const scheme =\n url === withoutScheme ? pi.innerProto : isHttp ? \"http\" : \"https\";\n const [hostname, path] = withoutScheme.split(\"/\", 1);\n const host = Paytos.parseHostPortPath2(hostname, path ?? \"/\", scheme)!;\n providers.push(host);\n });\n return {\n type: TalerUriAction.Restore,\n walletRootPriv,\n providers,\n };\n}\n\n// ================================================\n// To string functions\n// ================================================\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyPayUri({\n merchantBaseUrl,\n orderId,\n sessionId,\n claimToken,\n noncePriv,\n}: Omit): string {\n const { proto, path, query } = getUrlInfo(merchantBaseUrl, {\n c: claimToken,\n n: noncePriv,\n });\n return `${proto}://pay/${path}${orderId}/${sessionId}${query}`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyPayPullUri({\n contractPriv,\n exchangeBaseUrl,\n}: Omit): string {\n const { proto, path } = getUrlInfo(exchangeBaseUrl);\n return `${proto}://pay-pull/${path}${contractPriv}`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyPayPushUri({\n contractPriv,\n exchangeBaseUrl,\n}: Omit): string {\n const { proto, path } = getUrlInfo(exchangeBaseUrl);\n\n return `${proto}://pay-push/${path}${contractPriv}`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyRestoreUri({\n providers,\n walletRootPriv,\n}: Omit): string {\n const list = providers\n .map((url) => `${encodeURIComponent(new URL(url).href)}`)\n .join(\",\");\n return `taler://restore/${walletRootPriv}/${list}`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyWithdrawExchange({\n exchangeBaseUrl,\n amount,\n}: Omit): string {\n const { proto, path, query } = getUrlInfo(exchangeBaseUrl, {\n a: amount,\n });\n return `${proto}://withdraw-exchange/${path}${query}`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyAddExchange({\n exchangeBaseUrl,\n}: Omit): string {\n const { proto, path } = getUrlInfo(exchangeBaseUrl);\n return `${proto}://add-exchange/${path}`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyAddContact({\n alias,\n aliasType,\n mailboxBaseUri: mailboxBaseUri,\n mailboxIdentity: mailboxIdentity,\n sourceBaseUrl,\n}: Omit): string {\n const { proto, path } = getUrlInfo(mailboxBaseUri);\n const baseUri = `${proto}://add-contact/${aliasType}/${alias}/${path}${mailboxIdentity}`;\n if (sourceBaseUrl) {\n return baseUri + `?sourceBaseUrl=${encodeURIComponent(sourceBaseUrl)}`;\n } else {\n return baseUri;\n }\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyDevExperimentUri({\n devExperimentId,\n}: Omit): string {\n return `taler://dev-experiment/${devExperimentId}`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyPayTemplateUri({\n merchantBaseUrl,\n templateId,\n fulfillmentUrl,\n sessionId,\n}: Omit): string {\n const { proto, path, query } = getUrlInfo(merchantBaseUrl, {\n session_id: sessionId,\n fulfillment_url: fulfillmentUrl,\n });\n return `${proto}://pay-template/${path}${templateId}${query}`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyRefundUri({\n merchantBaseUrl,\n orderId,\n}: Omit): string {\n const { proto, path } = getUrlInfo(merchantBaseUrl);\n return `${proto}://refund/${path}${orderId}/`;\n}\n\n/**\n * @deprecated\n * @param param0\n * @returns\n */\nexport function stringifyWithdrawUri({\n bankIntegrationApiBaseUrl,\n withdrawalOperationId,\n}: Omit): string {\n const { proto, path } = getUrlInfo(bankIntegrationApiBaseUrl);\n return `${proto}://withdraw/${path}${withdrawalOperationId}`;\n}\n\nexport function getURLHostnamePortPath(baseUrl: string) {\n const path = getUrlInfo(baseUrl).path;\n if (path.endsWith(\"/\")) {\n return path.substring(0, path.length - 1);\n }\n return path;\n}\n\n/**\n * Use baseUrl to defined http or https\n * create path using host+port+pathname\n * use params to create a query parameter string or empty\n */\nfunction getUrlInfo(\n baseUrl: string,\n params: Record = {},\n): { proto: string; path: string; query: string } {\n const url = new URL(baseUrl);\n let proto: string;\n if (url.protocol === \"https:\") {\n proto = \"taler\";\n } else if (url.protocol === \"http:\") {\n proto = \"taler+http\";\n } else {\n throw Error(`Unsupported URL protocol in ${baseUrl}`);\n }\n let path = url.hostname;\n if (url.port) {\n path = path + \":\" + url.port;\n }\n if (url.pathname) {\n path = path + url.pathname;\n }\n if (!path.endsWith(\"/\")) {\n path = path + \"/\";\n }\n\n const qp = new URLSearchParams();\n let withParams = false;\n Object.entries(params).forEach(([name, value]) => {\n if (value !== undefined) {\n withParams = true;\n qp.append(name, value);\n }\n });\n const query = withParams ? \"?\" + qp.toString() : \"\";\n\n return { proto, path, query };\n}\n\n/**\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#encoding_for_rfc3986\n */\nfunction encodeRFC3986URIComponent(str: string): string {\n return encodeURIComponent(str).replace(\n /[!'()*]/g,\n (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`,\n );\n}\nconst rfc3986 = encodeRFC3986URIComponent;\n\n/**\n *\n * https://www.rfc-editor.org/rfc/rfc3986\n */\nfunction createSearchParams(paramList: [string, string][]): string {\n return paramList\n .map(([key, value]) => `${rfc3986(key)}=${rfc3986(value)}`)\n .join(\"&\");\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AbsoluteTime,\n AccessToken,\n BasicOrTokenAuth,\n ChallengeResponse,\n HttpStatusCode,\n LibtoolVersion,\n Logger,\n LongPollParams,\n OperationAlternative,\n OperationFail,\n OperationOk,\n PaginationParams,\n TalerErrorCode,\n TokenRequest,\n UserAndToken,\n carefullyParseConfig,\n codecForTokenInfoList,\n codecForTokenSuccessResponse,\n opKnownAlternativeHttpFailure,\n opKnownHttpFailure,\n opKnownTalerFailure,\n} from \"@gnu-taler/taler-util\";\nimport {\n HttpRequestLibrary,\n createPlatformHttpLib,\n readTalerErrorResponse,\n} from \"@gnu-taler/taler-util/http\";\nimport {\n FailCasesByMethod,\n ResultByMethod,\n opEmptySuccess,\n opFixedSuccess,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n} from \"../operation.js\";\nimport { WithdrawalOperationStatusFlag } from \"../types-taler-bank-integration.js\";\nimport {\n AccountPasswordChange,\n AccountReconfiguration,\n BankAccountConfirmWithdrawalRequest,\n BankAccountCreateWithdrawalRequest,\n CashoutRequest,\n ConversionRateClassInput,\n CreateTransactionRequest,\n MonitorTimeframeParam,\n RegisterAccountRequest,\n RegisterAccountResponse,\n codecForAccountData,\n codecForBankAccountCreateWithdrawalResponse,\n codecForBankAccountTransactionInfo,\n codecForBankAccountTransactionsResponse,\n codecForCashoutPending,\n codecForCashoutStatusResponse,\n codecForCashouts,\n codecForConversionRateClass,\n codecForConversionRateClassResponse,\n codecForConversionRateClasses,\n codecForCoreBankConfig,\n codecForCreateTransactionResponse,\n codecForGlobalCashouts,\n codecForListBankAccountsResponse,\n codecForMonitorResponse,\n codecForPublicAccountsResponse,\n codecForRegisterAccountResponse,\n codecForWithdrawalPublicInfo,\n} from \"../types-taler-corebank.js\";\nimport {\n ChallengeRequestResponse,\n ChallengeSolveRequest,\n codecForChallengeRequestResponse,\n codecForChallengeResponse,\n} from \"../types-taler-merchant.js\";\nimport {\n CacheEvictor,\n addLongPollingParam,\n addPaginationParams,\n authHeaders,\n makeBearerTokenAuthHeader,\n nullEvictor,\n} from \"./utils.js\";\n\nconst logger = new Logger(\"bank-core.ts\");\n\nexport type TalerCoreBankResultByMethod<\n prop extends keyof TalerCoreBankHttpClient,\n> = ResultByMethod;\nexport type TalerCoreBankErrorsByMethod<\n prop extends keyof TalerCoreBankHttpClient,\n> = FailCasesByMethod;\n\nexport enum TalerCoreBankCacheEviction {\n DELETE_ACCOUNT,\n CREATE_ACCOUNT,\n UPDATE_ACCOUNT,\n UPDATE_PASSWORD,\n CREATE_TRANSACTION,\n CONFIRM_WITHDRAWAL,\n ABORT_WITHDRAWAL,\n CREATE_WITHDRAWAL,\n CREATE_CASHOUT,\n CREATE_CONVERSION_RATE_CLASS,\n UPDATE_CONVERSION_RATE_CLASS,\n DELETE_CONVERSION_RATE_CLASS,\n}\n\n/**\n * Protocol version spoken with the core bank.\n *\n * Endpoint must be ordered in the same way that in the docs\n * Response code (http and taler) must have the same order that in the docs\n * That way is easier to see changes\n *\n * Uses libtool's current:revision:age versioning.\n */\nexport class TalerCoreBankHttpClient {\n public static readonly PROTOCOL_VERSION = \"10:0:2\";\n\n httpLib: HttpRequestLibrary;\n cacheEvictor: CacheEvictor;\n constructor(\n readonly baseUrl: string,\n httpClient?: HttpRequestLibrary,\n cacheEvictor?: CacheEvictor,\n ) {\n this.httpLib = httpClient ?? createPlatformHttpLib();\n this.cacheEvictor = cacheEvictor ?? nullEvictor;\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version);\n return compare?.compatible ?? false;\n }\n\n private checkUsernameAuthMatch(\n username: string,\n auth: BasicOrTokenAuth,\n ): void {\n if (auth.type === \"basic\" && username !== auth.username) {\n logger.warn(`username and basic auth name do not match`);\n }\n }\n\n /**\n *\n * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token\n */\n async createAccessToken(\n username: string,\n auth: BasicOrTokenAuth,\n body: TokenRequest,\n params: { challengeIds?: string[] } = {},\n ) {\n const url = new URL(`accounts/${username}/token`, this.baseUrl);\n\n this.checkUsernameAuthMatch(username, auth);\n\n const headers = authHeaders(auth);\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers,\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTokenSuccessResponse());\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.GENERIC_FORBIDDEN:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_ACCOUNT_LOCKED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * @deprecated use createAccessToken\n * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token\n */\n async createAccessTokenBasic(\n username: string,\n password: string,\n body: TokenRequest,\n ) {\n return this.createAccessToken(\n username,\n { type: \"basic\", username, password },\n body,\n );\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#delete--accounts-$USERNAME-token\n */\n async deleteAccessToken(user: string, token: AccessToken) {\n const url = new URL(`accounts/${user}/token`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opEmptySuccess();\n // FIXME: missing in docs\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n // FIXME: missing in docs\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-tokens\n *\n */\n async getAccessTokenList(user: string, pagination?: PaginationParams) {\n const url = new URL(`accounts/${user}/token`, this.baseUrl);\n addPaginationParams(url, pagination);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTokenInfoList());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ public_accounts: [] });\n case HttpStatusCode.NotFound:\n return opFixedSuccess({ public_accounts: [] });\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#config\n *\n */\n async getConfig() {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-corebank\",\n TalerCoreBankHttpClient.PROTOCOL_VERSION,\n resp,\n codecForCoreBankConfig(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // ACCOUNTS\n //\n\n /**\n * https://docs.taler.net/core/api-corebank.html#post--accounts\n *\n */\n async createAccount(\n auth: BasicOrTokenAuth | undefined,\n body: RegisterAccountRequest,\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n > {\n const url = new URL(`accounts`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers: authHeaders(auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.CREATE_ACCOUNT,\n );\n return opSuccessFromHttp(resp, codecForRegisterAccountResponse());\n }\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_MISSING_TAN_INFO:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_PASSWORD_TOO_SHORT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_PASSWORD_TOO_LONG:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_CONVERSION_RATE_CLASS_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n /**\n * https://docs.taler.net/core/api-corebank.html#delete--accounts-$USERNAME\n *\n */\n async deleteAccount(\n auth: UserAndToken,\n params: { challengeIds?: string[] } = {},\n ) {\n const url = new URL(`accounts/${auth.username}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(auth.token);\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Accepted:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.DELETE_ACCOUNT,\n );\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#patch--accounts-$USERNAME\n *\n */\n async updateAccount(\n auth: UserAndToken,\n body: AccountReconfiguration,\n params: { challengeIds?: string[] } = {},\n ) {\n const url = new URL(`accounts/${auth.username}`, this.baseUrl);\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(auth.token);\n\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.NoContent:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.UPDATE_ACCOUNT,\n );\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_MISSING_TAN_INFO:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_PASSWORD_TOO_SHORT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_PASSWORD_TOO_LONG:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_CONVERSION_RATE_CLASS_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#patch--accounts-$USERNAME-auth\n *\n */\n async updatePassword(\n auth: UserAndToken,\n body: AccountPasswordChange,\n params: { challengeIds?: string[] } = {},\n ) {\n const url = new URL(`accounts/${auth.username}/auth`, this.baseUrl);\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(auth.token);\n\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_PASSWORD_TOO_SHORT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_PASSWORD_TOO_LONG:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--public-accounts\n *\n */\n async getPublicAccounts(\n filter: { account?: string } = {},\n pagination?: PaginationParams,\n ) {\n const url = new URL(`public-accounts`, this.baseUrl);\n addPaginationParams(url, pagination);\n if (filter.account !== undefined) {\n url.searchParams.set(\"filter_name\", filter.account);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForPublicAccountsResponse());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ public_accounts: [] });\n case HttpStatusCode.NotFound:\n return opFixedSuccess({ public_accounts: [] });\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--accounts\n *\n */\n async listAccounts(\n auth: AccessToken,\n params?: PaginationParams & { account?: string; conversionRateId?: number },\n ) {\n const url = new URL(`accounts`, this.baseUrl);\n addPaginationParams(url, params);\n if (params?.account !== undefined) {\n url.searchParams.set(\"filter_name\", params.account);\n }\n if (params?.conversionRateId !== undefined) {\n url.searchParams.set(\n \"conversion_rate_class_id\",\n String(params.conversionRateId),\n );\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForListBankAccountsResponse());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ accounts: [] });\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME\n *\n */\n async getAccount(auth: UserAndToken) {\n const url = new URL(`accounts/${auth.username}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth.token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAccountData());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // TRANSACTIONS\n //\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-transactions\n *\n */\n async getTransactions(\n auth: UserAndToken,\n params?: PaginationParams & LongPollParams,\n ) {\n const url = new URL(`accounts/${auth.username}/transactions`, this.baseUrl);\n addPaginationParams(url, params);\n addLongPollingParam(url, params);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth.token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(\n resp,\n codecForBankAccountTransactionsResponse(),\n );\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ transactions: [] });\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-transactions-$TRANSACTION_ID\n *\n */\n async getTransactionById(auth: UserAndToken, txid: number) {\n const url = new URL(\n `accounts/${auth.username}/transactions/${String(txid)}`,\n this.baseUrl,\n );\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth.token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForBankAccountTransactionInfo());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-transactions\n *\n */\n async createTransaction(\n auth: UserAndToken,\n body: CreateTransactionRequest,\n params: { challengeIds?: string[] } = {},\n ) {\n const url = new URL(`accounts/${auth.username}/transactions`, this.baseUrl);\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(auth.token);\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers,\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.CREATE_TRANSACTION,\n );\n return opSuccessFromHttp(resp, codecForCreateTransactionResponse());\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_ADMIN_CREDITOR:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_SAME_ACCOUNT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_UNKNOWN_CREDITOR:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // WITHDRAWALS\n //\n\n /**\n * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals\n *\n */\n async createWithdrawal(\n auth: UserAndToken,\n body: BankAccountCreateWithdrawalRequest,\n ) {\n const url = new URL(`accounts/${auth.username}/withdrawals`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth.token),\n },\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.CREATE_WITHDRAWAL,\n );\n return opSuccessFromHttp(\n resp,\n codecForBankAccountCreateWithdrawalResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n //FIXME: missing in docs\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-confirm\n *\n */\n async confirmWithdrawalById(\n auth: UserAndToken,\n body: BankAccountConfirmWithdrawalRequest,\n wid: string,\n params: { challengeIds?: string[] } = {},\n ): Promise<\n | OperationFail\n | OperationAlternative\n | OperationOk\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n > {\n const url = new URL(\n `accounts/${auth.username}/withdrawals/${wid}/confirm`,\n this.baseUrl,\n );\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(auth.token);\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers,\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.NoContent:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.CONFIRM_WITHDRAWAL,\n );\n return opEmptySuccess();\n //FIXME: missing in docs\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_CONFIRM_INCOMPLETE:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_AMOUNT_DIFFERS:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_AMOUNT_REQUIRED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-withdrawals-$WITHDRAWAL_ID-abort\n *\n */\n async abortWithdrawalById(auth: UserAndToken, wid: string) {\n const url = new URL(\n `accounts/${auth.username}/withdrawals/${wid}/abort`,\n this.baseUrl,\n );\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth.token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.ABORT_WITHDRAWAL,\n );\n return opEmptySuccess();\n //FIXME: missing in docs\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--withdrawals-$WITHDRAWAL_ID\n *\n */\n async getWithdrawalById(\n wid: string,\n params?: {\n old_state?: WithdrawalOperationStatusFlag;\n } & LongPollParams,\n ) {\n const url = new URL(`withdrawals/${wid}`, this.baseUrl);\n addLongPollingParam(url, params);\n if (params) {\n url.searchParams.set(\n \"old_state\",\n !params.old_state ? \"pending\" : params.old_state,\n );\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForWithdrawalPublicInfo());\n //FIXME: missing in docs\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // CASHOUTS\n //\n\n /**\n * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts\n *\n */\n async createCashout(\n auth: UserAndToken,\n body: CashoutRequest,\n params: { challengeIds?: string[] } = {},\n ) {\n const url = new URL(`accounts/${auth.username}/cashouts`, this.baseUrl);\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(auth.token);\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers,\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.CREATE_CASHOUT,\n );\n return opSuccessFromHttp(resp, codecForCashoutPending());\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_BAD_CONVERSION:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_CONVERSION_AMOUNT_TO_SMALL:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_CONFIRM_INCOMPLETE:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.BadGateway: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.NotImplemented:\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opKnownHttpFailure(resp.status, resp);\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-cashouts-$CASHOUT_ID\n *\n */\n async getCashoutById(auth: UserAndToken, cid: number) {\n const url = new URL(\n `accounts/${auth.username}/cashouts/${cid}`,\n this.baseUrl,\n );\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth.token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForCashoutStatusResponse());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-cashouts\n *\n */\n async getAccountCashouts(auth: UserAndToken, pagination?: PaginationParams) {\n const url = new URL(`accounts/${auth.username}/cashouts`, this.baseUrl);\n addPaginationParams(url, pagination);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth.token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForCashouts());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ cashouts: [] });\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--cashouts\n *\n */\n async getGlobalCashouts(auth: AccessToken, pagination?: PaginationParams) {\n const url = new URL(`cashouts`, this.baseUrl);\n addPaginationParams(url, pagination);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForGlobalCashouts());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ cashouts: [] });\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // CONVERSION RATE CLASS\n //\n\n /**\n * https://docs.taler.net/core/api-corebank.html#post--conversion-rate-classes\n *\n */\n async createConversionRateClass(\n auth: AccessToken,\n body: ConversionRateClassInput,\n ) {\n const url = new URL(`conversion-rate-classes`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth),\n },\n body,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.CREATE_CONVERSION_RATE_CLASS,\n );\n return opSuccessFromHttp(resp, codecForConversionRateClassResponse());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_NAME_REUSE:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#patch--conversion-rate-classes-CLASS_ID\n *\n */\n async updateConversionRateClass(\n auth: AccessToken,\n cid: number,\n body: ConversionRateClassInput,\n ) {\n const url = new URL(`conversion-rate-classes/${cid}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth),\n },\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.UPDATE_CONVERSION_RATE_CLASS,\n );\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_NAME_REUSE:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--accounts-$USERNAME-cashouts\n *\n */\n async deleteConversionRateClass(auth: AccessToken, cid: number) {\n const url = new URL(`conversion-rate-classes/${cid}`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n await this.cacheEvictor.notifySuccess(\n TalerCoreBankCacheEviction.DELETE_CONVERSION_RATE_CLASS,\n );\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n // case HttpStatusCode.Conflict: {\n // const details = await readTalerErrorResponse(resp);\n // switch (details.code) {\n // case TalerErrorCode.BANK_LI:\n // return opKnownTalerFailure(details.code, details);\n // default:\n // return opUnknownHttpFailure(resp, details);\n // }\n // }\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--conversion-rate-classes-CLASS_ID\n *\n */\n async getConversionRateClass(auth: AccessToken, cid: number) {\n const url = new URL(`conversion-rate-classes/${cid}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForConversionRateClass());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--conversion-rate-classes\n *\n */\n async listConversionRateClasses(\n auth: AccessToken,\n params: PaginationParams & { className?: string } = {},\n ) {\n const url = new URL(`conversion-rate-classes`, this.baseUrl);\n addPaginationParams(url, params);\n if (params.className) {\n url.searchParams.set(\"filter_name\", params.className);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForConversionRateClasses());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ classes: [], default: {} as any });\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n //\n // 2FA\n //\n\n /**\n * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-challenge-$CHALLENGE_ID\n *\n */\n\n async sendChallenge(username: string, cid: string) {\n const url = new URL(`accounts/${username}/challenge/${cid}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForChallengeRequestResponse());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({});\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.TooManyRequests:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.BadGateway: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-challenge-$CHALLENGE_ID-confirm\n *\n */\n async confirmChallenge(\n username: string,\n cid: string,\n body: ChallengeSolveRequest,\n ) {\n const url = new URL(\n `accounts/${username}/challenge/${cid}/confirm`,\n this.baseUrl,\n );\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_TAN_CHALLENGE_FAILED:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.NotFound: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.BANK_TRANSACTION_NOT_FOUND:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_TAN_CHALLENGE_EXPIRED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.TooManyRequests: {\n return opKnownHttpFailure(resp.status, resp);\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // MONITOR\n //\n\n /**\n * https://docs.taler.net/core/api-corebank.html#get--monitor\n *\n */\n async getMonitor(\n auth: AccessToken,\n params: {\n timeframe?: MonitorTimeframeParam;\n date?: AbsoluteTime;\n } = {},\n ) {\n const url = new URL(`monitor`, this.baseUrl);\n if (params.timeframe) {\n url.searchParams.set(\n \"timeframe\",\n MonitorTimeframeParam[params.timeframe],\n );\n }\n if (params.date) {\n const { t_s: seconds } = AbsoluteTime.toProtocolTimestamp(params.date);\n if (seconds !== \"never\") {\n url.searchParams.set(\"date_s\", String(seconds));\n }\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(auth),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForMonitorResponse());\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Others API\n //\n\n /**\n * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api\n *\n */\n getIntegrationAPI(): URL {\n return new URL(`taler-integration/`, this.baseUrl);\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api\n *\n */\n getWireGatewayAPI(username: string): URL {\n return new URL(`accounts/${username}/taler-wire-gateway/`, this.baseUrl);\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api\n *\n */\n getRevenueAPI(username: string): URL {\n return new URL(`accounts/${username}/taler-revenue/`, this.baseUrl);\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#any--accounts-$USERNAME-conversion-info-*\n *\n */\n getConversionInfoAPIForUser(username: string): URL {\n return new URL(`accounts/${username}/conversion-info/`, this.baseUrl);\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#any--conversion-rate-classes-$CLASS_ID-conversion-info-*\n *\n */\n getConversionInfoAPIForClass(classId: number): URL {\n return new URL(\n `conversion-rate-classes/${String(classId)}/conversion-info/`,\n this.baseUrl,\n );\n }\n\n /**\n * https://docs.taler.net/core/api-corebank.html#any--conversion-info-*\n *\n */\n getConversionInfoAPI(): URL {\n return new URL(`conversion-info/`, this.baseUrl);\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n Codec,\n buildCodecForObject,\n codecForBoolean,\n codecForConstString,\n codecForEither,\n codecForList,\n codecForString,\n codecOptional,\n} from \"./codec.js\";\nimport { PaytoString, codecForPaytoString } from \"./payto.js\";\nimport {\n AmountString,\n CurrencySpecification,\n codecForCurrencyName,\n codecForCurrencySpecificiation,\n codecForLibtoolVersion,\n codecForURLString,\n} from \"./types-taler-common.js\";\n\nexport type WithdrawalOperationStatusFlag =\n | \"pending\"\n | \"selected\"\n | \"aborted\"\n | \"confirmed\";\n\nexport interface BankVersion {\n // libtool-style representation of the Bank protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Currency used by this bank.\n currency: string;\n\n // How the bank SPA should render this currency.\n currency_specification?: CurrencySpecification;\n\n // Name of the API.\n name: \"taler-bank-integration\";\n}\n\nexport interface BankWithdrawalOperationStatus {\n // Current status of the operation\n // pending: the operation is pending parameters selection (exchange and reserve public key)\n // selected: the operations has been selected and is pending confirmation\n // aborted: the operation has been aborted\n // confirmed: the transfer has been confirmed and registered by the bank\n status: WithdrawalOperationStatusFlag;\n\n // Currency used for the withdrawal.\n // MUST be present when amount is absent.\n // @since v2, may become mandatory in the future.\n currency?: string;\n\n // Amount that will be withdrawn with this operation\n // (raw amount without fee considerations). Only\n // given once the amount is fixed and cannot be changed.\n // Optional since **vC2EC**.\n amount?: AmountString;\n\n // Suggestion for the amount to be withdrawn with this\n // operation. Given if a suggestion was made but the\n // user may still change the amount.\n // Optional since **vC2EC**.\n suggested_amount?: AmountString;\n\n // Minimum amount that the wallet can choose to withdraw.\n // Only applicable when the amount is not fixed.\n // @since **v4**.\n min_amount?: AmountString;\n\n // Maximum amount that the wallet can choose to withdraw.\n // Only applicable when the amount is not fixed.\n // @since **v4**.\n max_amount?: AmountString;\n\n // The non-Taler card fees the customer will have\n // to pay to the bank / payment service provider\n // they are using to make the withdrawal.\n // @since **vC2EC**\n card_fees?: AmountString;\n\n // Bank account of the customer that is debiting, as an\n // RFC 8905 payto URI.\n sender_wire?: PaytoString;\n\n // Base URL of the suggested exchange. The bank may have\n // neither a suggestion nor a requirement for the exchange.\n // This value is typically set in the bank's configuration.\n suggested_exchange?: string;\n\n // Base URL of an exchange that must be used. Optional,\n // not given *unless* a particular exchange is mandatory.\n // This value is typically set in the bank's configuration.\n // @since **vC2EC**\n required_exchange?: string;\n\n // URL that the user needs to navigate to in order to\n // complete some final confirmation (e.g. 2FA).\n // Only applicable when status is selected or pending.\n // It may contain the withdrawal operation id.\n confirm_transfer_url?: string;\n\n // Wire transfer types supported by the bank.\n wire_types: string[];\n\n // Reserve public key selected by the exchange,\n // only non-null if status is selected or confirmed.\n selected_reserve_pub?: string;\n\n // Exchange account selected by the wallet;\n // only non-null if status is selected or confirmed.\n // @since **v1**\n selected_exchange_account?: string;\n\n // If true, tells the wallet not to allow the user to\n // specify an amount to withdraw and to not provide\n // any amount when registering with the withdrawal\n // operation. The amount to withdraw will be set\n // by the final /withdrawals/$WITHDRAWAL_ID/confirm step.\n // @since **v5**\n no_amount_to_wallet?: boolean;\n}\n\nexport interface BankWithdrawalOperationPostRequest {\n // Reserve public key that should become the wire transfer\n // subject to fund the withdrawal.\n reserve_pub: string;\n\n // Payto address of the exchange selected for the withdrawal.\n selected_exchange: PaytoString;\n\n // Selected amount to be transferred. Optional if the\n // backend already knows the amount.\n // @since **v4**\n amount?: AmountString;\n}\n\nexport interface BankWithdrawalOperationPostResponse {\n // Current status of the operation\n // pending: the operation is pending parameters selection (exchange and reserve public key)\n // selected: the operations has been selected and is pending confirmation\n // aborted: the operation has been aborted\n // confirmed: the transfer has been confirmed and registered by the bank\n status: Omit<\"pending\", WithdrawalOperationStatusFlag>;\n\n // URL that the user needs to navigate to in order to\n // complete some final confirmation (e.g. 2FA).\n //\n // Only applicable when status is selected or pending.\n // It may contain withdrawal operation id\n confirm_transfer_url?: string;\n}\n\nexport const codecForBankVersion = (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForCurrencyName())\n .property(\"currency_specification\", codecForCurrencySpecificiation())\n .property(\"name\", codecForConstString(\"taler-bank-integration\"))\n .property(\"version\", codecForLibtoolVersion())\n .build(\"TalerBankIntegrationApi.BankVersion\");\n\nexport const codecForBankWithdrawalOperationStatus =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"status\",\n codecForEither(\n codecForConstString(\"pending\"),\n codecForConstString(\"selected\"),\n codecForConstString(\"aborted\"),\n codecForConstString(\"confirmed\"),\n ),\n )\n .property(\"currency\", codecOptional(codecForCurrencyName()))\n .property(\"amount\", codecOptional(codecForAmountString()))\n .property(\"suggested_amount\", codecOptional(codecForAmountString()))\n .property(\"min_amount\", codecOptional(codecForAmountString()))\n .property(\"max_amount\", codecOptional(codecForAmountString()))\n .property(\"card_fees\", codecOptional(codecForAmountString()))\n .property(\"sender_wire\", codecOptional(codecForPaytoString()))\n .property(\"suggested_exchange\", codecOptional(codecForURLString()))\n .property(\"required_exchange\", codecOptional(codecForURLString()))\n .property(\"confirm_transfer_url\", codecOptional(codecForURLString()))\n .property(\"wire_types\", codecForList(codecForString()))\n .property(\"selected_reserve_pub\", codecOptional(codecForString()))\n .property(\"selected_exchange_account\", codecOptional(codecForString()))\n .property(\"no_amount_to_wallet\", codecOptional(codecForBoolean()))\n .deprecatedProperty(\"aborted\")\n .deprecatedProperty(\"selection_done\")\n .deprecatedProperty(\"transfer_done\")\n .build(\"TalerBankIntegrationApi.BankWithdrawalOperationStatus\");\n\nexport const codecForBankWithdrawalOperationPostResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"status\",\n codecForEither(\n codecForConstString(\"selected\"),\n codecForConstString(\"aborted\"),\n codecForConstString(\"confirmed\"),\n ),\n )\n .property(\"confirm_transfer_url\", codecOptional(codecForURLString()))\n .deprecatedProperty(\"transfer_done\")\n .build(\"TalerBankIntegrationApi.BankWithdrawalOperationPostResponse\");\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { HttpRequestLibrary, readTalerErrorResponse } from \"../http-common.js\";\nimport { HttpStatusCode } from \"../http-status-codes.js\";\nimport { createPlatformHttpLib } from \"../http.js\";\nimport { LibtoolVersion } from \"../libtool-version.js\";\nimport { Logger } from \"../logging.js\";\nimport {\n FailCasesByMethod,\n ResultByMethod,\n carefullyParseConfig,\n opEmptySuccess,\n opKnownHttpFailure,\n opKnownTalerFailure,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n} from \"../operation.js\";\nimport { TalerErrorCode } from \"../taler-error-codes.js\";\nimport {\n BankWithdrawalOperationPostRequest,\n WithdrawalOperationStatusFlag,\n codecForBankWithdrawalOperationPostResponse,\n codecForBankWithdrawalOperationStatus,\n} from \"../types-taler-bank-integration.js\";\nimport { LongPollParams } from \"../types-taler-common.js\";\nimport { codecForIntegrationBankConfig } from \"../types-taler-corebank.js\";\nimport { codecForTalerErrorDetail } from \"../types-taler-wallet.js\";\nimport { addLongPollingParam } from \"./utils.js\";\n\nexport type TalerBankIntegrationResultByMethod<\n prop extends keyof TalerBankIntegrationHttpClient,\n> = ResultByMethod;\nexport type TalerBankIntegrationErrorsByMethod<\n prop extends keyof TalerBankIntegrationHttpClient,\n> = FailCasesByMethod;\n\nconst logger = new Logger(\"bank-integration.ts\");\n\n/**\n * The API is used by the wallets.\n */\nexport class TalerBankIntegrationHttpClient {\n public static readonly PROTOCOL_VERSION = \"5:0:0\";\n\n httpLib: HttpRequestLibrary;\n\n constructor(\n readonly baseUrl: string,\n httpClient?: HttpRequestLibrary,\n ) {\n this.httpLib = httpClient ?? createPlatformHttpLib();\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version);\n return compare?.compatible ?? false;\n }\n\n /**\n * https://docs.taler.net/core/api-bank-integration.html#get--config\n *\n */\n async getConfig() {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-bank-integration\",\n TalerBankIntegrationHttpClient.PROTOCOL_VERSION,\n resp,\n codecForIntegrationBankConfig(),\n );\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-integration.html#get--withdrawal-operation-$WITHDRAWAL_ID\n *\n */\n async getWithdrawalOperationById(\n woid: string,\n params?: {\n old_state?: WithdrawalOperationStatusFlag;\n } & LongPollParams,\n ) {\n const url = new URL(`withdrawal-operation/${woid}`, this.baseUrl);\n addLongPollingParam(url, params);\n if (params) {\n url.searchParams.set(\n \"old_state\",\n !params.old_state ? \"pending\" : params.old_state,\n );\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForBankWithdrawalOperationStatus());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * FIXME: This is a misnomer!\n *\n * https://docs.taler.net/core/api-bank-integration.html#post-$BANK_API_BASE_URL-withdrawal-operation-$wopid\n */\n async completeWithdrawalOperationById(\n woid: string,\n body: BankWithdrawalOperationPostRequest,\n ) {\n const url = new URL(`withdrawal-operation/${woid}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(\n resp,\n codecForBankWithdrawalOperationPostResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const body = await readTalerErrorResponse(resp);\n const details = codecForTalerErrorDetail().decode(body);\n switch (details.code) {\n case TalerErrorCode.BANK_UPDATE_ABORT_CONFLICT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_UNKNOWN_ACCOUNT:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_ACCOUNT_IS_NOT_EXCHANGE:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_AMOUNT_DIFFERS:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-integration.html#post-$BANK_API_BASE_URL-withdrawal-operation-$wopid\n *\n */\n async abortWithdrawalOperationById(woid: string) {\n const url = new URL(`withdrawal-operation/${woid}/abort`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n Codec,\n buildCodecForObject,\n codecForConstString,\n codecForList,\n codecForNumber,\n codecForString,\n codecOptional,\n} from \"./codec.js\";\nimport { codecForPaytoString } from \"./payto.js\";\nimport { codecForTimestamp } from \"./time.js\";\nimport { AmountString, SafeUint64, Timestamp } from \"./types-taler-common.js\";\n\nexport interface RevenueConfig {\n // Name of the API.\n name: \"taler-revenue\";\n\n // libtool-style representation of the Bank protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Currency used by this gateway.\n currency: string;\n\n // URN of the implementation (needed to interpret 'revision' in version).\n // @since v0, may become mandatory in the future.\n implementation?: string;\n}\n\nexport interface RevenueIncomingHistory {\n // Array of incoming transactions.\n incoming_transactions: RevenueIncomingBankTransaction[];\n\n // Payto URI to identify the receiver of funds.\n // Credit account is shared by all incoming transactions\n // as per the nature of the request.\n credit_account: string;\n}\n\nexport interface RevenueIncomingBankTransaction {\n // Opaque identifier of the returned record.\n row_id: SafeUint64;\n\n // Date of the transaction.\n date: Timestamp;\n\n // Amount transferred.\n amount: AmountString;\n\n // Payto URI to identify the sender of funds.\n debit_account: string;\n\n // The wire transfer subject.\n subject: string;\n}\n\nexport const codecForRevenueConfig = (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForConstString(\"taler-revenue\"))\n .property(\"version\", codecForString())\n .property(\"currency\", codecForString())\n .property(\"implementation\", codecOptional(codecForString()))\n .build(\"TalerRevenueApi.RevenueConfig\");\n\nexport const codecForRevenueIncomingHistory =\n (): Codec =>\n buildCodecForObject()\n .property(\"credit_account\", codecForPaytoString())\n .property(\n \"incoming_transactions\",\n codecForList(codecForRevenueIncomingBankTransaction()),\n )\n .build(\"TalerRevenueApi.MerchantIncomingHistory\");\n\nexport const codecForRevenueIncomingBankTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"row_id\", codecForNumber())\n .property(\"date\", codecForTimestamp)\n .property(\"amount\", codecForAmountString())\n .property(\"debit_account\", codecForPaytoString())\n .property(\"subject\", codecForString())\n .build(\"TalerRevenueApi.RevenueIncomingBankTransaction\");\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { HttpRequestLibrary } from \"../http-common.js\";\nimport { HttpStatusCode } from \"../http-status-codes.js\";\nimport { createPlatformHttpLib } from \"../http.js\";\nimport { LibtoolVersion } from \"../libtool-version.js\";\nimport {\n carefullyParseConfig,\n FailCasesByMethod,\n opFixedSuccess,\n opKnownHttpFailure,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n ResultByMethod,\n} from \"../operation.js\";\nimport { LongPollParams, PaginationParams } from \"../types-taler-common.js\";\nimport {\n codecForRevenueConfig,\n codecForRevenueIncomingHistory,\n} from \"../types-taler-revenue.js\";\nimport {\n addLongPollingParam,\n addPaginationParams,\n authHeaders,\n BasicOrTokenAuth,\n} from \"./utils.js\";\n\nexport type TalerBankRevenueResultByMethod<\n prop extends keyof TalerRevenueHttpClient,\n> = ResultByMethod;\nexport type TalerBankRevenueErrorsByMethod<\n prop extends keyof TalerRevenueHttpClient,\n> = FailCasesByMethod;\n\n/**\n * The API is used by the merchant (or other parties) to query\n * for incoming transactions to their account.\n */\nexport class TalerRevenueHttpClient {\n httpLib: HttpRequestLibrary;\n\n constructor(\n readonly baseUrl: string,\n httpClient?: HttpRequestLibrary,\n ) {\n this.httpLib = httpClient ?? createPlatformHttpLib();\n }\n\n public static readonly PROTOCOL_VERSION = \"1:0:0\";\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version);\n return compare?.compatible ?? false;\n }\n\n /**\n * https://docs.taler.net/core/api-bank-revenue.html#get--config\n *\n */\n async getConfig(auth?: BasicOrTokenAuth) {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-revenue\",\n TalerRevenueHttpClient.PROTOCOL_VERSION,\n resp,\n codecForRevenueConfig(),\n );\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n /**\n * https://docs.taler.net/core/api-bank-revenue.html#get--history\n *\n * @returns\n */\n async getHistory(\n auth?: BasicOrTokenAuth,\n params?: PaginationParams & LongPollParams,\n ) {\n const url = new URL(`history`, this.baseUrl);\n addPaginationParams(url, params);\n addLongPollingParam(url, params);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForRevenueIncomingHistory());\n // FIXME: missing in docs\n case HttpStatusCode.NoContent:\n return opFixedSuccess({\n incoming_transactions: [],\n credit_account: \"\",\n });\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport {\n Codec,\n buildCodecForObject,\n buildCodecForUnion,\n codecForBoolean,\n codecForConstString,\n codecForEither,\n codecForList,\n codecForNumber,\n codecForString,\n codecForStringURL,\n codecOptional,\n} from \"./codec.js\";\nimport {\n codecForEddsaSignature,\n EddsaSignature,\n TalerWireGatewayApi,\n} from \"./index.js\";\nimport { codecForAmountString } from \"./amounts.js\";\nimport { PaytoString, codecForPaytoString } from \"./payto.js\";\nimport { codecForTimestamp } from \"./time.js\";\nimport {\n AmountString,\n EddsaPublicKey,\n HashCode,\n SafeUint64,\n ShortHashCode,\n Timestamp,\n WadId,\n codecForEddsaPublicKey,\n} from \"./types-taler-common.js\";\n\nexport interface TransferResponse {\n // Timestamp that indicates when the wire transfer will be executed.\n // In cases where the wire transfer gateway is unable to know when\n // the wire transfer will be executed, the time at which the request\n // has been received and stored will be returned.\n // The purpose of this field is for debugging (humans trying to find\n // the transaction) as well as for taxation (determining which\n // time period a transaction belongs to).\n timestamp: Timestamp;\n\n // Opaque ID of the transaction that the bank has made.\n row_id: SafeUint64;\n}\n\nexport interface WireConfig {\n // Name of the API.\n name: \"taler-wire-gateway\";\n\n // libtool-style representation of the Bank protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Currency used by this gateway.\n currency: string;\n\n // URN of the implementation (needed to interpret 'revision' in version).\n // @since v0, may become mandatory in the future.\n implementation?: string;\n\n // Whether implementation support account existence check\n support_account_check: boolean;\n}\n\nexport interface TransferRequest {\n // Nonce to make the request idempotent. Requests with the same\n // request_uid that differ in any of the other fields\n // are rejected.\n request_uid: HashCode;\n\n // Amount to transfer.\n amount: AmountString;\n\n // Base URL of the exchange. Shall be included by the bank gateway\n // in the appropriate section of the wire transfer details.\n exchange_base_url: string;\n\n // Wire transfer identifier chosen by the exchange,\n // used by the merchant to identify the Taler order(s)\n // associated with this wire transfer.\n wtid: ShortHashCode;\n\n // The recipient's account identifier as a payto URI.\n credit_account: PaytoString;\n}\n\nexport interface IncomingHistory {\n // Array of incoming transactions.\n incoming_transactions: IncomingBankTransaction[];\n\n // Payto URI to identify the receiver of funds.\n // This must be one of the exchange's bank accounts.\n // Credit account is shared by all incoming transactions\n // as per the nature of the request.\n\n // undefined if incoming transaction is empty\n credit_account?: PaytoString;\n}\n\n// Union discriminated by the \"type\" field.\nexport type IncomingBankTransaction =\n | IncomingKycAuthTransaction\n | IncomingReserveTransaction\n | IncomingWadTransaction;\n\nexport interface IncomingReserveTransaction {\n type: \"RESERVE\";\n\n // Opaque identifier of the returned record.\n row_id: SafeUint64;\n\n // Date of the transaction.\n date: Timestamp;\n\n // Amount transferred.\n amount: AmountString;\n\n // Payto URI to identify the sender of funds.\n debit_account: PaytoString;\n\n // The reserve public key extracted from the transaction details.\n reserve_pub: EddsaPublicKey;\n\n // The authorization public key used for mapping\n authorization_pub?: EddsaPublicKey;\n\n // Signature of the account public key using the authorization private key\n authorization_sig?: EddsaSignature;\n}\n\nexport interface IncomingKycAuthTransaction {\n type: \"KYCAUTH\";\n\n // Opaque identifier of the returned record.\n row_id: SafeUint64;\n\n // Date of the transaction.\n date: Timestamp;\n\n // Amount transferred.\n amount: AmountString;\n\n // Payto URI to identify the sender of funds.\n debit_account: PaytoString;\n\n // The reserve public key extracted from the transaction details.\n account_pub: EddsaPublicKey;\n\n // The authorization public key used for mapping\n authorization_pub?: EddsaPublicKey;\n\n // Signature of the account public key using the authorization private key\n authorization_sig?: EddsaSignature;\n}\n\nexport interface IncomingWadTransaction {\n type: \"WAD\";\n\n // Opaque identifier of the returned record.\n row_id: SafeUint64;\n\n // Date of the transaction.\n date: Timestamp;\n\n // Amount transferred.\n amount: AmountString;\n\n // Payto URI to identify the sender of funds.\n debit_account: PaytoString;\n\n // Base URL of the exchange that originated the wad.\n origin_exchange_url: string;\n\n // The reserve public key extracted from the transaction details.\n wad_id: WadId;\n\n // The authorization public key used for mapping\n authorization_pub?: EddsaPublicKey;\n\n // Signature of the account public key using the authorization private key\n authorization_sig?: EddsaSignature;\n}\n\nexport interface OutgoingHistory {\n // Array of outgoing transactions.\n outgoing_transactions: OutgoingBankTransaction[];\n\n // Payto URI to identify the sender of funds.\n // This must be one of the exchange's bank accounts.\n // Credit account is shared by all incoming transactions\n // as per the nature of the request.\n\n // undefined if outgoing transactions is empty\n debit_account?: PaytoString;\n}\n\nexport interface OutgoingBankTransaction {\n // Opaque identifier of the returned record.\n row_id: SafeUint64;\n\n // Date of the transaction.\n date: Timestamp;\n\n // Amount transferred.\n amount: AmountString;\n\n // Payto URI to identify the receiver of funds.\n credit_account: PaytoString;\n\n // The wire transfer ID in the outgoing transaction.\n wtid: ShortHashCode;\n\n // Base URL of the exchange.\n exchange_base_url: string;\n}\n\nexport interface AddIncomingRequest {\n // Amount to transfer.\n amount: AmountString;\n\n // Reserve public key that is included in the wire transfer details\n // to identify the reserve that is being topped up.\n reserve_pub: EddsaPublicKey;\n\n // Account (as payto URI) that makes the wire transfer to the exchange.\n // Usually this account must be created by the test harness before this API is\n // used. An exception is the \"exchange-fakebank\", where any debit account can be\n // specified, as it is automatically created.\n debit_account: PaytoString;\n}\n\nexport interface AddKycauthRequest {\n // Amount to transfer.\n amount: AmountString;\n\n // Account public key that is included in the wire transfer details\n // to associate this key with the originating bank account.\n account_pub: EddsaPublicKey;\n\n // Account (as payto URI) that makes the wire transfer to the exchange.\n // Usually this account must be created by the test harness before this\n // API is used. An exception is the \"fakebank\", where any debit account\n // can be specified, as it is automatically created.\n debit_account: string;\n}\n\nexport interface AddMappedRequest {\n // Amount to transfer.\n amount: AmountString;\n\n // Authorization public key used for registration.\n authorization_pub: EddsaPublicKey;\n\n // Account (as full payto URI) that makes the wire transfer to the exchange.\n // Usually this account must be created by the test harness before this\n // API is used. An exception is the \"fakebank\", where any debit account\n // can be specified, as it is automatically created.\n debit_account: string;\n}\n\nexport interface AddIncomingResponse {\n // Timestamp that indicates when the wire transfer will be executed.\n // In cases where the wire transfer gateway is unable to know when\n // the wire transfer will be executed, the time at which the request\n // has been received and stored will be returned.\n // The purpose of this field is for debugging (humans trying to find\n // the transaction) as well as for taxation (determining which\n // time period a transaction belongs to).\n timestamp: Timestamp;\n\n // Opaque ID of the transaction that the bank has made.\n row_id: SafeUint64;\n}\n\nexport interface BankWireTransferList {\n // Array of initiated transfers.\n transfers: BankWireTransferListStatus[];\n\n // Payto URI to identify the sender of funds.\n // This must be one of the exchange's bank accounts.\n // Credit account is shared by all incoming transactions\n // as per the nature of the request.\n debit_account: string;\n}\n\nexport type WireTransferStatus =\n | \"pending\"\n | \"transient_failure\"\n | \"permanent_failure\"\n | \"success\";\n\nexport interface BankWireTransferListStatus {\n // Opaque ID of the wire transfer initiation performed by the bank.\n // It is different from the /history endpoints row_id.\n row_id: SafeUint64;\n\n // Current status of the transfer\n // pending: the transfer is in progress\n // transient_failure: the transfer has failed but may succeed later\n // permanent_failure: the transfer has failed permanently and will never appear in the outgoing history\n // success: the transfer has succeeded and appears in the outgoing history\n status: WireTransferStatus;\n\n // Amount to transfer.\n amount: AmountString;\n\n // The recipient's account identifier as a payto URI.\n credit_account: string;\n\n // Timestamp that indicates when the wire transfer was executed.\n // In cases where the wire transfer gateway is unable to know when\n // the wire transfer will be executed, the time at which the request\n // has been received and stored will be returned.\n // The purpose of this field is for debugging (humans trying to find\n // the transaction) as well as for taxation (determining which\n // time period a transaction belongs to).\n timestamp: Timestamp;\n}\n\nexport interface BankWireTransferStatus {\n // Current status of the transfer\n // pending: the transfer is in progress\n // transient_failure: the transfer has failed but may succeed later\n // permanent_failure: the transfer has failed permanently and will never appear in the outgoing history\n // success: the transfer has succeeded and appears in the outgoing history\n status: WireTransferStatus;\n\n // Optional unstructured messages about the transfer's status. Can be used to document the reasons for failure or the state of progress.\n status_msg?: string;\n\n // Amount to transfer.\n amount: AmountString;\n\n // Base URL of the exchange. Shall be included by the bank gateway\n // in the appropriate section of the wire transfer details.\n exchange_base_url: string;\n\n // Wire transfer identifier chosen by the exchange,\n // used by the merchant to identify the Taler order(s)\n // associated with this wire transfer.\n wtid: ShortHashCode;\n\n // The recipient's account identifier as a payto URI.\n credit_account: string;\n\n // Timestamp that indicates when the wire transfer was executed.\n // In cases where the wire transfer gateway is unable to know when\n // the wire transfer will be executed, the time at which the request\n // has been received and stored will be returned.\n // The purpose of this field is for debugging (humans trying to find\n // the transaction) as well as for taxation (determining which\n // time period a transaction belongs to).\n timestamp: Timestamp;\n}\n\nexport const codecForWireConfigResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"implementation\", codecForString())\n .property(\"name\", codecForConstString(\"taler-wire-gateway\"))\n .property(\"support_account_check\", codecForBoolean())\n .property(\"version\", codecForString())\n .build(\"TalerWireGatewayApi.WireConfig\");\n\nexport const codecForTransferResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"row_id\", codecForNumber())\n .property(\"timestamp\", codecForTimestamp)\n .build(\"TalerWireGatewayApi.TransferResponse\");\n\nexport const codecForIncomingHistory =\n (): Codec =>\n buildCodecForObject()\n .property(\"credit_account\", codecForPaytoString())\n .property(\n \"incoming_transactions\",\n codecForList(codecForIncomingBankTransaction()),\n )\n .build(\"TalerWireGatewayApi.IncomingHistory\");\n\nexport const codecForIncomingBankTransaction =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\"RESERVE\", codecForIncomingReserveTransaction())\n .alternative(\"KYCAUTH\", codecForIncomingKycAuthTransaction())\n .alternative(\"WAD\", codecForIncomingWadTransaction())\n .build(\"TalerWireGatewayApi.IncomingBankTransaction\");\n\nexport const codecForIncomingReserveTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"date\", codecForTimestamp)\n .property(\"debit_account\", codecForPaytoString())\n .property(\"reserve_pub\", codecForEddsaPublicKey())\n .property(\"row_id\", codecForNumber())\n .property(\"type\", codecForConstString(\"RESERVE\"))\n .property(\"authorization_pub\", codecOptional(codecForEddsaPublicKey()))\n .property(\"authorization_sig\", codecOptional(codecForEddsaSignature()))\n .build(\"TalerWireGatewayApi.IncomingReserveTransaction\");\n\nexport const codecForIncomingKycAuthTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"date\", codecForTimestamp)\n .property(\"debit_account\", codecForPaytoString())\n .property(\"account_pub\", codecForEddsaPublicKey())\n .property(\"row_id\", codecForNumber())\n .property(\"type\", codecForConstString(\"KYCAUTH\"))\n .property(\"authorization_pub\", codecOptional(codecForEddsaPublicKey()))\n .property(\"authorization_sig\", codecOptional(codecForEddsaSignature()))\n .build(\"TalerWireGatewayApi.IncomingKycAuthTransaction\");\n\nexport const codecForIncomingWadTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"date\", codecForTimestamp)\n .property(\"debit_account\", codecForPaytoString())\n .property(\"origin_exchange_url\", codecForString())\n .property(\"row_id\", codecForNumber())\n .property(\"type\", codecForConstString(\"WAD\"))\n .property(\"wad_id\", codecForString())\n .property(\"authorization_pub\", codecOptional(codecForEddsaPublicKey()))\n .property(\"authorization_sig\", codecOptional(codecForEddsaSignature()))\n .build(\"TalerWireGatewayApi.IncomingWadTransaction\");\n\nexport const codecForOutgoingHistory =\n (): Codec =>\n buildCodecForObject()\n .property(\"debit_account\", codecForPaytoString())\n .property(\n \"outgoing_transactions\",\n codecForList(codecForOutgoingBankTransaction()),\n )\n .build(\"TalerWireGatewayApi.OutgoingHistory\");\n\nexport const codecForOutgoingBankTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"row_id\", codecForNumber())\n .property(\"date\", codecForTimestamp)\n .property(\"amount\", codecForAmountString())\n .property(\"credit_account\", codecForPaytoString())\n .property(\"wtid\", codecForString())\n .property(\"exchange_base_url\", codecForString())\n .build(\"TalerWireGatewayApi.OutgoingBankTransaction\");\n\nexport const codecForAddIncomingResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"row_id\", codecForNumber())\n .property(\"timestamp\", codecForTimestamp)\n .build(\"TalerWireGatewayApi.AddIncomingResponse\");\n\nexport const codecForBankWireTransferList =\n (): Codec =>\n buildCodecForObject()\n .property(\"debit_account\", codecForPaytoString())\n .property(\"transfers\", codecForList(codecForBankWireTransferListStatus()))\n .build(\"TalerWireGatewayApi.BankWireTransferList\");\n\nexport const codecForBankWireTransferStatus =\n (): Codec =>\n buildCodecForObject()\n .property(\n \"status\",\n codecForEither(\n codecForConstString(\"pending\"),\n codecForConstString(\"transient_failure\"),\n codecForConstString(\"permanent_failure\"),\n codecForConstString(\"success\"),\n ),\n )\n .property(\"status_msg\", codecOptional(codecForString()))\n .property(\"amount\", codecForAmountString())\n .property(\"exchange_base_url\", codecForStringURL())\n .property(\"wtid\", codecForString())\n .property(\"credit_account\", codecForPaytoString())\n .property(\"timestamp\", codecForTimestamp)\n .build(\"TalerWireGatewayApi.BankWireTransferStatus\");\n\nexport const codecForBankWireTransferListStatus =\n (): Codec =>\n buildCodecForObject()\n .property(\"row_id\", codecForNumber())\n .property(\n \"status\",\n codecForEither(\n codecForConstString(\"pending\"),\n codecForConstString(\"transient_failure\"),\n codecForConstString(\"permanent_failure\"),\n codecForConstString(\"success\"),\n ),\n )\n .property(\"amount\", codecForAmountString())\n .property(\"credit_account\", codecForPaytoString())\n .property(\"timestamp\", codecForTimestamp)\n .build(\"TalerWireGatewayApi.BankWireTransferListStatus\");\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { HttpRequestLibrary, readTalerErrorResponse } from \"../http-common.js\";\nimport { HttpStatusCode } from \"../http-status-codes.js\";\nimport { createPlatformHttpLib } from \"../http.js\";\nimport {\n FailCasesByMethod,\n ResultByMethod,\n opFixedSuccess,\n opKnownHttpFailure,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n} from \"../operation.js\";\nimport {\n codecForAddIncomingResponse,\n codecForBankWireTransferList,\n codecForIncomingHistory,\n codecForOutgoingHistory,\n codecForTransferResponse,\n} from \"../types-taler-wire-gateway.js\";\nimport {\n addLongPollingParam,\n addPaginationParams,\n authHeaders,\n BasicOrTokenAuth,\n} from \"./utils.js\";\n\nimport { LongPollParams, PaginationParams } from \"../types-taler-common.js\";\nimport * as TalerWireGatewayApi from \"../types-taler-wire-gateway.js\";\nimport {\n carefullyParseConfig,\n codecForTalerErrorDetail,\n LibtoolVersion,\n opKnownTalerFailure,\n TalerErrorCode,\n} from \"../index.js\";\n\nexport type TalerWireGatewayResultByMethod<\n prop extends keyof TalerWireGatewayHttpClient,\n> = ResultByMethod;\nexport type TalerWireGatewayErrorsByMethod<\n prop extends keyof TalerWireGatewayHttpClient,\n> = FailCasesByMethod;\n\n/**\n * The API is used by the exchange to trigger transactions and query\n * incoming transactions, as well as by the auditor to query incoming\n * and outgoing transactions.\n *\n * https://docs.taler.net/core/api-bank-wire.html\n */\nexport class TalerWireGatewayHttpClient {\n httpLib: HttpRequestLibrary;\n public static readonly PROTOCOL_VERSION = \"5:0:1\";\n\n constructor(\n readonly baseUrl: string,\n options: {\n httpClient?: HttpRequestLibrary;\n } = {},\n ) {\n this.httpLib = options.httpClient ?? createPlatformHttpLib();\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version);\n return compare?.compatible ?? false;\n }\n\n /**\n * https://docs.taler.net/core/api-bank-wire.html#get--config\n *\n */\n async getConfig() {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-wire-gateway\",\n TalerWireGatewayHttpClient.PROTOCOL_VERSION,\n resp,\n TalerWireGatewayApi.codecForWireConfigResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-wire.html#post--transfer\n *\n */\n async makeWireTransfer(req: {\n body: TalerWireGatewayApi.TransferRequest;\n auth?: BasicOrTokenAuth;\n }) {\n const url = new URL(`transfer`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: authHeaders(req.auth),\n body: req.body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTransferResponse());\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const body = await readTalerErrorResponse(resp);\n const details = codecForTalerErrorDetail().decode(body);\n switch (details.code) {\n case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED:\n case TalerErrorCode.BANK_TRANSFER_WTID_REUSED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opKnownHttpFailure(resp.status, resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-wire.html#get--transfers\n *\n */\n async getTransfers(req: {\n params?: {\n status?: TalerWireGatewayApi.WireTransferStatus;\n } & PaginationParams;\n auth?: BasicOrTokenAuth;\n }) {\n const url = new URL(`transfers`, this.baseUrl);\n if (req.params) {\n if (req.params.status) {\n url.searchParams.set(\"status\", req.params.status);\n }\n }\n addPaginationParams(url, req.params);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(req.auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForBankWireTransferList());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({\n transfers: [],\n debit_account: undefined,\n });\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-wire.html#get--transfers-$ROW_ID\n *\n */\n async getTransferStatus(req: { rowId?: number; auth?: BasicOrTokenAuth }) {\n const url = new URL(`transfers/${req.rowId}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(req.auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForBankWireTransferList());\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-wire.html#get--history-incoming\n *\n */\n async getHistoryIncoming(req: {\n params?: PaginationParams & LongPollParams;\n auth?: BasicOrTokenAuth;\n }) {\n const url = new URL(`history/incoming`, this.baseUrl);\n addPaginationParams(url, req.params);\n addLongPollingParam(url, req.params);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(req.auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForIncomingHistory());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({\n incoming_transactions: [],\n credit_account: undefined,\n });\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-wire.html#get--history-outgoing\n *\n */\n async getHistoryOutgoing(req: {\n params?: PaginationParams & LongPollParams;\n auth?: BasicOrTokenAuth;\n }) {\n const url = new URL(`history/outgoing`, this.baseUrl);\n addPaginationParams(url, req.params);\n addLongPollingParam(url, req.params);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: authHeaders(req.auth),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForOutgoingHistory());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({\n outgoing_transactions: [],\n debit_account: undefined,\n });\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-wire.html#post--admin-add-incoming\n *\n */\n async addIncoming(req: {\n body: TalerWireGatewayApi.AddIncomingRequest;\n auth?: BasicOrTokenAuth;\n }) {\n const url = new URL(`admin/add-incoming`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: authHeaders(req.auth),\n body: req.body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAddIncomingResponse());\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const body = await readTalerErrorResponse(resp);\n const details = codecForTalerErrorDetail().decode(body);\n switch (details.code) {\n case TalerErrorCode.BANK_DUPLICATE_RESERVE_PUB_SUBJECT:\n return opKnownTalerFailure(details.code, details);\n default:\n return opKnownHttpFailure(resp.status, resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-wire.html#post--admin-add-kycauth\n *\n */\n async addKycAuth(req: {\n body: TalerWireGatewayApi.AddKycauthRequest;\n auth?: BasicOrTokenAuth;\n }) {\n const url = new URL(`admin/add-kycauth`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: authHeaders(req.auth),\n body: req.body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAddIncomingResponse());\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /** https://docs.taler.net/core/api-bank-wire.html#post--admin-add-mapped */\n async addMapped(req: {\n body: TalerWireGatewayApi.AddMappedRequest;\n auth?: BasicOrTokenAuth;\n }) {\n const url = new URL(`admin/add-mapped`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: authHeaders(req.auth),\n body: req.body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAddIncomingResponse());\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const body = await readTalerErrorResponse(resp);\n const details = codecForTalerErrorDetail().decode(body);\n switch (details.code) {\n case TalerErrorCode.BANK_TRANSFER_MAPPING_UNKNOWN:\n case TalerErrorCode.BANK_TRANSFER_MAPPING_REUSED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opKnownHttpFailure(resp.status, resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport {\n Codec,\n buildCodecForObject,\n buildCodecForUnion,\n codecForBoolean,\n codecForConstString,\n codecForEither,\n codecForList,\n codecForString,\n codecForStringURL,\n codecOptional,\n} from \"./codec.js\";\nimport { TalerPreparedTransferApi } from \"./index.js\";\nimport { codecForAmountString } from \"./amounts.js\";\nimport { codecForTimestamp } from \"./time.js\";\nimport {\n AmountString,\n EddsaPublicKey,\n EddsaSignature,\n Timestamp,\n codecForEddsaPublicKey,\n codecForEddsaSignature,\n} from \"./types-taler-common.js\";\n\nexport type SubjectFormat = \"SIMPLE\" | \"URI\" | \"CH_QR_BILL\";\n\nexport interface PreparedTransferConfig {\n // Name of the API.\n name: \"taler-prepared-transfer\";\n\n // libtool-style representation of the protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Currency used by this API.\n currency: string;\n\n // URN of the implementation (needed to interpret 'revision' in version).\n // @since v0, may become mandatory in the future.\n implementation?: string;\n\n // Supported formats for registration, there must at least one.\n supported_formats: SubjectFormat[];\n}\n\nexport interface RegistrationRequest {\n // Amount to transfer\n credit_amount: AmountString;\n\n // Transfer types\n type: \"reserve\" | \"kyc\";\n\n // Public key algorithm\n alg: \"EdDSA\";\n\n // Account public key for the exchange\n account_pub: EddsaPublicKey;\n\n // Public key encoded inside the subject\n authorization_pub: EddsaPublicKey;\n\n // Signature of the account_pub key using the authorization_pub private key\n authorization_sig: EddsaSignature;\n\n // Whether the authorization_pub will be reused for recurrent transfers\n // Disable bounces in case of authorization_pub reuse\n recurrent: boolean;\n}\n\n// Union discriminated by the \"type\" field.\nexport type TransferSubject = SimpleSubject | UriSubject | SwissQrBillSubject;\n\nexport interface SimpleSubject {\n // Subject for system accepting large subjects\n type: \"SIMPLE\";\n\n // Amount to transfer\n credit_amount: AmountString;\n\n // Encoded string containing either the full key and transfer type or a\n // derived short subject\n subject: string;\n}\n\nexport interface UriSubject {\n // Subject for system accepting prepared payments\n type: \"URI\";\n\n // Amount to transfer\n credit_amount: AmountString;\n\n // Prepared payments confirmation URI\n uri: string;\n}\n\nexport interface SwissQrBillSubject {\n // Subject for Swiss QR Bill\n type: \"CH_QR_BILL\";\n\n // Amount to transfer\n credit_amount: AmountString;\n\n // 27-digit QR Reference number\n qr_reference_number: string;\n}\n\nexport interface RegistrationResponse {\n // The transfer subject encoded in all supported formats\n subjects: TransferSubject[];\n\n // Expiration date after which this subject is expected to be reused\n expiration: Timestamp;\n}\n\nexport interface Unregistration {\n // Current timestamp in the ISO 8601\n timestamp: string;\n\n // Public key used for registration\n authorization_pub: EddsaPublicKey;\n\n // Signature of the timestamp using the authorization_pub private key\n // Prevent replay attack\n authorization_sig: EddsaSignature;\n}\n\nexport const codeForSubjectFormat =\n (): Codec =>\n codecForEither(\n codecForConstString(\"SIMPLE\"),\n codecForConstString(\"URI\"),\n codecForConstString(\"CH_QR_BILL\"),\n );\n\nexport const codecForPreparedTransferConfig =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecForString())\n .property(\"implementation\", codecOptional(codecForString()))\n .property(\"name\", codecForConstString(\"taler-prepared-transfer\"))\n .property(\"supported_formats\", codecForList(codeForSubjectFormat()))\n .property(\"version\", codecForString())\n .build(\"TalerPreparedTransferApi.PreparedTransferConfig\");\n\nexport const codecForRegistrationRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"credit_amount\", codecForAmountString())\n .property(\n \"type\",\n codecForEither(\n codecForConstString(\"reserve\"),\n codecForConstString(\"kyc\"),\n ),\n )\n .property(\"alg\", codecForEither(codecForConstString(\"EdDSA\")))\n .property(\"account_pub\", codecForEddsaPublicKey())\n .property(\"authorization_pub\", codecForEddsaPublicKey())\n .property(\"authorization_sig\", codecForEddsaSignature())\n .property(\"recurrent\", codecForBoolean())\n .build(\"TalerWireGatewayApi.RegistrationRequest\");\n\nexport const codecForTransferSubject =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\"SIMPLE\", codecForSimpleSubject())\n .alternative(\"URI\", codecForUriSubject())\n .alternative(\"CH_QR_BILL\", codecForSwissQrBillSubject())\n .build(\"TalerPreparedTransferApi.TransferSubject\");\n\nexport const codecForSimpleSubject =\n (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"SIMPLE\"))\n .property(\"credit_amount\", codecForAmountString())\n .property(\"subject\", codecForString())\n .build(\"TalerPreparedTransferApi.SimpleSubject\");\n\nexport const codecForUriSubject =\n (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"URI\"))\n .property(\"credit_amount\", codecForAmountString())\n .property(\"uri\", codecForStringURL())\n .build(\"TalerPreparedTransferApi.UriSubject\");\n\nexport const codecForSwissQrBillSubject =\n (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"CH_QR_BILL\"))\n .property(\"credit_amount\", codecForAmountString())\n .property(\"qr_reference_number\", codecForString())\n .build(\"TalerPreparedTransferApi.SwissQrBillSubject\");\n\nexport const codecForRegistrationResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"subjects\", codecForList(codecForTransferSubject()))\n .property(\"expiration\", codecForTimestamp)\n .build(\"TalerWireGatewayApi.RegistrationResponse\");\n\nexport const codecForUnregistration =\n (): Codec =>\n buildCodecForObject()\n .property(\"timestamp\", codecForString())\n .property(\"authorization_pub\", codecForEddsaPublicKey())\n .property(\"authorization_sig\", codecForEddsaSignature())\n .build(\"TalerPreparedTransferApi.Unregistration\");\n", "/*\n This file is part of GNU Taler\n (C) 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { HttpRequestLibrary, readTalerErrorResponse } from \"../http-common.js\";\nimport { HttpStatusCode } from \"../http-status-codes.js\";\nimport { createPlatformHttpLib } from \"../http.js\";\nimport {\n FailCasesByMethod,\n ResultByMethod,\n opKnownHttpFailure,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n} from \"../operation.js\";\nimport {\n carefullyParseConfig,\n codecForTalerErrorDetail,\n LibtoolVersion,\n opEmptySuccess,\n opKnownTalerFailure,\n TalerErrorCode,\n TalerPreparedTransferApi,\n} from \"../index.js\";\nimport {\n codecForPreparedTransferConfig,\n codecForRegistrationResponse,\n} from \"../types-taler-prepared-transfer.js\";\n\nexport type TalerPreparedTransferResultByMethod<\n prop extends keyof TalerPreparedTransferHttpClient,\n> = ResultByMethod;\nexport type TalerPreparedTransferErrorsByMethod<\n prop extends keyof TalerPreparedTransferHttpClient,\n> = FailCasesByMethod;\n\n/**\n * Allows Taler clients to prepared wire transfers, enabling recurring\n * wire transfers and optimized transfer flow.\n *\n * https://docs.taler.net/core/api-bank-transfer.html\n */\nexport class TalerPreparedTransferHttpClient {\n httpLib: HttpRequestLibrary;\n public static readonly PROTOCOL_VERSION = \"0:0:0\";\n\n constructor(\n readonly baseUrl: string,\n options: {\n httpClient?: HttpRequestLibrary;\n } = {},\n ) {\n this.httpLib = options.httpClient ?? createPlatformHttpLib();\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version);\n return compare?.compatible ?? false;\n }\n\n /**\n * https://docs.taler.net/core/api-bank-transfer.html#get--config\n *\n */\n async getConfig() {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-prepared-transfer\",\n TalerPreparedTransferHttpClient.PROTOCOL_VERSION,\n resp,\n codecForPreparedTransferConfig(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-transfer.html#post--registration\n *\n */\n async register(body: TalerPreparedTransferApi.RegistrationRequest) {\n const url = new URL(`registration`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n console.log(body);\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForRegistrationResponse());\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-bank-transfer.html#delete--registration\n *\n */\n async unregister(body: TalerPreparedTransferApi.Unregistration) {\n const url = new URL(`unregistration`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict: {\n const body = await readTalerErrorResponse(resp);\n const details = codecForTalerErrorDetail().decode(body);\n switch (details.code) {\n case TalerErrorCode.BANK_OLD_TIMESTAMP:\n case TalerErrorCode.BANK_BAD_SIGNATURE:\n return opKnownTalerFailure(details.code, details);\n default:\n return opKnownHttpFailure(resp.status, resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport {\n Codec,\n buildCodecForObject,\n buildCodecForUnion,\n codecForAny,\n codecForBoolean,\n codecForConstString,\n codecForEither,\n codecForMap,\n codecForNumber,\n codecForString,\n codecOptional,\n} from \"./codec.js\";\nimport { TalerProtocolTimestamp, codecForTimestamp } from \"./time.js\";\nimport {\n Integer,\n InternationalizedString,\n Timestamp,\n} from \"./types-taler-common.js\";\n\nexport interface ChallengerTermsOfServiceResponse {\n // Name of the service\n name: \"challenger\";\n\n // libtool-style representation of the Challenger protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // URN of the implementation (needed to interpret 'revision' in version).\n // @since v0, may become mandatory in the future.\n implementation?: string;\n\n // Object; map of keys (names of the fields of the address\n // to be entered by the user) to objects with a \"regex\" (string)\n // containing an extended Posix regular expression for allowed\n // address field values, and a \"hint\"/\"hint_i18n\" giving a\n // human-readable explanation to display if the value entered\n // by the user does not match the regex. Keys that are not mapped\n // to such an object have no restriction on the value provided by\n // the user. See \"ADDRESS_RESTRICTIONS\" in the challenger configuration.\n restrictions: Record | undefined;\n\n // @since v2.\n address_type: \"email\" | \"phone\" | \"postal\" | \"postal-ch\";\n}\n\nexport interface ChallengeSetupResponse {\n // Nonce to use when constructing /authorize endpoint.\n nonce: string;\n}\n\nexport interface Restriction {\n regex?: string;\n hint?: string;\n hint_i18n?: InternationalizedString;\n}\n\nexport interface ChallengeStatus {\n // indicates if the given address cannot be changed anymore, the\n // form should be read-only if set to true.\n fix_address: boolean;\n\n // form values from the previous submission if available, details depend\n // on the ADDRESS_TYPE, should be used to pre-populate the form\n last_address: Record | undefined;\n\n // number of times the address can still be changed, may or may not be\n // shown to the user\n changes_left: Integer;\n\n // is the challenge already solved?\n solved: boolean;\n\n // when we would re-transmit the challenge the next\n // time (at the earliest) if requested by the user\n // only present if challenge already created\n // @since v2\n retransmission_time: Timestamp;\n\n // how many times might the PIN still be retransmitted\n // only present if challenge already created\n // @since v2\n pin_transmissions_left: Integer;\n\n // how many times might the user still try entering the PIN code\n // only present if challenge already created\n // @since v2\n auth_attempts_left: Integer;\n}\n\nexport type ChallengeResponse = ChallengeRedirect | ChallengeCreateResponse;\n\nexport interface ChallengeRedirect {\n type: \"completed\";\n // challenge is completed, use should redirect here\n redirect_url: string;\n}\n\nexport interface ChallengeCreateResponse {\n type: \"created\";\n // how many more attempts are allowed, might be shown to the user,\n // highlighting might be appropriate for low values such as 1 or 2 (the\n // form will never be used if the value is zero)\n attempts_left: Integer;\n\n // the address that is being validated, might be shown or not\n address: Object;\n\n // true if we just retransmitted the challenge, false if we sent a\n // challenge recently and thus refused to transmit it again this time;\n // might make a useful hint to the user\n transmitted: boolean;\n\n // FIXME: not in the spec\n nonce?: string;\n\n // timestamp explaining when we would re-transmit the challenge the next\n // time (at the earliest) if requested by the user\n retransmission_time: TalerProtocolTimestamp;\n}\n\nexport type ChallengeSolveResponse = ChallengeRedirect | InvalidPinResponse;\n\nexport interface InvalidPinResponse {\n type: \"pending\";\n\n // numeric Taler error code, should be shown to indicate the error\n // compactly for reporting to developers\n ec?: number;\n\n // FIXME: not documented\n code?: number;\n\n // human-readable Taler error code, should be shown for the user to\n // understand the error\n hint: string;\n\n // how many times is the user still allowed to change the address;\n // if 0, the user should not be shown a link to jump to the\n // address entry form\n addresses_left: Integer;\n\n // how many times might the PIN still be retransmitted\n pin_transmissions_left: Integer;\n\n // how many times might the user still try entering the PIN code\n auth_attempts_left: Integer;\n\n // if true, the PIN was not even evaluated as the user previously\n // exhausted the number of attempts\n exhausted: boolean;\n\n // if true, the PIN was not even evaluated as no challenge was ever\n // issued (the user must have skipped the step of providing their\n // address first!)\n no_challenge: boolean;\n}\n\nexport interface ChallengerAuthResponse {\n // Token used to authenticate access in /info.\n access_token: string;\n\n // Type of the access token.\n token_type: \"Bearer\";\n\n // Amount of time that an access token is valid (in seconds).\n expires_in: Integer;\n}\n\nexport interface ChallengerInfoResponse {\n // Unique ID of the record within Challenger\n // (identifies the rowid of the token).\n id: Integer;\n\n // Address that was validated.\n // Key-value pairs, details depend on the\n // address_type.\n address: Object;\n\n // Type of the address.\n address_type: string;\n\n // How long do we consider the address to be\n // valid for this user.\n expires: Timestamp;\n}\n\nexport const codecForChallengerTermsOfServiceResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"name\", codecForConstString(\"challenger\"))\n .property(\"version\", codecForString())\n .property(\"implementation\", codecOptional(codecForString()))\n .property(\"restrictions\", codecOptional(codecForMap(codecForAny())))\n .property(\n \"address_type\",\n codecForEither(\n codecForConstString(\"phone\"),\n codecForConstString(\"email\"),\n codecForConstString(\"postal\"),\n codecForConstString(\"postal-ch\"),\n ),\n )\n .build(\"ChallengerApi.ChallengerTermsOfServiceResponse\");\n\nexport const codecForChallengeSetupResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"nonce\", codecForString())\n .build(\"ChallengerApi.ChallengeSetupResponse\");\n\nexport const codecForChallengeStatus = (): Codec =>\n buildCodecForObject()\n .property(\"fix_address\", codecForBoolean())\n .property(\"solved\", codecForBoolean())\n .property(\"last_address\", codecOptional(codecForMap(codecForAny())))\n .property(\"changes_left\", codecForNumber())\n .property(\"retransmission_time\", codecForTimestamp)\n .property(\"pin_transmissions_left\", codecForNumber())\n .property(\"auth_attempts_left\", codecForNumber())\n .build(\"ChallengerApi.ChallengeStatus\");\n\nexport const codecForChallengeResponse = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\"completed\", codecForChallengeRedirect())\n .alternative(\"created\", codecForChallengeCreateResponse())\n .build(\"ChallengerApi.ChallengeResponse\");\n\nexport const codecForChallengeCreateResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"attempts_left\", codecForNumber())\n .property(\"type\", codecForConstString(\"created\"))\n .property(\"nonce\", codecOptional(codecForString()))\n .property(\"address\", codecForAny())\n .property(\"transmitted\", codecForBoolean())\n .property(\"retransmission_time\", codecForTimestamp)\n .build(\"ChallengerApi.ChallengeCreateResponse\");\n\nexport const codecForChallengeRedirect = (): Codec =>\n buildCodecForObject()\n .property(\"type\", codecForConstString(\"completed\"))\n .property(\"redirect_url\", codecForString())\n .build(\"ChallengerApi.ChallengeRedirect\");\n\nexport const codecForChallengeInvalidPinResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"ec\", codecOptional(codecForNumber()))\n .property(\"code\", codecOptional(codecForNumber()))\n .property(\"hint\", codecForAny())\n .property(\"type\", codecForConstString(\"pending\"))\n .property(\"addresses_left\", codecForNumber())\n .property(\"pin_transmissions_left\", codecForNumber())\n .property(\"auth_attempts_left\", codecForNumber())\n .property(\"exhausted\", codecForBoolean())\n .property(\"no_challenge\", codecForBoolean())\n .build(\"ChallengerApi.InvalidPinResponse\");\n\nexport const codecForChallengeSolveResponse =\n (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\"completed\", codecForChallengeRedirect())\n .alternative(\"pending\", codecForChallengeInvalidPinResponse())\n .build(\"ChallengerApi.ChallengeSolveResponse\");\n\nexport const codecForChallengerAuthResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"access_token\", codecForString())\n .property(\"token_type\", codecForAny())\n .property(\"expires_in\", codecForNumber())\n .build(\"ChallengerApi.ChallengerAuthResponse\");\n\nexport const codecForChallengerInfoResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"id\", codecForNumber())\n .property(\"address\", codecForAny())\n .property(\"address_type\", codecForString())\n .property(\"expires\", codecForTimestamp)\n .build(\"ChallengerApi.ChallengerInfoResponse\");\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\n/**\n * Imports.\n */\nimport { HttpRequestLibrary, readTalerErrorResponse } from \"../http-common.js\";\nimport { HttpStatusCode } from \"../http-status-codes.js\";\nimport { createPlatformHttpLib } from \"../http.js\";\nimport { LibtoolVersion } from \"../libtool-version.js\";\nimport {\n FailCasesByMethod,\n ResultByMethod,\n carefullyParseConfig,\n opKnownAlternativeHttpFailure,\n opKnownHttpFailure,\n opSuccessFromHttp,\n opUnknownFailure,\n opUnknownHttpFailure,\n} from \"../operation.js\";\nimport {\n codecForChallengeInvalidPinResponse,\n codecForChallengeResponse,\n codecForChallengeSetupResponse,\n codecForChallengeSolveResponse,\n codecForChallengeStatus,\n codecForChallengerAuthResponse,\n codecForChallengerInfoResponse,\n codecForChallengerTermsOfServiceResponse,\n} from \"../types-taler-challenger.js\";\nimport { AccessToken } from \"../types-taler-common.js\";\nimport {\n CacheEvictor,\n makeBearerTokenAuthHeader,\n nullEvictor,\n} from \"./utils.js\";\n\nexport type ChallengerResultByMethod =\n ResultByMethod;\nexport type ChallengerErrorsByMethod =\n FailCasesByMethod;\n\nexport enum ChallengerCacheEviction {\n CREATE_CHALLENGE,\n SOLVE_CHALLENGE,\n}\n\n/**\n */\nexport class ChallengerHttpClient {\n httpLib: HttpRequestLibrary;\n cacheEvictor: CacheEvictor;\n public static readonly PROTOCOL_VERSION = \"2:0:0\";\n\n constructor(\n readonly baseUrl: string,\n httpClient?: HttpRequestLibrary,\n cacheEvictor?: CacheEvictor,\n ) {\n this.httpLib = httpClient ?? createPlatformHttpLib();\n this.cacheEvictor = cacheEvictor ?? nullEvictor;\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version);\n return compare?.compatible ?? false;\n }\n /**\n * https://docs.taler.net/core/api-challenger.html#get--config\n *\n */\n async getConfig() {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"challenger\",\n ChallengerHttpClient.PROTOCOL_VERSION,\n resp,\n codecForChallengerTermsOfServiceResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n /**\n * https://docs.taler.net/core/api-challenger.html#post--setup-$CLIENT_ID\n *\n */\n async setup(clientId: string, token: AccessToken, body?: object) {\n const url = new URL(`setup/${clientId}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForChallengeSetupResponse());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // LOGIN\n\n /**\n * https://docs.taler.net/core/api-challenger.html#post--authorize-$NONCE\n *\n */\n async login(\n nonce: string,\n clientId: string,\n redirectUri: string,\n state: string | undefined,\n ) {\n const url = new URL(`authorize/${nonce}`, this.baseUrl);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"client_id\", clientId);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n if (state) {\n url.searchParams.set(\"state\", state);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForChallengeStatus());\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotAcceptable:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.TooManyRequests:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.InternalServerError:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // CHALLENGE\n\n /**\n * https://docs.taler.net/core/api-challenger.html#post--challenge-$NONCE\n *\n */\n async challenge(nonce: string, body: Record) {\n const url = new URL(`challenge/${nonce}`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n await this.cacheEvictor.notifySuccess(\n ChallengerCacheEviction.CREATE_CHALLENGE,\n );\n return opSuccessFromHttp(resp, codecForChallengeResponse());\n }\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotAcceptable:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.TooManyRequests:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.InternalServerError:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // SOLVE\n\n /**\n * https://docs.taler.net/core/api-challenger.html#post--solve-$NONCE\n *\n */\n async solve(nonce: string, body: Record) {\n const url = new URL(`solve/${nonce}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body: new URLSearchParams(Object.entries(body)).toString(),\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n redirect: \"manual\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n await this.cacheEvictor.notifySuccess(\n ChallengerCacheEviction.SOLVE_CHALLENGE,\n );\n return opSuccessFromHttp(resp, codecForChallengeSolveResponse());\n }\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownAlternativeHttpFailure(\n resp,\n HttpStatusCode.Forbidden,\n codecForChallengeInvalidPinResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotAcceptable:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.TooManyRequests:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.InternalServerError:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // AUTH\n\n /**\n * https://docs.taler.net/core/api-challenger.html#post--token\n *\n */\n async token(\n client_id: string,\n redirect_uri: string,\n client_secret: AccessToken,\n code: string,\n ) {\n const url = new URL(`token`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams(\n Object.entries({\n client_id,\n redirect_uri,\n client_secret,\n code,\n grant_type: \"authorization_code\",\n }),\n ).toString(),\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForChallengerAuthResponse());\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // INFO\n\n /**\n * https://docs.taler.net/core/api-challenger.html#get--info\n *\n */\n async info(token: AccessToken) {\n const url = new URL(`info`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForChallengerInfoResponse());\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n buildCodecForObject,\n buildCodecForUnion,\n Codec,\n codecForAny,\n codecForConstString,\n codecForList,\n codecForNumber,\n codecForString,\n} from \"./codec.js\";\nimport { codecForTimestamp, TalerProtocolTimestamp } from \"./time.js\";\nimport {\n EddsaPublicKeyString,\n BlindedRsaSignature,\n codecForEddsaPublicKey,\n codecForEddsaSignature,\n Cs25519Point,\n Cs25519Scalar,\n CSNonce,\n CsRPublic,\n EddsaPublicKey,\n EddsaSignatureString,\n HashCodeString,\n Integer,\n RsaPublicKeyString,\n RsaSignature,\n AmountString,\n} from \"./types-taler-common.js\";\nimport { DenomKeyType } from \"./types-taler-exchange.js\";\n\nexport interface DonauVersionResponse {\n // libtool-style representation of the Donau protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Name of the protocol.\n name: \"donau\";\n\n // Currency supported by this Donau.\n currency: string;\n\n // Financial domain by this Donau.\n legal_domain: string;\n}\n\nexport const codecForDonauVersionResponse = (): Codec =>\n buildCodecForObject()\n .property(\"version\", codecForString())\n .property(\"name\", codecForConstString(\"donau\"))\n .property(\"currency\", codecForString())\n .property(\"legal_domain\", codecForString())\n .build(\"DonauApi.DonauVersionResponse\");\n\n/**\n * Structure of one exchange signing key in the /keys response.\n */\nexport class DonauSignKeyJson {\n stamp_start: TalerProtocolTimestamp;\n stamp_expire: TalerProtocolTimestamp;\n stamp_end: TalerProtocolTimestamp;\n key: EddsaPublicKeyString;\n master_sig: EddsaSignatureString;\n}\n\nexport const codecForDonauSignKeyJson = (): Codec =>\n buildCodecForObject()\n .property(\"key\", codecForEddsaPublicKey())\n .property(\"master_sig\", codecForEddsaSignature())\n .property(\"stamp_end\", codecForTimestamp)\n .property(\"stamp_start\", codecForTimestamp)\n .property(\"stamp_expire\", codecForTimestamp)\n .build(\"DonauSignKeyJson\");\n\nexport interface DonauKeysResponse {\n // libtool-style representation of the Donau protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Financial domain this Donau operates for.\n //domain: string;\n\n // The Donau's base URL.\n base_url: string;\n\n // The Donau's currency.\n currency: string;\n\n // How many digits should the amounts be rendered\n // with by default. Small capitals should\n // be used to render fractions beyond the number\n // given here (like on gas stations).\n //currency_fraction_digits: number;\n\n // Donation Units offered by this Donau\n donation_units: DonationUnitKeyGroup[];\n\n // The Donau's signing keys.\n signkeys: DonauSignKeyJson[];\n}\n\nexport type DonationUnitKeyGroup =\n | DonationUnitKeyGroupRsa\n | DonationUnitKeyGroupCs;\n\nexport interface DonationUnitKeyGroupCommon {\n // How much are coins of this denomination worth?\n value: AmountString;\n\n // For which year is this donation unit key valid.\n year: number;\n\n // Set to 'true' if the Donau somehow \"lost\" the private key. The donation unit was not\n // revoked, but still cannot be used to withdraw receipts at this time (theoretically,\n // the private key could be recovered in the future; receipts signed with the private key\n // remain valid).\n lost?: boolean;\n}\n\nexport interface DonationUnitKeyGroupRsa extends DonationUnitKeyGroupCommon {\n donation_unit_pub: {\n cipher: \"RSA\";\n pub_key_hash: HashCodeString;\n rsa_public_key: RsaPublicKeyString;\n };\n}\n\nexport interface DonationUnitKeyGroupCs extends DonationUnitKeyGroupCommon {\n donation_unit_pub: {\n cipher: \"CS\";\n pub_key_hash: HashCodeString;\n cs_pub: Cs25519Point;\n };\n}\n\n// FIXME: Validate properly!\nexport const codecForDonationUnitKeyGroup: Codec =\n codecForAny();\n\nexport const codecForDonauKeysResponse = (): Codec =>\n buildCodecForObject()\n .property(\"version\", codecForString())\n .property(\"base_url\", codecForString())\n .property(\"currency\", codecForString())\n //.property(\"domain\", codecForString())\n .property(\"signkeys\", codecForAny())\n .property(\"donation_units\", codecForList(codecForDonationUnitKeyGroup))\n //.property(\"currency_fraction_digits\", codecForNumber())\n .build(\"DonauApi.DonauKeysResponse\");\n\nexport interface BlindedDonationReceiptKeyPair {\n // Hash of the public key that should be used to sign\n // the donation receipt.\n h_donation_unit_pub: HashCodeString;\n\n // Blinded value to give to the Donau to sign over.\n blinded_udi: BlindedUniqueDonationIdentifier;\n}\n\nexport type BlindedUniqueDonationIdentifier = RSABUDI | CSBUDI;\n\nexport interface RSABUDI {\n cipher: \"RSA\";\n rsa_blinded_identifier: string; // Crockford Base32 encoded\n}\n\n// For donation unit signatures based on Blind Clause-Schnorr, the BUDI\n// consists of the public nonce and two Curve25519 scalars which are two\n// blinded challenges in the Blinded Clause-Schnorr signature scheme.\n// See https://taler.net/papers/cs-thesis.pdf for details.\nexport interface CSBUDI {\n cipher: \"CS\";\n cs_nonce: string; // Crockford Base32 encoded\n cs_blinded_c0: string; // Crockford Base32 encoded\n cs_blinded_c1: string; // Crockford Base32 encoded\n}\n\nexport type DonationReceiptSignature =\n | RSADonationReceiptSignature\n | CSDonationReceiptSignature;\n\nexport interface RSADonationReceiptSignature {\n cipher: \"RSA\";\n\n // RSA signature\n rsa_signature: RsaSignature;\n}\n\nexport interface CSDonationReceiptSignature {\n cipher: \"CS\";\n\n // R value component of the signature.\n cs_signature_r: Cs25519Point;\n\n // s value component of the signature.\n cs_signature_s: Cs25519Scalar;\n}\n\nexport type DonauUnitPubKey = RsaDonauUnitPubKey | CsDonauUnitPubKey;\n\nexport interface RsaDonauUnitPubKey {\n readonly cipher: DenomKeyType.Rsa;\n readonly rsa_public_key: string;\n readonly age_mask: number;\n}\n\nexport interface CsDonauUnitPubKey {\n readonly cipher: DenomKeyType.ClauseSchnorr;\n readonly age_mask: number;\n readonly cs_public_key: string;\n}\n\nexport interface CharityRequest {\n // Long-term EdDSA public key that identifies the charity.\n charity_pub: EddsaPublicKey;\n // Canonical URL that should be presented to donors.\n charity_url: string;\n // Human-readable display name of the charity.\n charity_name: string;\n // Allowed donation volume for the charity per calendar year.\n max_per_year: AmountString;\n // Donation volume that has already been received for current_year.\n receipts_to_date: AmountString;\n // Calendar year the accounting information refers to.\n current_year: Integer;\n}\n\nexport interface IssuePrepareRequest {\n // Nonce to be used by the donau to derive\n // its private inputs from. Must not have ever\n // been used before.\n nonce: CSNonce;\n\n // Hash of the public key of the donation unit\n // the request relates to.\n du_pub_hash: HashCodeString;\n}\nexport interface DonauCharityResponse {\n charity_id: Integer;\n}\n\nexport interface IssueReceiptsRequest {\n // Signature by the charity approving that the\n // Donau should sign the donation receipts below.\n charity_sig: EddsaSignatureString;\n\n // Year for which the donation receipts are expected.\n // Also determines which keys are used to sign the\n // blinded donation receipts.\n year: Integer;\n\n // Array of blinded donation receipts to sign.\n // Must NOT be empty (if no donation receipts\n // are desired, just leave the entire donau\n // argument blank).\n budikeypairs: BlindedDonationReceiptKeyPair[];\n}\n\nexport type IssuePrepareResponse = DonauIssueValue;\n\nexport type DonauIssueValue = DonauRsaIssueValue | DonauCsIssueValue;\n\nexport interface DonauRsaIssueValue {\n cipher: \"RSA\";\n}\n\nexport interface DonauCsIssueValue {\n cipher: \"CS\";\n\n // CSR R0 value\n r_pub_0: CsRPublic;\n\n // CSR R1 value\n r_pub_1: CsRPublic;\n}\n\nexport interface BlindedDonationReceiptSignatures {\n blind_signed_receipt_signatures: BlindedDonationReceiptSignature[];\n}\nexport type BlindedDonationReceiptSignature =\n | RSABlindedDonationReceiptSignature\n | CSBlindedDonationReceiptSignature;\nexport interface RSABlindedDonationReceiptSignature {\n cipher: \"RSA\";\n\n // (blinded) RSA signature\n blinded_rsa_signature: BlindedRsaSignature;\n}\nexport interface CSBlindedDonationReceiptSignature {\n cipher: \"CS\";\n\n // Signer chosen bit value, 0 or 1, used\n // in Clause Blind Schnorr to make the\n // ROS problem harder.\n b: Integer;\n\n // Blinded scalar calculated from c_b.\n s: Cs25519Scalar;\n}\n\nexport const codecForIssuePrepareResponse = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"cipher\")\n .alternative(\n \"CS\",\n codecForAny(), //FIXME: complete\n )\n .alternative(\n \"RSA\",\n codecForAny(), //FIXME: complete\n )\n .build(\"DonauApi.IssuePrepareResponse\");\n\nexport const codecForDonauCharityResponse = (): Codec =>\n buildCodecForObject()\n .property(\"charity_id\", codecForNumber())\n .build(\"DonauApi.DonauCharityResponse\");\n\nexport interface SubmitDonationReceiptsRequest {\n // hashed taxpayer ID plus salt\n h_donor_tax_id: HashCodeString;\n // All donation receipts must be for this year.\n donation_year: Integer;\n // Receipts should be sorted by amount.\n donation_receipts: DonationReceipt[];\n}\n\nexport interface DonationReceipt {\n h_donation_unit_pub: HashCodeString;\n nonce: string;\n donation_unit_sig: DonationReceiptSignature;\n}\n\nexport interface DonationStatementResponse {\n total: AmountString;\n // signature over h_donor_tax_id, total, donation_year\n donation_statement_sig: EddsaSignatureString;\n // the corresponding public key to the signature\n donau_pub: EddsaPublicKeyString;\n}\n\nexport const codecForDonauDonationStatementResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"total\", codecForAmountString())\n .property(\"donau_pub\", codecForEddsaPublicKey())\n .property(\"donation_statement_sig\", codecForEddsaSignature())\n .build(\"DonauApi.DonationStatementResponse\");\n\nexport interface Charities {\n charities: CharitySummary[];\n}\n\nexport interface CharitySummary {\n charity_id: Integer;\n charity_pub: EddsaPublicKeyString;\n name: string;\n max_per_year: AmountString;\n receipts_to_date: AmountString;\n}\n\nexport interface Charity {\n charity_pub: EddsaPublicKey;\n name: string;\n url: string;\n max_per_year: AmountString;\n receipts_to_date: AmountString;\n current_year: Integer;\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { HttpRequestLibrary } from \"../http-common.js\";\nimport { HttpStatusCode } from \"../http-status-codes.js\";\nimport { createPlatformHttpLib } from \"../http.js\";\nimport { LibtoolVersion } from \"../libtool-version.js\";\nimport {\n carefullyParseConfig,\n opEmptySuccess,\n OperationFail,\n OperationOk,\n opFixedSuccess,\n opKnownFailure,\n opKnownHttpFailure,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n} from \"../operation.js\";\n\nimport { AccessToken, Codec, codecForAny } from \"../index.js\";\nimport {\n BlindedDonationReceiptSignatures,\n Charities,\n Charity,\n CharityRequest,\n codecForDonauCharityResponse,\n codecForDonauDonationStatementResponse,\n codecForDonauKeysResponse,\n codecForDonauVersionResponse,\n codecForIssuePrepareResponse,\n DonauVersionResponse,\n IssuePrepareRequest,\n IssueReceiptsRequest,\n SubmitDonationReceiptsRequest,\n} from \"../types-donau.js\";\nimport { makeBearerTokenAuthHeader } from \"./utils.js\";\n\n/**\n * Client library for the GNU Taler donau service.\n */\nexport class DonauHttpClient {\n public static readonly SUPPORTED_DONAU_PROTOCOL_VERSION = \"0:0:0\";\n private httpLib: HttpRequestLibrary;\n\n constructor(\n readonly baseUrl: string,\n params: {\n httpClient?: HttpRequestLibrary;\n preventCompression?: boolean;\n } = {},\n ) {\n this.httpLib = params.httpClient ?? createPlatformHttpLib();\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(\n DonauHttpClient.SUPPORTED_DONAU_PROTOCOL_VERSION,\n version,\n );\n return compare?.compatible ?? false;\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#get--keys\n *\n * @returns\n */\n async getKeys() {\n const url = new URL(`keys`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForDonauKeysResponse());\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#get--seed\n *\n */\n async getSeed() {\n const url = new URL(`keys`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n const buffer = await resp.bytes();\n const uintar = new Uint8Array(buffer);\n return opFixedSuccess(uintar);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#get--config\n *\n * @returns\n */\n async getConfig(): Promise<\n OperationOk | OperationFail\n > {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"donau\",\n DonauHttpClient.SUPPORTED_DONAU_PROTOCOL_VERSION,\n resp,\n codecForDonauVersionResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#csr-issue\n *\n * @param args\n * @returns\n */\n async prepareIssueReceipt(body: IssuePrepareRequest) {\n const url = new URL(`csr-issue`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForIssuePrepareResponse());\n case HttpStatusCode.NotFound:\n return opKnownFailure(resp.status);\n case HttpStatusCode.Gone:\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#post--batch-issue-$CHARITY_ID\n *\n * @param args\n * @returns\n */\n async issueReceipts(charityId: number, body: IssueReceiptsRequest) {\n const url = new URL(`batch-issue/${charityId}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n //FIXME: incomplete\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(\n resp,\n codecForAny() as Codec,\n );\n case HttpStatusCode.Forbidden:\n return opKnownFailure(resp.status);\n case HttpStatusCode.NotFound:\n return opKnownFailure(resp.status);\n case HttpStatusCode.Conflict:\n return opKnownFailure(resp.status);\n case HttpStatusCode.Gone:\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#post--batch-submit\n *\n * @param args\n * @returns\n */\n async submitDonationReceipts(body: SubmitDonationReceiptsRequest) {\n const url = new URL(`batch-submit`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Created:\n return opEmptySuccess();\n case HttpStatusCode.Forbidden:\n return opKnownFailure(resp.status);\n case HttpStatusCode.NotFound:\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#get--donation-statement-$YEAR-$HASH_DONOR_ID\n *\n * @param args\n * @returns\n */\n async getDonationStatement(year: number, hash: string) {\n const url = new URL(`donation-statement/${year}/${hash}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(\n resp,\n codecForDonauDonationStatementResponse(),\n );\n case HttpStatusCode.Forbidden:\n return opKnownFailure(resp.status);\n case HttpStatusCode.NotFound:\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#get--charities\n *\n * @param args\n * @returns\n */\n async getCharities(token: AccessToken): Promise> {\n const url = new URL(`charities`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAny() as Codec); // FIXME: complete codec\n case HttpStatusCode.NoContent:\n return opFixedSuccess({\n charities: [],\n });\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#get--charities-$CHARITY_ID\n */\n async getCharitiesById(\n token: AccessToken,\n id: string,\n ): Promise | OperationOk> {\n const url = new URL(`charities/${id}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAny() as Codec); // FIXME: complete codec\n case HttpStatusCode.NotFound:\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#post--charities\n *\n * @param args\n * @returns\n */\n async createCharity(token: AccessToken, body: CharityRequest) {\n const url = new URL(`charities`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Created:\n return opSuccessFromHttp(resp, codecForDonauCharityResponse());\n case HttpStatusCode.NoContent:\n return opKnownFailure(resp.status);\n case HttpStatusCode.Forbidden:\n return opKnownFailure(resp.status);\n case HttpStatusCode.NotFound:\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#patch--charities-id\n *\n * @returns\n */\n async updateCharity(token: AccessToken, id: number, body: CharityRequest) {\n const url = new URL(`charities/${id}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opEmptySuccess();\n case HttpStatusCode.Forbidden:\n return opKnownFailure(resp.status);\n case HttpStatusCode.NotFound: // FIXME: missing in the spec\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-donau.html#patch--charities-id\n *\n * @returns\n */\n async deleteCharity(token: AccessToken, id: number) {\n const url = new URL(`charities/${id}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.Forbidden:\n return opKnownFailure(resp.status);\n case HttpStatusCode.NotFound: // FIXME: missing in the spec\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { codecForAny } from \"../codec.js\";\nimport {\n HttpRequestLibrary,\n HttpRequestOptions,\n HttpResponse,\n readSuccessResponseJsonOrThrow,\n readTalerErrorResponse,\n} from \"../http-common.js\";\nimport { HttpStatusCode } from \"../http-status-codes.js\";\nimport { createPlatformHttpLib } from \"../http.js\";\nimport { LibtoolVersion } from \"../libtool-version.js\";\nimport {\n FailCasesByMethod,\n OperationAlternative,\n OperationFail,\n OperationOk,\n ResultByMethod,\n carefullyParseConfig,\n opEmptySuccess,\n opFixedSuccess,\n opKnownAlternativeHttpFailure,\n opKnownFailure,\n opKnownHttpFailure,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n} from \"../operation.js\";\nimport { encodeCrock } from \"../taler-crypto.js\";\nimport {\n AccessToken,\n EddsaPublicKeyString,\n EddsaSignatureString,\n LongPollParams,\n OfficerSession,\n PaginationParams,\n} from \"../types-taler-common.js\";\nimport {\n AccountKycStatus,\n AmlDecisionRequest,\n AmlDecisionsResponse,\n AvailableMeasureSummary,\n EventCounter,\n ExchangeGetContractResponse,\n ExchangeKeysResponse,\n ExchangeKycUploadFormRequest,\n ExchangeMeltRequestV2,\n ExchangeMeltResponse,\n ExchangeMergeConflictResponse,\n ExchangeMergeSuccessResponse,\n ExchangePurseDeposits,\n ExchangePurseMergeRequest,\n ExchangePurseStatus,\n ExchangeRefreshRevealRequestV2,\n ExchangeReservePurseRequest,\n ExchangeTransferList,\n ExchangeVersionResponse,\n ExchangeWithdrawRequest,\n ExchangeWithdrawResponse,\n KycAttributes,\n KycProcessClientInformation,\n KycProcessClientInformationWithEtag,\n KycProcessStartInformation,\n KycRequirementInformationId,\n LegitimizationMeasuresList,\n LegitimizationNeededResponse,\n PurseConflict,\n PurseConflictPartial,\n PurseCreateSuccessResponse,\n WalletKycCheckResponse,\n WalletKycRequest,\n codecForAccountKycStatus,\n codecForAmlDecisionsAccounts,\n codecForAmlDecisionsResponse,\n codecForAmlKycAttributes,\n codecForAmlStatisticsResponse,\n codecForAmlWalletKycCheckResponse,\n codecForAvailableMeasureSummary,\n codecForExchangeConfig,\n codecForExchangeGetContractResponse,\n codecForExchangeKeysResponse,\n codecForExchangeMeltResponse,\n codecForExchangeMergeConflictResponse,\n codecForExchangeMergeSuccessResponse,\n codecForExchangePurseStatus,\n codecForExchangeTransferList,\n codecForExchangeWithdrawResponse,\n codecForKycProcessClientInformation,\n codecForKycProcessStartInformation,\n codecForLegitimizationMeasuresList,\n codecForLegitimizationNeededResponse,\n codecForPurseConflict,\n codecForPurseConflictPartial,\n codecForPurseCreateSuccessResponse,\n} from \"../types-taler-exchange.js\";\nimport {\n CacheEvictor,\n addLongPollingParam,\n addPaginationParams,\n nullEvictor,\n} from \"./utils.js\";\n\nimport {\n AmountJson,\n Amounts,\n CancellationToken,\n Logger,\n LongpollQueue,\n PaytoHash,\n TalerErrorCode,\n opKnownFailureWithBody,\n opKnownTalerFailure,\n signAmlDecision,\n signAmlQuery,\n} from \"../index.js\";\nimport { AbsoluteTime } from \"../time.js\";\nimport { EmptyObject, codecForEmptyObject } from \"../types-taler-wallet.js\";\n\nexport type TalerExchangeResultByMethod2<\n prop extends keyof TalerExchangeHttpClient,\n> = ResultByMethod;\nexport type TalerExchangeErrorsByMethod2<\n prop extends keyof TalerExchangeHttpClient,\n> = FailCasesByMethod;\n\nconst logger = new Logger(\"exchange-client.ts\");\n\nexport enum TalerExchangeCacheEviction {\n UPLOAD_KYC_FORM,\n MAKE_AML_DECISION,\n}\n\n/**\n * Client library for the GNU Taler exchange service.\n */\nexport class TalerExchangeHttpClient {\n public static readonly SUPPORTED_EXCHANGE_PROTOCOL_VERSION = \"34:0:9\";\n private httpLib: HttpRequestLibrary;\n private cacheEvictor: CacheEvictor;\n private preventCompression: boolean;\n private cancelationToken: CancellationToken;\n private longPollQueue: LongpollQueue;\n\n constructor(\n readonly baseUrl: string,\n params: {\n httpClient?: HttpRequestLibrary;\n cacheEvictor?: CacheEvictor;\n preventCompression?: boolean;\n cancelationToken?: CancellationToken;\n longPollQueue?: LongpollQueue;\n } = {},\n ) {\n this.httpLib = params.httpClient ?? createPlatformHttpLib();\n this.cacheEvictor = params.cacheEvictor ?? nullEvictor;\n this.preventCompression = !!params.preventCompression;\n this.cancelationToken =\n params.cancelationToken ?? CancellationToken.CONTINUE;\n this.longPollQueue = params.longPollQueue ?? new LongpollQueue();\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(\n TalerExchangeHttpClient.SUPPORTED_EXCHANGE_PROTOCOL_VERSION,\n version,\n );\n return compare?.compatible ?? false;\n }\n\n private async fetch(\n url_or_path: URL | string,\n opts: HttpRequestOptions = {},\n longpoll: boolean = false,\n ): Promise {\n const url =\n typeof url_or_path == \"string\"\n ? new URL(url_or_path, this.baseUrl)\n : url_or_path;\n if (longpoll || url.searchParams.has(\"timeout_ms\")) {\n return this.longPollQueue.run(\n url,\n this.cancelationToken,\n async (timeoutMs) => {\n url.searchParams.set(\"timeout_ms\", String(timeoutMs));\n return this.httpLib.fetch(url.href, {\n cancellationToken: this.cancelationToken,\n ...opts,\n });\n },\n );\n } else {\n return this.httpLib.fetch(url.href, {\n cancellationToken: this.cancelationToken,\n ...opts,\n });\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--seed\n *\n */\n async getSeed() {\n const resp = await this.fetch(\"seed\");\n switch (resp.status) {\n case HttpStatusCode.Ok:\n const buffer = await resp.bytes();\n const uintar = new Uint8Array(buffer);\n return opFixedSuccess(uintar);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n /**\n * https://docs.taler.net/core/api-exchange.html#get--config\n *\n */\n async getConfig(): Promise<\n | OperationFail\n | OperationOk\n > {\n const resp = await this.fetch(\"config\");\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-exchange\",\n TalerExchangeHttpClient.SUPPORTED_EXCHANGE_PROTOCOL_VERSION,\n resp,\n codecForExchangeConfig(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get--config\n *\n * PARTIALLY IMPLEMENTED!!\n */\n async getKeys(): Promise> {\n const resp = await this.fetch(\"keys\");\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeKeysResponse());\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // WALLET TO WALLET\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--purses-$PURSE_PUB-merge\n *\n */\n async getPurseStatusAtMerge(\n pursePub: string,\n longpoll: boolean = false,\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n > {\n const resp = await this.fetch(`purses/${pursePub}/merge`, {}, longpoll);\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangePurseStatus());\n case HttpStatusCode.Gone:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--purses-$PURSE_PUB-deposit\n *\n */\n async getPurseStatusAtDeposit(\n pursePub: string,\n longpoll: boolean = false,\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n > {\n const resp = await this.fetch(`purses/${pursePub}/deposit`, {}, longpoll);\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangePurseStatus());\n case HttpStatusCode.Gone:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-create\n *\n */\n async createPurseFromDeposit(\n pursePub: string,\n body: any, // FIXME\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n | OperationAlternative\n | OperationFail\n > {\n const resp = await this.fetch(`purses/${pursePub}/create`, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForPurseCreateSuccessResponse());\n case HttpStatusCode.Conflict:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForPurseConflict(),\n );\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.TooEarly:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#delete--purses-$PURSE_PUB\n *\n */\n async deletePurse(\n pursePub: string,\n purseSig: string,\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n | OperationFail\n > {\n const resp = await this.fetch(`purses/${pursePub}`, {\n method: \"DELETE\",\n headers: {\n \"taler-purse-signature\": purseSig,\n },\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * POST /purses/$PURSE_PUB/merge\n *\n * https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-merge\n */\n async postPurseMerge(\n pursePub: string,\n body: ExchangePurseMergeRequest,\n ): Promise<\n | OperationOk\n | OperationAlternative<\n HttpStatusCode.UnavailableForLegalReasons,\n LegitimizationNeededResponse\n >\n | OperationAlternative<\n HttpStatusCode.Conflict,\n ExchangeMergeConflictResponse\n >\n | OperationFail\n | OperationFail\n | OperationFail\n > {\n const resp = await this.fetch(`purses/${pursePub}/merge`, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeMergeSuccessResponse());\n case HttpStatusCode.UnavailableForLegalReasons:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForLegitimizationNeededResponse(),\n );\n case HttpStatusCode.Conflict:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForExchangeMergeConflictResponse(),\n );\n case HttpStatusCode.Gone:\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#post--reserves-$RESERVE_PUB-purse\n *\n */\n async createPurseFromReserve(\n pursePub: string,\n body: ExchangeReservePurseRequest,\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationAlternative\n | OperationAlternative<\n HttpStatusCode.UnavailableForLegalReasons,\n LegitimizationNeededResponse\n >\n > {\n const resp = await this.fetch(`reserves/${pursePub}/purse`, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForPurseCreateSuccessResponse());\n case HttpStatusCode.PaymentRequired:\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForPurseConflictPartial(),\n );\n case HttpStatusCode.UnavailableForLegalReasons:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForLegitimizationNeededResponse(),\n );\n case HttpStatusCode.BadRequest: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--contracts-$CONTRACT_PUB\n *\n */\n async getContract(\n pursePub: string,\n ): Promise<\n | OperationOk\n | OperationFail\n > {\n const resp = await this.fetch(`contracts/${pursePub}`);\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeGetContractResponse());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#post--purses-$PURSE_PUB-deposit\n *\n */\n async depositIntoPurse(\n pursePub: string,\n body: ExchangePurseDeposits,\n ): Promise<\n | OperationOk\n | OperationAlternative\n | OperationFail\n | OperationFail\n | OperationFail\n > {\n const resp = await this.fetch(`purses/${pursePub}/deposit`, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n // FIXME: parse PurseDepositSuccessResponse\n return opSuccessFromHttp(resp, codecForAny());\n case HttpStatusCode.Conflict:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForPurseConflict(),\n );\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Gone:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // WADS\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--wads-$WAD_ID\n *\n */\n async getWadInfo(): Promise {\n throw Error(\"not yet implemented\");\n }\n\n //\n // KYC\n //\n\n /**\n * https://docs.taler.net/core/api-exchange.html#post--kyc-wallet\n *\n */\n async notifyKycBalanceLimit(\n body: WalletKycRequest,\n ): Promise<\n | OperationOk\n | OperationOk\n | OperationFail\n | OperationAlternative<\n HttpStatusCode.UnavailableForLegalReasons,\n LegitimizationNeededResponse\n >\n > {\n const url = new URL(`kyc-wallet`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAmlWalletKycCheckResponse());\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.UnavailableForLegalReasons:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForLegitimizationNeededResponse(),\n );\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--kyc-check-$H_NORMALIZED_PAYTO\n *\n */\n async checkKycStatus(args: {\n paytoHash: string;\n accountPub: EddsaPublicKeyString;\n accountSig: EddsaSignatureString;\n longpoll?: boolean;\n awaitAuth?: boolean;\n }): Promise<\n | OperationOk\n | OperationAlternative\n | OperationAlternative\n | OperationFail<\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n >\n > {\n const { paytoHash, accountPub, accountSig, longpoll, awaitAuth } = args;\n const url = new URL(`kyc-check/${paytoHash}`, this.baseUrl);\n if (awaitAuth !== undefined) {\n url.searchParams.set(\"await_auth\", awaitAuth ? \"YES\" : \"NO\");\n }\n\n const resp = await this.fetch(\n url,\n {\n headers: {\n \"Account-Owner-Signature\": accountSig,\n \"Account-Owner-Pub\": accountPub,\n },\n },\n longpoll,\n );\n\n switch (resp.status) {\n case HttpStatusCode.Ok: // means there are voluntary checks\n return opSuccessFromHttp(resp, codecForAccountKycStatus());\n case HttpStatusCode.Accepted: // means there are required checks\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForAccountKycStatus(),\n );\n case HttpStatusCode.NoContent: // no checks can be done\n return opKnownFailureWithBody(resp.status, undefined);\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * Do a /kyc-check request, but don't specify\n * the account pub explicitly.\n *\n * Deprecated, but used in tests.\n */\n async testingCheckKycStatusNoPub(args: {\n paytoHash: string;\n accountSig: EddsaSignatureString;\n longpoll?: boolean;\n awaitAuth?: boolean;\n }): Promise<\n | OperationOk\n | OperationAlternative\n | OperationAlternative\n | OperationFail<\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n >\n > {\n const { paytoHash, accountSig, longpoll, awaitAuth } = args;\n const url = new URL(`kyc-check/${paytoHash}`, this.baseUrl);\n if (awaitAuth !== undefined) {\n url.searchParams.set(\"await_auth\", awaitAuth ? \"YES\" : \"NO\");\n }\n\n const resp = await this.fetch(\n url,\n {\n headers: {\n \"Account-Owner-Signature\": accountSig,\n },\n },\n longpoll,\n );\n\n switch (resp.status) {\n case HttpStatusCode.Ok: // means there are voluntary checks\n return opSuccessFromHttp(resp, codecForAccountKycStatus());\n case HttpStatusCode.Accepted: // means there are required checks\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForAccountKycStatus(),\n );\n case HttpStatusCode.NoContent: // no checks can be done\n return opKnownFailureWithBody(resp.status, undefined);\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--kyc-info-$ACCESS_TOKEN\n *\n */\n async checkKycInfo(\n token: AccessToken,\n known: KycRequirementInformationId[] = [],\n longpoll: boolean = false,\n ): Promise<\n | OperationOk\n | OperationAlternative\n | OperationAlternative\n | OperationFail\n > {\n const resp = await this.fetch(\n `kyc-info/${token}`,\n {\n method: \"GET\",\n headers: {\n \"If-None-Match\": known.length\n ? known.map((d) => `\"${d}\"`).join(\",\")\n : undefined,\n },\n },\n longpoll,\n );\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForKycProcessClientInformation());\n case HttpStatusCode.Accepted:\n case HttpStatusCode.NoContent:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForEmptyObject(),\n );\n case HttpStatusCode.NotModified:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * SPA-Specific version of checkKycInfo\n *\n * FIXME: Unify with checkKycInfo\n */\n async checkKycInfoSpa(\n token: AccessToken,\n etag: string | undefined,\n params: LongPollParams = {},\n ) {\n const url = new URL(`kyc-info/${token}`, this.baseUrl);\n\n addLongPollingParam(url, params);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n \"If-None-Match\": !etag ? undefined : `\"${etag}\"`,\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n // we need to add the etag to the response because the\n // client needs it to repeat the request and\n // do the long polling\n const etagRaw = resp.headers.get(\"etag\") ?? undefined;\n let etag: string | undefined;\n if (\n etagRaw != null &&\n etagRaw.startsWith('\"') &&\n etagRaw.endsWith('\"')\n ) {\n etag = etagRaw.substring(1, etagRaw.length - 1);\n } else if (etagRaw == null) {\n // No ETag, fine.\n etag = etagRaw;\n } else {\n logger.warn(`malformed ETag header in kyc-info response`);\n }\n const body = await readSuccessResponseJsonOrThrow(\n resp,\n codecForKycProcessClientInformation(),\n );\n return opFixedSuccess({\n ...body,\n etag,\n });\n }\n case HttpStatusCode.Accepted:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NoContent:\n return opKnownFailure(resp.status);\n case HttpStatusCode.NotModified:\n // do not read details from response\n return opKnownFailure(resp.status);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#post--kyc-upload-$ID\n *\n */\n async uploadKycForm(\n requirement: KycRequirementInformationId,\n body: T,\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n > {\n const resp = await this.fetch(`kyc-upload/${requirement}`, {\n method: \"POST\",\n body,\n compress: this.preventCompression ? undefined : \"deflate\",\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerExchangeCacheEviction.UPLOAD_KYC_FORM,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.NotFound:\n case HttpStatusCode.InternalServerError:\n case HttpStatusCode.Conflict:\n case HttpStatusCode.PayloadTooLarge:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#post--kyc-start-$ID\n *\n */\n async startExternalKycProcess(\n requirement: KycRequirementInformationId,\n body: object = {},\n ): Promise<\n | OperationFail<\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n | HttpStatusCode.PayloadTooLarge\n >\n | OperationOk\n > {\n const resp = await this.fetch(`kyc-start/${requirement}`, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForKycProcessStartInformation());\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n case HttpStatusCode.PayloadTooLarge:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--kyc-proof-$PROVIDER_NAME?state=$H_PAYTO\n *\n */\n async completeExternalKycProcess(\n provider: string,\n state: string,\n code: string,\n ) {\n const resp = await this.fetch(\n `kyc-proof/${provider}?state=${state}&code=${code}`,\n {\n method: \"GET\",\n redirect: \"manual\",\n },\n );\n\n switch (resp.status) {\n case HttpStatusCode.SeeOther:\n return opEmptySuccess();\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // AML operations\n //\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-measures\n *\n */\n async getAmlMeasures(\n auth: OfficerSession,\n ): Promise<\n | OperationOk\n | OperationFail<\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n >\n > {\n const resp = await this.fetch(`aml/${auth.id}/measures`, {\n method: \"GET\",\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAvailableMeasureSummary());\n case HttpStatusCode.Conflict:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-kyc-statistics-$NAMES\n *\n */\n async getAmlKycStatistics(\n auth: OfficerSession,\n names: string[],\n filter: {\n since?: AbsoluteTime;\n until?: AbsoluteTime;\n } = {},\n ) {\n const url = new URL(\n `aml/${auth.id}/kyc-statistics/${names.join(\" \")}`,\n this.baseUrl,\n );\n\n if (filter.since !== undefined && filter.since.t_ms !== \"never\") {\n url.searchParams.set(\"start_date\", String(filter.since.t_ms));\n }\n if (filter.until !== undefined && filter.until.t_ms !== \"never\") {\n url.searchParams.set(\"end_date\", String(filter.until.t_ms));\n }\n\n const resp = await this.fetch(url, {\n method: \"GET\",\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAmlStatisticsResponse());\n case HttpStatusCode.NoContent: {\n return opFixedSuccess({\n statistics: names.map(\n (name) => ({ counter: 0, name }) as EventCounter,\n ),\n });\n }\n case HttpStatusCode.Conflict:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-accounts\n *\n */\n async getAmlAccounts(\n auth: OfficerSession,\n params: PaginationParams & {\n highRisk?: boolean;\n open?: boolean;\n investigation?: boolean;\n } = {},\n ) {\n const url = new URL(`aml/${auth.id}/accounts`, this.baseUrl);\n\n addPaginationParams(url, params);\n if (params.investigation !== undefined) {\n url.searchParams.set(\n \"investigation\",\n params.investigation ? \"YES\" : \"NO\",\n );\n }\n if (params.open !== undefined && params.open) {\n url.searchParams.set(\"open\", \"YES\");\n }\n if (params.highRisk !== undefined && params.highRisk) {\n url.searchParams.set(\"high_risk\", \"YES\");\n }\n\n const resp = await this.fetch(url, {\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAmlDecisionsAccounts());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ accounts: [] });\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-accounts\n *\n */\n async getAmlAccountsAsOtherFormat(\n auth: OfficerSession,\n mime: \"text/csv\" | \"application/vnd.ms-excel\" | \"application/json\",\n params: {\n highRisk?: boolean;\n open?: boolean;\n investigation?: boolean;\n } = {},\n ) {\n const url = new URL(`aml/${auth.id}/accounts`, this.baseUrl);\n\n /**\n * These are documents so it should bring all the rows\n * from start to the last and no pagination.\n */\n url.searchParams.set(\"offset\", \"0\");\n url.searchParams.set(\"limit\", \"99999999\");\n\n if (params.investigation !== undefined) {\n url.searchParams.set(\n \"investigation\",\n params.investigation ? \"YES\" : \"NO\",\n );\n }\n if (params.open !== undefined && params.open) {\n url.searchParams.set(\"open\", \"YES\");\n }\n if (params.highRisk !== undefined && params.highRisk) {\n url.searchParams.set(\"high_risk\", \"YES\");\n }\n\n const resp = await this.fetch(url, {\n headers: {\n Accept: mime,\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n return opFixedSuccess(await resp.bytes());\n }\n case HttpStatusCode.NoContent:\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-decisions\n *\n */\n async getAmlDecisions(\n auth: OfficerSession,\n params: PaginationParams & {\n account?: PaytoHash;\n active?: boolean;\n investigation?: boolean;\n } = {},\n ): Promise<\n | OperationFail<\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n >\n | OperationOk\n > {\n const url = new URL(`aml/${auth.id}/decisions`, this.baseUrl);\n\n addPaginationParams(url, params);\n if (params.account !== undefined) {\n url.searchParams.set(\"h_payto\", params.account);\n }\n if (params.active !== undefined) {\n url.searchParams.set(\"active\", params.active ? \"YES\" : \"NO\");\n }\n if (params.investigation !== undefined) {\n url.searchParams.set(\n \"investigation\",\n params.investigation ? \"YES\" : \"NO\",\n );\n }\n\n const resp = await this.fetch(url, {\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAmlDecisionsResponse());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ records: [] });\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-legitimizations\n */\n async getAmlLegitimizations(\n officer: OfficerSession,\n params: PaginationParams & {\n account?: PaytoHash;\n active?: boolean;\n } = {},\n ): Promise> {\n const url = new URL(`aml/${officer.id}/legitimizations`, this.baseUrl);\n\n addPaginationParams(url, params);\n if (params.account !== undefined) {\n url.searchParams.set(\"h_payto\", params.account);\n }\n if (params.active !== undefined) {\n url.searchParams.set(\"active\", params.active ? \"YES\" : \"NO\");\n }\n\n const resp = await this.httpLib.fetch(url.href, {\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(officer.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForLegitimizationMeasuresList());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({\n measures: [],\n });\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-attributes-$H_NORMALIZED_PAYTO\n *\n */\n async getAmlAttributesForAccount(\n auth: OfficerSession,\n account: string,\n params: PaginationParams = {},\n ): Promise<\n | OperationOk\n | OperationFail<\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n >\n > {\n const url = new URL(`aml/${auth.id}/attributes/${account}`, this.baseUrl);\n\n addPaginationParams(url, params);\n const resp = await this.fetch(url, {\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAmlKycAttributes());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ details: [] });\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-attributes-$H_NORMALIZED_PAYTO\n *\n */\n async getAmlAttributesForAccountAsPdf(\n auth: OfficerSession,\n account: string,\n params: PaginationParams = {},\n ): Promise<\n | OperationOk\n | OperationFail<\n | HttpStatusCode.NoContent\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n | HttpStatusCode.NotImplemented\n >\n > {\n const url = new URL(`aml/${auth.id}/attributes/${account}`, this.baseUrl);\n\n addPaginationParams(url, params);\n const resp = await this.fetch(url, {\n headers: {\n Accept: \"application/pdf\",\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n return opFixedSuccess(await resp.bytes());\n }\n case HttpStatusCode.NoContent:\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotImplemented:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#post--aml-$OFFICER_PUB-decision\n *\n */\n async makeAmlDesicion(\n auth: OfficerSession,\n decision: Omit,\n ) {\n const body: AmlDecisionRequest = {\n officer_sig: encodeCrock(\n signAmlDecision(auth.signingKey, decision),\n ) as any,\n ...decision,\n };\n const resp = await this.fetch(`aml/${auth.id}/decision`, {\n method: \"POST\",\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n body,\n compress: this.preventCompression ? undefined : \"deflate\",\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerExchangeCacheEviction.MAKE_AML_DECISION,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-transfers-credit\n *\n */\n async getTransfersCredit(\n auth: OfficerSession,\n params: PaginationParams & {\n threshold?: AmountJson;\n account?: PaytoHash;\n } = {},\n ): Promise<\n | OperationOk\n | OperationFail<\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n >\n > {\n const url = new URL(`aml/${auth.id}/transfers-credit`, this.baseUrl);\n\n addPaginationParams(url, params);\n\n if (params.threshold) {\n url.searchParams.set(\"threshold\", Amounts.stringify(params.threshold));\n }\n if (params.account) {\n url.searchParams.set(\"h_payto\", params.account);\n }\n\n const resp = await this.fetch(url, {\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeTransferList());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ transfers: [] });\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-transfers-debit\n *\n */\n async getTransfersDebit(\n auth: OfficerSession,\n params: PaginationParams & {\n threshold?: AmountJson;\n account?: PaytoHash;\n } = {},\n ): Promise<\n | OperationOk\n | OperationFail<\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n >\n > {\n const url = new URL(`aml/${auth.id}/transfers-debit`, this.baseUrl);\n\n addPaginationParams(url, params);\n\n if (params.threshold) {\n url.searchParams.set(\"threshold\", Amounts.stringify(params.threshold));\n }\n if (params.account) {\n url.searchParams.set(\"h_payto\", params.account);\n }\n\n const resp = await this.fetch(url, {\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeTransferList());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ transfers: [] });\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-exchange.html#get--aml-$OFFICER_PUB-transfers-kycauth\n *\n */\n async getTransfersKycAuth(\n auth: OfficerSession,\n params: PaginationParams & {\n threshold?: AmountJson;\n account?: PaytoHash;\n } = {},\n ): Promise<\n | OperationOk\n | OperationFail<\n | HttpStatusCode.Forbidden\n | HttpStatusCode.NotFound\n | HttpStatusCode.Conflict\n >\n > {\n const url = new URL(`aml/${auth.id}/transfers-kycauth`, this.baseUrl);\n\n addPaginationParams(url, params);\n\n if (params.threshold) {\n url.searchParams.set(\"threshold\", Amounts.stringify(params.threshold));\n }\n if (params.account) {\n url.searchParams.set(\"h_payto\", params.account);\n }\n\n const resp = await this.fetch(url, {\n headers: {\n \"Taler-AML-Officer-Signature\": encodeCrock(\n signAmlQuery(auth.signingKey),\n ),\n },\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeTransferList());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ transfers: [] });\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * Request: POST /withdraw\n *\n * https://docs.taler.net/core/api-exchange.html#withdrawal\n */\n async withdraw(args: {\n body: ExchangeWithdrawRequest;\n }): Promise<\n | OperationOk\n | OperationFail\n > {\n const url = new URL(`withdraw`, this.baseUrl);\n const resp = await this.fetch(url, {\n method: \"POST\",\n body: args.body,\n });\n // FIXME: Some documented cases are missing.\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeWithdrawResponse());\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * Request: POST /melt\n *\n * https://docs.taler.net/core/api-exchange.html#post--melt\n */\n async postMelt(args: {\n body: ExchangeMeltRequestV2;\n }): Promise<\n OperationOk | OperationFail\n > {\n const url = new URL(`melt`, this.baseUrl);\n const resp = await this.fetch(url, {\n method: \"POST\",\n body: args.body,\n });\n // FIXME: Some documented cases are missing.\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeMeltResponse());\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n async postRevealMelt(args: {\n body: ExchangeRefreshRevealRequestV2;\n }): Promise<\n | OperationOk\n | OperationFail\n > {\n const url = new URL(`reveal-melt`, this.baseUrl);\n const resp = await this.fetch(url, {\n method: \"POST\",\n body: args.body,\n });\n // FIXME: Some documented cases are missing.\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeWithdrawResponse());\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n CancellationToken,\n EddsaSignatureString,\n FailCasesByMethod,\n HttpStatusCode,\n LibtoolVersion,\n MailboxConfiguration,\n MailboxMetadata,\n MailboxRegisterRequest,\n MailboxRegisterResult,\n OperationAlternative,\n OperationFail,\n OperationOk,\n ResultByMethod,\n TalerMailboxApi,\n carefullyParseConfig,\n codecForEmptyObject,\n codecForTalerMailboxConfigResponse,\n codecForTalerMailboxMetadata,\n codecForTalerMailboxRateLimitedResponse,\n decodeCrock,\n eddsaGetPublic,\n encodeCrock,\n opEmptySuccess,\n opFixedSuccess,\n opKnownAlternativeHttpFailure,\n opKnownHttpFailure,\n opSuccessFromHttp,\n opUnknownHttpFailure,\n} from \"@gnu-taler/taler-util\";\nimport {\n HttpRequestLibrary,\n createPlatformHttpLib,\n} from \"@gnu-taler/taler-util/http\";\n\nexport type TalerMailboxInstanceResultByMethod<\n prop extends keyof TalerMailboxInstanceHttpClient,\n> = ResultByMethod;\nexport type TalerMailboxInstanceErrorsByMethod<\n prop extends keyof TalerMailboxInstanceHttpClient,\n> = FailCasesByMethod;\n\nexport interface MailboxMessagesResponseRaw {\n messages: Uint8Array;\n etag: string;\n}\n\n/**\n * Protocol version spoken with the service.\n *\n * Endpoint must be ordered in the same way that in the docs\n * Response code (http and taler) must have the same order that in the docs\n * That way is easier to see changes\n *\n * Uses libtool's current:revision:age versioning.\n */\nexport class TalerMailboxInstanceHttpClient {\n public static readonly PROTOCOL_VERSION = \"1:0:0\";\n\n readonly httpLib: HttpRequestLibrary;\n readonly cancellationToken: CancellationToken | undefined;\n\n constructor(\n readonly baseUrl: string,\n httpClient?: HttpRequestLibrary,\n cancellationToken?: CancellationToken,\n ) {\n this.httpLib = httpClient ?? createPlatformHttpLib();\n this.cancellationToken = cancellationToken;\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(\n TalerMailboxInstanceHttpClient.PROTOCOL_VERSION,\n version,\n );\n return compare?.compatible ?? false;\n }\n\n /**\n * https://docs.taler.net/core/api-mailbox.html#get--config\n */\n async getConfig(): Promise<\n | OperationOk\n | OperationFail\n > {\n const url = new URL(`/config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-mailbox\",\n TalerMailboxInstanceHttpClient.PROTOCOL_VERSION,\n resp,\n codecForTalerMailboxConfigResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-mailbox.html#post--$H_MAILBOX\n */\n async sendMessage(args: {\n h_address: string;\n body: Uint8Array;\n }): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n > {\n const { h_address: hAddress, body } = args;\n const url = new URL(`${hAddress.toUpperCase()}`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n cancellationToken: this.cancellationToken,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n return opEmptySuccess();\n }\n case HttpStatusCode.PaymentRequired: {\n return opKnownHttpFailure(resp.status, resp);\n }\n case HttpStatusCode.Forbidden: {\n return opKnownHttpFailure(resp.status, resp);\n }\n case HttpStatusCode.TooManyRequests: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForTalerMailboxRateLimitedResponse(),\n );\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-mailbox.html#get--$H_MAILBOX\n */\n async getMessages(args: {\n hMailbox: string;\n }): Promise<\n | OperationOk\n | OperationFail\n > {\n const { hMailbox: hMailbox } = args;\n const url = new URL(`${hMailbox.toUpperCase()}`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n cancellationToken: this.cancellationToken,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n const uintar = (await resp.bytes()) as Uint8Array;\n const etag = resp.headers.get(\"etag\");\n const index = etag ? etag : \"0\";\n return opFixedSuccess({ messages: uintar, etag: index });\n }\n case HttpStatusCode.NoContent: {\n const etag = resp.headers.get(\"etag\");\n const index = etag ? etag : \"0\";\n return opFixedSuccess({ messages: new Uint8Array(), etag: index });\n }\n case HttpStatusCode.TooManyRequests: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForTalerMailboxRateLimitedResponse(),\n );\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-mailbox.html#delete--$ADDRESS\n */\n async deleteMessages(args: {\n mailboxConf: MailboxConfiguration;\n matchIf: string;\n count: number;\n signature: EddsaSignatureString;\n }): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n > {\n const {\n mailboxConf,\n matchIf: etag,\n count: count,\n signature: signature,\n } = args;\n const mailboxPubkeyString = encodeCrock(\n eddsaGetPublic(decodeCrock(mailboxConf.privateKey)),\n );\n const url = new URL(\n `${mailboxPubkeyString.toUpperCase()}?count=${count}`,\n this.baseUrl,\n );\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers: {\n \"If-Match\": etag,\n \"Taler-Mailbox-Delete-Signature\": signature,\n },\n cancellationToken: this.cancellationToken,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n return opEmptySuccess();\n }\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-mailbox.html#get--info-$H_MAILBOX\n */\n async getMailboxInfo(\n hMailbox: string,\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n > {\n const url = new URL(`info/${hMailbox.toUpperCase()}`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n cancellationToken: this.cancellationToken,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n return opSuccessFromHttp(resp, codecForTalerMailboxMetadata());\n }\n case HttpStatusCode.NotFound: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForEmptyObject(),\n );\n }\n case HttpStatusCode.TooManyRequests: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForTalerMailboxRateLimitedResponse(),\n );\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-mailbox.html#post--register\n */\n async registerMailbox(\n req: MailboxRegisterRequest,\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationAlternative<\n HttpStatusCode.PaymentRequired,\n MailboxRegisterResult\n >\n > {\n const url = new URL(`register`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body: req,\n cancellationToken: this.cancellationToken,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n return opFixedSuccess({ status: \"ok\" } as MailboxRegisterResult);\n }\n case HttpStatusCode.Forbidden: {\n return opKnownHttpFailure(resp.status, resp);\n }\n case HttpStatusCode.PaymentRequired: {\n return {\n type: \"fail\",\n case: resp.status,\n body: {\n status: \"payment-required\",\n talerUri: resp.headers.get(\"Taler\"),\n } as MailboxRegisterResult,\n };\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AbsoluteTime,\n AccessToken,\n CancellationToken,\n ChallengeRequestResponse,\n ChallengeSolveRequest,\n Duration,\n FailCasesByMethod,\n HttpStatusCode,\n LibtoolVersion,\n LoginTokenRequest,\n MerchantPostDonauBody,\n OperationAlternative,\n OperationFail,\n OperationOk,\n PaginationParams,\n ResultByMethod,\n TalerErrorCode,\n TalerMerchantApi,\n TokenFamilyDetails,\n assertUnreachable,\n carefullyParseConfig,\n codecForAbortResponse,\n codecForAccountAddResponse,\n codecForAccountKycRedirects,\n codecForAccountsSummaryResponse,\n codecForBankAccountDetail,\n codecForCategoryListResponse,\n codecForCategoryProductList,\n codecForChallengeRequestResponse,\n codecForChallengeResponse,\n codecForClaimResponse,\n codecForExchangeStatusResponse,\n codecForExpectedTansferList,\n codecForExpectedTransferDetails,\n codecForFullInventoryDetailsResponse,\n codecForGetSessionStatusPaidResponse,\n codecForGroupAddedResponse,\n codecForGroupsSummaryResponse,\n codecForInstancesResponse,\n codecForInventorySummaryResponse,\n codecForLoginTokenSuccessResponse,\n codecForMerchantOrderPrivateStatusResponse,\n codecForMerchantRefundResponse,\n codecForMerchantStatisticsReportResponse,\n codecForOrderHistory,\n codecForOtpDeviceDetails,\n codecForOtpDeviceSummaryResponse,\n codecForOutOfStockResponse,\n codecForPaidRefundStatusResponse,\n codecForPaymentDeniedLegallyResponse,\n codecForPaymentResponse,\n codecForPostOrderResponse,\n codecForPotAddedResponse,\n codecForPotDetailResponse,\n codecForPotsSummaryResponse,\n codecForProductDetailResponse,\n codecForQueryInstancesResponse,\n codecForReportAddedResponse,\n codecForReportDetailResponse,\n codecForReportsSummaryResponse,\n codecForStatisticsAmountResponse,\n codecForStatisticsCounterResponse,\n codecForStatusGoto,\n codecForStatusPaid,\n codecForStatusStatusUnpaid,\n codecForTalerErrorDetail,\n codecForTalerMerchantConfigResponse,\n codecForTansferList,\n codecForTemplateDetails,\n codecForTemplateSummaryResponse,\n codecForTokenFamiliesList,\n codecForTokenFamilyDetails,\n codecForTokenInfoList,\n codecForWalletRefundResponse,\n codecForWalletTemplateDetails,\n codecForWebhookDetails,\n codecForWebhookSummaryResponse,\n opEmptySuccess,\n opFixedSuccess,\n opKnownAlternativeHttpFailure,\n opKnownFailure,\n opKnownFailureWithBody,\n opKnownHttpFailure,\n opKnownTalerFailure,\n opUnknownHttpFailure,\n} from \"@gnu-taler/taler-util\";\nimport {\n HttpRequestLibrary,\n HttpResponse,\n createPlatformHttpLib,\n readTalerErrorResponse,\n} from \"@gnu-taler/taler-util/http\";\nimport { opSuccessFromHttp } from \"../operation.js\";\nimport {\n CacheEvictor,\n addPaginationParams,\n authHeaders,\n makeBearerTokenAuthHeader,\n nullEvictor,\n} from \"./utils.js\";\n\nexport type TalerMerchantInstanceResultByMethod<\n prop extends keyof TalerMerchantInstanceHttpClient,\n> = ResultByMethod;\nexport type TalerMerchantInstanceErrorsByMethod<\n prop extends keyof TalerMerchantInstanceHttpClient,\n> = FailCasesByMethod;\n\n/**\n * FIXME: This should probably not be part of the core merchant HTTP client.\n */\nexport enum TalerMerchantInstanceCacheEviction {\n CREATE_ORDER,\n UPDATE_ORDER,\n DELETE_ORDER,\n UPDATE_CURRENT_INSTANCE,\n DELETE_CURRENT_INSTANCE,\n CREATE_BANK_ACCOUNT,\n UPDATE_BANK_ACCOUNT,\n DELETE_BANK_ACCOUNT,\n CREATE_PRODUCT,\n UPDATE_PRODUCT,\n DELETE_PRODUCT,\n CREATE_CATEGORY,\n UPDATE_CATEGORY,\n DELETE_CATEGORY,\n CREATE_TRANSFER,\n DELETE_TRANSFER,\n CREATE_DEVICE,\n UPDATE_DEVICE,\n DELETE_DEVICE,\n CREATE_TEMPLATE,\n UPDATE_TEMPLATE,\n DELETE_TEMPLATE,\n CREATE_WEBHOOK,\n UPDATE_WEBHOOK,\n DELETE_WEBHOOK,\n CREATE_TOKENFAMILY,\n UPDATE_TOKENFAMILY,\n DELETE_TOKENFAMILY,\n CREATE_ACCESSTOKEN,\n DELETE_ACCESSTOKEN,\n CREATE_REPORTS,\n UPDATE_REPORTS,\n DELETE_REPORTS,\n CREATE_POTS,\n UPDATE_POTS,\n DELETE_POTS,\n CREATE_GROUPS,\n UPDATE_GROUPS,\n DELETE_GROUPS,\n LAST,\n}\n\nexport enum TalerMerchantManagementCacheEviction {\n CREATE_INSTANCE = TalerMerchantInstanceCacheEviction.LAST + 1,\n UPDATE_INSTANCE,\n DELETE_INSTANCE,\n}\n\nexport interface MerchantKycStatusResult {\n kyc_data: TalerMerchantApi.MerchantAccountKycRedirect[];\n etag?: string;\n}\n\n/**\n * Protocol version spoken with the core bank.\n *\n * Endpoint must be ordered in the same way that in the docs\n * Response code (http and taler) must have the same order that in the docs\n * That way is easier to see changes\n *\n * Uses libtool's current:revision:age versioning.\n */\nexport class TalerMerchantInstanceHttpClient {\n public static readonly PROTOCOL_VERSION = \"25:0:2\";\n\n readonly httpLib: HttpRequestLibrary;\n readonly cacheEvictor: CacheEvictor;\n readonly cancellationToken: CancellationToken | undefined;\n\n constructor(\n readonly baseUrl: string,\n httpClient?: HttpRequestLibrary,\n cacheEvictor?: CacheEvictor,\n cancellationToken?: CancellationToken,\n ) {\n this.httpLib = httpClient ?? createPlatformHttpLib();\n this.cacheEvictor = cacheEvictor ?? nullEvictor;\n this.cancellationToken = cancellationToken;\n }\n\n static isCompatible(version: string): boolean {\n const compare = LibtoolVersion.compare(\n TalerMerchantInstanceHttpClient.PROTOCOL_VERSION,\n version,\n );\n return compare?.compatible ?? false;\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get--config\n */\n async getConfig() {\n const url = new URL(`config`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return carefullyParseConfig(\n \"taler-merchant\",\n TalerMerchantInstanceHttpClient.PROTOCOL_VERSION,\n resp,\n codecForTalerMerchantConfigResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get--exchanges\n */\n async listExchanges() {\n const url = new URL(`exchanges`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExchangeStatusResponse());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.InternalServerError:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Auth\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-token\n *\n */\n async createAccessToken(\n instance: string,\n password: string,\n body: LoginTokenRequest,\n params: {\n challengeIds?: string[];\n } = {},\n ): Promise<\n | OperationFail\n | OperationOk\n | OperationAlternative<\n HttpStatusCode.Accepted,\n TalerMerchantApi.ChallengeResponse\n >\n | OperationFail\n > {\n const url = new URL(`private/token`, this.baseUrl);\n const headers = authHeaders({\n type: \"basic\",\n username: instance,\n password,\n });\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers,\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_ACCESSTOKEN,\n );\n return opSuccessFromHttp(resp, codecForLoginTokenSuccessResponse());\n }\n case HttpStatusCode.Accepted: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n }\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-tokens\n *\n */\n async listAccessTokens(token: AccessToken, params: PaginationParams = {}) {\n const url = new URL(`private/tokens`, this.baseUrl);\n addPaginationParams(url, params);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers: {\n Authorization: makeBearerTokenAuthHeader(token),\n },\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTokenInfoList());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({ tokens: [] });\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-tokens-$SERIAL\n *\n */\n async deleteAccessToken(token: AccessToken, serial: number) {\n const url = new URL(`private/tokens/${String(serial)}`, this.baseUrl);\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_ACCESSTOKEN,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Wallet API\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-orders-$ORDER_ID-claim\n */\n async claimOrder(args: {\n orderId: string;\n body: TalerMerchantApi.ClaimRequest;\n }): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n > {\n const { orderId, body } = args;\n const url = new URL(`orders/${orderId}/claim`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n cancellationToken: this.cancellationToken,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_ORDER,\n );\n return opSuccessFromHttp(resp, codecForClaimResponse());\n }\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: {\n const body = await resp.json();\n const details = codecForTalerErrorDetail().decode(body);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_POST_ORDERS_ID_CLAIM_NOT_FOUND:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-orders-$ORDER_ID-pay\n */\n async makePayment(orderId: string, body: TalerMerchantApi.PayRequest) {\n const url = new URL(`orders/${orderId}/pay`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_ORDER,\n );\n return opSuccessFromHttp(resp, codecForPaymentResponse());\n }\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.PaymentRequired:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.RequestTimeout:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Gone:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.PreconditionFailed:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.BadGateway:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.GatewayTimeout:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.UnavailableForLegalReasons:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForPaymentDeniedLegallyResponse(),\n );\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-orders-$ORDER_ID\n */\n\n async getPaymentStatus(\n orderId: string,\n params: TalerMerchantApi.PaymentStatusRequestParams = {},\n ) {\n const url = new URL(`orders/${orderId}`, this.baseUrl);\n\n if (params.allowRefundedForRepurchase !== undefined) {\n url.searchParams.set(\n \"allow_refunded_for_repurchase\",\n params.allowRefundedForRepurchase ? \"YES\" : \"NO\",\n );\n }\n if (params.awaitRefundObtained !== undefined) {\n url.searchParams.set(\n \"await_refund_obtained\",\n params.allowRefundedForRepurchase ? \"YES\" : \"NO\",\n );\n }\n if (params.claimToken !== undefined) {\n url.searchParams.set(\"token\", params.claimToken);\n }\n if (params.contractTermHash !== undefined) {\n url.searchParams.set(\"h_contract\", params.contractTermHash);\n }\n if (params.refund !== undefined) {\n url.searchParams.set(\"refund\", params.refund);\n }\n if (params.sessionId !== undefined) {\n url.searchParams.set(\"session_id\", params.sessionId);\n }\n if (params.timeout !== undefined) {\n url.searchParams.set(\"timeout_ms\", String(params.timeout));\n }\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n // body,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForStatusPaid());\n case HttpStatusCode.Accepted:\n return opSuccessFromHttp(resp, codecForStatusGoto());\n // case HttpStatusCode.Found: not possible since content is not HTML\n case HttpStatusCode.PaymentRequired:\n return opSuccessFromHttp(resp, codecForStatusStatusUnpaid());\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotAcceptable:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-sessions-$SESSION_ID?fulfillment_url=$URL\n */\n async getOrderIdForSessionAndUrl(\n sessionId: string,\n fulfillmentUrl: string,\n params: {\n timeout?: number;\n } = {},\n ) {\n const url = new URL(`sessions/${sessionId}`, this.baseUrl);\n\n if (fulfillmentUrl !== undefined) {\n url.searchParams.set(\"fulfillment_url\", fulfillmentUrl);\n }\n if (params.timeout) {\n url.searchParams.set(\"timeout_ms\", String(params.timeout));\n }\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n const final = await opSuccessFromHttp(\n resp,\n codecForGetSessionStatusPaidResponse(),\n );\n return { paid: true, ...final };\n }\n case HttpStatusCode.Accepted: {\n const final = opSuccessFromHttp(\n resp,\n codecForGetSessionStatusPaidResponse(),\n );\n return { paid: false, ...final };\n }\n case HttpStatusCode.NotFound: {\n return opKnownHttpFailure(resp.status, resp);\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#demonstrating-payment\n */\n async demostratePayment(orderId: string, body: TalerMerchantApi.PaidRequest) {\n const url = new URL(`orders/${orderId}/paid`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_ORDER,\n );\n return opSuccessFromHttp(resp, codecForPaidRefundStatusResponse());\n }\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#aborting-incomplete-payments\n */\n async abortIncompletePayment(\n orderId: string,\n body: TalerMerchantApi.AbortRequest,\n ) {\n const url = new URL(`orders/${orderId}/abort`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_ORDER,\n );\n return opSuccessFromHttp(resp, codecForAbortResponse());\n }\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#obtaining-refunds\n */\n async obtainRefund(\n orderId: string,\n body: TalerMerchantApi.WalletRefundRequest,\n ) {\n const url = new URL(`orders/${orderId}/refund`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_ORDER,\n );\n return opSuccessFromHttp(resp, codecForWalletRefundResponse());\n }\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.UnavailableForLegalReasons:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForPaymentDeniedLegallyResponse(),\n );\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Management\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-auth\n */\n async updateCurrentInstanceAuthentication(\n token: AccessToken,\n body: TalerMerchantApi.InstanceAuthConfigurationMessage,\n params: {\n challengeIds?: string[];\n } = {},\n ) {\n const url = new URL(`private/auth`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: // FIXME: missing in docs\n return opEmptySuccess();\n case HttpStatusCode.Accepted: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n }\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private\n */\n async updateCurrentInstance(\n token: AccessToken,\n body: TalerMerchantApi.InstanceReconfigurationMessage,\n params: { challengeIds?: string[] } = {},\n ) {\n const url = new URL(`private`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_CURRENT_INSTANCE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Accepted: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private\n *\n */\n async getCurrentInstanceDetails(token: AccessToken | undefined) {\n const url = new URL(`private`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForQueryInstancesResponse());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private\n */\n async deleteCurrentInstance(\n token: AccessToken,\n params: { purge?: boolean; challengeIds?: string[] } = {},\n ) {\n const url = new URL(`private`, this.baseUrl);\n\n if (params.purge !== undefined) {\n url.searchParams.set(\"purge\", params.purge ? \"YES\" : \"NO\");\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_CURRENT_INSTANCE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-kyc\n */\n async getCurrentInstanceKycStatus(\n token: AccessToken,\n params: TalerMerchantApi.GetKycStatusRequestParams = {},\n ) {\n const url = new URL(`private/kyc`, this.baseUrl);\n\n if (params.wireHash) {\n url.searchParams.set(\"h_wire\", params.wireHash);\n }\n if (params.exchangeURL) {\n url.searchParams.set(\"exchange_url\", params.exchangeURL);\n }\n\n const headers: Record = {};\n if (params.longpoll) {\n switch (params.longpoll.type) {\n case \"state-enter\":\n url.searchParams.set(\"lp_status\", params.longpoll.status);\n break;\n case \"state-exit\":\n url.searchParams.set(\"lp_not_status\", params.longpoll.status);\n break;\n case \"state-change\":\n url.searchParams.set(\"lp_not_etag\", params.longpoll.etag);\n headers[\"If-none-match\"] = `\"${params.longpoll.etag}\"`;\n break;\n default:\n assertUnreachable(params.longpoll);\n }\n url.searchParams.set(\"timeout_ms\", String(params.longpoll.timeout));\n } else {\n // backward compat, prefer longpoll\n if (params.timeout) {\n url.searchParams.set(\"timeout_ms\", String(params.timeout));\n }\n if (params.reason) {\n url.searchParams.set(\"lpt\", String(params.reason));\n }\n }\n\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const cancellationToken = params.ct ?? this.cancellationToken;\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n cancellationToken,\n });\n const etag = resp.headers.get(\"etag\")?.replace(/\"/g, \"\");\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n const f = await opSuccessFromHttp(resp, codecForAccountKycRedirects());\n return opFixedSuccess({ etag, ...f.body });\n }\n case HttpStatusCode.NoContent:\n // FIXME: using opKnownHttpFailure is wrong here\n // we expect to read a body with the error description\n return opKnownFailure(resp.status);\n case HttpStatusCode.NotModified:\n return opKnownFailureWithBody(resp.status, { etag });\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.ServiceUnavailable:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.GatewayTimeout: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Bank Accounts\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-accounts\n */\n async addBankAccount(\n token: AccessToken,\n body: TalerMerchantApi.AccountAddDetails,\n params: {\n challengeIds?: string[];\n } = {},\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationAlternative<\n HttpStatusCode.Accepted,\n TalerMerchantApi.ChallengeResponse\n >\n | OperationFail\n | OperationFail\n > {\n const url = new URL(`private/accounts`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_BANK_ACCOUNT,\n );\n return opSuccessFromHttp(resp, codecForAccountAddResponse());\n }\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-accounts-$H_WIRE\n */\n async updateBankAccount(\n token: AccessToken,\n wireAccount: string,\n body: TalerMerchantApi.AccountPatchDetails,\n ) {\n const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_BANK_ACCOUNT,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-accounts\n */\n async listBankAccounts(token: AccessToken, params?: PaginationParams) {\n const url = new URL(`private/accounts`, this.baseUrl);\n\n // addPaginationParams(url, params);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForAccountsSummaryResponse());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-accounts-$H_WIRE\n */\n async getBankAccountDetails(token: AccessToken, wireAccount: string) {\n const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForBankAccountDetail());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-accounts-$H_WIRE\n */\n async deleteBankAccount(token: AccessToken, wireAccount: string) {\n const url = new URL(`private/accounts/${wireAccount}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_BANK_ACCOUNT,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Inventory Management\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-categories\n */\n async listCategories(token: AccessToken, params?: PaginationParams) {\n const url = new URL(`private/categories`, this.baseUrl);\n\n // addPaginationParams(url, params);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForCategoryListResponse());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-categories-$CATEGORY_ID\n */\n async getCategoryDetails(token: AccessToken, cId: string) {\n const url = new URL(`private/categories/${cId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForCategoryProductList());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-categories\n */\n async addCategory(\n token: AccessToken,\n body: TalerMerchantApi.CategoryCreateRequest,\n ) {\n const url = new URL(`private/categories`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_CATEGORY,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n // case HttpStatusCode.Conflict:\n // return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-categories\n */\n async updateCategory(\n token: AccessToken,\n cid: string,\n body: TalerMerchantApi.CategoryCreateRequest,\n ) {\n const url = new URL(`private/categories/${cid}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_CATEGORY,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n // case HttpStatusCode.Conflict:\n // return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-categories-$CATEGORY_ID\n */\n async deleteCategory(token: AccessToken, cId: string) {\n const url = new URL(`private/categories/${cId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_CATEGORY,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n // case HttpStatusCode.Conflict:\n // return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-products\n */\n async addProduct(\n token: AccessToken,\n body: TalerMerchantApi.ProductAddDetailRequest,\n ) {\n const url = new URL(`private/products`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_PRODUCT,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_GENERIC_PRODUCT_GROUP_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.MERCHANT_GENERIC_CATEGORY_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.MERCHANT_GENERIC_MONEY_POT_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.MERCHANT_GENERIC_INSTANCE_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-products-$PRODUCT_ID\n */\n async updateProduct(\n token: AccessToken,\n productId: string,\n body: TalerMerchantApi.ProductPatchDetailRequest,\n ) {\n const url = new URL(`private/products/${productId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_PRODUCT,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-products\n */\n async listProducts(\n token: AccessToken,\n params: PaginationParams & {\n category?: string;\n name?: string;\n description?: string;\n groupId?: number;\n } = {},\n ) {\n const url = new URL(`private/products`, this.baseUrl);\n\n addPaginationParams(url, params);\n if (params.category) {\n url.searchParams.set(\"category_filter\", params.category);\n }\n if (params.name) {\n url.searchParams.set(\"name_filter\", params.name);\n }\n if (params.description) {\n url.searchParams.set(\"description_filter\", params.description);\n }\n if (params.groupId !== undefined) {\n url.searchParams.set(\"product_group_serial\", String(params.groupId));\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForInventorySummaryResponse());\n case HttpStatusCode.Unauthorized: // FIXME: not in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-pos\n */\n async getPointOfSaleInventory(token: AccessToken | undefined) {\n const url = new URL(`private/pos`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForFullInventoryDetailsResponse());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-products-$PRODUCT_ID\n */\n async getProductDetails(token: AccessToken, productId: string) {\n const url = new URL(`private/products/${productId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForProductDetailResponse());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-products-$PRODUCT_ID-lock\n */\n async lockProduct(\n token: AccessToken,\n productId: string,\n body: TalerMerchantApi.LockRequest,\n ) {\n const url = new URL(`private/products/${productId}/lock`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_PRODUCT,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Gone:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-products-$PRODUCT_ID\n */\n async deleteProduct(\n token: AccessToken,\n productId: string,\n params: {\n force?: boolean;\n } = {},\n ) {\n const url = new URL(`private/products/${productId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n if (params.force) {\n url.searchParams.set(\"force\", \"yes\");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_PRODUCT,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Payment processing\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-orders\n */\n async createOrder(\n token: AccessToken,\n body: TalerMerchantApi.PostOrderRequest,\n ) {\n const url = new URL(`private/orders`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n return this.procesOrderCreationResponse(resp);\n }\n\n private async procesOrderCreationResponse(resp: HttpResponse) {\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_ORDER,\n );\n return opSuccessFromHttp(resp, codecForPostOrderResponse());\n }\n case HttpStatusCode.NotFound: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.UnavailableForLegalReasons:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForPaymentDeniedLegallyResponse(),\n );\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Gone:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForOutOfStockResponse(),\n );\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-orders\n */\n async listOrders(\n token: AccessToken,\n params: TalerMerchantApi.ListOrdersRequestParams = {},\n ) {\n const url = new URL(`private/orders`, this.baseUrl);\n\n if (params.paid !== undefined) {\n url.searchParams.set(\"paid\", params.paid ? \"YES\" : \"NO\");\n }\n if (params.refunded !== undefined) {\n url.searchParams.set(\"refunded\", params.refunded ? \"YES\" : \"NO\");\n }\n if (params.wired !== undefined) {\n url.searchParams.set(\"wired\", params.wired ? \"YES\" : \"NO\");\n }\n if (params.date && !AbsoluteTime.isNever(params.date)) {\n const time = AbsoluteTime.toProtocolTimestamp(params.date);\n url.searchParams.set(\"date_s\", String(time.t_s));\n }\n if (params.maxAge && !Duration.isForever(params.maxAge)) {\n const time = Duration.toTalerProtocolDuration(params.maxAge);\n url.searchParams.set(\"max_age\", String(time.d_us));\n }\n if (params.timeout) {\n url.searchParams.set(\"timeout_ms\", String(params.timeout));\n }\n if (params.sessionId) {\n url.searchParams.set(\"session_id\", params.sessionId);\n }\n if (params.fulfillmentUrl) {\n url.searchParams.set(\"fulfillment_url\", params.fulfillmentUrl);\n }\n if (params.summary) {\n url.searchParams.set(\"summary_filter\", params.summary);\n }\n addPaginationParams(url, params);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n\n const cancellationToken = params.ct ?? this.cancellationToken;\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n cancellationToken,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForOrderHistory());\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-orders\n */\n async listOrdersRaw(\n token: AccessToken,\n params: TalerMerchantApi.ListOrdersRequestParams & { mime: string },\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n > {\n const url = new URL(`private/orders`, this.baseUrl);\n\n if (params.paid !== undefined) {\n url.searchParams.set(\"paid\", params.paid ? \"YES\" : \"NO\");\n }\n if (params.refunded !== undefined) {\n url.searchParams.set(\"refunded\", params.refunded ? \"YES\" : \"NO\");\n }\n if (params.wired !== undefined) {\n url.searchParams.set(\"wired\", params.wired ? \"YES\" : \"NO\");\n }\n if (params.date && !AbsoluteTime.isNever(params.date)) {\n const time = AbsoluteTime.toProtocolTimestamp(params.date);\n url.searchParams.set(\"date_s\", String(time.t_s));\n }\n if (params.maxAge && !Duration.isForever(params.maxAge)) {\n const time = Duration.toTalerProtocolDuration(params.maxAge);\n url.searchParams.set(\"max_age\", String(time.d_us));\n }\n if (params.timeout) {\n url.searchParams.set(\"timeout_ms\", String(params.timeout));\n }\n if (params.sessionId) {\n url.searchParams.set(\"session_id\", params.sessionId);\n }\n if (params.fulfillmentUrl) {\n url.searchParams.set(\"fulfillment_url\", params.fulfillmentUrl);\n }\n if (params.summary) {\n url.searchParams.set(\"summary_filter\", params.summary);\n }\n addPaginationParams(url, params);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n headers[\"Accept\"] = params.mime;\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opFixedSuccess(new Uint8Array(await resp.bytes()));\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-orders-$ORDER_ID\n */\n async getOrderDetails(\n token: AccessToken,\n orderId: string,\n params: TalerMerchantApi.GetOrderRequestParams = {},\n ) {\n const url = new URL(`private/orders/${orderId}`, this.baseUrl);\n\n if (params.allowRefundedForRepurchase !== undefined) {\n url.searchParams.set(\n \"allow_refunded_for_repurchase\",\n params.allowRefundedForRepurchase ? \"YES\" : \"NO\",\n );\n }\n if (params.sessionId) {\n url.searchParams.set(\"session_id\", params.sessionId);\n }\n if (params.timeout) {\n url.searchParams.set(\"timeout_ms\", String(params.timeout));\n }\n\n const headers: Record = {};\n if (params.longpoll) {\n url.searchParams.set(\"lp_not_etag\", params.longpoll.etag);\n headers[\"If-none-match\"] = `\"${params.longpoll.etag}\"`;\n url.searchParams.set(\"timeout_ms\", String(params.longpoll.timeout));\n } else {\n // backward compat, prefer longpoll\n if (params.timeout) {\n url.searchParams.set(\"timeout_ms\", String(params.timeout));\n }\n }\n\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const cancellationToken = params.ct ?? this.cancellationToken;\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n cancellationToken,\n });\n const etag = resp.headers.get(\"etag\")?.replace(/\"/g, \"\");\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n const f = await opSuccessFromHttp(\n resp,\n codecForMerchantOrderPrivateStatusResponse(),\n );\n return opFixedSuccess({ etag, ...f.body });\n }\n case HttpStatusCode.NotFound: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_GENERIC_ORDER_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n case TalerErrorCode.MERCHANT_GENERIC_INSTANCE_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#private-order-data-cleanup\n */\n async forgetOrder(\n token: AccessToken,\n orderId: string,\n body: TalerMerchantApi.ForgetRequest,\n ) {\n const url = new URL(`private/orders/${orderId}/forget`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_ORDER,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.BadRequest:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-orders-$ORDER_ID\n */\n async deleteOrder(\n token: AccessToken,\n orderId: string,\n force: boolean = false,\n ) {\n const url = new URL(`private/orders/${orderId}`, this.baseUrl);\n if (force) {\n url.searchParams.set(\"force\", \"yes\");\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_ORDER,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Refunds\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-orders-$ORDER_ID-refund\n */\n async addRefund(\n token: AccessToken,\n orderId: string,\n body: TalerMerchantApi.RefundRequest,\n ) {\n const url = new URL(`private/orders/${orderId}/refund`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_ORDER,\n );\n return opSuccessFromHttp(resp, codecForMerchantRefundResponse());\n }\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Gone:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.UnavailableForLegalReasons:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForPaymentDeniedLegallyResponse(),\n );\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Wire Transfer\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-transfers\n */\n async informWireTransfer(\n token: AccessToken,\n body: TalerMerchantApi.TransferInformation,\n ) {\n const url = new URL(`private/transfers`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_TRANSFER,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-transfers\n */\n async listConfirmedWireTransfers(\n token: AccessToken,\n params: TalerMerchantApi.ListConfirmedWireTransferRequestParams = {},\n ) {\n const url = new URL(`private/transfers`, this.baseUrl);\n\n if (params.paytoURI) {\n url.searchParams.set(\"payto_uri\", params.paytoURI);\n }\n if (params.before) {\n url.searchParams.set(\"before\", String(params.before));\n }\n if (params.after) {\n url.searchParams.set(\"after\", String(params.after));\n }\n if (params.expected !== undefined) {\n url.searchParams.set(\"expected\", params.expected ? \"YES\" : \"NO\");\n }\n addPaginationParams(url, params);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTansferList());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-incoming\n */\n async listIncomingWireTransfers(\n token: AccessToken,\n params: TalerMerchantApi.ListIncomingWireTransferRequestParams = {},\n ) {\n const url = new URL(`private/incoming`, this.baseUrl);\n\n if (params.paytoURI) {\n url.searchParams.set(\"payto_uri\", params.paytoURI);\n }\n if (params.before) {\n url.searchParams.set(\"before\", String(params.before));\n }\n if (params.after) {\n url.searchParams.set(\"after\", String(params.after));\n }\n if (params.verified !== undefined) {\n url.searchParams.set(\"verified\", params.verified ? \"YES\" : \"NO\");\n }\n if (params.confirmed !== undefined) {\n url.searchParams.set(\"confirmed\", params.confirmed ? \"YES\" : \"NO\");\n }\n addPaginationParams(url, params);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExpectedTansferList());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-incoming-$ID\n */\n async getIncomingWireTransfersDetails(\n token: AccessToken,\n serial_wid: number,\n ) {\n const url = new URL(`private/incoming/${String(serial_wid)}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForExpectedTransferDetails());\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // /**\n // * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-transfers-$TID\n // * @deprecated\n // */\n // async deleteWireTransfer(token: AccessToken, transferId: string) {\n // const url = new URL(`private/transfers/${transferId}`, this.baseUrl);\n\n // const headers: Record = {};\n // if (token) {\n // headers.Authorization = makeBearerTokenAuthHeader(token);\n // }\n // const resp = await this.httpLib.fetch(url.href, {\n // method: \"DELETE\",\n // headers,\n // });\n\n // switch (resp.status) {\n // case HttpStatusCode.NoContent: {\n // this.cacheEvictor.notifySuccess(\n // TalerMerchantInstanceCacheEviction.DELETE_TRANSFER,\n // );\n // return opEmptySuccess();\n // }\n // case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n // return opKnownHttpFailure(resp.status, resp);\n // case HttpStatusCode.NotFound:\n // return opKnownHttpFailure(resp.status, resp);\n // case HttpStatusCode.Conflict:\n // return opKnownHttpFailure(resp.status, resp);\n // default:\n // return opUnknownHttpFailure(resp);\n // }\n // }\n\n //\n // OTP Devices\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-otp-devices\n */\n async addOtpDevice(\n token: AccessToken,\n body: TalerMerchantApi.OtpDeviceAddDetails,\n ) {\n const url = new URL(`private/otp-devices`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_DEVICE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID\n */\n async updateOtpDevice(\n token: AccessToken,\n deviceId: string,\n body: TalerMerchantApi.OtpDevicePatchDetails,\n ) {\n const url = new URL(`private/otp-devices/${deviceId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_DEVICE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-otp-devices\n */\n async listOtpDevices(token: AccessToken, params?: PaginationParams) {\n const url = new URL(`private/otp-devices`, this.baseUrl);\n\n addPaginationParams(url, params);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForOtpDeviceSummaryResponse());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID\n */\n async getOtpDeviceDetails(\n token: AccessToken,\n deviceId: string,\n params: TalerMerchantApi.GetOtpDeviceRequestParams = {},\n ) {\n const url = new URL(`private/otp-devices/${deviceId}`, this.baseUrl);\n\n if (params.faketime) {\n url.searchParams.set(\"faketime\", String(params.faketime));\n }\n if (params.price) {\n url.searchParams.set(\"price\", params.price);\n }\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForOtpDeviceDetails());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-otp-devices-$DEVICE_ID\n */\n async deleteOtpDevice(token: AccessToken, deviceId: string) {\n const url = new URL(`private/otp-devices/${deviceId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_DEVICE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Templates\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-templates\n */\n async addTemplate(\n token: AccessToken,\n body: TalerMerchantApi.TemplateAddDetails,\n ) {\n const url = new URL(`private/templates`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_TEMPLATE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID\n */\n async updateTemplate(\n token: AccessToken,\n templateId: string,\n body: TalerMerchantApi.TemplatePatchDetails,\n ) {\n const url = new URL(`private/templates/${templateId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_TEMPLATE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#inspecting-template\n */\n async listTemplates(token: AccessToken, params?: PaginationParams) {\n const url = new URL(`private/templates`, this.baseUrl);\n\n addPaginationParams(url, params);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTemplateSummaryResponse());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID\n */\n async getTemplateDetails(token: AccessToken, templateId: string) {\n const url = new URL(`private/templates/${templateId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTemplateDetails());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-templates-$TEMPLATE_ID\n */\n async deleteTemplate(token: AccessToken, templateId: string) {\n const url = new URL(`private/templates/${templateId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_TEMPLATE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCE]-templates-$TEMPLATE_ID\n */\n async useTemplateGetInfo(templateId: string) {\n const url = new URL(`templates/${templateId}`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForWalletTemplateDetails());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-templates-$TEMPLATE_ID\n */\n async useTemplateCreateOrder(\n templateId: string,\n body: TalerMerchantApi.UsingTemplateDetailsRequest,\n ) {\n const url = new URL(`templates/${templateId}`, this.baseUrl);\n\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n\n return this.procesOrderCreationResponse(resp);\n }\n\n //\n // Webhooks\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-webhooks\n */\n async addWebhook(\n token: AccessToken,\n body: TalerMerchantApi.WebhookAddDetails,\n ) {\n const url = new URL(`private/webhooks`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_WEBHOOK,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID\n */\n async updateWebhook(\n token: AccessToken,\n webhookId: string,\n body: TalerMerchantApi.WebhookPatchDetails,\n ) {\n const url = new URL(`private/webhooks/${webhookId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_WEBHOOK,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-webhooks\n */\n async listWebhooks(token: AccessToken, params?: PaginationParams) {\n const url = new URL(`private/webhooks`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForWebhookSummaryResponse());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID\n */\n async getWebhookDetails(token: AccessToken, webhookId: string) {\n const url = new URL(`private/webhooks/${webhookId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForWebhookDetails());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-webhooks-$WEBHOOK_ID\n */\n async deleteWebhook(token: AccessToken, webhookId: string) {\n const url = new URL(`private/webhooks/${webhookId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_WEBHOOK,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // token families\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-tokenfamilies\n */\n async createTokenFamily(\n token: AccessToken,\n body: TalerMerchantApi.TokenFamilyCreateRequest,\n ) {\n const url = new URL(`private/tokenfamilies`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_TOKENFAMILY,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG\n */\n async updateTokenFamily(\n token: AccessToken,\n tokenSlug: string,\n body: TalerMerchantApi.TokenFamilyUpdateRequest,\n ): Promise<\n | OperationOk\n | OperationOk\n | OperationFail\n | OperationFail\n > {\n const url = new URL(`private/tokenfamilies/${tokenSlug}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_TOKENFAMILY,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_TOKENFAMILY,\n );\n return opSuccessFromHttp(resp, codecForTokenFamilyDetails());\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-tokenfamilies\n */\n async listTokenFamilies(token: AccessToken, params?: PaginationParams) {\n const url = new URL(`private/tokenfamilies`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTokenFamiliesList());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG\n */\n async getTokenFamilyDetails(token: AccessToken, tokenSlug: string) {\n const url = new URL(`private/tokenfamilies/${tokenSlug}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForTokenFamilyDetails());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-tokenfamilies-$TOKEN_FAMILY_SLUG\n */\n async deleteTokenFamily(token: AccessToken, tokenSlug: string) {\n const url = new URL(`private/tokenfamilies/${tokenSlug}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_TOKENFAMILY,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-challenge-$CHALLENGE_ID\n *\n */\n async sendChallenge(cid: string) {\n const url = new URL(`challenge/${cid}`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n // FIXME: this should be removed\n body: {},\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForChallengeRequestResponse());\n case HttpStatusCode.NoContent:\n return opFixedSuccess({});\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_TAN_CHALLENGE_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.Gone: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_TAN_CHALLENGE_SOLVED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.TooManyRequests: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_TAN_TOO_EARLY:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.BadGateway: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_TAN_MFA_HELPER_EXEC_FAILED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-challenge-$CHALLENGE_ID-confirm\n *\n */\n async confirmChallenge(cid: string, body: ChallengeSolveRequest) {\n const url = new URL(`challenge/${cid}/confirm`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_TAN_CHALLENGE_UNKNOWN:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.Conflict: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_TAN_CHALLENGE_FAILED:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n case HttpStatusCode.TooManyRequests: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_TAN_TOO_MANY_ATTEMPTS:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n /**\n * https://docs.taler.net/core/api-merchant.html#post--instances-$INSTANCE-forgot-password\n */\n async forgotPasswordSelfProvision(\n body: TalerMerchantApi.InstanceAuthConfigurationMessage,\n params: {\n challengeIds?: string[];\n } = {},\n ) {\n const url = new URL(`forgot-password`, this.baseUrl);\n\n const headers: Record = {};\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n return opEmptySuccess();\n }\n case HttpStatusCode.Accepted: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n }\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Forbidden:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized: {\n const details = await readTalerErrorResponse(resp);\n switch (details.code) {\n case TalerErrorCode.MERCHANT_GENERIC_MFA_MISSING:\n return opKnownTalerFailure(details.code, details);\n default:\n return opUnknownHttpFailure(resp, details);\n }\n }\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n async postDonau(args: {\n body: MerchantPostDonauBody;\n token?: AccessToken;\n }): Promise<\n OperationOk | OperationFail\n > {\n const headers: Record = {};\n if (args.token) {\n headers.Authorization = makeBearerTokenAuthHeader(args.token);\n }\n const url = new URL(`private/donau`, this.baseUrl);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n headers,\n body: args.body,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n case HttpStatusCode.Created:\n case HttpStatusCode.Ok: {\n return opEmptySuccess();\n }\n case HttpStatusCode.BadGateway:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Reports\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post--reports-$REPORT_ID\n */\n async generateReport(\n id: string,\n body: TalerMerchantApi.ReportGenerationRequest,\n ) {\n const url = new URL(`reports/${id}`, this.baseUrl);\n\n const headers: Record = {};\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n return opEmptySuccess();\n }\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-reports\n */\n async createScheduledReport(\n token: AccessToken,\n body: TalerMerchantApi.ReportAddRequest,\n ) {\n const url = new URL(`private/reports`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_REPORTS,\n );\n return opSuccessFromHttp(resp, codecForReportAddedResponse());\n }\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-reports-$REPORT_ID\n */\n async updateScheduledReport(\n token: AccessToken,\n id: string,\n body: TalerMerchantApi.ReportAddRequest,\n ) {\n const url = new URL(`private/reports/${id}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_REPORTS,\n );\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-reports\n */\n async listScheduledReports(\n token: AccessToken,\n params: PaginationParams = {},\n ) {\n const url = new URL(`private/reports`, this.baseUrl);\n addPaginationParams(url, params);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForReportsSummaryResponse());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-reports-$REPORT_SERIAL\n */\n async getScheduledReportDetails(token: AccessToken, id: string) {\n const url = new URL(`private/reports/${id}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForReportDetailResponse());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-reports-$REPORT_SERIAL\n */\n async deleteScheduledReport(token: AccessToken, serial: string) {\n const url = new URL(`private/reports/${serial}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_REPORTS,\n );\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Money Pots\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-pots\n */\n async createMoneyPot(\n token: AccessToken,\n body: TalerMerchantApi.PotAddRequest,\n ) {\n const url = new URL(`private/pots`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_POTS,\n );\n return opSuccessFromHttp(resp, codecForPotAddedResponse());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-pots-$POT_ID\n */\n async updateMoneyPot(\n token: AccessToken,\n id: string,\n body: TalerMerchantApi.PotModifyRequest,\n ) {\n const url = new URL(`private/pots/${id}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_POTS,\n );\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-pots\n */\n async listMoneyPots(token: AccessToken, params: PaginationParams = {}) {\n const url = new URL(`private/pots`, this.baseUrl);\n addPaginationParams(url, params);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForPotsSummaryResponse());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-pots-$POT_SERIAL\n */\n async getMoneyPotDetails(token: AccessToken, id: string) {\n const url = new URL(`private/pots/${id}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForPotDetailResponse());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-pots-$POT_SERIAL\n */\n async deleteMoneyPot(token: AccessToken, serial: string) {\n const url = new URL(`private/pots/${serial}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_POTS,\n );\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n //\n // Product groups\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCES]-private-groups\n */\n async createProductGroup(\n token: AccessToken,\n body: TalerMerchantApi.GroupAddRequest,\n ) {\n const url = new URL(`private/groups`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_GROUPS,\n );\n return opSuccessFromHttp(resp, codecForGroupAddedResponse());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch-[-instances-$INSTANCES]-private-groups-$GROUP_ID\n */\n async updateProductGroup(\n token: AccessToken,\n id: string,\n body: TalerMerchantApi.GroupAddRequest,\n ) {\n const url = new URL(`private/reports/${id}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.UPDATE_GROUPS,\n );\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get-[-instances-$INSTANCES]-private-groups\n */\n async listProductGroups(token: AccessToken, params: PaginationParams = {}) {\n const url = new URL(`private/groups`, this.baseUrl);\n addPaginationParams(url, params);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForGroupsSummaryResponse());\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCES]-private-groups-$GROUP_SERIAL\n */\n async deleteProductGroup(token: AccessToken, serial: string) {\n const url = new URL(`private/groups/${serial}`, this.baseUrl);\n\n const headers: Record = {};\n headers.Authorization = makeBearerTokenAuthHeader(token);\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent:\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.DELETE_GROUPS,\n );\n\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * Get the auth api against the current instance\n *\n * https://docs.taler.net/core/api-merchant.html#post-[-instances-$INSTANCE]-private-token\n * https://docs.taler.net/core/api-merchant.html#delete-[-instances-$INSTANCE]-private-token\n */\n getAuthenticationAPI(): URL {\n return new URL(`private/`, this.baseUrl);\n }\n}\n\nexport type TalerMerchantManagementResultByMethod<\n prop extends keyof TalerMerchantManagementHttpClient,\n> = ResultByMethod;\nexport type TalerMerchantManagementErrorsByMethod<\n prop extends keyof TalerMerchantManagementHttpClient,\n> = FailCasesByMethod;\n\nexport class TalerMerchantManagementHttpClient extends TalerMerchantInstanceHttpClient {\n readonly cacheManagementEvictor: CacheEvictor<\n TalerMerchantInstanceCacheEviction | TalerMerchantManagementCacheEviction\n >;\n constructor(\n readonly baseUrl: string,\n httpClient?: HttpRequestLibrary,\n // cacheManagementEvictor?: CacheEvictor,\n cacheEvictor?: CacheEvictor<\n TalerMerchantInstanceCacheEviction | TalerMerchantManagementCacheEviction\n >,\n cancellationToken?: CancellationToken,\n ) {\n super(baseUrl, httpClient, cacheEvictor, cancellationToken);\n this.cacheManagementEvictor = cacheEvictor ?? nullEvictor;\n }\n\n getSubInstanceAPI(instanceId: string): string {\n return new URL(`instances/${instanceId}/`, this.baseUrl).href;\n }\n\n //\n // Instance Management\n //\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post--instances\n */\n async createInstanceSelfProvision(\n body: TalerMerchantApi.InstanceConfigurationMessage,\n params: {\n tokenValidity?: Duration;\n challengeIds?: string[];\n } = {},\n ) {\n const url = new URL(`instances`, this.baseUrl);\n\n const headers: Record = {};\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n if (params.tokenValidity) {\n url.searchParams.append(\n \"token_validity_ms\",\n String(params.tokenValidity.d_ms),\n );\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok: {\n this.cacheManagementEvictor.notifySuccess(\n TalerMerchantManagementCacheEviction.CREATE_INSTANCE,\n );\n this.cacheEvictor.notifySuccess(\n TalerMerchantInstanceCacheEviction.CREATE_ACCESSTOKEN,\n );\n return opSuccessFromHttp(resp, codecForLoginTokenSuccessResponse());\n }\n case HttpStatusCode.NoContent: {\n this.cacheManagementEvictor.notifySuccess(\n TalerMerchantManagementCacheEviction.CREATE_INSTANCE,\n );\n return opFixedSuccess(undefined);\n }\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post--management-instances\n */\n async createInstance(\n token: AccessToken | undefined,\n body: TalerMerchantApi.InstanceConfigurationMessage,\n params: {\n challengeIds?: string[];\n } = {},\n ) {\n const url = new URL(`management/instances`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheManagementEvictor.notifySuccess(\n TalerMerchantManagementCacheEviction.CREATE_INSTANCE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#post--management-instances-$INSTANCE-auth\n */\n async updateInstanceAuthentication(\n token: AccessToken,\n instanceId: string,\n body: TalerMerchantApi.InstanceAuthConfigurationMessage,\n params: {\n challengeIds?: string[];\n } = {},\n ) {\n const url = new URL(\n `management/instances/${instanceId}/auth`,\n this.baseUrl,\n );\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"POST\",\n body,\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Accepted:\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#patch--management-instances-$INSTANCE\n */\n async updateInstance(\n token: AccessToken,\n instanceId: string,\n body: TalerMerchantApi.InstanceReconfigurationMessage,\n ) {\n const url = new URL(`management/instances/${instanceId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"PATCH\",\n body,\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheManagementEvictor.notifySuccess(\n TalerMerchantManagementCacheEviction.UPDATE_INSTANCE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get--management-instances\n */\n async listInstances(token: AccessToken, params?: PaginationParams) {\n const url = new URL(`management/instances`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForInstancesResponse());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE\n *\n */\n async getInstanceDetails(token: AccessToken, instanceId: string) {\n const url = new URL(`management/instances/${instanceId}`, this.baseUrl);\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForQueryInstancesResponse());\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#delete--management-instances-$INSTANCE\n */\n async deleteInstance(\n token: AccessToken,\n instanceId: string,\n params: { purge?: boolean; challengeIds?: string[] } = {},\n ) {\n const url = new URL(`management/instances/${instanceId}`, this.baseUrl);\n\n if (params.purge !== undefined) {\n url.searchParams.set(\"purge\", params.purge ? \"YES\" : \"NO\");\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n if (params.challengeIds && params.challengeIds.length > 0) {\n headers[\"Taler-Challenge-Ids\"] = params.challengeIds.join(\", \");\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"DELETE\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.NoContent: {\n this.cacheManagementEvictor.notifySuccess(\n TalerMerchantManagementCacheEviction.DELETE_INSTANCE,\n );\n return opEmptySuccess();\n }\n case HttpStatusCode.Accepted: {\n return opKnownAlternativeHttpFailure(\n resp,\n resp.status,\n codecForChallengeResponse(),\n );\n }\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE-kyc\n */\n async getIntanceKycStatus(\n token: AccessToken,\n instanceId: string,\n params: TalerMerchantApi.GetKycStatusRequestParams,\n ) {\n const url = new URL(`management/instances/${instanceId}/kyc`, this.baseUrl);\n\n if (params.wireHash) {\n url.searchParams.set(\"h_wire\", params.wireHash);\n }\n if (params.exchangeURL) {\n url.searchParams.set(\"exchange_url\", params.exchangeURL);\n }\n if (params.timeout) {\n url.searchParams.set(\"timeout_ms\", String(params.timeout));\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Accepted:\n return opSuccessFromHttp(resp, codecForAccountKycRedirects());\n case HttpStatusCode.NoContent:\n return opEmptySuccess();\n case HttpStatusCode.NotFound:\n return opEmptySuccess();\n case HttpStatusCode.Unauthorized: // FIXME: missing in docs\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.BadGateway:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.ServiceUnavailable:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Conflict:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE-statistics-counter-$SLUG\n */\n async getStatisticsCounter(\n token: AccessToken,\n statSlug: string,\n params: TalerMerchantApi.GetStatisticsRequestParams = {},\n ) {\n const url = new URL(`private/statistics-counter/${statSlug}`, this.baseUrl);\n\n if (params.by) {\n url.searchParams.set(\"by\", params.by);\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForStatisticsCounterResponse());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.BadGateway:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.ServiceUnavailable:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n /**\n * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE-statistics-amount-$SLUG\n */\n async getStatisticsAmount(\n token: AccessToken,\n statSlug: string,\n params: TalerMerchantApi.GetStatisticsRequestParams = {},\n ) {\n const url = new URL(`private/statistics-amount/${statSlug}`, this.baseUrl);\n\n if (params.by) {\n url.searchParams.set(\"by\", params.by);\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(resp, codecForStatisticsAmountResponse());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.BadGateway:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.ServiceUnavailable:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // FIXME: This should not go into the management API, but\n // the instance API.\n /**\n * https://docs.taler.net/core/api-merchant.html#get--management-instances-$INSTANCE-statistics-report-$NAME\n */\n async getStatisticsReport(\n token: AccessToken,\n name: \"transactions\" | \"money-pots\" | \"taxes\" | \"sales-funnel\",\n params: TalerMerchantApi.GetStatisticsReportParams = {},\n ): Promise<\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationOk\n | OperationFail\n > {\n const url = new URL(`private/statistics-report/${name}`, this.baseUrl);\n\n if (params.count !== undefined) {\n url.searchParams.set(\"count\", String(params.count));\n }\n if (params.granularity) {\n url.searchParams.set(\"granularity\", params.granularity);\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opSuccessFromHttp(\n resp,\n codecForMerchantStatisticsReportResponse(),\n );\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Gone:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n\n // FIXME: This should not go into the management API, but\n // the instance API.\n async getStatisticsReportPdf(\n token: AccessToken,\n name: \"transactions\" | \"money-pots\" | \"taxes\" | \"sales-funnel\",\n params: TalerMerchantApi.GetStatisticsReportParams = {},\n ): Promise<\n | OperationOk\n | OperationFail\n | OperationFail\n | OperationFail\n | OperationFail\n > {\n const url = new URL(`private/statistics-report/${name}`, this.baseUrl);\n\n if (params.count !== undefined) {\n url.searchParams.set(\"count\", String(params.count));\n }\n if (params.granularity) {\n url.searchParams.set(\"granularity\", params.granularity);\n }\n\n const headers: Record = {};\n if (token) {\n headers.Authorization = makeBearerTokenAuthHeader(token);\n }\n headers[\"Accept\"] = \"application/pdf\";\n const resp = await this.httpLib.fetch(url.href, {\n method: \"GET\",\n headers,\n });\n switch (resp.status) {\n case HttpStatusCode.Ok:\n return opFixedSuccess(await resp.bytes());\n case HttpStatusCode.NotFound:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Unauthorized:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.Gone:\n return opKnownHttpFailure(resp.status, resp);\n case HttpStatusCode.NotImplemented:\n return opKnownHttpFailure(resp.status, resp);\n default:\n return opUnknownHttpFailure(resp);\n }\n }\n}\n", "// @ts-ignore: no type decl for this library\nimport * as jedLib from \"jed\";\nimport { Logger } from \"./logging.js\";\n\nconst logger = new Logger(\"i18n/index.ts\");\n\nexport let jed: any = undefined;\n\n/**\n * Set up jed library for internationalization,\n * based on browser language settings.\n */\nexport function setupI18n(lang: string, strings: { [s: string]: any }): void {\n lang = lang.replace(\"_\", \"-\");\n\n if (!strings[lang]) {\n strings[lang] = {};\n // logger.warn(`language ${lang} not found, defaulting to source strings`);\n }\n jed = new jedLib.Jed(strings[lang]);\n}\n\n/**\n * Use different translations for testing. Should not be used outside\n * of test cases.\n */\nexport function internalSetStrings(langStrings: any): void {\n jed = new jedLib.Jed(langStrings);\n}\n\ndeclare const __translated: unique symbol;\nexport type TranslatedString = string & { [__translated]: true };\nexport type ToTranslateString = string & { [__translated]: true };\n\n/**\n * Convert template strings to a msgid\n */\nfunction toI18nString(stringSeq: ReadonlyArray): TranslatedString {\n let s = \"\";\n for (let i = 0; i < stringSeq.length; i++) {\n s += stringSeq[i];\n if (i < stringSeq.length - 1) {\n s += `%${i + 1}$s`;\n }\n }\n return s as TranslatedString;\n}\n\n/**\n * Internationalize a string template with arbitrary serialized values.\n */\nexport function singular(\n stringSeq: TemplateStringsArray,\n ...values: any[]\n): TranslatedString {\n const s = toI18nString(stringSeq);\n // jed throws a Error when key is empty\n if (!s) return \"\" as TranslatedString;\n const tr = jed\n .translate(s)\n .ifPlural(1, s)\n .fetch(...values);\n return tr;\n}\n\nfunction withContext(ctx: string): typeof singular {\n return function (t: TemplateStringsArray, ...v: any[]): TranslatedString {\n const s = toI18nString(t);\n const tr = jed\n .translate(s)\n .withContext(ctx)\n .ifPlural(1, s)\n .fetch(...v);\n return tr;\n };\n}\n\n/**\n * Internationalize a string template without serializing\n */\nexport function translate(\n stringSeq: TemplateStringsArray,\n ...values: any[]\n): TranslatedString[] {\n const s = toI18nString(stringSeq);\n if (!s) return [];\n const translation: TranslatedString = jed.ngettext(s, s, 1);\n return replacePlaceholderWithValues(translation, values);\n}\n\n/**\n * Internationalize a string template without serializing\n */\nexport function Translate({\n children,\n debug,\n context: ctx,\n}: {\n children: any;\n debug?: boolean;\n context?: string;\n}): any {\n const c = [].concat(children);\n const s = stringifyArray(c);\n if (!s) return [];\n const translation: TranslatedString = ctx\n ? jed.npgettext(ctx, s, s, 1)\n : jed.ngettext(s, s, 1);\n if (debug) {\n console.log(\"looking for \", s, \"got\", translation);\n }\n return replacePlaceholderWithValues(translation, c);\n}\n\n/**\n * Get an internationalized string (based on the globally set, current language)\n * from a JSON object. Fall back to the default language of the JSON object\n * if no match exists.\n */\nexport function getJsonI18n(\n obj: Record,\n key: K,\n): string {\n return obj[key];\n}\n\nexport function getTranslatedArray(array: Array) {\n const s = stringifyArray(array);\n const translation: TranslatedString = jed.ngettext(s, s, 1);\n return replacePlaceholderWithValues(translation, array);\n}\n\nfunction replacePlaceholderWithValues(\n translation: TranslatedString,\n childArray: Array,\n): Array {\n const tr = translation.split(/%(\\d+)\\$s/);\n // const childArray = toChildArray(children);\n // Merge consecutive string children.\n const placeholderChildren = [];\n for (let i = 0; i < childArray.length; i++) {\n const x = childArray[i];\n if (x === undefined) {\n continue;\n } else if (typeof x === \"string\") {\n continue;\n } else {\n placeholderChildren.push(x);\n }\n }\n const result = [];\n for (let i = 0; i < tr.length; i++) {\n if (i % 2 == 0) {\n // Text\n result.push(tr[i]);\n } else {\n const childIdx = Number.parseInt(tr[i]) - 1;\n result.push(placeholderChildren[childIdx]);\n }\n }\n return result;\n}\n\nfunction stringifyArray(children: Array): string {\n let n = 1;\n const ss = children.map((c) => {\n if (typeof c === \"string\") {\n return c;\n }\n return `%${n++}$s`;\n });\n const s = ss.join(\"\").replace(/ +/g, \" \").trim();\n return s;\n}\n\nexport type InternationalizationAPI = typeof i18n;\nexport type Translator = (i18n: InternationalizationAPI) => TranslatedString;\n\nexport const i18n = {\n str: singular,\n ctx: withContext,\n singular,\n Translate,\n translate,\n};\n", "/*\n This file is part of GNU Taler\n (C) 2019 GNUnet e.V.\n\n TALER is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n TALER is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n TALER; see the file COPYING. If not, see \n */\n\n/**\n * An opened promise.\n *\n * @see {@link openPromise}\n */\nexport interface OpenedPromise {\n promise: Promise;\n resolve: (val: T) => void;\n reject: (err: any) => void;\n lastError?: any;\n}\n\n/**\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers\n *\n * Get an unresolved promise together with its extracted resolve / reject\n * function.\n *\n * Recent ECMAScript proposals also call this a promise capability.\n */\nexport function openPromise(): OpenedPromise {\n let resolve: ((x?: any) => void) | null = null;\n let promiseReject: ((reason?: any) => void) | null = null;\n const promise = new Promise((res, rej) => {\n resolve = res;\n promiseReject = rej;\n });\n if (!(resolve && promiseReject)) {\n // Never happens, unless JS implementation is broken\n throw Error(\"JS implementation is broken\");\n }\n const result: OpenedPromise = { resolve, reject: promiseReject, promise };\n function saveLastError(reason?: any) {\n result.lastError = reason;\n promiseReject!(reason);\n }\n result.reject = saveLastError;\n return result;\n}\n\nexport class AsyncCondition {\n private promCap?: OpenedPromise = undefined;\n constructor() {}\n\n wait(): Promise {\n if (!this.promCap) {\n this.promCap = openPromise();\n }\n return this.promCap.promise;\n }\n\n trigger(): void {\n if (this.promCap) {\n this.promCap.resolve();\n }\n this.promCap = undefined;\n }\n}\n\n/**\n * Flag that can be raised to notify asynchronous waiters.\n *\n * You can think of it as a promise that can\n * be un-resolved.\n */\nexport class AsyncFlag {\n private promCap?: OpenedPromise = undefined;\n private internalFlagRaised: boolean = false;\n\n constructor() {}\n\n /**\n * Wait until the flag is raised.\n *\n * Reset if before returning.\n */\n wait(): Promise {\n if (this.internalFlagRaised) {\n return Promise.resolve();\n }\n if (!this.promCap) {\n this.promCap = openPromise();\n }\n return this.promCap.promise;\n }\n\n raise(): void {\n this.internalFlagRaised = true;\n if (this.promCap) {\n this.promCap.resolve();\n }\n }\n\n reset(): void {\n this.internalFlagRaised = false;\n this.promCap = undefined;\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL3.0-or-later\n*/\n\nimport { CancellationToken } from \"./CancellationToken.js\";\nimport { Logger } from \"./logging.js\";\nimport { openPromise } from \"./promises.js\";\n\nconst logger = new Logger(\"longpoll-queue.ts\");\n\nconst PERMITS: number = 20;\ntype LongpollRunFn = (timeoutMs: number) => Promise;\n\nexport class LongpollQueue {\n private idCounter: number = 0;\n private queue: (() => void)[] = [];\n private permits: number = PERMITS;\n\n constructor() {}\n\n async run(\n url: URL,\n cancellationToken: CancellationToken,\n f: LongpollRunFn,\n ): Promise {\n const hostname = url.hostname;\n const rid = this.idCounter++;\n\n const triggerNextLongpoll = () => {\n logger.trace(`cleaning up after long-poll ${rid} to ${hostname}`);\n // Run pending task\n const next = this.queue.shift();\n if (next != null) {\n next();\n } else {\n // Else release permit\n this.permits++;\n }\n };\n\n const doRunLongpoll: () => Promise = async () => {\n const numWaiting = this.queue.length;\n const numConcurrent = PERMITS - this.permits;\n logger.info(\n `running long-poll ${rid} to ${hostname} with ${numWaiting} waiting and ${numConcurrent} running`,\n );\n try {\n const timeoutMs = Math.round(Math.max(10000, 30000 / (numWaiting + 1)));\n return await f(timeoutMs);\n } finally {\n triggerNextLongpoll();\n }\n };\n\n if (this.permits > 0) {\n this.permits--;\n return doRunLongpoll();\n } else {\n logger.info(`long-poll ${rid} to ${hostname} queued`);\n const promcap = openPromise();\n this.queue.push(promcap.resolve);\n try {\n await cancellationToken.racePromise(promcap.promise);\n } finally {\n logger.info(`long-poll ${rid} to ${hostname} cancelled while queued`);\n triggerNextLongpoll();\n }\n return doRunLongpoll();\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019-2023 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Type and schema definitions for notifications from the wallet to clients\n * of the wallet.\n */\n\n/**\n * Imports.\n */\nimport { AbsoluteTime } from \"./time.js\";\nimport { TransactionState } from \"./types-taler-wallet-transactions.js\";\nimport {\n ContactEntry,\n ExchangeEntryState,\n MailboxMessageRecord,\n TalerErrorDetail,\n TransactionIdStr,\n} from \"./types-taler-wallet.js\";\n\nexport enum NotificationType {\n BalanceChange = \"balance-change\",\n BankAccountChange = \"bank-account-change\",\n BackupOperationError = \"backup-error\",\n ContactAdded = \"contact-added\",\n ContactDeleted = \"contact-deleted\",\n MailboxMessageAdded = \"mailbox-message-added\",\n MailboxMessageDeleted = \"mailbox-message-deleted\",\n TransactionStateTransition = \"transaction-state-transition\",\n ExchangeStateTransition = \"exchange-state-transition\",\n Idle = \"idle\",\n TaskObservabilityEvent = \"task-observability-event\",\n RequestObservabilityEvent = \"request-observability-event\",\n}\n\nexport interface ErrorInfoSummary {\n code: number;\n hint?: string;\n message?: string;\n}\n\nexport interface TransactionStateTransitionNotification {\n type: NotificationType.TransactionStateTransition;\n\n /**\n * Identifier of the affected transaction.\n */\n transactionId: string;\n\n /**\n * State before the transition.\n */\n oldTxState: TransactionState;\n\n /**\n * State after the transition.\n */\n newTxState: TransactionState;\n\n /**\n * Internal ID of the new state.\n * Must not be used by the UI, only used for testing.\n */\n newStId: number;\n\n /**\n * Short summary of the error for an error transition.\n */\n errorInfo?: ErrorInfoSummary;\n\n /**\n * Additional \"user data\" that is dependent on the\n * state transition.\n *\n * Usage should be avoided.\n *\n * Currently used to notify the iOS app about\n * the KYC URL.\n */\n experimentalUserData?: any;\n}\n\nexport interface ExchangeStateTransitionNotification {\n type: NotificationType.ExchangeStateTransition;\n /**\n * Identification of the exchange entry that this\n * notification is about.\n */\n exchangeBaseUrl: string;\n\n /**\n * If missing, the notification means that\n * the exchange entry is newly created.\n */\n oldExchangeState?: ExchangeEntryState;\n\n /**\n * New state of the exchange.\n *\n * If missing, exchange got deleted.\n */\n newExchangeState?: ExchangeEntryState;\n\n /**\n * Summary of the error that occurred when trying to update the exchange entry,\n * if applicable.\n */\n errorInfo?: ErrorInfoSummary;\n}\n\n/**\n * Notification emitted when a contact is added\n */\nexport interface ContactAddedNotification {\n type: NotificationType.ContactAdded;\n\n /**\n * The contact that was added\n */\n contact: ContactEntry;\n}\n\n/**\n * Notification emitted when a contact is deleted\n */\nexport interface ContactDeletedNotification {\n type: NotificationType.ContactDeleted;\n\n /**\n * The contact that was deleted\n */\n contact: ContactEntry;\n}\n\n/**\n * Notification emitted when a mailbox message is added\n */\nexport interface MailboxMessageAddedNotification {\n type: NotificationType.MailboxMessageAdded;\n\n /**\n * The message that was added\n */\n message: MailboxMessageRecord;\n}\n\n/**\n * Notification emitted when a mailbox message is deleted\n */\nexport interface MailboxMessageDeletedNotification {\n type: NotificationType.MailboxMessageDeleted;\n\n /**\n * The message that was deleted\n */\n message: MailboxMessageRecord;\n}\n\n/**\n * Transaction emitted when a bank account changes.\n */\nexport interface BankAccountChangeNotification {\n type: NotificationType.BankAccountChange;\n\n /**\n * ID of the affected bank account.\n */\n bankAccountId: string;\n}\n\nexport interface BalanceChangeNotification {\n type: NotificationType.BalanceChange;\n\n /**\n * If set to true, the balance change is internal\n * to the wallet and not visible to the user.\n *\n * (For example when the material balance changes via a refresh, but\n * the available balance stays the same.)\n */\n isInternal?: boolean;\n\n /**\n * Transaction ID of the transaction that caused the balance update.\n *\n * Only used as a hint for debugging, should not be relied upon by clients.\n */\n hintTransactionId: string;\n}\n\nexport interface TaskProgressNotification {\n type: NotificationType.TaskObservabilityEvent;\n taskId: string;\n event: ObservabilityEvent;\n}\n\nexport interface RequestProgressNotification {\n type: NotificationType.RequestObservabilityEvent;\n requestId: string;\n operation: string;\n event: ObservabilityEvent;\n}\n\nexport enum ObservabilityEventType {\n HttpFetchStart = \"http-fetch-start\",\n HttpFetchFinishError = \"http-fetch-finish-error\",\n HttpFetchFinishSuccess = \"http-fetch-finish-success\",\n DbQueryStart = \"db-query-start\",\n DbQueryFinishSuccess = \"db-query-finish-success\",\n DbQueryFinishError = \"db-query-finish-error\",\n RequestStart = \"request-start\",\n RequestFinishSuccess = \"request-finish-success\",\n RequestFinishError = \"request-finish-error\",\n TaskStart = \"task-start\",\n TaskStop = \"task-stop\",\n TaskReset = \"task-reset\",\n ShepherdTaskResult = \"shepherd-task-result\",\n DeclareTaskDependency = \"declare-task-dependency\",\n CryptoStart = \"crypto-start\",\n CryptoFinishSuccess = \"crypto-finish-success\",\n CryptoFinishError = \"crypto-finish-error\",\n Message = \"message\",\n /**\n * Declare that an observability event is relevant to a particular transaction.\n * If emitted from a request/task, all past/future events for that request/task\n * should be shown for the transaction as well.\n */\n DeclareConcernsTransaction = \"declare-concerns-transaction\",\n}\n\nexport type ObservabilityEvent =\n | {\n id: string;\n when: AbsoluteTime;\n type: ObservabilityEventType.HttpFetchStart;\n url: string;\n longPolling: boolean;\n }\n | {\n id: string;\n when: AbsoluteTime;\n type: ObservabilityEventType.HttpFetchFinishSuccess;\n url: string;\n status: number;\n durationMs: number;\n longPolling: boolean;\n }\n | {\n id: string;\n when: AbsoluteTime;\n type: ObservabilityEventType.HttpFetchFinishError;\n url: string;\n error: TalerErrorDetail;\n durationMs: number;\n longPolling: boolean;\n }\n | {\n type: ObservabilityEventType.DbQueryStart;\n name: string;\n location: string;\n }\n | {\n type: ObservabilityEventType.DbQueryFinishSuccess;\n name: string;\n location: string;\n durationMs: number;\n }\n | {\n type: ObservabilityEventType.DbQueryFinishError;\n name: string;\n location: string;\n error: TalerErrorDetail;\n durationMs: number;\n }\n | {\n type: ObservabilityEventType.RequestStart;\n name: string;\n }\n | {\n type: ObservabilityEventType.RequestFinishSuccess;\n operation: string;\n requestId: string;\n durationMs: number;\n }\n | {\n type: ObservabilityEventType.RequestFinishError;\n operation: string;\n requestId: string;\n durationMs: number;\n }\n | {\n type: ObservabilityEventType.TaskStart;\n taskId: string;\n }\n | {\n type: ObservabilityEventType.TaskStop;\n taskId: string;\n }\n | {\n type: ObservabilityEventType.TaskReset;\n taskId: string;\n }\n | {\n type: ObservabilityEventType.DeclareTaskDependency;\n taskId: string;\n }\n | {\n type: ObservabilityEventType.CryptoStart;\n operation: string;\n }\n | {\n type: ObservabilityEventType.CryptoFinishSuccess;\n operation: string;\n durationMs: number;\n }\n | {\n type: ObservabilityEventType.CryptoFinishError;\n operation: string;\n durationMs: number;\n }\n | {\n type: ObservabilityEventType.ShepherdTaskResult;\n taskId: string;\n resultType: string;\n durationMs: number;\n }\n | {\n type: ObservabilityEventType.Message;\n contents: string;\n }\n | {\n type: ObservabilityEventType.DeclareConcernsTransaction;\n transactionId: TransactionIdStr;\n };\n\nexport interface BackupOperationErrorNotification {\n type: NotificationType.BackupOperationError;\n error: TalerErrorDetail;\n}\n\nexport interface IdleNotification {\n type: NotificationType.Idle;\n}\n\nexport type WalletNotification =\n | BalanceChangeNotification\n | BankAccountChangeNotification\n | BackupOperationErrorNotification\n | ContactAddedNotification\n | ContactDeletedNotification\n | MailboxMessageAddedNotification\n | MailboxMessageDeletedNotification\n | ExchangeStateTransitionNotification\n | TransactionStateTransitionNotification\n | TaskProgressNotification\n | RequestProgressNotification\n | IdleNotification;\n", "/*\n This file is part of GNU Taler\n (C) 2017-2019 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Cross-platform timers.\n *\n * NodeJS and the browser use slightly different timer API,\n * this abstracts over these differences.\n */\n\n/**\n * Imports.\n */\nimport { Logger, Duration } from \"@gnu-taler/taler-util\";\n\nconst logger = new Logger(\"timer.ts\");\n\n/**\n * Cancelable timer.\n */\nexport interface TimerHandle {\n clear(): void;\n\n /**\n * Make sure the event loop exits when the timer is the\n * only event left. Has no effect in the browser.\n */\n unref(): void;\n}\n\nclass IntervalHandle {\n constructor(public h: any) {}\n\n clear(): void {\n clearInterval(this.h);\n }\n\n /**\n * Make sure the event loop exits when the timer is the\n * only event left. Has no effect in the browser.\n */\n unref(): void {\n if (typeof this.h === \"object\" && \"unref\" in this.h) {\n this.h.unref();\n }\n }\n}\n\nclass TimeoutHandle {\n constructor(public h: any) {}\n\n clear(): void {\n clearTimeout(this.h);\n }\n\n /**\n * Make sure the event loop exits when the timer is the\n * only event left. Has no effect in the browser.\n */\n unref(): void {\n if (typeof this.h === \"object\" && \"unref\" in this.h) {\n this.h.unref();\n }\n }\n}\n\n/**\n * Get a performance counter in nanoseconds.\n */\nexport const performanceNow: () => bigint = (() => {\n // @ts-ignore\n if (typeof process !== \"undefined\" && process.hrtime) {\n return () => {\n return process.hrtime.bigint();\n };\n }\n\n // @ts-ignore\n if (typeof performance !== \"undefined\") {\n // @ts-ignore\n return () => BigInt(Math.floor(performance.now() * 1000)) * BigInt(1000);\n }\n\n return () => BigInt(new Date().getTime()) * BigInt(1000) * BigInt(1000);\n})();\n\nexport const performanceDelta = (start: bigint, end: bigint) =>\n Number((end - start) / 1000n / 1000n);\n\nconst nullTimerHandle = {\n clear() {\n // do nothing\n return;\n },\n unref() {\n // do nothing\n return;\n },\n};\n\n/**\n * Group of timers that can be destroyed at once.\n */\nexport interface TimerAPI {\n after(delayMs: number, callback: () => void): TimerHandle;\n every(delayMs: number, callback: () => void): TimerHandle;\n}\n\nexport class SetTimeoutTimerAPI implements TimerAPI {\n /**\n * Call a function every time the delay given in milliseconds passes.\n */\n every(delayMs: number, callback: () => void): TimerHandle {\n return new IntervalHandle(setInterval(callback, delayMs));\n }\n\n /**\n * Call a function after the delay given in milliseconds passes.\n */\n after(delayMs: number, callback: () => void): TimerHandle {\n return new TimeoutHandle(setTimeout(callback, delayMs));\n }\n}\n\nexport const timer = new SetTimeoutTimerAPI();\n\n/**\n * Implementation of [[TimerGroup]] using setTimeout\n */\nexport class TimerGroup {\n private stopped = false;\n\n private readonly timerMap: { [index: number]: TimerHandle } = {};\n\n private idGen = 1;\n\n constructor(public readonly timerApi: TimerAPI) {}\n\n stopCurrentAndFutureTimers(): void {\n this.stopped = true;\n for (const x in this.timerMap) {\n if (!this.timerMap.hasOwnProperty(x)) {\n continue;\n }\n this.timerMap[x].clear();\n delete this.timerMap[x];\n }\n }\n\n resolveAfter(delayMs: Duration): Promise {\n return new Promise((resolve, reject) => {\n if (delayMs.d_ms !== \"forever\") {\n this.after(delayMs.d_ms, () => {\n resolve();\n });\n }\n });\n }\n\n after(delayMs: number, callback: () => void): TimerHandle {\n if (this.stopped) {\n logger.warn(\"dropping timer since timer group is stopped\");\n return nullTimerHandle;\n }\n const h = this.timerApi.after(delayMs, callback);\n const myId = this.idGen++;\n this.timerMap[myId] = h;\n\n const tm = this.timerMap;\n\n return {\n clear() {\n h.clear();\n delete tm[myId];\n },\n unref() {\n h.unref();\n },\n };\n }\n\n every(delayMs: number, callback: () => void): TimerHandle {\n if (this.stopped) {\n logger.warn(\"dropping timer since timer group is stopped\");\n return nullTimerHandle;\n }\n const h = this.timerApi.every(delayMs, callback);\n const myId = this.idGen++;\n this.timerMap[myId] = h;\n\n const tm = this.timerMap;\n\n return {\n clear() {\n h.clear();\n delete tm[myId];\n },\n unref() {\n h.unref();\n },\n };\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n HttpRequestLibrary,\n HttpRequestOptions,\n HttpResponse,\n} from \"./http-common.js\";\nimport { ObservabilityEvent, ObservabilityEventType } from \"./notifications.js\";\nimport { getErrorDetailFromException } from \"./errors.js\";\nimport { CancellationToken } from \"./CancellationToken.js\";\nimport { AbsoluteTime } from \"./time.js\";\nimport { performanceDelta, performanceNow } from \"./timer.js\";\n\n/**\n * Observability sink can be passed into various operations (HTTP requests, DB access)\n * to do structured logging within a particular context (task, request, ...).\n */\nexport interface ObservabilityContext {\n observe(evt: ObservabilityEvent): void;\n}\n\nlet seqId = 1000;\n\nexport class ObservableHttpClientLibrary implements HttpRequestLibrary {\n private readonly cancelatorById = new Map();\n constructor(\n private impl: HttpRequestLibrary,\n private oc: ObservabilityContext,\n ) {}\n\n public cancelRequest(id: string): void {\n const cancelator = this.cancelatorById.get(id);\n if (!cancelator) return;\n cancelator.cancel();\n }\n\n async fetch(\n url: string,\n opt?: HttpRequestOptions | undefined,\n ): Promise {\n const id = `req-${seqId}`;\n seqId = seqId + 1;\n\n const cancelator = CancellationToken.create();\n if (opt?.cancellationToken) {\n opt.cancellationToken.onCancelled(cancelator.cancel);\n }\n this.cancelatorById.set(id, cancelator);\n\n this.oc.observe({\n id,\n when: AbsoluteTime.now(),\n type: ObservabilityEventType.HttpFetchStart,\n url: url,\n longPolling: !opt?.cancellationToken,\n });\n\n const optsWithCancel = opt ?? {};\n optsWithCancel.cancellationToken = cancelator.token;\n const start = performanceNow();\n try {\n const res = await this.impl.fetch(url, optsWithCancel);\n const end = performanceNow();\n const event: ObservabilityEvent = {\n id,\n when: AbsoluteTime.now(),\n type: ObservabilityEventType.HttpFetchFinishSuccess,\n url,\n status: res.status,\n durationMs: performanceDelta(start, end),\n longPolling: !opt?.cancellationToken,\n };\n this.oc.observe(event);\n return res;\n } catch (e) {\n const end = performanceNow();\n this.oc.observe({\n id,\n when: AbsoluteTime.now(),\n type: ObservabilityEventType.HttpFetchFinishError,\n url,\n error: getErrorDetailFromException(e),\n durationMs: performanceDelta(start, end),\n longPolling: !opt?.cancellationToken,\n });\n throw e;\n } finally {\n this.cancelatorById.delete(id);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Type and schema definitions for performance stats from the wallet to\n * clients of the wallet.\n */\n\n/**\n * Imports.\n */\nimport { assertUnreachable } from \"./index.js\";\nimport { ObservabilityEvent, ObservabilityEventType } from \"./notifications.js\";\n\nexport enum PerformanceStatType {\n HttpFetch = \"http-fetch\",\n DbQuery = \"db-query\",\n Crypto = \"crypto\",\n WalletRequest = \"wallet-request\",\n WalletTask = \"wallet-task\",\n}\n\nexport type PerformanceStat =\n | {\n type: PerformanceStatType.HttpFetch;\n url: string;\n avgDurationMs: number;\n maxDurationMs: number;\n minDurationMs: number;\n totalDurationMs: number;\n count: number;\n }\n | {\n type: PerformanceStatType.DbQuery;\n name: string;\n location: string;\n avgDurationMs: number;\n maxDurationMs: number;\n minDurationMs: number;\n totalDurationMs: number;\n count: number;\n }\n | {\n type: PerformanceStatType.Crypto;\n operation: string;\n avgDurationMs: number;\n maxDurationMs: number;\n minDurationMs: number;\n totalDurationMs: number;\n count: number;\n }\n | {\n type: PerformanceStatType.WalletRequest;\n operation: string;\n avgDurationMs: number;\n maxDurationMs: number;\n minDurationMs: number;\n totalDurationMs: number;\n count: number;\n }\n | {\n type: PerformanceStatType.WalletTask;\n taskId: string;\n avgDurationMs: number;\n maxDurationMs: number;\n minDurationMs: number;\n totalDurationMs: number;\n count: number;\n };\n\nexport namespace PerformanceStat {\n export function fromNotification(\n evt: ObservabilityEvent & { durationMs: number },\n ): PerformanceStat | undefined {\n if (\n (evt.type === ObservabilityEventType.HttpFetchFinishSuccess ||\n evt.type === ObservabilityEventType.HttpFetchFinishError) &&\n !evt.longPolling\n ) {\n return {\n type: PerformanceStatType.HttpFetch,\n url: evt.url,\n avgDurationMs: evt.durationMs,\n maxDurationMs: evt.durationMs,\n minDurationMs: evt.durationMs,\n totalDurationMs: evt.durationMs,\n count: 1,\n };\n } else if (\n evt.type === ObservabilityEventType.DbQueryFinishSuccess ||\n evt.type === ObservabilityEventType.DbQueryFinishError\n ) {\n return {\n type: PerformanceStatType.DbQuery,\n name: evt.name,\n location: evt.location,\n avgDurationMs: evt.durationMs,\n maxDurationMs: evt.durationMs,\n minDurationMs: evt.durationMs,\n totalDurationMs: evt.durationMs,\n count: 1,\n };\n } else if (\n evt.type === ObservabilityEventType.CryptoFinishSuccess ||\n evt.type === ObservabilityEventType.CryptoFinishError\n ) {\n return {\n type: PerformanceStatType.Crypto,\n operation: evt.operation,\n avgDurationMs: evt.durationMs,\n maxDurationMs: evt.durationMs,\n minDurationMs: evt.durationMs,\n totalDurationMs: evt.durationMs,\n count: 1,\n };\n } else if (\n evt.type === ObservabilityEventType.RequestFinishSuccess ||\n evt.type === ObservabilityEventType.RequestFinishError\n ) {\n return {\n type: PerformanceStatType.WalletRequest,\n operation: evt.operation,\n avgDurationMs: evt.durationMs,\n maxDurationMs: evt.durationMs,\n minDurationMs: evt.durationMs,\n totalDurationMs: evt.durationMs,\n count: 1,\n };\n } else if (evt.type === ObservabilityEventType.ShepherdTaskResult) {\n return {\n type: PerformanceStatType.WalletTask,\n taskId: evt.taskId,\n avgDurationMs: evt.durationMs,\n maxDurationMs: evt.durationMs,\n minDurationMs: evt.durationMs,\n totalDurationMs: evt.durationMs,\n count: 1,\n };\n }\n\n return undefined;\n }\n\n export function equals(a: PerformanceStat, b: PerformanceStat): boolean {\n if (a.type !== b.type) return false;\n if (a.type === PerformanceStatType.HttpFetch) {\n return a.url === b[\"url\" as keyof typeof b];\n } else if (a.type === PerformanceStatType.DbQuery) {\n return (\n a.name === b[\"name\" as keyof typeof b] &&\n a.location === b[\"location\" as keyof typeof b]\n );\n } else if (a.type === PerformanceStatType.Crypto) {\n return a.operation === b[\"operation\" as keyof typeof b];\n } else if (a.type === PerformanceStatType.WalletRequest) {\n return a.operation === b[\"operation\" as keyof typeof b];\n } else if (a.type === PerformanceStatType.WalletTask) {\n return a.taskId === b[\"taskId\" as keyof typeof b];\n } else {\n assertUnreachable(a);\n }\n }\n}\n\n/**\n * Max size of each performance table.\n */\nconst MAX_PERFORMANCE_TABLE_SIZE = 500;\n\nexport type PerformanceTable = {\n [key in PerformanceStatType]?: PerformanceStat[];\n};\n\nexport namespace PerformanceTable {\n export function insertEvent(tab: PerformanceTable, evt: ObservabilityEvent) {\n if (\"durationMs\" in evt && typeof evt.durationMs === \"number\") {\n const stat = PerformanceStat.fromNotification(evt);\n if (!stat) return;\n insertOrIncrement(tab, stat);\n sort(tab);\n rotate(tab, stat.type);\n }\n }\n\n /**\n * Extract the N largest stats of each table.\n */\n export function limit(tab: PerformanceTable, n?: number): PerformanceTable {\n if (n === undefined || n === Number.MAX_VALUE) {\n return tab;\n }\n const limited: PerformanceTable = {};\n for (const k of Object.keys(tab)) {\n const key = k as keyof typeof tab;\n limited[key] = tab[key]!!.slice(0, n);\n }\n return limited;\n }\n\n /**\n * Insert event to performance table.\n *\n * If matching event is found, increment durationMs in place.\n */\n function insertOrIncrement(tab: PerformanceTable, stat: PerformanceStat) {\n if (!tab[stat.type]) {\n tab[stat.type] = [];\n tab[stat.type]?.push(stat);\n return;\n }\n\n const index = tab[stat.type]!!.findIndex((el) =>\n PerformanceStat.equals(el, stat),\n );\n if (index === -1) {\n tab[stat.type]?.push(stat);\n } else {\n const existing = tab[stat.type]!![index];\n existing.avgDurationMs = Math.floor(\n (existing.avgDurationMs + stat.totalDurationMs) / 2,\n );\n existing.maxDurationMs = Math.max(\n existing.maxDurationMs,\n stat.maxDurationMs,\n );\n existing.minDurationMs = Math.min(\n existing.minDurationMs,\n stat.minDurationMs,\n );\n existing.totalDurationMs =\n existing.totalDurationMs + stat.totalDurationMs;\n existing.count += 1;\n tab[stat.type]!![index] = existing;\n }\n }\n\n /**\n * Sort all performance tables in place.\n */\n function sort(tab: PerformanceTable) {\n for (const k of Object.keys(tab)) {\n const key = k as keyof typeof tab;\n tab[key]!!.sort((a, b) => b.avgDurationMs - a.avgDurationMs);\n }\n }\n\n /**\n * Keep performance table under size limit.\n */\n function rotate(tab: PerformanceTable, type: PerformanceStatType) {\n if (tab[type]!!.length > MAX_PERFORMANCE_TABLE_SIZE) {\n tab[type]?.splice(0, 1);\n }\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019 GNUnet e.V.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n TALER is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { Logger } from \"./logging.js\";\nimport { AbsoluteTime } from \"./time.js\";\n\n/**\n * Implementation of token bucket throttling.\n */\n\nconst logger = new Logger(\"RequestThrottler.ts\");\n\n/**\n * Maximum request per second, per origin.\n */\nconst MAX_PER_SECOND = 100;\n\n/**\n * Maximum request per minute, per origin.\n */\nconst MAX_PER_MINUTE = 500;\n\n/**\n * Maximum request per hour, per origin.\n */\nconst MAX_PER_HOUR = 2000;\n\n/**\n * Throttling state for one origin.\n */\nclass OriginState {\n tokensSecond: number = MAX_PER_SECOND;\n tokensMinute: number = MAX_PER_MINUTE;\n tokensHour: number = MAX_PER_HOUR;\n private lastUpdate = AbsoluteTime.now();\n\n private refill(): void {\n const now = AbsoluteTime.now();\n if (AbsoluteTime.cmp(now, this.lastUpdate) < 0) {\n // Did the system time change?\n this.lastUpdate = now;\n return;\n }\n const d = AbsoluteTime.difference(now, this.lastUpdate);\n if (d.d_ms === \"forever\") {\n throw Error(\"assertion failed\");\n }\n // Be lazy and avoid rounding issues.\n if (d.d_ms < 1000 / MAX_PER_SECOND) {\n return;\n }\n this.tokensSecond = Math.min(\n MAX_PER_SECOND,\n this.tokensSecond + (d.d_ms / 1000) * MAX_PER_SECOND,\n );\n this.tokensMinute = Math.min(\n MAX_PER_MINUTE,\n this.tokensMinute + (d.d_ms / 1000 / 60) * MAX_PER_MINUTE,\n );\n this.tokensHour = Math.min(\n MAX_PER_HOUR,\n this.tokensHour + (d.d_ms / 1000 / 60 / 60) * MAX_PER_HOUR,\n );\n this.lastUpdate = now;\n }\n\n /**\n * Return true if the request for this origin should be throttled.\n * Otherwise, take a token out of the respective buckets.\n */\n applyThrottle(): boolean {\n this.refill();\n if (this.tokensSecond < 1) {\n logger.warn(\"request throttled (per second limit exceeded)\");\n return true;\n }\n if (this.tokensMinute < 1) {\n logger.warn(\"request throttled (per minute limit exceeded)\");\n return true;\n }\n if (this.tokensHour < 1) {\n logger.warn(\"request throttled (per hour limit exceeded)\");\n return true;\n }\n this.tokensSecond--;\n this.tokensMinute--;\n this.tokensHour--;\n return false;\n }\n}\n\n/**\n * Request throttler, used as a \"last layer of defense\" when some\n * other part of the re-try logic is broken and we're sending too\n * many requests to the same exchange/bank/merchant.\n */\nexport class RequestThrottler {\n private perOriginInfo: { [origin: string]: OriginState } = {};\n\n /**\n * Get the throttling state for an origin, or\n * initialize if no state is associated with the\n * origin yet.\n */\n private getState(origin: string): OriginState {\n const s = this.perOriginInfo[origin];\n if (s) {\n return s;\n }\n const ns = (this.perOriginInfo[origin] = new OriginState());\n return ns;\n }\n\n /**\n * Apply throttling to a request.\n *\n * @returns whether the request should be throttled.\n */\n applyThrottle(requestUrl: string): boolean {\n const origin = new URL(requestUrl).origin;\n return this.getState(origin).applyThrottle();\n }\n\n /**\n * Get the throttle statistics for a particular URL.\n */\n getThrottleStats(requestUrl: string): Record {\n const origin = new URL(requestUrl).origin;\n const state = this.getState(origin);\n return {\n tokensHour: state.tokensHour,\n tokensMinute: state.tokensMinute,\n tokensSecond: state.tokensSecond,\n maxTokensHour: MAX_PER_HOUR,\n maxTokensMinute: MAX_PER_MINUTE,\n maxTokensSecond: MAX_PER_SECOND,\n };\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n * Type declarations for the exchange's reserve transaction information.\n *\n * @author Florian Dold \n */\n\n/**\n * Imports.\n */\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n codecForString,\n buildCodecForObject,\n codecForConstString,\n buildCodecForUnion,\n Codec,\n codecForNumber,\n} from \"./codec.js\";\nimport {\n AmountString,\n Base32String,\n EddsaSignatureString,\n EddsaPublicKeyString,\n CoinPublicKeyString,\n codecForEddsaSignature,\n codecForEddsaPublicKey,\n} from \"./types-taler-common.js\";\nimport {\n AbsoluteTime,\n codecForTimestamp,\n TalerProtocolTimestamp,\n} from \"./time.js\";\n\nexport enum ReserveTransactionType {\n Withdraw = \"WITHDRAW\",\n Credit = \"CREDIT\",\n Recoup = \"RECOUP\",\n Closing = \"CLOSING\",\n}\n\nexport interface ReserveWithdrawTransaction {\n type: ReserveTransactionType.Withdraw;\n\n /**\n * Amount withdrawn.\n */\n amount: AmountString;\n\n /**\n * Hash of the denomination public key of the coin.\n */\n h_denom_pub: Base32String;\n\n /**\n * Hash of the blinded coin to be signed\n */\n h_coin_envelope: Base32String;\n\n /**\n * Signature of 'TALER_WithdrawRequestPS' created with the reserves's\n * private key.\n */\n reserve_sig: EddsaSignatureString;\n\n /**\n * Fee that is charged for withdraw.\n */\n withdraw_fee: AmountString;\n}\n\nexport interface ReserveCreditTransaction {\n type: ReserveTransactionType.Credit;\n\n /**\n * Amount withdrawn.\n */\n amount: AmountString;\n\n /**\n * Sender account payto://-URL\n */\n sender_account_url: string;\n\n /**\n * Transfer details uniquely identifying the transfer.\n */\n wire_reference: number;\n\n /**\n * Timestamp of the incoming wire transfer.\n */\n timestamp: TalerProtocolTimestamp;\n}\n\nexport interface ReserveClosingTransaction {\n type: ReserveTransactionType.Closing;\n\n /**\n * Closing balance.\n */\n amount: AmountString;\n\n /**\n * Closing fee charged by the exchange.\n */\n closing_fee: AmountString;\n\n /**\n * Wire transfer subject.\n */\n wtid: string;\n\n /**\n * Hash of the wire account into which the funds were returned to.\n */\n h_wire: string;\n\n /**\n * This is a signature over a\n * struct TALER_ReserveCloseConfirmationPS with purpose\n * TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED.\n */\n exchange_sig: EddsaSignatureString;\n\n /**\n * Public key used to create exchange_sig.\n */\n exchange_pub: EddsaPublicKeyString;\n\n /**\n * Time when the reserve was closed.\n */\n timestamp: TalerProtocolTimestamp;\n}\n\nexport interface ReserveRecoupTransaction {\n type: ReserveTransactionType.Recoup;\n\n /**\n * Amount paid back.\n */\n amount: AmountString;\n\n /**\n * This is a signature over\n * a struct TALER_PaybackConfirmationPS with purpose\n * TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK.\n */\n exchange_sig: EddsaSignatureString;\n\n /**\n * Public key used to create exchange_sig.\n */\n exchange_pub: EddsaPublicKeyString;\n\n /**\n * Time when the funds were paid back into the reserve.\n */\n timestamp: TalerProtocolTimestamp;\n\n /**\n * Public key of the coin that was paid back.\n */\n coin_pub: CoinPublicKeyString;\n}\n\n/**\n * Format of the exchange's transaction history for a reserve.\n */\nexport type ReserveTransaction =\n | ReserveWithdrawTransaction\n | ReserveCreditTransaction\n | ReserveClosingTransaction\n | ReserveRecoupTransaction;\n\nexport const codecForReserveWithdrawTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"h_coin_envelope\", codecForString())\n .property(\"h_denom_pub\", codecForString())\n .property(\"reserve_sig\", codecForEddsaSignature())\n .property(\"type\", codecForConstString(ReserveTransactionType.Withdraw))\n .property(\"withdraw_fee\", codecForAmountString())\n .build(\"ReserveWithdrawTransaction\");\n\nexport const codecForReserveCreditTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"sender_account_url\", codecForString())\n .property(\"timestamp\", codecForTimestamp)\n .property(\"wire_reference\", codecForNumber())\n .property(\"type\", codecForConstString(ReserveTransactionType.Credit))\n .build(\"ReserveCreditTransaction\");\n\nexport const codecForReserveClosingTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"closing_fee\", codecForAmountString())\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"h_wire\", codecForString())\n .property(\"timestamp\", codecForTimestamp)\n .property(\"type\", codecForConstString(ReserveTransactionType.Closing))\n .property(\"wtid\", codecForString())\n .build(\"ReserveClosingTransaction\");\n\nexport const codecForReserveRecoupTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"amount\", codecForAmountString())\n .property(\"coin_pub\", codecForString())\n .property(\"exchange_pub\", codecForEddsaPublicKey())\n .property(\"exchange_sig\", codecForEddsaSignature())\n .property(\"timestamp\", codecForTimestamp)\n .property(\"type\", codecForConstString(ReserveTransactionType.Recoup))\n .build(\"ReserveRecoupTransaction\");\n\nexport const codecForReserveTransaction = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"type\")\n .alternative(\n ReserveTransactionType.Withdraw,\n codecForReserveWithdrawTransaction(),\n )\n .alternative(\n ReserveTransactionType.Closing,\n codecForReserveClosingTransaction(),\n )\n .alternative(\n ReserveTransactionType.Recoup,\n codecForReserveRecoupTransaction(),\n )\n .alternative(\n ReserveTransactionType.Credit,\n codecForReserveCreditTransaction(),\n )\n .build(\"ReserveTransaction\");\n", "/*\n This file is part of GNU Taler\n (C) 2019 GNUnet e.V.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n TALER is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { Logger } from \"./logging.js\";\nimport { AbsoluteTime, Duration } from \"./time.js\";\n\n/**\n * Implementation of token bucket throttling.\n */\n\n/**\n * Logger.\n */\nconst logger = new Logger(\"OperationThrottler.ts\");\n\n/**\n * Maximum request per second, per origin.\n */\nconst MAX_PER_SECOND = 100;\n\n/**\n * Maximum request per minute, per origin.\n */\nconst MAX_PER_MINUTE = 500;\n\n/**\n * Maximum request per hour, per origin.\n */\nconst MAX_PER_HOUR = 2000;\n\n/**\n * Throttling state for one task.\n */\nclass TaskState {\n tokensSecond: number = MAX_PER_SECOND;\n tokensMinute: number = MAX_PER_MINUTE;\n tokensHour: number = MAX_PER_HOUR;\n lastUpdate = AbsoluteTime.now();\n\n private refill(): void {\n const now = AbsoluteTime.now();\n if (AbsoluteTime.cmp(now, this.lastUpdate) < 0) {\n // Did the system time change?\n this.lastUpdate = now;\n return;\n }\n const d = AbsoluteTime.difference(now, this.lastUpdate);\n if (d.d_ms === \"forever\") {\n throw Error(\"assertion failed\");\n }\n this.tokensSecond = Math.min(\n MAX_PER_SECOND,\n this.tokensSecond + d.d_ms / 1000,\n );\n this.tokensMinute = Math.min(\n MAX_PER_MINUTE,\n this.tokensMinute + d.d_ms / 1000 / 60,\n );\n this.tokensHour = Math.min(\n MAX_PER_HOUR,\n this.tokensHour + d.d_ms / 1000 / 60 / 60,\n );\n this.lastUpdate = now;\n }\n\n /**\n * Return true if the request for this origin should be throttled.\n * Otherwise, take a token out of the respective buckets.\n */\n applyThrottle(): boolean {\n this.refill();\n if (this.tokensSecond < 1) {\n logger.warn(\"request throttled (per second limit exceeded)\");\n return true;\n }\n if (this.tokensMinute < 1) {\n logger.warn(\"request throttled (per minute limit exceeded)\");\n return true;\n }\n if (this.tokensHour < 1) {\n logger.warn(\"request throttled (per hour limit exceeded)\");\n return true;\n }\n this.tokensSecond--;\n this.tokensMinute--;\n this.tokensHour--;\n return false;\n }\n}\n\n/**\n * Request throttler, used as a \"last layer of defense\" when some\n * other part of the re-try logic is broken and we're sending too\n * many requests to the same exchange/bank/merchant.\n */\nexport class TaskThrottler {\n private perTaskInfo: { [taskId: string]: TaskState } = {};\n\n /**\n * Get the throttling state for an origin, or\n * initialize if no state is associated with the\n * origin yet.\n */\n private getState(origin: string): TaskState {\n const s = this.perTaskInfo[origin];\n if (s) {\n return s;\n }\n const ns = (this.perTaskInfo[origin] = new TaskState());\n return ns;\n }\n\n /**\n * Apply throttling to a request.\n *\n * @returns whether the request should be throttled.\n */\n applyThrottle(taskId: string): boolean {\n for (let [k, v] of Object.entries(this.perTaskInfo)) {\n // Remove throttled tasks that haven't seen an update in more than one hour.\n if (\n Duration.cmp(\n AbsoluteTime.difference(v.lastUpdate, AbsoluteTime.now()),\n Duration.fromSpec({ hours: 1 }),\n ) > 1\n ) {\n delete this.perTaskInfo[k];\n }\n }\n return this.getState(taskId).applyThrottle();\n }\n\n /**\n * Get the throttle statistics for a particular URL.\n */\n getThrottleStats(taskId: string): Record {\n const state = this.getState(taskId);\n return {\n tokensHour: state.tokensHour,\n tokensMinute: state.tokensMinute,\n tokensSecond: state.tokensSecond,\n maxTokensHour: MAX_PER_HOUR,\n maxTokensMinute: MAX_PER_MINUTE,\n maxTokensSecond: MAX_PER_SECOND,\n };\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2019-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\n/**\n * Type and schema definitions for the wallet's transaction list.\n *\n * @author Florian Dold\n * @author Torsten Grote\n */\n\n/**\n * Imports.\n */\nimport {\n Codec,\n buildCodecForObject,\n codecForAny,\n codecForBoolean,\n codecForConstString,\n codecForEither,\n codecForList,\n codecForNumber,\n codecForString,\n codecOptional,\n} from \"./codec.js\";\nimport {\n TalerPreciseTimestamp,\n TalerProtocolDuration,\n TalerProtocolTimestamp,\n codecForPreciseTimestamp,\n} from \"./time.js\";\nimport {\n AmountString,\n InternationalizedString,\n codecForInternationalizedString,\n} from \"./types-taler-common.js\";\nimport {\n MerchantContractTerms,\n MerchantInfo,\n codecForMerchantInfo,\n} from \"./types-taler-merchant.js\";\nimport {\n RefreshReason,\n ScopeInfo,\n TalerErrorDetail,\n TransactionIdStr,\n TransactionStateFilter,\n WithdrawalExchangeAccountDetails,\n codecForScopeInfo,\n} from \"./types-taler-wallet.js\";\n\nexport interface TransactionsRequest {\n /**\n * return only transactions in the given currency\n *\n * it will be removed in next release\n *\n * @deprecated use scopeInfo\n */\n currency?: string;\n\n /**\n * return only transactions in the given scopeInfo\n */\n scopeInfo?: ScopeInfo;\n\n /**\n * if present, results will be limited to transactions related to the given search string\n */\n search?: string;\n\n /**\n * Sort order of the transaction items.\n * By default, items are sorted ascending by their\n * main timestamp.\n *\n * ascending: ascending by timestamp, but pending transactions first\n * descending: ascending by timestamp, but pending transactions first\n * stable-ascending: ascending by timestamp, with pending transactions amidst other transactions\n * (stable in the sense of: pending transactions don't jump around)\n */\n sort?: \"ascending\" | \"descending\" | \"stable-ascending\";\n\n /**\n * If true, include all refreshes in the transactions list.\n */\n includeRefreshes?: boolean;\n\n filterByState?: TransactionStateFilter;\n}\n\nexport interface GetTransactionsV2Request {\n /**\n * Return only transactions in the given currency.\n */\n currency?: string;\n\n /**\n * Return only transactions in the given scopeInfo\n */\n scopeInfo?: ScopeInfo;\n\n /**\n * If true, include all refreshes in the transactions list.\n */\n includeRefreshes?: boolean;\n\n /**\n * If true, include transactions that would usually be filtered out.\n * Implies includeRefreshes.\n */\n includeAll?: boolean;\n\n /**\n * Only return transactions before/after this offset.\n */\n offsetTransactionId?: TransactionIdStr;\n\n /**\n * Only return transactions before/after the transaction with this\n * timestamp.\n *\n * Used as a fallback if the offsetTransactionId was deleted.\n */\n offsetTimestamp?: TalerPreciseTimestamp;\n\n /**\n * Number of transactions to return.\n *\n * When the limit is positive, results are returned\n * in ascending order of their timestamp. If no offset is specified,\n * the result list begins with the first transaction.\n * If an offset is specified, transactions after the offset are returned.\n *\n * When the limit is negative, results are returned\n * in descending order of their timestamp. If no offset is specified,\n * the result list begins with with the last transaction.\n * If an offset is specified, transactions before the offset are returned.\n */\n limit?: number;\n\n /**\n * Filter transactions by their state / state category.\n *\n * If not specified, all transactions are returned.\n *\n * final: Transactions in any final state\n * nonfinal: Transactions in any state but the final states\n * nonfinal-dialog: nonfinal transactions that require confirmation / some\n * choice by the user\n * nonfinal-approved: nonfinal transactions that need no further user approval\n * done: Transactions in the \"done\" major state\n */\n filterByState?:\n | \"final\"\n | \"nonfinal\"\n | \"done\"\n | \"nonfinal-approved\"\n | \"nonfinal-dialog\";\n}\n\nexport interface TransactionState {\n major: TransactionMajorState;\n minor?: TransactionMinorState;\n}\n\nexport type TransactionStateWildcard = \"*\";\n\nexport enum TransactionMajorState {\n // No state, only used when reporting transitions into the initial state\n None = \"none\",\n Pending = \"pending\",\n Done = \"done\",\n Aborting = \"aborting\",\n Aborted = \"aborted\",\n Dialog = \"dialog\",\n Finalizing = \"finalizing\",\n // Plain suspended is always a suspended pending state.\n Suspended = \"suspended\",\n SuspendedFinalizing = \"suspended-finalizing\",\n SuspendedAborting = \"suspended-aborting\",\n Failed = \"failed\",\n Expired = \"expired\",\n // Only used for the notification, never in the transaction history\n Deleted = \"deleted\",\n}\n\nexport enum TransactionMinorState {\n // Placeholder until D37 is fully implemented\n AbortingBank = \"aborting-bank\",\n AcceptRefund = \"accept-refund\",\n AutoRefund = \"auto-refund\",\n BalanceKycRequired = \"balance-kyc\",\n Bank = \"bank\",\n BankConfirmTransfer = \"bank-confirm-transfer\",\n BankRegisterReserve = \"bank-register-reserve\",\n CheckRefund = \"check-refund\",\n ClaimProposal = \"claim-proposal\",\n CompletedByOtherWallet = \"completed-by-other-wallet\",\n CreatePurse = \"create-purse\",\n DeletePurse = \"delete-purse\",\n Deposit = \"deposit\",\n Exchange = \"exchange\",\n ExchangeWaitReserve = \"exchange-wait-reserve\",\n KycAuthRequired = \"kyc-auth\",\n KycInit = \"kyc-init\",\n KycRequired = \"kyc\",\n Merge = \"merge\",\n PaidByOther = \"paid-by-other\",\n Proposed = \"proposed\",\n Ready = \"ready\",\n RebindSession = \"rebind-session\",\n Refresh = \"refresh\",\n Refused = \"refused\",\n Repurchase = \"repurchase\",\n SubmitPayment = \"submit-payment\",\n Track = \"track\",\n Unknown = \"unknown\",\n Withdraw = \"withdraw\",\n}\n\nexport enum TransactionAction {\n Delete = \"delete\",\n Suspend = \"suspend\",\n Resume = \"resume\",\n Abort = \"abort\",\n Fail = \"fail\",\n Retry = \"retry\",\n}\n\nexport interface TransactionsResponse {\n // a list of past and pending transactions sorted by pending, timestamp and transactionId.\n // In case two events are both pending and have the same timestamp,\n // they are sorted by the transactionId\n // (lexically ascending and locale-independent comparison).\n transactions: Transaction[];\n}\n\nexport interface TransactionCommon {\n // opaque unique ID for the transaction, used as a starting point for paginating queries\n // and for invoking actions on the transaction (e.g. deleting/hiding it from the history)\n transactionId: TransactionIdStr;\n\n // the type of the transaction; different types might provide additional information\n type: TransactionType;\n\n // main timestamp of the transaction\n timestamp: TalerPreciseTimestamp;\n\n /**\n * Scope of this tx\n */\n scopes: ScopeInfo[];\n\n /**\n * Transaction state, as per DD37.\n */\n txState: TransactionState;\n\n /**\n * Wallet-internal state ID, only used for debugging and testing.\n */\n stId: number;\n\n /**\n * Possible transitions based on the current state.\n */\n txActions: TransactionAction[];\n\n /**\n * Raw amount of the transaction (exclusive of fees or other extra costs).\n */\n amountRaw: AmountString;\n\n /**\n * Amount added or removed from the wallet's balance (including all fees and other costs).\n */\n amountEffective: AmountString;\n\n error?: TalerErrorDetail;\n\n abortReason?: TalerErrorDetail;\n\n failReason?: TalerErrorDetail;\n\n /**\n * If the transaction minor state is in KycRequired this field is going to\n * have the location where the user need to go to complete KYC information.\n */\n kycUrl?: string;\n\n /**\n * KYC payto hash. Useful for testing, not so useful for UIs.\n */\n kycPaytoHash?: string;\n\n /**\n * KYC access token. Useful for testing, not so useful for UIs.\n */\n kycAccessToken?: string;\n\n kycAuthTransferInfo?: KycAuthTransferInfo;\n}\n\nexport interface KycAuthTransferInfo {\n /**\n * Payto URI of the account that must make the transfer.\n *\n * The KYC auth transfer will *not* work if it originates\n * from a different account.\n */\n debitPaytoUri: string;\n\n /**\n * Account public key that must be included in the subject.\n */\n accountPub: string;\n\n /**\n * Amount that the exchange expects to be deposited.\n *\n * Usually corresponds to the TINY_AMOUNT configuration of the exchange,\n * and thus is the smallest amount that can be transferred\n * via a bank transfer.\n */\n amount: AmountString;\n\n /**\n * Possible target payto URIs.\n */\n creditPaytoUris: string[];\n}\n\nexport type Transaction =\n | TransactionWithdrawal\n | TransactionPayment\n | TransactionRefund\n | TransactionRefresh\n | TransactionDeposit\n | TransactionPeerPullCredit\n | TransactionPeerPullDebit\n | TransactionPeerPushCredit\n | TransactionPeerPushDebit\n | TransactionInternalWithdrawal\n | TransactionRecoup\n | TransactionDenomLoss;\n\nexport enum TransactionType {\n Withdrawal = \"withdrawal\",\n InternalWithdrawal = \"internal-withdrawal\",\n Payment = \"payment\",\n Refund = \"refund\",\n Refresh = \"refresh\",\n Deposit = \"deposit\",\n PeerPushDebit = \"peer-push-debit\",\n PeerPushCredit = \"peer-push-credit\",\n PeerPullDebit = \"peer-pull-debit\",\n PeerPullCredit = \"peer-pull-credit\",\n Recoup = \"recoup\",\n DenomLoss = \"denom-loss\",\n}\n\nexport enum WithdrawalType {\n TalerBankIntegrationApi = \"taler-bank-integration-api\",\n ManualTransfer = \"manual-transfer\",\n}\n\nexport type WithdrawalDetails =\n | WithdrawalDetailsForManualTransfer\n | WithdrawalDetailsForTalerBankIntegrationApi;\n\ninterface WithdrawalDetailsForManualTransfer {\n type: WithdrawalType.ManualTransfer;\n\n /**\n * Payto URIs that the exchange supports.\n *\n * Already contains the amount and message.\n *\n * @deprecated in favor of exchangeCreditAccounts\n */\n exchangePaytoUris: string[];\n\n exchangeCreditAccountDetails?: WithdrawalExchangeAccountDetails[];\n\n // Public key of the reserve\n reservePub: string;\n\n /**\n * Is the reserve ready for withdrawal?\n */\n reserveIsReady: boolean;\n\n /**\n * How long does the exchange wait to transfer back funds from a\n * reserve?\n */\n reserveClosingDelay: TalerProtocolDuration;\n}\n\ninterface WithdrawalDetailsForTalerBankIntegrationApi {\n type: WithdrawalType.TalerBankIntegrationApi;\n\n /**\n * Set to true if the bank has confirmed the withdrawal, false if not.\n * An unconfirmed withdrawal usually requires user-input and should be highlighted in the UI.\n * See also bankConfirmationUrl below.\n */\n confirmed: boolean;\n\n /**\n * If the withdrawal is unconfirmed, this can include a URL for user\n * initiated confirmation.\n */\n bankConfirmationUrl?: string;\n\n // Public key of the reserve\n reservePub: string;\n\n /**\n * Is the reserve ready for withdrawal?\n */\n reserveIsReady: boolean;\n\n /**\n * Is the bank transfer for the withdrawal externally confirmed?\n */\n externalConfirmation?: boolean;\n\n exchangeCreditAccountDetails?: WithdrawalExchangeAccountDetails[];\n}\n\nexport enum DenomLossEventType {\n DenomExpired = \"denom-expired\",\n DenomVanished = \"denom-vanished\",\n DenomUnoffered = \"denom-unoffered\",\n}\n\n/**\n * A transaction to indicate financial loss due to denominations\n * that became unusable for deposits.\n */\nexport interface TransactionDenomLoss extends TransactionCommon {\n type: TransactionType.DenomLoss;\n lossEventType: DenomLossEventType;\n exchangeBaseUrl: string;\n}\n\n/**\n * A withdrawal transaction (either bank-integrated or manual).\n */\nexport interface TransactionWithdrawal extends TransactionCommon {\n type: TransactionType.Withdrawal;\n\n /**\n * Exchange of the withdrawal.\n */\n exchangeBaseUrl: string | undefined;\n\n /**\n * Amount that got subtracted from the reserve balance.\n */\n amountRaw: AmountString;\n\n /**\n * Amount that actually was (or will be) added to the wallet's balance.\n */\n amountEffective: AmountString;\n\n withdrawalDetails: WithdrawalDetails;\n}\n\n/**\n * Internal withdrawal operation, only reported on request.\n *\n * Some transactions (peer-*-credit) internally do a withdrawal,\n * but only the peer-*-credit transaction is reported.\n *\n * The internal withdrawal transaction allows to access the details of\n * the underlying withdrawal for testing/debugging.\n *\n * It is usually not reported, so that amounts of transactions properly\n * add up, since the amountEffecive of the withdrawal is already reported\n * in the peer-*-credit transaction.\n */\nexport interface TransactionInternalWithdrawal extends TransactionCommon {\n type: TransactionType.InternalWithdrawal;\n\n /**\n * Exchange of the withdrawal.\n */\n exchangeBaseUrl: string;\n\n /**\n * Amount that got subtracted from the reserve balance.\n */\n amountRaw: AmountString;\n\n /**\n * Amount that actually was (or will be) added to the wallet's balance.\n */\n amountEffective: AmountString;\n\n withdrawalDetails: WithdrawalDetails;\n}\n\nexport interface PeerInfoShort {\n expiration: TalerProtocolTimestamp | undefined;\n summary: string | undefined;\n iconId: string | undefined;\n}\n\n/**\n * Credit because we were paid for a P2P invoice we created.\n */\nexport interface TransactionPeerPullCredit extends TransactionCommon {\n type: TransactionType.PeerPullCredit;\n\n info: PeerInfoShort;\n /**\n * Exchange used.\n */\n exchangeBaseUrl: string;\n\n /**\n * Amount that got subtracted from the reserve balance.\n */\n amountRaw: AmountString;\n\n /**\n * Amount that actually was (or will be) added to the wallet's balance.\n */\n amountEffective: AmountString;\n\n /**\n * URI to send to the other party.\n *\n * Only available in the right state.\n */\n talerUri: string | undefined;\n}\n\n/**\n * Debit because we paid someone's invoice.\n */\nexport interface TransactionPeerPullDebit extends TransactionCommon {\n type: TransactionType.PeerPullDebit;\n\n info: PeerInfoShort;\n /**\n * Exchange used.\n */\n exchangeBaseUrl: string;\n\n amountRaw: AmountString;\n\n amountEffective: AmountString;\n}\n\n/**\n * We sent money via a P2P payment.\n */\nexport interface TransactionPeerPushDebit extends TransactionCommon {\n type: TransactionType.PeerPushDebit;\n\n info: PeerInfoShort;\n /**\n * Exchange used.\n */\n exchangeBaseUrl: string;\n\n /**\n * Amount that got subtracted from the reserve balance.\n */\n amountRaw: AmountString;\n\n /**\n * Amount that actually was (or will be) added to the wallet's balance.\n */\n amountEffective: AmountString;\n\n /**\n * URI to accept the payment.\n *\n * Only present if the transaction is in a state where the other party can\n * accept the payment.\n */\n talerUri?: string;\n}\n\n/**\n * We received money via a P2P payment.\n */\nexport interface TransactionPeerPushCredit extends TransactionCommon {\n type: TransactionType.PeerPushCredit;\n\n info: PeerInfoShort;\n /**\n * Exchange used.\n */\n exchangeBaseUrl: string;\n\n /**\n * Amount that got subtracted from the reserve balance.\n */\n amountRaw: AmountString;\n\n /**\n * Amount that actually was (or will be) added to the wallet's balance.\n */\n amountEffective: AmountString;\n}\n\n/**\n * The exchange revoked a key and the wallet recoups funds.\n */\nexport interface TransactionRecoup extends TransactionCommon {\n type: TransactionType.Recoup;\n}\n\nexport enum PaymentStatus {\n /**\n * Explicitly aborted after timeout / failure\n */\n Aborted = \"aborted\",\n\n /**\n * Payment failed, wallet will auto-retry.\n * User should be given the option to retry now / abort.\n */\n Failed = \"failed\",\n\n /**\n * Paid successfully\n */\n Paid = \"paid\",\n\n /**\n * User accepted, payment is processing.\n */\n Accepted = \"accepted\",\n}\n\nexport interface TransactionPayment extends TransactionCommon {\n type: TransactionType.Payment;\n\n /**\n * Additional information about the payment.\n */\n info: OrderShortInfo;\n\n /**\n * Full contract terms.\n *\n * Only included if explicitly included in the request.\n */\n contractTerms?: MerchantContractTerms;\n\n /**\n * Amount that must be paid for the contract\n */\n amountRaw: AmountString;\n\n /**\n * Amount that was paid, including deposit, wire and refresh fees.\n */\n amountEffective: AmountString;\n\n /**\n * Amount that has been refunded by the merchant\n */\n totalRefundRaw: AmountString;\n\n /**\n * Amount will be added to the wallet's balance after fees and refreshing\n */\n totalRefundEffective: AmountString;\n\n /**\n * Amount pending to be picked up\n */\n refundPending: AmountString | undefined;\n\n /**\n * Reference to applied refunds\n */\n refunds: RefundInfoShort[];\n\n /**\n * Is the wallet currently checking for a refund?\n */\n refundQueryActive: boolean;\n\n /**\n * PoS confirmation codes, separated by newlines.\n * Only present for purchases that support PoS confirmation.\n */\n posConfirmation: string | undefined;\n\n /**\n * Until when will the posConfirmation be valid?\n */\n posConfirmationDeadline?: TalerProtocolTimestamp;\n\n /**\n * Did we receive the payment via a taler://pay-template/ URI\n * and did the URI contain a nfc=1 flag?\n */\n posConfirmationViaNfc?: boolean;\n}\n\nexport interface OrderShortInfo {\n /**\n * Order ID, uniquely identifies the order within a merchant instance\n */\n orderId: string;\n\n /**\n * Hash of the contract terms.\n */\n contractTermsHash: string;\n\n /**\n * More information about the merchant\n */\n merchant: MerchantInfo;\n\n /**\n * Summary of the order, given by the merchant\n */\n summary: string;\n\n /**\n * Map from IETF BCP 47 language tags to localized summaries\n */\n summary_i18n?: InternationalizedString;\n\n /**\n * URL of the fulfillment, given by the merchant\n */\n fulfillmentUrl?: string;\n\n /**\n * Plain text message that should be shown to the user\n * when the payment is complete.\n */\n fulfillmentMessage?: string;\n\n /**\n * Translations of fulfillmentMessage.\n */\n fulfillmentMessage_i18n?: InternationalizedString;\n}\n\nexport interface RefundInfoShort {\n transactionId: string;\n timestamp: TalerProtocolTimestamp;\n amountEffective: AmountString;\n amountRaw: AmountString;\n}\n\n/**\n * Summary information about the payment that we got a refund for.\n */\nexport interface RefundPaymentInfo {\n summary: string;\n summary_i18n?: InternationalizedString;\n /**\n * More information about the merchant\n */\n merchant: MerchantInfo;\n}\n\nexport interface TransactionRefund extends TransactionCommon {\n type: TransactionType.Refund;\n\n // Amount that has been refunded by the merchant\n amountRaw: AmountString;\n\n // Amount will be added to the wallet's balance after fees and refreshing\n amountEffective: AmountString;\n\n // ID for the transaction that is refunded\n refundedTransactionId: string;\n\n paymentInfo: RefundPaymentInfo | undefined;\n}\n\n/**\n * A transaction shown for refreshes.\n * Only shown for (1) refreshes not associated with other transactions\n * and (2) refreshes in an error state.\n */\nexport interface TransactionRefresh extends TransactionCommon {\n type: TransactionType.Refresh;\n\n refreshReason: RefreshReason;\n\n /**\n * Transaction ID that caused this refresh.\n */\n originatingTransactionId?: string;\n\n /**\n * Always zero for refreshes\n */\n amountRaw: AmountString;\n\n /**\n * Fees, i.e. the effective, negative effect of the refresh\n * on the balance.\n *\n * Only applicable for stand-alone refreshes, and zero for\n * other refreshes where the transaction itself accounts for the\n * refresh fee.\n */\n amountEffective: AmountString;\n\n refreshInputAmount: AmountString;\n refreshOutputAmount: AmountString;\n}\n\nexport interface DepositTransactionTrackingState {\n // Raw wire transfer identifier of the deposit.\n wireTransferId: string;\n // When was the wire transfer given to the bank.\n timestampExecuted: TalerProtocolTimestamp;\n // Total amount transfer for this wtid (including fees)\n amountRaw: AmountString;\n // Wire fee amount for this exchange\n wireFee: AmountString;\n}\n\n/**\n * Deposit transaction, which effectively sends\n * money from this wallet somewhere else.\n */\nexport interface TransactionDeposit extends TransactionCommon {\n type: TransactionType.Deposit;\n\n depositGroupId: string;\n\n /**\n * Target for the deposit.\n */\n targetPaytoUri: string;\n\n /**\n * Raw amount that is being deposited\n */\n amountRaw: AmountString;\n\n /**\n * Deposit account public key.\n */\n accountPub: string;\n\n /**\n * Effective amount that is being deposited\n */\n amountEffective: AmountString;\n\n wireTransferDeadline: TalerProtocolTimestamp;\n\n wireTransferProgress: number;\n\n /**\n * Did all the deposit requests succeed?\n */\n deposited: boolean;\n\n trackingState: Array;\n}\n\nexport interface TransactionByIdRequest {\n transactionId: string;\n\n /**\n * If set to true, report the full contract terms in the response\n * if the transaction has them.\n */\n includeContractTerms?: boolean;\n}\n\nexport const codecForTransactionByIdRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForString())\n .property(\"includeContractTerms\", codecOptional(codecForBoolean()))\n .build(\"TransactionByIdRequest\");\n\nexport const codecForGetTransactionsV2Request =\n (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecOptional(codecForString()))\n .property(\"scopeInfo\", codecOptional(codecForScopeInfo()))\n .property(\n \"offsetTransactionId\",\n codecOptional(codecForString() as Codec),\n )\n .property(\"offsetTimestamp\", codecOptional(codecForPreciseTimestamp))\n .property(\"limit\", codecOptional(codecForNumber()))\n .property(\n \"filterByState\",\n codecOptional(\n codecForEither(\n codecForConstString(\"final\"),\n codecForConstString(\"nonfinal\"),\n codecForConstString(\"done\"),\n codecForConstString(\"nonfinal-approved\"),\n codecForConstString(\"nonfinal-dialog\"),\n ),\n ),\n )\n .property(\"includeRefreshes\", codecOptional(codecForBoolean()))\n .property(\"includeAll\", codecOptional(codecForBoolean()))\n .build(\"GetTransactionsV2Request\");\n\nexport const codecForTransactionsRequest = (): Codec =>\n buildCodecForObject()\n .property(\"currency\", codecOptional(codecForString()))\n .property(\"scopeInfo\", codecOptional(codecForScopeInfo()))\n .property(\"search\", codecOptional(codecForString()))\n .property(\n \"sort\",\n codecOptional(\n codecForEither(\n codecForConstString(\"ascending\"),\n codecForConstString(\"descending\"),\n codecForConstString(\"stable-ascending\"),\n ),\n ),\n )\n .property(\"includeRefreshes\", codecOptional(codecForBoolean()))\n .build(\"TransactionsRequest\");\n\n// FIXME: do full validation here!\nexport const codecForTransactionsResponse = (): Codec =>\n buildCodecForObject()\n .property(\"transactions\", codecForList(codecForAny()))\n .build(\"TransactionsResponse\");\n\nexport const codecForOrderShortInfo = (): Codec =>\n buildCodecForObject()\n .property(\"contractTermsHash\", codecForString())\n .property(\"fulfillmentMessage\", codecOptional(codecForString()))\n .property(\n \"fulfillmentMessage_i18n\",\n codecOptional(codecForInternationalizedString()),\n )\n .property(\"fulfillmentUrl\", codecOptional(codecForString()))\n .property(\"merchant\", codecForMerchantInfo())\n .property(\"orderId\", codecForString())\n .property(\"summary\", codecForString())\n .property(\"summary_i18n\", codecOptional(codecForInternationalizedString()))\n .build(\"OrderShortInfo\");\n\nexport interface ListAssociatedRefreshesRequest {\n transactionId: string;\n}\n\nexport const codecForListAssociatedRefreshesRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"transactionId\", codecForString())\n .build(\"ListAssociatedRefreshesRequest\");\n\nexport interface ListAssociatedRefreshesResponse {\n transactionIds: string[];\n}\n", "/*\n This file is part of GNU Taler\n (C) 2023 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n TransactionType,\n PaymentStatus,\n TransactionMajorState,\n} from \"./types-taler-wallet-transactions.js\";\nimport { RefreshReason } from \"./types-taler-wallet.js\";\n\n/**\n * Sample transaction list entries.\n */\nexport const sampleWalletCoreTransactions = [\n {\n type: TransactionType.Payment,\n txState: {\n major: TransactionMajorState.Done,\n },\n amountRaw: \"KUDOS:10\",\n amountEffective: \"KUDOS:10\",\n totalRefundRaw: \"KUDOS:0\",\n totalRefundEffective: \"KUDOS:0\",\n status: PaymentStatus.Paid,\n refundPending: undefined,\n posConfirmation: undefined,\n pending: false,\n refunds: [],\n timestamp: {\n t_s: 1677166045,\n },\n transactionId:\n \"txn:payment:NRRD9KJ8970P5HDAGPW1MBA6HZHB1XMFKF5M3CNR6WA0GT98DHY0\",\n proposalId: \"NRRD9KJ8970P5HDAGPW1MBA6HZHB1XMFKF5M3CNR6WA0GT98DHY0\",\n info: {\n merchant: {\n name: \"woocommerce\",\n website: \"woocommerce.demo.taler.net\",\n email: \"foo@example.com\",\n address: {},\n jurisdiction: {},\n },\n orderId: \"wc_order_KQCRldghIgDRB-100\",\n products: [\n {\n description: \"Using GCC\",\n quantity: 1,\n price: \"KUDOS:10\",\n product_id: \"28\",\n },\n ],\n summary: \"WooTalerShop #100\",\n contractTermsHash:\n \"A02E1M6ARWKBJ87K2TV4S6WQ4X5YH7BRVR6MYCHCTVAED8MBXTFD6PZ5Q50Y7Z5K18PYBTDA14NQ56XPC1VCQW1EVRWTSB7ZYT65B5G\",\n fulfillmentUrl:\n \"https://woocommerce.demo.taler.net/?wc-api=wc_gnutaler_gateway&order_id=wc_order_KQCRldghIgDRB-100\",\n },\n refundQueryActive: false,\n frozen: false,\n },\n {\n type: TransactionType.Refresh,\n txState: {\n major: TransactionMajorState.Pending,\n },\n refreshReason: RefreshReason.PayMerchant,\n amountEffective: \"KUDOS:0\",\n amountRaw: \"KUDOS:0\",\n refreshInputAmount: \"KUDOS:1.5\",\n refreshOutputAmount: \"KUDOS:1.4\",\n originatingTransactionId:\n \"txn:proposal:ZCGBZFE8KZ1CBYYGSC3ZC8E40KVJWV16VYCTHGC8FFSVZ5HD24BG\",\n pending: true,\n timestamp: {\n t_s: 1681376214,\n },\n transactionId:\n \"txn:refresh:QQSWHHXCRQ269G0E3RW14JMC6F7NFDYDW26NSFHRTXSKDS6CMCZ0\",\n frozen: false,\n error: {\n code: 7029,\n when: {\n t_ms: 1681376473665,\n },\n hint: \"Error (WALLET_REFRESH_GROUP_INCOMPLETE)\",\n numErrors: 1,\n errors: [\n {\n code: 7001,\n when: {\n t_ms: 1681376473189,\n },\n hint: \"unexpected exception (message: exchange wire fee signature invalid)\",\n stack:\n \" at validateWireInfo (../taler-wallet-core-qjs.mjs:23166)\\n\",\n },\n ],\n },\n },\n];\n", "/*\n This file is part of GNU Taler\n (C) 2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Taler; see the file COPYING. If not, see \n\n SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { codecForAmountString } from \"./amounts.js\";\nimport {\n Codec,\n buildCodecForObject,\n buildCodecForUnion,\n codecForNumber,\n codecOptional,\n} from \"./codec.js\";\nimport { codecForString, codecForConstString } from \"./index.js\";\nimport { codecForDuration, codecForTimestamp } from \"./time.js\";\nimport {\n AmountString,\n codecForEddsaPublicKey,\n EddsaPublicKeyString,\n EddsaSignatureString,\n HashCodeString,\n Integer,\n RelativeTime,\n Timestamp,\n} from \"./types-taler-common.js\";\n\nexport const codecForTalerMailboxConfigResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"version\", codecForString())\n .property(\"name\", codecForConstString(\"taler-mailbox\"))\n .property(\"monthly_fee\", codecForAmountString())\n .property(\"registration_update_fee\", codecForAmountString())\n .property(\"message_body_bytes\", codecForNumber())\n .property(\"message_response_limit\", codecForNumber())\n .property(\"delivery_period\", codecForDuration)\n .build(\"TalerMailboxApi.VersionResponse\");\n\nexport interface TalerMailboxConfigResponse {\n // libtool-style representation of the Mailbox protocol version, see\n // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning\n // The format is \"current:revision:age\".\n version: string;\n\n // Name of the protocol.\n name: \"taler-mailbox\";\n\n // Fixed size of message body.\n message_body_bytes: Integer;\n\n // Maximum number of messages in a\n // single response.\n message_response_limit: Integer;\n\n // How long will the service store a message\n // before giving up on delivery?\n delivery_period: RelativeTime;\n\n // How much is the cost of a single\n // registration (update) of a mailbox\n // May be 0 for a free update/registration.\n registration_update_fee: AmountString;\n\n // How much is the cost of a single\n // registration period (30 days) of a mailbox\n // May be 0 for a free registration.\n monthly_fee: AmountString;\n}\n\nexport type MailboxRegisterResult =\n | MailboxRegisterOk\n | MailboxRegisterPaymentRequired;\n\nexport interface MailboxRegisterOk {\n status: \"ok\";\n}\n\nexport interface MailboxRegisterPaymentRequired {\n status: \"payment-required\";\n talerUri?: string;\n}\n\nexport const codecForMailboxRegisterOk = (): Codec =>\n buildCodecForObject()\n .property(\"status\", codecForConstString(\"ok\"))\n .build(\"MailboxRegisterOk\");\n\nexport const codecForMailboxRegisterPaymentRequired =\n (): Codec =>\n buildCodecForObject()\n .property(\"status\", codecForConstString(\"payment-required\"))\n .property(\"talerUri\", codecOptional(codecForString()))\n .build(\"MailboxRegisterPaymentRequired\");\n\nexport const codecForMailboxRegisterResult = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"status\")\n .alternative(\"ok\", codecForMailboxRegisterOk())\n .alternative(\"payment-required\", codecForMailboxRegisterPaymentRequired())\n .build(\"MailboxRegisterResult\");\n\nexport const codecForTalerMailboxRegisterRequest =\n (): Codec =>\n buildCodecForObject()\n .property(\"mailbox_metadata\", codecForTalerMailboxMetadata())\n .property(\"signature\", codecForString())\n .build(\"TalerMailboxApi.MailboxRegisterRequest\");\n\nexport interface MailboxRegisterRequest {\n // Mailbox metadata.\n mailbox_metadata: MailboxMetadata;\n\n // Signature by the mailbox's signing key affirming\n // the update of keys, of purpose\n // TALER_SIGNATURE_WALLET_MAILBOX_UPDATE_KEYS.\n // The signature is created over the SHA-512 hash\n // of (encryptionKeyType||encryptionKey||expiration)\n signature: EddsaSignatureString;\n}\n\nexport const codecForTalerMailboxMetadata = (): Codec =>\n buildCodecForObject()\n .property(\"signing_key\", codecForEddsaPublicKey())\n .property(\"signing_key_type\", codecForConstString(\"EdDSA\"))\n .property(\"encryption_key\", codecForString())\n .property(\"encryption_key_type\", codecForConstString(\"X25519\"))\n .property(\"expiration\", codecForTimestamp)\n .build(\"TalerMailboxApi.MailboxMessageKeys\");\n\nexport interface MailboxMetadata {\n // The mailbox signing key.\n // Note that $H_MAILBOX == H(singingKey).\n // Note also how this key cannot be updated\n // as it identifies the mailbox.\n signing_key: EddsaPublicKeyString;\n\n // Type of key.\n // Optional, as currently only\n // EdDSA keys are supported.\n signing_key_type?: string;\n\n // The mailbox encryption key.\n // This is an HPKE public key\n // in the X25519 format for use\n // in a X25519-DHKEM (RFC 9180).\n // Base32 crockford-encoded.\n encryption_key: string;\n\n // Type of key.\n // Optional, as currently only\n // X25519 keys are supported.\n encryption_key_type?: string;\n\n // Expiration of this mapping.\n expiration: Timestamp;\n}\n\nexport const codecForTalerMailboxRateLimitedResponse =\n (): Codec =>\n buildCodecForObject()\n .property(\"code\", codecForNumber())\n .property(\"retry_delay\", codecForDuration)\n .property(\"hint\", codecForString())\n .build(\"TalerMailboxApi.MailboxRateLimitedResponse\");\n\nexport interface MailboxRateLimitedResponse {\n // Taler error code, TALER_EC_MAILBOX_DELIVERY_RATE_LIMITED.\n code: number;\n\n // When the client should retry.\n retry_delay: RelativeTime;\n\n // The human readable error message.\n hint: string;\n}\n", "/*\n This file is part of GNU Taler\n Copyright (C) 2012-2025 Taler Systems SA\n\n GNU Taler is free software: you can redistribute it and/or modify it\n under the terms of the GNU Lesser General Public License as published\n by the Free Software Foundation, either version 3 of the License,\n or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but\n WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see .\n\n SPDX-License-Identifier: LGPL3.0-or-later\n\n Note: the LGPL does not apply to all components of GNU Taler,\n but it does apply to this file.\n */\n\n/**\n * Imports.\n */\n\nexport const TalerAmlProperties = {\n /**\n * Description: Current note on the GWG file.\n *\n * GANA Type: String\n * Deployment: TOPS\n */\n FILE_NOTE: \"FILE_NOTE\" as const,\n /**\n * Description: Customer name or internal alias.\n *\n * GANA Type: String\n * Deployment: TOPS\n */\n CUSTOMER_LABEL: \"CUSTOMER_LABEL\" as const,\n /**\n * Description: Boolean flag indicating whether the account has been opened. The definition of opening an account is deployment-specific.\n *\n * GANA Type: Boolean\n * Deployment: TOPS\n */\n ACCOUNT_OPEN: \"ACCOUNT_OPEN\" as const,\n /**\n * Description: True if the customer is a domestic PEP.\n *\n * GANA Type: Boolean\n * Deployment: TOPS\n */\n PEP_DOMESTIC: \"PEP_DOMESTIC\" as const,\n /**\n * Description: True if the customer is a foreign PEP.\n *\n * GANA Type: Boolean\n * Deployment: TOPS\n */\n PEP_FOREIGN: \"PEP_FOREIGN\" as const,\n /**\n * Description: True if the customer is a international organization PEP.\n *\n * GANA Type: Boolean\n * Deployment: TOPS\n */\n PEP_INTERNATIONAL_ORGANIZATION: \"PEP_INTERNATIONAL_ORGANIZATION\" as const,\n /**\n * Description: True if the customer is a high-risk business.\n *\n * GANA Type: Boolean\n * Deployment: TOPS\n */\n HIGH_RISK_CUSTOMER: \"HIGH_RISK_CUSTOMER\" as const,\n /**\n * Description: True if the customer is associated with a high-risk country.\n *\n * GANA Type: Boolean\n * Deployment: TOPS\n */\n HIGH_RISK_COUNTRY: \"HIGH_RISK_COUNTRY\" as const,\n /**\n * Description: The account has been marked as idle.\n *\n * GANA Type: Boolean\n * Deployment: TOPS\n */\n ACCOUNT_IDLE: \"ACCOUNT_IDLE\" as const,\n /**\n * Description: The MROS reporting state for the account.\n *\n * GANA Type: 'NONE' | 'INVESTIGATION_PENDING' | 'INVESTIGATION_COMPLETED_WITHOUT_SUSPICION' | 'REPORTED_SUSPICION_SIMPLE' | 'REPORTED_SUSPICION_SUBSTANTIATED'\n * Deployment: TOPS\n */\n INVESTIGATION_STATE: \"INVESTIGATION_STATE\" as const,\n /**\n * Description: Informal reason why the AML investigation was triggered. Examples include suspicious transaction or (automated) sanction list match\n *\n * GANA Type: String\n * Deployment: TOPS\n */\n INVESTIGATION_TRIGGER: \"INVESTIGATION_TRIGGER\" as const,\n /**\n * Description: Identifies the sanction list entry that the account matched against (best match, does not mean it was a good match)\n *\n * GANA Type: String\n * Deployment: TOPS\n */\n SANCTION_LIST_BEST_MATCH: \"SANCTION_LIST_BEST_MATCH\" as const,\n /**\n * Description: Score for how good the sanction list match was (0: none, 10**9: perfect match)\n *\n * GANA Type: Integer\n * Deployment: TOPS\n */\n SANCTION_LIST_RATING: \"SANCTION_LIST_RATING\" as const,\n /**\n * Description: Score for how much supporting data we had for the sanction list match (0: none, 10**9: all fields available)\n *\n * GANA Type: Integer\n * Deployment: TOPS\n */\n SANCTION_LIST_CONFIDENCE: \"SANCTION_LIST_CONFIDENCE\" as const,\n /**\n * Description: Suppress flagging this account when it creates a hit on a sanctions list, this is a false-positive.\n *\n * GANA Type: Boolean\n * Deployment: TOPS\n */\n SANCTION_LIST_SUPPRESS: \"SANCTION_LIST_SUPPRESS\" as const,\n};\n", "/*\n This file is part of GNU Taler\n (C) 2024 GNUnet e.V.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { AmountLike } from \"./amounts.js\";\nimport { canonicalJson } from \"./helpers.js\";\nimport {\n bufferFromAmount,\n bufferForUint64,\n buildSigPS,\n decodeCrock,\n EddsaPrivP,\n eddsaSign,\n EddsaSigP,\n hash,\n stringToBytes,\n timestampRoundedToBuffer,\n} from \"./taler-crypto.js\";\nimport { TalerSignaturePurpose } from \"./taler_signatures.js\";\nimport { TalerProtocolTimestamp } from \"./time.js\";\nimport { AmlDecisionRequestWithoutSignature } from \"./types-taler-exchange.js\";\n\n/**\n * Implementation of Taler protocol signatures.\n *\n * In this file, we have implementations of signatures that are not used in the wallet,\n * but in other places (tests, SPAs, ...).\n */\n\n/**\n * Signature for the POST /aml/$OFFICER_PUB/decisions endpoint.\n */\nexport function signAmlDecision(\n priv: Uint8Array,\n decision: AmlDecisionRequestWithoutSignature,\n): Uint8Array {\n const builder = buildSigPS(TalerSignaturePurpose.AML_DECISION);\n\n const flags: number = decision.keep_investigating ? 1 : 0;\n\n builder.put(timestampRoundedToBuffer(decision.decision_time));\n builder.put(\n timestampRoundedToBuffer(\n decision.attributes_expiration ?? TalerProtocolTimestamp.fromSeconds(0),\n ),\n );\n builder.put(decodeCrock(decision.h_payto));\n builder.put(hash(stringToBytes(decision.justification)));\n builder.put(hash(stringToBytes(canonicalJson(decision.properties) + \"\\0\")));\n builder.put(hash(stringToBytes(canonicalJson(decision.new_rules) + \"\\0\")));\n if (decision.new_measures != null) {\n builder.put(hash(stringToBytes(decision.new_measures)));\n } else {\n builder.put(new Uint8Array(64));\n }\n if (decision.attributes != null) {\n builder.put(hash(stringToBytes(canonicalJson(decision.attributes) + \"\\0\")));\n } else {\n builder.put(new Uint8Array(64));\n }\n builder.put(bufferForUint64(flags));\n\n const sigBlob = builder.build();\n\n return eddsaSign(sigBlob, priv);\n}\n\nexport function signAmlQuery(key: Uint8Array): EddsaSigP {\n const sigBlob = buildSigPS(TalerSignaturePurpose.AML_QUERY).build();\n\n return eddsaSign(sigBlob, key);\n}\n\nexport function signWalletAccountSetup(\n key: EddsaPrivP,\n balance: AmountLike,\n): EddsaSigP {\n const sigBlob = buildSigPS(TalerSignaturePurpose.WALLET_ACCOUNT_SETUP)\n .put(bufferFromAmount(balance))\n .build();\n\n return eddsaSign(sigBlob, key);\n}\n\nexport function signKycAuth(key: EddsaPrivP): EddsaSigP {\n const sigBlob = buildSigPS(TalerSignaturePurpose.KYC_AUTH).build();\n\n return eddsaSign(sigBlob, key);\n}\n", "import { TalerAmlProperties } from \"../taler-account-properties.js\";\nimport { TalerFormAttributes } from \"../taler-form-attributes.js\";\nimport { AccountProperties } from \"../types-taler-exchange.js\";\n\n/**\n * List of account properties required by TOPS\n */\nexport const TOPS_AccountProperties = [\n TalerAmlProperties.FILE_NOTE,\n TalerAmlProperties.CUSTOMER_LABEL,\n TalerAmlProperties.ACCOUNT_OPEN,\n TalerAmlProperties.PEP_DOMESTIC,\n TalerAmlProperties.PEP_FOREIGN,\n TalerAmlProperties.PEP_INTERNATIONAL_ORGANIZATION,\n TalerAmlProperties.HIGH_RISK_CUSTOMER,\n TalerAmlProperties.HIGH_RISK_COUNTRY,\n TalerAmlProperties.ACCOUNT_IDLE,\n TalerAmlProperties.INVESTIGATION_TRIGGER,\n TalerAmlProperties.INVESTIGATION_STATE,\n TalerAmlProperties.SANCTION_LIST_BEST_MATCH,\n TalerAmlProperties.SANCTION_LIST_RATING,\n TalerAmlProperties.SANCTION_LIST_CONFIDENCE,\n TalerAmlProperties.SANCTION_LIST_SUPPRESS,\n] as const;\n\n/**\n * List of account properties required by GLS\n */\nexport const GLS_AccountProperties = [TalerAmlProperties.FILE_NOTE] as const;\n\nexport type PropertiesDerivationFunctionByPropertyName = {\n [name in T]: {\n /**\n * Based on all the current properties, the current account limits and\n * new attributes of the account calculate if the property should\n * change. The value \"undefined\" means no change.\n *\n * @param formId the current form being filled by the officer\n * @param newAttributes the values of the current form\n * @param limits\n * @param state the current state of the account\n * @returns\n */\n deriveProperty: (\n formId: string,\n newAttributes: AmlFormAttributesMap,\n state: AccountProperties,\n ) => string | boolean | undefined;\n };\n};\n\n// FIXME: Does this enum really belong in aml/properties.ts?\nexport enum KnownForms {\n vqf_902_1_customer,\n vqf_902_1_officer,\n vqf_902_4,\n vqf_902_5,\n vqf_902_9_customer,\n vqf_902_9_officer,\n vqf_902_11_customer,\n vqf_902_11_officer,\n vqf_902_12,\n vqf_902_13,\n vqf_902_14,\n vqf_902_15,\n}\n\n/**\n * Type of account properties for TOPS AML.\n * Maps account property names to the property value.\n */\nexport type TopsAccountPropertiesMap = {\n [x in (typeof TOPS_AccountProperties)[number]]?: any;\n};\n\n/**\n * Type of form attributes for TOPS AML.\n * Maps form attribute names to the attribute value.\n */\nexport type AmlFormAttributesMap = {\n [x in keyof typeof TalerFormAttributes]?: any;\n};\n\nexport function isOneOf(formId: string, ...allowedForms: KnownForms[]) {\n return (\n -1 !==\n allowedForms.findIndex((af) => {\n return formId === KnownForms[af];\n })\n );\n}\n\n/**\n * Calculate the value of the propertiy for TOPS account properties\n */\nexport const PropertiesDerivation_TOPS: PropertiesDerivationFunctionByPropertyName<\n (typeof TOPS_AccountProperties)[number]\n> = {\n ACCOUNT_OPEN: {\n deriveProperty(formId, attributes, state) {\n if (\n isOneOf(\n formId,\n KnownForms.vqf_902_1_customer,\n KnownForms.vqf_902_1_officer,\n )\n ) {\n // if one of the vqf 902.1 then the account is being open\n return true;\n }\n return undefined;\n },\n },\n PEP_DOMESTIC: {\n deriveProperty(formId, attributes, state) {\n if (isOneOf(formId, KnownForms.vqf_902_4)) {\n return !!attributes[TalerFormAttributes.PEP_DOMESTIC];\n }\n return undefined;\n },\n },\n PEP_FOREIGN: {\n deriveProperty(formId, attributes, state) {\n if (isOneOf(formId, KnownForms.vqf_902_4)) {\n return !!attributes[TalerFormAttributes.PEP_FOREIGN];\n }\n return undefined;\n },\n },\n PEP_INTERNATIONAL_ORGANIZATION: {\n deriveProperty(formId, attributes, state) {\n if (isOneOf(formId, KnownForms.vqf_902_4)) {\n return !!attributes[TalerFormAttributes.PEP_INTERNATIONAL_ORGANIZATION];\n }\n return undefined;\n },\n },\n HIGH_RISK_CUSTOMER: {\n deriveProperty(formId, attributes, state) {\n if (isOneOf(formId, KnownForms.vqf_902_4)) {\n return (\n attributes[TalerFormAttributes.RISK_CLASSIFICATION_LEVEL] ===\n \"HIGH_RISK\"\n );\n }\n return undefined;\n },\n },\n HIGH_RISK_COUNTRY: {\n deriveProperty(formId, attributes, state) {\n if (isOneOf(formId, KnownForms.vqf_902_4)) {\n return (\n attributes[TalerFormAttributes.COUNTRY_RISK_NATIONALITY_LEVEL] ===\n \"HIGH\"\n );\n }\n return undefined;\n },\n },\n ACCOUNT_IDLE: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n CUSTOMER_LABEL: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n FILE_NOTE: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n INVESTIGATION_STATE: {\n deriveProperty(formId, attributes, state) {\n if (isOneOf(formId, KnownForms.vqf_902_14)) {\n if (\n attributes[TalerFormAttributes.INCRISK_RESULT] === \"SIMPLE_SUSPICION\"\n ) {\n return \"REPORTED_SUSPICION_SIMPLE\";\n }\n if (\n attributes[TalerFormAttributes.INCRISK_RESULT] ===\n \"SUBSTANTIATED_SUSPICION\"\n ) {\n return \"REPORTED_SUSPICION_SUBSTANTIATED\";\n }\n if (attributes[TalerFormAttributes.INCRISK_RESULT] === \"NO_SUSPICION\") {\n return \"INVESTIGATION_COMPLETED_WITHOUT_SUSPICION\";\n }\n if (attributes[TalerFormAttributes.INCRISK_RESULT] === \"OTHER\") {\n return null as any;\n }\n }\n\n return undefined;\n },\n },\n INVESTIGATION_TRIGGER: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n SANCTION_LIST_BEST_MATCH: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n SANCTION_LIST_CONFIDENCE: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n SANCTION_LIST_RATING: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n SANCTION_LIST_SUPPRESS: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n};\n\nexport const GLS_AML_PROPERTIES: PropertiesDerivationFunctionByPropertyName<\n (typeof GLS_AccountProperties)[number]\n> = {\n FILE_NOTE: {\n deriveProperty(formId, attributes, state) {\n return undefined;\n },\n },\n};\n\nexport function deriveTopsAmlProperties(\n formId: string,\n newAttributes: AmlFormAttributesMap,\n oldProperties: TopsAccountPropertiesMap,\n): TopsAccountPropertiesMap {\n const props: TopsAccountPropertiesMap = {};\n for (const propName of TOPS_AccountProperties) {\n const propVal = PropertiesDerivation_TOPS[propName].deriveProperty(\n formId,\n newAttributes,\n oldProperties,\n );\n if (propVal !== undefined) {\n props[propName] = propVal;\n }\n }\n return props;\n}\n", "import { Amounts } from \"../amounts.js\";\nimport { TalerAmlProperties } from \"../taler-account-properties.js\";\nimport {\n AccountProperties,\n KycRule,\n LimitOperationType,\n} from \"../types-taler-exchange.js\";\nimport {\n AmlFormAttributesMap,\n isOneOf,\n TopsAccountPropertiesMap,\n} from \"./properties.js\";\n\n// FIXME: We really ought to have a GANA registry for AML event names\n\n/**\n * List of events triggered by TOPS\n */\nexport enum TOPS_AmlEventsName {\n INCR_ACCOUNT_OPEN = \"INCR_ACCOUNT_OPEN\",\n DECR_ACCOUNT_OPEN = \"DECR_ACCOUNT_OPEN\",\n INCR_HIGH_RISK_CUSTOMER = \"INCR_HIGH_RISK_CUSTOMER\",\n DECR_HIGH_RISK_CUSTOMER = \"DECR_HIGH_RISK_CUSTOMER\",\n INCR_HIGH_RISK_COUNTRY = \"INCR_HIGH_RISK_COUNTRY\",\n DECR_HIGH_RISK_COUNTRY = \"DECR_HIGH_RISK_COUNTRY\",\n INCR_PEP = \"INCR_PEP\",\n DECR_PEP = \"DECR_PEP\",\n INCR_PEP_FOREIGN = \"INCR_PEP_FOREIGN\",\n DECR_PEP_FOREIGN = \"DECR_PEP_FOREIGN\",\n INCR_PEP_DOMESTIC = \"INCR_PEP_DOMESTIC\",\n DECR_PEP_DOMESTIC = \"DECR_PEP_DOMESTIC\",\n INCR_PEP_INTERNATIONAL_ORGANIZATION = \"INCR_PEP_INTERNATIONAL_ORGANIZATION\",\n DECR_PEP_INTERNATIONAL_ORGANIZATION = \"DECR_PEP_INTERNATIONAL_ORGANIZATION\",\n MROS_REPORTED_SUSPICION_SIMPLE = \"MROS_REPORTED_SUSPICION_SIMPLE\",\n MROS_REPORTED_SUSPICION_SUBSTANTIATED = \"MROS_REPORTED_SUSPICION_SUBSTANTIATED\",\n INCR_INVESTIGATION_CONCLUDED = \"INCR_INVESTIGATION_CONCLUDED\",\n DECR_INVESTIGATION_CONCLUDED = \"DECR_INVESTIGATION_CONCLUDED\",\n}\n\n/**\n * List of events triggered by GLS\n */\nexport enum GLS_AmlEventsName {\n ACCOUNT_OPENED = \"ACCOUNT_OPENED\",\n ACCOUNT_CLOSED = \"ACCOUNT_CLOSED\",\n}\n\nenum KnownForms {\n vqf_902_1_customer,\n vqf_902_1_officer,\n vqf_902_4,\n vqf_902_5,\n vqf_902_9_customer,\n vqf_902_9_officer,\n vqf_902_11_customer,\n vqf_902_11_officer,\n vqf_902_12,\n vqf_902_13,\n vqf_902_14,\n vqf_902_15,\n}\n\nexport type EventMapInfo = {\n [name in keyof T]: {\n /**\n * Based on the current properties and next properties,\n * the current account limits and new attributes of the account\n * calculate if the event should be triggered.\n *\n * return false if there is no enough information to decide.\n *\n * @param prevLimits current active decision limits, undefined if this account has no active decision yet\n * @param nextLimits limits of the decision to be made, undefined if not yet decided\n * @param prevState current active decision properties, undefined if this account has no active decision yet\n * @param nextState new properties of the account defined by the decision, undefined if not yet decided\n * @param newAttributes new information added by this decision\n * @returns\n */\n shouldBeTriggered: (\n formId: string,\n prevState: AccountProperties | undefined,\n nextState: AccountProperties | undefined,\n newAttributes: Record,\n ) => boolean;\n };\n};\n\nfunction isAllowToMakeDeposits(limits: KycRule[]) {\n const depositLimits = limits.filter(\n (r) => r.operation_type === LimitOperationType.deposit,\n );\n // no deposit limits\n if (!depositLimits.length) return true;\n const zero = depositLimits.find((d) => Amounts.isZero(d.threshold));\n // there is a rule that prohibit deposit\n if (zero) return false;\n // the cusomter can at least make some deposits\n return true;\n}\n\nfunction propBecameTrue(\n prevState: AccountProperties | undefined,\n nextState: AccountProperties,\n prop: string,\n): boolean {\n const wasFalse = prevState === undefined || !prevState[prop];\n const isTrue = !!nextState[prop];\n return wasFalse && isTrue;\n}\n\nfunction propBecameFalse(\n prevState: AccountProperties | undefined,\n nextState: AccountProperties,\n prop: string,\n): boolean {\n const wasTrue = prevState !== undefined && !!prevState[prop];\n const isFalse = !nextState[prop];\n return wasTrue && isFalse;\n}\n\nfunction isAnyKindOfPep(state: AccountProperties): boolean {\n return (\n !!state[TalerAmlProperties.PEP_INTERNATIONAL_ORGANIZATION] ||\n !!state[TalerAmlProperties.PEP_DOMESTIC] ||\n !!state[TalerAmlProperties.PEP_FOREIGN]\n );\n}\n\n/**\n * Calculate if an event should be triggered for TOPS decisions\n */\nexport const EventsDerivation_TOPS: EventMapInfo = {\n INCR_ACCOUNT_OPEN: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n if (\n isOneOf(\n formId,\n KnownForms.vqf_902_1_customer,\n KnownForms.vqf_902_1_officer,\n ) &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.ACCOUNT_OPEN)\n ) {\n return true; // # event-rule 1\n }\n\n return false;\n },\n },\n DECR_ACCOUNT_OPEN: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n return false;\n },\n },\n INCR_HIGH_RISK_CUSTOMER: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n if (\n isOneOf(\n formId,\n KnownForms.vqf_902_1_customer,\n KnownForms.vqf_902_1_officer,\n ) &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.ACCOUNT_OPEN) &&\n !!nextState[TalerAmlProperties.HIGH_RISK_CUSTOMER]\n ) {\n return true; // # event-rule 6\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameTrue(\n prevState,\n nextState,\n TalerAmlProperties.HIGH_RISK_CUSTOMER,\n )\n ) {\n return true; // # event-rule 18\n }\n return false;\n },\n },\n DECR_HIGH_RISK_CUSTOMER: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameFalse(\n prevState,\n nextState,\n TalerAmlProperties.HIGH_RISK_CUSTOMER,\n )\n ) {\n return true; // # event-rule 19\n }\n return false;\n },\n },\n INCR_HIGH_RISK_COUNTRY: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n if (\n isOneOf(\n formId,\n KnownForms.vqf_902_1_customer,\n KnownForms.vqf_902_1_officer,\n ) &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.ACCOUNT_OPEN) &&\n !!nextState[TalerAmlProperties.HIGH_RISK_COUNTRY]\n ) {\n return true; // # event-rule 7\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameTrue(\n prevState,\n nextState,\n TalerAmlProperties.HIGH_RISK_CUSTOMER,\n )\n ) {\n return true; // # event-rule 16\n }\n return false;\n },\n },\n DECR_HIGH_RISK_COUNTRY: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameFalse(\n prevState,\n nextState,\n TalerAmlProperties.HIGH_RISK_CUSTOMER,\n )\n ) {\n return true; // # event-rule 17\n }\n return false;\n },\n },\n INCR_PEP: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n const isPep = isAnyKindOfPep(nextState);\n if (\n isOneOf(\n formId,\n KnownForms.vqf_902_1_customer,\n KnownForms.vqf_902_1_officer,\n ) &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.ACCOUNT_OPEN) &&\n isPep\n ) {\n return true; // # event-rule 2\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n const wasPep = isAnyKindOfPep(prevState);\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n !wasPep &&\n isPep\n ) {\n return true; // # event-rule 15\n }\n return false;\n },\n },\n DECR_PEP: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n const wasPep = isAnyKindOfPep(prevState);\n const isPep = isAnyKindOfPep(nextState);\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n wasPep &&\n !isPep\n ) {\n return true; // # event-rule 14\n }\n return false;\n },\n },\n INCR_PEP_FOREIGN: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n if (\n isOneOf(\n formId,\n KnownForms.vqf_902_1_customer,\n KnownForms.vqf_902_1_officer,\n ) &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.ACCOUNT_OPEN) &&\n !!nextState[TalerAmlProperties.PEP_FOREIGN]\n ) {\n return true; // # event-rule 3\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.PEP_FOREIGN)\n ) {\n return true; // # event-rule 8\n }\n return false;\n },\n },\n DECR_PEP_FOREIGN: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameFalse(prevState, nextState, TalerAmlProperties.PEP_FOREIGN)\n ) {\n return true; // # event-rule 11\n }\n return false;\n },\n },\n INCR_PEP_DOMESTIC: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n if (\n isOneOf(\n formId,\n KnownForms.vqf_902_1_customer,\n KnownForms.vqf_902_1_officer,\n ) &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.ACCOUNT_OPEN) &&\n !!nextState[TalerAmlProperties.PEP_DOMESTIC]\n ) {\n return true; // # event-rule 4\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.PEP_DOMESTIC)\n ) {\n return true; // # event-rule 10\n }\n return false;\n },\n },\n DECR_PEP_DOMESTIC: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameFalse(prevState, nextState, TalerAmlProperties.PEP_DOMESTIC)\n ) {\n return true; // # event-rule 13\n }\n return false;\n },\n },\n INCR_PEP_INTERNATIONAL_ORGANIZATION: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n if (\n isOneOf(\n formId,\n KnownForms.vqf_902_1_customer,\n KnownForms.vqf_902_1_officer,\n ) &&\n propBecameTrue(prevState, nextState, TalerAmlProperties.ACCOUNT_OPEN) &&\n !!nextState[TalerAmlProperties.PEP_INTERNATIONAL_ORGANIZATION]\n ) {\n return true; // # event-rule 5\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameTrue(\n prevState,\n nextState,\n TalerAmlProperties.PEP_INTERNATIONAL_ORGANIZATION,\n )\n ) {\n return true; // # event-rule 9\n }\n return false;\n },\n },\n DECR_PEP_INTERNATIONAL_ORGANIZATION: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (nextState === undefined) {\n return false;\n }\n // only accounts with history after this\n if (prevState === undefined) {\n return false;\n }\n if (\n isOneOf(formId, KnownForms.vqf_902_4) &&\n !!prevState[TalerAmlProperties.ACCOUNT_OPEN] &&\n propBecameFalse(\n prevState,\n nextState,\n TalerAmlProperties.PEP_INTERNATIONAL_ORGANIZATION,\n )\n ) {\n return true; // # event-rule 12\n }\n return false;\n },\n },\n MROS_REPORTED_SUSPICION_SIMPLE: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (prevState === undefined || nextState === undefined) {\n return false;\n }\n if (\n prevState[TalerAmlProperties.INVESTIGATION_STATE] === \"NONE\" ||\n prevState[TalerAmlProperties.INVESTIGATION_STATE] ===\n \"INVESTIGATION_PENDING\" ||\n !prevState[TalerAmlProperties.INVESTIGATION_STATE]\n ) {\n if (\n nextState[TalerAmlProperties.INVESTIGATION_STATE] ===\n \"REPORTED_SUSPICION_SIMPLE\"\n ) {\n return true; // # event-rule 22\n }\n }\n return false;\n },\n },\n MROS_REPORTED_SUSPICION_SUBSTANTIATED: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (prevState === undefined || nextState === undefined) {\n return false;\n }\n if (\n prevState[TalerAmlProperties.INVESTIGATION_STATE] === \"NONE\" ||\n prevState[TalerAmlProperties.INVESTIGATION_STATE] ===\n \"INVESTIGATION_PENDING\" ||\n !prevState[TalerAmlProperties.INVESTIGATION_STATE]\n ) {\n if (\n nextState[TalerAmlProperties.INVESTIGATION_STATE] ===\n \"REPORTED_SUSPICION_SUBSTANTIATED\"\n ) {\n return true; // # event-rule 21\n }\n }\n return false;\n },\n },\n INCR_INVESTIGATION_CONCLUDED: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n if (prevState === undefined || nextState === undefined) {\n return false;\n }\n if (\n prevState[TalerAmlProperties.INVESTIGATION_STATE] === \"NONE\" ||\n prevState[TalerAmlProperties.INVESTIGATION_STATE] ===\n \"INVESTIGATION_PENDING\" ||\n !prevState[TalerAmlProperties.INVESTIGATION_STATE]\n ) {\n if (\n nextState[TalerAmlProperties.INVESTIGATION_STATE] ===\n \"REPORTED_SUSPICION_SIMPLE\" ||\n nextState[TalerAmlProperties.INVESTIGATION_STATE] ===\n \"REPORTED_SUSPICION_SUBSTANTIATED\" ||\n nextState[TalerAmlProperties.INVESTIGATION_STATE] ===\n \"INVESTIGATION_COMPLETED_WITHOUT_SUSPICION\"\n ) {\n return true; // # event-rule 20\n }\n }\n return false;\n },\n },\n DECR_INVESTIGATION_CONCLUDED: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n return false;\n },\n },\n};\n\nexport const GLS_AML_EVENTS: EventMapInfo = {\n ACCOUNT_OPENED: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n return false;\n },\n },\n ACCOUNT_CLOSED: {\n shouldBeTriggered(formId, prevState, nextState, attr) {\n return false;\n },\n },\n};\n\nconst topsEventNames = Object.values(TOPS_AmlEventsName);\n\nexport function deriveTopsAmlEvents(\n formId: string,\n newAttributes: AmlFormAttributesMap,\n oldProperties: TopsAccountPropertiesMap,\n newProperties: TopsAccountPropertiesMap,\n): Set {\n const events: Set = new Set();\n for (const evt of topsEventNames) {\n const h = EventsDerivation_TOPS[evt];\n if (\n h.shouldBeTriggered(formId, oldProperties, newProperties, newAttributes)\n ) {\n events.add(evt);\n }\n }\n return events;\n}\n", "import { TalerExchangeHttpClient } from \"../http-client/exchange-client.js\";\nimport { AbsoluteTime, Duration } from \"../time.js\";\nimport { OfficerSession } from \"../types-taler-common.js\";\nimport { TOPS_AmlEventsName } from \"./events.js\";\n\n/**\n * Define a set of parameters to make a request to the server\n */\nexport type EventQuery = {\n event: Ev;\n start: AbsoluteTime | undefined;\n end: AbsoluteTime | undefined;\n};\n\n/**\n * Map between a name and a request parameter\n */\nexport type QueryModel = {\n [name: string]: EventQuery;\n};\n\n/**\n * All the request needed to create the Event Reporting (TOPS)\n * https://docs.taler.net/deployments/tops.html#event-reporting-tops\n *\n * Maps a request key to request parameters\n *\n */\nexport const EventReporting_TOPS_queries = {\n // Number of accounts that are opened\n accounts_open_incr: {\n event: TOPS_AmlEventsName.INCR_ACCOUNT_OPEN,\n start: undefined,\n end: undefined,\n },\n accounts_open_decr: {\n event: TOPS_AmlEventsName.DECR_ACCOUNT_OPEN,\n start: undefined,\n end: undefined,\n },\n // Number of new GwG files in the last year\n gwg_files_new_last_year: {\n event: TOPS_AmlEventsName.INCR_ACCOUNT_OPEN,\n start: AbsoluteTime.addDuration(\n AbsoluteTime.now(),\n Duration.fromSpec({ years: -1 }),\n ),\n end: AbsoluteTime.now(),\n },\n // Number of GwG files closed in the last year\n gwg_files_closed_last_year: {\n event: TOPS_AmlEventsName.DECR_ACCOUNT_OPEN,\n start: AbsoluteTime.addDuration(\n AbsoluteTime.now(),\n Duration.fromSpec({ years: -1 }),\n ),\n end: AbsoluteTime.now(),\n },\n // Number of GwG files of high-risk customers\n gwg_files_high_risk_incr: {\n event: TOPS_AmlEventsName.INCR_HIGH_RISK_CUSTOMER, //FIXME: spec refers to INCR_HIGH_RISK\n start: undefined,\n end: undefined,\n },\n gwg_files_high_risk_decr: {\n event: TOPS_AmlEventsName.DECR_HIGH_RISK_CUSTOMER,\n start: undefined,\n end: undefined,\n },\n // Number of GwG files managed with \u201Cincreased risk\u201D due to PEP status\n gwg_files_pep_incr: {\n event: TOPS_AmlEventsName.INCR_PEP,\n start: undefined,\n end: undefined,\n },\n gwg_files_pep_decr: {\n event: TOPS_AmlEventsName.DECR_PEP,\n start: undefined,\n end: undefined,\n },\n // Number of MROS reports based on Art 9 Abs. 1 GwG (per year)\n mros_reports_art9_last_year: {\n event: TOPS_AmlEventsName.MROS_REPORTED_SUSPICION_SUBSTANTIATED,\n start: AbsoluteTime.addDuration(\n AbsoluteTime.now(),\n Duration.fromSpec({ years: -1 }),\n ),\n end: AbsoluteTime.now(),\n },\n // Number of MROS reports based on Art 305ter Abs. 2 StGB (per year)\n mros_reports_art305_last_year: {\n event: TOPS_AmlEventsName.MROS_REPORTED_SUSPICION_SIMPLE,\n start: AbsoluteTime.addDuration(\n AbsoluteTime.now(),\n Duration.fromSpec({ years: -1 }),\n ),\n end: AbsoluteTime.now(),\n },\n // Number of customers involved in proceedings for which Art 6 GwG did apply\n accounts_involed_in_proceedings_last_year: {\n event: TOPS_AmlEventsName.INCR_INVESTIGATION_CONCLUDED, //FIXME: spec refers to INCR_INVESTIGATION\n start: AbsoluteTime.addDuration(\n AbsoluteTime.now(),\n Duration.fromSpec({ years: -1 }),\n ),\n end: AbsoluteTime.now(),\n },\n} satisfies QueryModel;\n\n/**\n * All the calculation needed to create the Event Reporting (TOPS)\n * https://docs.taler.net/deployments/tops.html#event-reporting-tops\n *\n * Maps a event reporting name with a calculation which uses the\n * result of a query to the server.\n *\n * @param events The result of event reporting query\n * @returns\n */\nexport const EventReporting_TOPS_calculation = (\n events: CounterResultByEventName,\n) =>\n ({\n // Number of accounts that are opened:\n accounts_opened: safeSub(\n events.accounts_open_incr,\n events.accounts_open_decr,\n ),\n\n // Number of new GwG files in the last year.\n new_gwg_files_last_year: events.gwg_files_new_last_year,\n\n // Number of GwG files closed in the last year\n gwg_files_closed_last_year: events.gwg_files_closed_last_year,\n\n // Number of GwG files of high-risk customers\n gwg_files_high_risk: safeSub(\n events.gwg_files_high_risk_incr,\n events.gwg_files_high_risk_decr,\n ),\n\n // Number of GwG files managed with \u201Cincreased risk\u201D due to PEP status\n gwg_files_pep: safeSub(\n events.gwg_files_pep_incr,\n events.gwg_files_pep_decr,\n ),\n\n // Number of MROS reports based on Art 9 Abs. 1 GwG (per year)\n mros_reports_art9_last_year: events.mros_reports_art9_last_year,\n\n // Number of MROS reports based on Art 305ter Abs. 2 StGB (per year)\n mros_reports_art305_last_year: events.mros_reports_art305_last_year,\n\n // Number of customers involved in proceedings for which Art 6 GwG did apply\n accounts_involed_in_proceedings_last_year:\n events.accounts_involed_in_proceedings_last_year,\n }) as const;\n\n/**\n * All the request needed to create the Event Reporting (CQF)\n * https://docs.taler.net/deployments/tops.html#event-reporting-vqf\n *\n * Maps a request key to request parameters.\n * Requires the times for the query range.\n *\n */\nexport const EventReporting_VQF_queries = (\n jan_1st: AbsoluteTime,\n dec_31st: AbsoluteTime,\n) => {\n const zero = AbsoluteTime.fromMilliseconds(0);\n\n return {\n // Number of open accounts on January 1st (self-declaration 3.1.1)\n accounts_open_first_jan_incr: {\n event: TOPS_AmlEventsName.INCR_ACCOUNT_OPEN,\n start: zero,\n end: jan_1st,\n },\n accounts_open_first_jan_decr: {\n event: TOPS_AmlEventsName.INCR_ACCOUNT_OPEN,\n start: zero,\n end: jan_1st,\n },\n // Number of newly opened accounts between 01.01.20XX and 31.12.20XX (self-declaration 3.1.2.)\n accounts_opened_on_year: {\n event: TOPS_AmlEventsName.INCR_ACCOUNT_OPEN,\n start: jan_1st,\n end: dec_31st,\n },\n // Number of AML files managed during the year 20XX (self-declaration 3.1.3.)\n aml_files_managed_on_year_incr: {\n event: TOPS_AmlEventsName.INCR_ACCOUNT_OPEN,\n start: zero,\n end: dec_31st,\n },\n aml_files_managed_on_year_decr: {\n event: TOPS_AmlEventsName.DECR_ACCOUNT_OPEN,\n start: zero,\n end: jan_1st,\n },\n // Number of AML files closed between 01.01.20XX and 31.12.20XX (self-declaration 3.1.4)\n aml_files_closed_on_year: {\n event: TOPS_AmlEventsName.DECR_ACCOUNT_OPEN,\n start: jan_1st,\n end: dec_31st,\n },\n // Were there business relationships in the year 20XX with high risk? (self-declaration 4.1)\n accounts_high_risk_incr: {\n event: TOPS_AmlEventsName.INCR_HIGH_RISK_CUSTOMER,\n start: zero,\n end: dec_31st,\n },\n accounts_high_risk_decr: {\n event: TOPS_AmlEventsName.DECR_HIGH_RISK_CUSTOMER,\n start: zero,\n end: dec_31st,\n },\n // Of those, how many were with PEPs? (self-declaration 4.2.)\n accounts_pep_incr: {\n event: TOPS_AmlEventsName.INCR_PEP,\n start: zero,\n end: dec_31st,\n },\n accounts_pep_decr: {\n event: TOPS_AmlEventsName.DECR_PEP,\n start: zero,\n end: dec_31st,\n },\n // Of those PEPs, how many were with foreign PEPs? (self-declaration 4.3.)\n accounts_pep_foreign_incr: {\n event: TOPS_AmlEventsName.INCR_PEP_FOREIGN,\n start: zero,\n end: dec_31st,\n },\n accounts_pep_foreign_decr: {\n event: TOPS_AmlEventsName.DECR_PEP_FOREIGN,\n start: zero,\n end: dec_31st,\n },\n // Number of other additional (other than PEPs and foreign PEPs) high-risk business relationships in 20XX\n // comment: no need to add extra query\n //\n // Number of high-risk business relationship n total in 20xx (self-declaration 4.5.)\n // comment: we have this information already\n //\n // Number of reports (substantiated suspicion) to MROS during 20xx (self-declaration 5.1)\n mros_suspicion_substantiated: {\n event: TOPS_AmlEventsName.MROS_REPORTED_SUSPICION_SUBSTANTIATED,\n start: jan_1st,\n end: dec_31st,\n },\n // Number of reports (simple suspicion) to MROS during 20xx (self-declaration 5.2)\n mros_suspicion_simple: {\n event: TOPS_AmlEventsName.MROS_REPORTED_SUSPICION_SIMPLE,\n start: jan_1st,\n end: dec_31st,\n },\n // Total number of reports to MROS during 20xx (self-declaration 5.3)\n // comment: no need to add extra query\n } satisfies QueryModel;\n};\n\nexport const EventReporting_VQF_calculation = (\n events: CounterResultByEventName<\n ReturnType\n >,\n) => {\n return {\n // Number of open accounts on January 1st (self-declaration 3.1.1)\n accounts_open_first_jan: safeSub(\n events.accounts_open_first_jan_incr,\n events.accounts_open_first_jan_decr,\n ),\n\n // Number of newly opened accounts between 01.01.20XX and 31.12.20XX (self-declaration 3.1.2.)\n accounts_opened_on_year: events.accounts_opened_on_year,\n\n // Number of AML files managed during the year 20XX (self-declaration 3.1.3.)\n aml_files_managed_on_year: safeSub(\n events.aml_files_managed_on_year_incr,\n events.aml_files_managed_on_year_decr,\n ),\n\n // Number of AML files closed between 01.01.20XX and 31.12.20XX (self-declaration 3.1.4)\n aml_files_closed_on_year: events.aml_files_closed_on_year,\n\n // Were there business relationships in the year 20XX with high risk? (self-declaration 4.1)\n accounts_high_risk: safeSub(\n events.accounts_high_risk_incr,\n events.accounts_high_risk_decr,\n ),\n\n // Of those, how many were with PEPs? (self-declaration 4.2.)\n accounts_pep: safeSub(events.accounts_pep_incr, events.accounts_pep_decr),\n\n // Of those PEPs, how many were with foreign PEPs? (self-declaration 4.3.)\n accounts_pep_foreign: safeSub(\n events.accounts_pep_foreign_incr,\n events.accounts_pep_foreign_decr,\n ),\n\n // Number of other additional (other than PEPs and foreign PEPs) high-risk business relationships in 20XX (self-declaration 4.4.)\n accounts_high_risk_other: safeSub(\n safeSub(events.accounts_high_risk_incr, events.accounts_high_risk_decr), // 4.5\n safeSub(events.accounts_pep_incr, events.accounts_pep_decr), // 4.2\n ),\n\n // Number of high-risk business relationship n total in 20xx (self-declaration 4.5.)\n // comment: already implemented on 4.1\n\n // Number of reports (substantiated suspicion) to MROS during 20xx (self-declaration 5.1)\n mros_suspicion_substantiated: events.mros_suspicion_substantiated,\n\n // Number of reports (simple suspicion) to MROS during 20xx (self-declaration 5.2)\n mros_suspicion_simple: events.mros_suspicion_simple,\n\n // Total number of reports to MROS during 20xx (self-declaration 5.3)\n mros_total: safeAdd(\n events.mros_suspicion_substantiated,\n events.mros_suspicion_simple,\n ),\n };\n};\n\nexport type CounterResultByEventName = {\n [name in keyof T]?: number;\n};\n\nexport type EventQueryByEventName = {\n [name in keyof T]: EventQuery;\n};\n\nfunction safeSub(\n a: number | undefined,\n b: number | undefined,\n): number | undefined {\n return a === undefined || b == undefined ? undefined : a - b;\n}\nfunction safeAdd(\n a: number | undefined,\n b: number | undefined,\n): number | undefined {\n return a === undefined || b == undefined ? undefined : a + b;\n}\n\nexport async function fetchTopsInfoFromServer(\n api: TalerExchangeHttpClient,\n officer: OfficerSession,\n) {\n type EventType = typeof EventReporting_TOPS_queries;\n const eventList = Object.entries(EventReporting_TOPS_queries);\n\n const allQueries = eventList.map(async ([_key, value]) => {\n const key = _key as keyof EventType;\n const response = await api.getAmlKycStatistics(officer, [value.event], {\n since: value.start,\n until: value.end,\n });\n return { key, response };\n });\n\n const allResponses = await Promise.all(allQueries);\n\n const resultMap = allResponses.reduce((prev, event) => {\n prev[event.key] =\n event.response.type === \"ok\"\n ? event.response.body.statistics[0].counter\n : undefined;\n return prev;\n }, {} as CounterResultByEventName);\n\n return EventReporting_TOPS_calculation(resultMap);\n}\n\nexport async function fetchVqfInfoFromServer(\n api: TalerExchangeHttpClient,\n officer: OfficerSession,\n jan_1st: AbsoluteTime,\n dec_31st: AbsoluteTime,\n) {\n const VQF_EVENTS_THIS_YEAR = EventReporting_VQF_queries(jan_1st, dec_31st);\n type EventType = typeof VQF_EVENTS_THIS_YEAR;\n const eventList = Object.entries(VQF_EVENTS_THIS_YEAR);\n\n // type QueryAndEvent = { query: string; eventName: string };\n // type RawTime = AbsoluteTime[\"t_ms\"];\n // // group by start & end\n // const groupedEvents = eventList.reduce(\n // (prev, [query, metric]) => {\n // if (!prev.has(metric.start.t_ms)) {\n // prev.set(metric.start.t_ms, new Map());\n // }\n // const st = prev.get(metric.start.t_ms)!;\n // if (!st.has(metric.end.t_ms)) {\n // st.set(metric.end.t_ms, []);\n // }\n // const ed = st.get(metric.end.t_ms)!;\n\n // ed.push({\n // query,\n // eventName: metric.event,\n // });\n // return prev;\n // },\n // {} as Map>,\n // );\n\n // groupedEvents.entries()\n // const groupedEventsList = Object.entries(groupedEvents).flatMap(\n // ([startStr, map]) => {\n // return Object.entries(map).flatMap(([endStr, list]) => {\n // const start =\n // startStr === \"never\"\n // ? AbsoluteTime.never()\n // : AbsoluteTime.fromMilliseconds(Number.parseInt(startStr, 10));\n // const end =\n // endStr === \"never\"\n // ? AbsoluteTime.never()\n // : AbsoluteTime.fromMilliseconds(Number.parseInt(endStr, 10));\n\n // return list;\n // });\n // },\n // );\n\n const allQueries = eventList.map(async ([_key, value]) => {\n const key = _key as keyof EventType;\n const response = await api.getAmlKycStatistics(officer, [value.event], {\n since: value.start,\n until: value.end,\n });\n return { key, response };\n });\n\n const allResponses = await Promise.all(allQueries);\n\n const resultMap = allResponses.reduce((prev, event) => {\n prev[event.key] =\n event.response.type === \"ok\"\n ? event.response.body.statistics[0].counter\n : undefined;\n return prev;\n }, {} as CounterResultByEventName);\n\n return EventReporting_VQF_calculation(resultMap);\n}\n", "/*\n This file is part of GNU Taler\n (C) 2021 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n// Entry point for the browser.\n\nimport { loadBrowserPrng } from \"./prng-browser.js\";\nloadBrowserPrng();\nexport * from \"./index.js\";\n\n// The web stuff doesn't support package.json export declarations yet,\n// so we export more stuff here than we should.\nexport * from \"./http-common.js\";\n", "//---------------------------------------------------------------------\n//\n// QR Code Generator for JavaScript\n//\n// Copyright (c) 2009 Kazuhiko Arase\n//\n// URL: http://www.d-project.com/\n//\n// Licensed under the MIT license:\n// http://www.opensource.org/licenses/mit-license.php\n//\n// The word 'QR Code' is registered trademark of\n// DENSO WAVE INCORPORATED\n// http://www.denso-wave.com/qrcode/faqpatent-e.html\n//\n//---------------------------------------------------------------------\n\nvar qrcode = function() {\n\n //---------------------------------------------------------------------\n // qrcode\n //---------------------------------------------------------------------\n\n /**\n * qrcode\n * @param typeNumber 1 to 40\n * @param errorCorrectionLevel 'L','M','Q','H'\n */\n var qrcode = function(typeNumber, errorCorrectionLevel) {\n\n var PAD0 = 0xEC;\n var PAD1 = 0x11;\n\n var _typeNumber = typeNumber;\n var _errorCorrectionLevel = QRErrorCorrectionLevel[errorCorrectionLevel];\n var _modules = null;\n var _moduleCount = 0;\n var _dataCache = null;\n var _dataList = [];\n\n var _this = {};\n\n var makeImpl = function(test, maskPattern) {\n\n _moduleCount = _typeNumber * 4 + 17;\n _modules = function(moduleCount) {\n var modules = new Array(moduleCount);\n for (var row = 0; row < moduleCount; row += 1) {\n modules[row] = new Array(moduleCount);\n for (var col = 0; col < moduleCount; col += 1) {\n modules[row][col] = null;\n }\n }\n return modules;\n }(_moduleCount);\n\n setupPositionProbePattern(0, 0);\n setupPositionProbePattern(_moduleCount - 7, 0);\n setupPositionProbePattern(0, _moduleCount - 7);\n setupPositionAdjustPattern();\n setupTimingPattern();\n setupTypeInfo(test, maskPattern);\n\n if (_typeNumber >= 7) {\n setupTypeNumber(test);\n }\n\n if (_dataCache == null) {\n _dataCache = createData(_typeNumber, _errorCorrectionLevel, _dataList);\n }\n\n mapData(_dataCache, maskPattern);\n };\n\n var setupPositionProbePattern = function(row, col) {\n\n for (var r = -1; r <= 7; r += 1) {\n\n if (row + r <= -1 || _moduleCount <= row + r) continue;\n\n for (var c = -1; c <= 7; c += 1) {\n\n if (col + c <= -1 || _moduleCount <= col + c) continue;\n\n if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )\n || (0 <= c && c <= 6 && (r == 0 || r == 6) )\n || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {\n _modules[row + r][col + c] = true;\n } else {\n _modules[row + r][col + c] = false;\n }\n }\n }\n };\n\n var getBestMaskPattern = function() {\n\n var minLostPoint = 0;\n var pattern = 0;\n\n for (var i = 0; i < 8; i += 1) {\n\n makeImpl(true, i);\n\n var lostPoint = QRUtil.getLostPoint(_this);\n\n if (i == 0 || minLostPoint > lostPoint) {\n minLostPoint = lostPoint;\n pattern = i;\n }\n }\n\n return pattern;\n };\n\n var setupTimingPattern = function() {\n\n for (var r = 8; r < _moduleCount - 8; r += 1) {\n if (_modules[r][6] != null) {\n continue;\n }\n _modules[r][6] = (r % 2 == 0);\n }\n\n for (var c = 8; c < _moduleCount - 8; c += 1) {\n if (_modules[6][c] != null) {\n continue;\n }\n _modules[6][c] = (c % 2 == 0);\n }\n };\n\n var setupPositionAdjustPattern = function() {\n\n var pos = QRUtil.getPatternPosition(_typeNumber);\n\n for (var i = 0; i < pos.length; i += 1) {\n\n for (var j = 0; j < pos.length; j += 1) {\n\n var row = pos[i];\n var col = pos[j];\n\n if (_modules[row][col] != null) {\n continue;\n }\n\n for (var r = -2; r <= 2; r += 1) {\n\n for (var c = -2; c <= 2; c += 1) {\n\n if (r == -2 || r == 2 || c == -2 || c == 2\n || (r == 0 && c == 0) ) {\n _modules[row + r][col + c] = true;\n } else {\n _modules[row + r][col + c] = false;\n }\n }\n }\n }\n }\n };\n\n var setupTypeNumber = function(test) {\n\n var bits = QRUtil.getBCHTypeNumber(_typeNumber);\n\n for (var i = 0; i < 18; i += 1) {\n var mod = (!test && ( (bits >> i) & 1) == 1);\n _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;\n }\n\n for (var i = 0; i < 18; i += 1) {\n var mod = (!test && ( (bits >> i) & 1) == 1);\n _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n }\n };\n\n var setupTypeInfo = function(test, maskPattern) {\n\n var data = (_errorCorrectionLevel << 3) | maskPattern;\n var bits = QRUtil.getBCHTypeInfo(data);\n\n // vertical\n for (var i = 0; i < 15; i += 1) {\n\n var mod = (!test && ( (bits >> i) & 1) == 1);\n\n if (i < 6) {\n _modules[i][8] = mod;\n } else if (i < 8) {\n _modules[i + 1][8] = mod;\n } else {\n _modules[_moduleCount - 15 + i][8] = mod;\n }\n }\n\n // horizontal\n for (var i = 0; i < 15; i += 1) {\n\n var mod = (!test && ( (bits >> i) & 1) == 1);\n\n if (i < 8) {\n _modules[8][_moduleCount - i - 1] = mod;\n } else if (i < 9) {\n _modules[8][15 - i - 1 + 1] = mod;\n } else {\n _modules[8][15 - i - 1] = mod;\n }\n }\n\n // fixed module\n _modules[_moduleCount - 8][8] = (!test);\n };\n\n var mapData = function(data, maskPattern) {\n\n var inc = -1;\n var row = _moduleCount - 1;\n var bitIndex = 7;\n var byteIndex = 0;\n var maskFunc = QRUtil.getMaskFunction(maskPattern);\n\n for (var col = _moduleCount - 1; col > 0; col -= 2) {\n\n if (col == 6) col -= 1;\n\n while (true) {\n\n for (var c = 0; c < 2; c += 1) {\n\n if (_modules[row][col - c] == null) {\n\n var dark = false;\n\n if (byteIndex < data.length) {\n dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);\n }\n\n var mask = maskFunc(row, col - c);\n\n if (mask) {\n dark = !dark;\n }\n\n _modules[row][col - c] = dark;\n bitIndex -= 1;\n\n if (bitIndex == -1) {\n byteIndex += 1;\n bitIndex = 7;\n }\n }\n }\n\n row += inc;\n\n if (row < 0 || _moduleCount <= row) {\n row -= inc;\n inc = -inc;\n break;\n }\n }\n }\n };\n\n var createBytes = function(buffer, rsBlocks) {\n\n var offset = 0;\n\n var maxDcCount = 0;\n var maxEcCount = 0;\n\n var dcdata = new Array(rsBlocks.length);\n var ecdata = new Array(rsBlocks.length);\n\n for (var r = 0; r < rsBlocks.length; r += 1) {\n\n var dcCount = rsBlocks[r].dataCount;\n var ecCount = rsBlocks[r].totalCount - dcCount;\n\n maxDcCount = Math.max(maxDcCount, dcCount);\n maxEcCount = Math.max(maxEcCount, ecCount);\n\n dcdata[r] = new Array(dcCount);\n\n for (var i = 0; i < dcdata[r].length; i += 1) {\n dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];\n }\n offset += dcCount;\n\n var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);\n\n var modPoly = rawPoly.mod(rsPoly);\n ecdata[r] = new Array(rsPoly.getLength() - 1);\n for (var i = 0; i < ecdata[r].length; i += 1) {\n var modIndex = i + modPoly.getLength() - ecdata[r].length;\n ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;\n }\n }\n\n var totalCodeCount = 0;\n for (var i = 0; i < rsBlocks.length; i += 1) {\n totalCodeCount += rsBlocks[i].totalCount;\n }\n\n var data = new Array(totalCodeCount);\n var index = 0;\n\n for (var i = 0; i < maxDcCount; i += 1) {\n for (var r = 0; r < rsBlocks.length; r += 1) {\n if (i < dcdata[r].length) {\n data[index] = dcdata[r][i];\n index += 1;\n }\n }\n }\n\n for (var i = 0; i < maxEcCount; i += 1) {\n for (var r = 0; r < rsBlocks.length; r += 1) {\n if (i < ecdata[r].length) {\n data[index] = ecdata[r][i];\n index += 1;\n }\n }\n }\n\n return data;\n };\n\n var createData = function(typeNumber, errorCorrectionLevel, dataList) {\n\n var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectionLevel);\n\n var buffer = qrBitBuffer();\n\n for (var i = 0; i < dataList.length; i += 1) {\n var data = dataList[i];\n buffer.put(data.getMode(), 4);\n buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );\n data.write(buffer);\n }\n\n // calc num max data.\n var totalDataCount = 0;\n for (var i = 0; i < rsBlocks.length; i += 1) {\n totalDataCount += rsBlocks[i].dataCount;\n }\n\n if (buffer.getLengthInBits() > totalDataCount * 8) {\n throw 'code length overflow. ('\n + buffer.getLengthInBits()\n + '>'\n + totalDataCount * 8\n + ')';\n }\n\n // end code\n if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {\n buffer.put(0, 4);\n }\n\n // padding\n while (buffer.getLengthInBits() % 8 != 0) {\n buffer.putBit(false);\n }\n\n // padding\n while (true) {\n\n if (buffer.getLengthInBits() >= totalDataCount * 8) {\n break;\n }\n buffer.put(PAD0, 8);\n\n if (buffer.getLengthInBits() >= totalDataCount * 8) {\n break;\n }\n buffer.put(PAD1, 8);\n }\n\n return createBytes(buffer, rsBlocks);\n };\n\n _this.addData = function(data, mode) {\n\n mode = mode || 'Byte';\n\n var newData = null;\n\n switch(mode) {\n case 'Numeric' :\n newData = qrNumber(data);\n break;\n case 'Alphanumeric' :\n newData = qrAlphaNum(data);\n break;\n case 'Byte' :\n newData = qr8BitByte(data);\n break;\n case 'Kanji' :\n newData = qrKanji(data);\n break;\n default :\n throw 'mode:' + mode;\n }\n\n _dataList.push(newData);\n _dataCache = null;\n };\n\n _this.isDark = function(row, col) {\n if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {\n throw row + ',' + col;\n }\n return _modules[row][col];\n };\n\n _this.getModuleCount = function() {\n return _moduleCount;\n };\n\n _this.make = function() {\n if (_typeNumber < 1) {\n var typeNumber = 1;\n\n for (; typeNumber < 40; typeNumber++) {\n var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, _errorCorrectionLevel);\n var buffer = qrBitBuffer();\n\n for (var i = 0; i < _dataList.length; i++) {\n var data = _dataList[i];\n buffer.put(data.getMode(), 4);\n buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );\n data.write(buffer);\n }\n\n var totalDataCount = 0;\n for (var i = 0; i < rsBlocks.length; i++) {\n totalDataCount += rsBlocks[i].dataCount;\n }\n\n if (buffer.getLengthInBits() <= totalDataCount * 8) {\n break;\n }\n }\n\n _typeNumber = typeNumber;\n }\n\n makeImpl(false, getBestMaskPattern() );\n };\n\n _this.createTableTag = function(cellSize, margin) {\n\n cellSize = cellSize || 2;\n margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n var qrHtml = '';\n\n qrHtml += '
' +\n escapeXml(title.text) + '' : '';\n qrSvg += (alt.text) ? '' +\n escapeXml(alt.text) + '' : '';\n qrSvg += '';\n qrSvg += '': escaped += '>'; break;\n case '&': escaped += '&'; break;\n case '\"': escaped += '"'; break;\n default : escaped += c; break;\n }\n }\n return escaped;\n };\n\n var _createHalfASCII = function(margin) {\n var cellSize = 1;\n margin = (typeof margin == 'undefined')? cellSize * 2 : margin;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n var min = margin;\n var max = size - margin;\n\n var y, x, r1, r2, p;\n\n var blocks = {\n '\u2588\u2588': '\u2588',\n '\u2588 ': '\u2580',\n ' \u2588': '\u2584',\n ' ': ' '\n };\n\n var blocksLastLineNoMargin = {\n '\u2588\u2588': '\u2580',\n '\u2588 ': '\u2580',\n ' \u2588': ' ',\n ' ': ' '\n };\n\n var ascii = '';\n for (y = 0; y < size; y += 2) {\n r1 = Math.floor((y - min) / cellSize);\n r2 = Math.floor((y + 1 - min) / cellSize);\n for (x = 0; x < size; x += 1) {\n p = '\u2588';\n\n if (min <= x && x < max && min <= y && y < max && _this.isDark(r1, Math.floor((x - min) / cellSize))) {\n p = ' ';\n }\n\n if (min <= x && x < max && min <= y+1 && y+1 < max && _this.isDark(r2, Math.floor((x - min) / cellSize))) {\n p += ' ';\n }\n else {\n p += '\u2588';\n }\n\n // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.\n ascii += (margin < 1 && y+1 >= max) ? blocksLastLineNoMargin[p] : blocks[p];\n }\n\n ascii += '\\n';\n }\n\n if (size % 2 && margin > 0) {\n return ascii.substring(0, ascii.length - size - 1) + Array(size+1).join('\u2580');\n }\n\n return ascii.substring(0, ascii.length-1);\n };\n\n _this.createASCII = function(cellSize, margin) {\n cellSize = cellSize || 1;\n\n if (cellSize < 2) {\n return _createHalfASCII(margin);\n }\n\n cellSize -= 1;\n margin = (typeof margin == 'undefined')? cellSize * 2 : margin;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n var min = margin;\n var max = size - margin;\n\n var y, x, r, p;\n\n var white = Array(cellSize+1).join('\u2588\u2588');\n var black = Array(cellSize+1).join(' ');\n\n var ascii = '';\n var line = '';\n for (y = 0; y < size; y += 1) {\n r = Math.floor( (y - min) / cellSize);\n line = '';\n for (x = 0; x < size; x += 1) {\n p = 1;\n\n if (min <= x && x < max && min <= y && y < max && _this.isDark(r, Math.floor((x - min) / cellSize))) {\n p = 0;\n }\n\n // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.\n line += p ? white : black;\n }\n\n for (r = 0; r < cellSize; r += 1) {\n ascii += line + '\\n';\n }\n }\n\n return ascii.substring(0, ascii.length-1);\n };\n\n _this.renderTo2dContext = function(context, cellSize) {\n cellSize = cellSize || 2;\n var length = _this.getModuleCount();\n for (var row = 0; row < length; row++) {\n for (var col = 0; col < length; col++) {\n context.fillStyle = _this.isDark(row, col) ? 'black' : 'white';\n context.fillRect(row * cellSize, col * cellSize, cellSize, cellSize);\n }\n }\n }\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrcode.stringToBytes\n //---------------------------------------------------------------------\n\n qrcode.stringToBytesFuncs = {\n 'default' : function(s) {\n var bytes = [];\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charCodeAt(i);\n bytes.push(c & 0xff);\n }\n return bytes;\n }\n };\n\n qrcode.stringToBytes = qrcode.stringToBytesFuncs['default'];\n\n //---------------------------------------------------------------------\n // qrcode.createStringToBytes\n //---------------------------------------------------------------------\n\n /**\n * @param unicodeData base64 string of byte array.\n * [16bit Unicode],[16bit Bytes], ...\n * @param numChars\n */\n qrcode.createStringToBytes = function(unicodeData, numChars) {\n\n // create conversion map.\n\n var unicodeMap = function() {\n\n var bin = base64DecodeInputStream(unicodeData);\n var read = function() {\n var b = bin.read();\n if (b == -1) throw 'eof';\n return b;\n };\n\n var count = 0;\n var unicodeMap = {};\n while (true) {\n var b0 = bin.read();\n if (b0 == -1) break;\n var b1 = read();\n var b2 = read();\n var b3 = read();\n var k = String.fromCharCode( (b0 << 8) | b1);\n var v = (b2 << 8) | b3;\n unicodeMap[k] = v;\n count += 1;\n }\n if (count != numChars) {\n throw count + ' != ' + numChars;\n }\n\n return unicodeMap;\n }();\n\n var unknownChar = '?'.charCodeAt(0);\n\n return function(s) {\n var bytes = [];\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charCodeAt(i);\n if (c < 128) {\n bytes.push(c);\n } else {\n var b = unicodeMap[s.charAt(i)];\n if (typeof b == 'number') {\n if ( (b & 0xff) == b) {\n // 1byte\n bytes.push(b);\n } else {\n // 2bytes\n bytes.push(b >>> 8);\n bytes.push(b & 0xff);\n }\n } else {\n bytes.push(unknownChar);\n }\n }\n }\n return bytes;\n };\n };\n\n //---------------------------------------------------------------------\n // QRMode\n //---------------------------------------------------------------------\n\n var QRMode = {\n MODE_NUMBER : 1 << 0,\n MODE_ALPHA_NUM : 1 << 1,\n MODE_8BIT_BYTE : 1 << 2,\n MODE_KANJI : 1 << 3\n };\n\n //---------------------------------------------------------------------\n // QRErrorCorrectionLevel\n //---------------------------------------------------------------------\n\n var QRErrorCorrectionLevel = {\n L : 1,\n M : 0,\n Q : 3,\n H : 2\n };\n\n //---------------------------------------------------------------------\n // QRMaskPattern\n //---------------------------------------------------------------------\n\n var QRMaskPattern = {\n PATTERN000 : 0,\n PATTERN001 : 1,\n PATTERN010 : 2,\n PATTERN011 : 3,\n PATTERN100 : 4,\n PATTERN101 : 5,\n PATTERN110 : 6,\n PATTERN111 : 7\n };\n\n //---------------------------------------------------------------------\n // QRUtil\n //---------------------------------------------------------------------\n\n var QRUtil = function() {\n\n var PATTERN_POSITION_TABLE = [\n [],\n [6, 18],\n [6, 22],\n [6, 26],\n [6, 30],\n [6, 34],\n [6, 22, 38],\n [6, 24, 42],\n [6, 26, 46],\n [6, 28, 50],\n [6, 30, 54],\n [6, 32, 58],\n [6, 34, 62],\n [6, 26, 46, 66],\n [6, 26, 48, 70],\n [6, 26, 50, 74],\n [6, 30, 54, 78],\n [6, 30, 56, 82],\n [6, 30, 58, 86],\n [6, 34, 62, 90],\n [6, 28, 50, 72, 94],\n [6, 26, 50, 74, 98],\n [6, 30, 54, 78, 102],\n [6, 28, 54, 80, 106],\n [6, 32, 58, 84, 110],\n [6, 30, 58, 86, 114],\n [6, 34, 62, 90, 118],\n [6, 26, 50, 74, 98, 122],\n [6, 30, 54, 78, 102, 126],\n [6, 26, 52, 78, 104, 130],\n [6, 30, 56, 82, 108, 134],\n [6, 34, 60, 86, 112, 138],\n [6, 30, 58, 86, 114, 142],\n [6, 34, 62, 90, 118, 146],\n [6, 30, 54, 78, 102, 126, 150],\n [6, 24, 50, 76, 102, 128, 154],\n [6, 28, 54, 80, 106, 132, 158],\n [6, 32, 58, 84, 110, 136, 162],\n [6, 26, 54, 82, 110, 138, 166],\n [6, 30, 58, 86, 114, 142, 170]\n ];\n var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);\n var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);\n var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);\n\n var _this = {};\n\n var getBCHDigit = function(data) {\n var digit = 0;\n while (data != 0) {\n digit += 1;\n data >>>= 1;\n }\n return digit;\n };\n\n _this.getBCHTypeInfo = function(data) {\n var d = data << 10;\n while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {\n d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );\n }\n return ( (data << 10) | d) ^ G15_MASK;\n };\n\n _this.getBCHTypeNumber = function(data) {\n var d = data << 12;\n while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {\n d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );\n }\n return (data << 12) | d;\n };\n\n _this.getPatternPosition = function(typeNumber) {\n return PATTERN_POSITION_TABLE[typeNumber - 1];\n };\n\n _this.getMaskFunction = function(maskPattern) {\n\n switch (maskPattern) {\n\n case QRMaskPattern.PATTERN000 :\n return function(i, j) { return (i + j) % 2 == 0; };\n case QRMaskPattern.PATTERN001 :\n return function(i, j) { return i % 2 == 0; };\n case QRMaskPattern.PATTERN010 :\n return function(i, j) { return j % 3 == 0; };\n case QRMaskPattern.PATTERN011 :\n return function(i, j) { return (i + j) % 3 == 0; };\n case QRMaskPattern.PATTERN100 :\n return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };\n case QRMaskPattern.PATTERN101 :\n return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };\n case QRMaskPattern.PATTERN110 :\n return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };\n case QRMaskPattern.PATTERN111 :\n return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };\n\n default :\n throw 'bad maskPattern:' + maskPattern;\n }\n };\n\n _this.getErrorCorrectPolynomial = function(errorCorrectLength) {\n var a = qrPolynomial([1], 0);\n for (var i = 0; i < errorCorrectLength; i += 1) {\n a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );\n }\n return a;\n };\n\n _this.getLengthInBits = function(mode, type) {\n\n if (1 <= type && type < 10) {\n\n // 1 - 9\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 10;\n case QRMode.MODE_ALPHA_NUM : return 9;\n case QRMode.MODE_8BIT_BYTE : return 8;\n case QRMode.MODE_KANJI : return 8;\n default :\n throw 'mode:' + mode;\n }\n\n } else if (type < 27) {\n\n // 10 - 26\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 12;\n case QRMode.MODE_ALPHA_NUM : return 11;\n case QRMode.MODE_8BIT_BYTE : return 16;\n case QRMode.MODE_KANJI : return 10;\n default :\n throw 'mode:' + mode;\n }\n\n } else if (type < 41) {\n\n // 27 - 40\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 14;\n case QRMode.MODE_ALPHA_NUM : return 13;\n case QRMode.MODE_8BIT_BYTE : return 16;\n case QRMode.MODE_KANJI : return 12;\n default :\n throw 'mode:' + mode;\n }\n\n } else {\n throw 'type:' + type;\n }\n };\n\n _this.getLostPoint = function(qrcode) {\n\n var moduleCount = qrcode.getModuleCount();\n\n var lostPoint = 0;\n\n // LEVEL1\n\n for (var row = 0; row < moduleCount; row += 1) {\n for (var col = 0; col < moduleCount; col += 1) {\n\n var sameCount = 0;\n var dark = qrcode.isDark(row, col);\n\n for (var r = -1; r <= 1; r += 1) {\n\n if (row + r < 0 || moduleCount <= row + r) {\n continue;\n }\n\n for (var c = -1; c <= 1; c += 1) {\n\n if (col + c < 0 || moduleCount <= col + c) {\n continue;\n }\n\n if (r == 0 && c == 0) {\n continue;\n }\n\n if (dark == qrcode.isDark(row + r, col + c) ) {\n sameCount += 1;\n }\n }\n }\n\n if (sameCount > 5) {\n lostPoint += (3 + sameCount - 5);\n }\n }\n };\n\n // LEVEL2\n\n for (var row = 0; row < moduleCount - 1; row += 1) {\n for (var col = 0; col < moduleCount - 1; col += 1) {\n var count = 0;\n if (qrcode.isDark(row, col) ) count += 1;\n if (qrcode.isDark(row + 1, col) ) count += 1;\n if (qrcode.isDark(row, col + 1) ) count += 1;\n if (qrcode.isDark(row + 1, col + 1) ) count += 1;\n if (count == 0 || count == 4) {\n lostPoint += 3;\n }\n }\n }\n\n // LEVEL3\n\n for (var row = 0; row < moduleCount; row += 1) {\n for (var col = 0; col < moduleCount - 6; col += 1) {\n if (qrcode.isDark(row, col)\n && !qrcode.isDark(row, col + 1)\n && qrcode.isDark(row, col + 2)\n && qrcode.isDark(row, col + 3)\n && qrcode.isDark(row, col + 4)\n && !qrcode.isDark(row, col + 5)\n && qrcode.isDark(row, col + 6) ) {\n lostPoint += 40;\n }\n }\n }\n\n for (var col = 0; col < moduleCount; col += 1) {\n for (var row = 0; row < moduleCount - 6; row += 1) {\n if (qrcode.isDark(row, col)\n && !qrcode.isDark(row + 1, col)\n && qrcode.isDark(row + 2, col)\n && qrcode.isDark(row + 3, col)\n && qrcode.isDark(row + 4, col)\n && !qrcode.isDark(row + 5, col)\n && qrcode.isDark(row + 6, col) ) {\n lostPoint += 40;\n }\n }\n }\n\n // LEVEL4\n\n var darkCount = 0;\n\n for (var col = 0; col < moduleCount; col += 1) {\n for (var row = 0; row < moduleCount; row += 1) {\n if (qrcode.isDark(row, col) ) {\n darkCount += 1;\n }\n }\n }\n\n var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n lostPoint += ratio * 10;\n\n return lostPoint;\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // QRMath\n //---------------------------------------------------------------------\n\n var QRMath = function() {\n\n var EXP_TABLE = new Array(256);\n var LOG_TABLE = new Array(256);\n\n // initialize tables\n for (var i = 0; i < 8; i += 1) {\n EXP_TABLE[i] = 1 << i;\n }\n for (var i = 8; i < 256; i += 1) {\n EXP_TABLE[i] = EXP_TABLE[i - 4]\n ^ EXP_TABLE[i - 5]\n ^ EXP_TABLE[i - 6]\n ^ EXP_TABLE[i - 8];\n }\n for (var i = 0; i < 255; i += 1) {\n LOG_TABLE[EXP_TABLE[i] ] = i;\n }\n\n var _this = {};\n\n _this.glog = function(n) {\n\n if (n < 1) {\n throw 'glog(' + n + ')';\n }\n\n return LOG_TABLE[n];\n };\n\n _this.gexp = function(n) {\n\n while (n < 0) {\n n += 255;\n }\n\n while (n >= 256) {\n n -= 255;\n }\n\n return EXP_TABLE[n];\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // qrPolynomial\n //---------------------------------------------------------------------\n\n function qrPolynomial(num, shift) {\n\n if (typeof num.length == 'undefined') {\n throw num.length + '/' + shift;\n }\n\n var _num = function() {\n var offset = 0;\n while (offset < num.length && num[offset] == 0) {\n offset += 1;\n }\n var _num = new Array(num.length - offset + shift);\n for (var i = 0; i < num.length - offset; i += 1) {\n _num[i] = num[i + offset];\n }\n return _num;\n }();\n\n var _this = {};\n\n _this.getAt = function(index) {\n return _num[index];\n };\n\n _this.getLength = function() {\n return _num.length;\n };\n\n _this.multiply = function(e) {\n\n var num = new Array(_this.getLength() + e.getLength() - 1);\n\n for (var i = 0; i < _this.getLength(); i += 1) {\n for (var j = 0; j < e.getLength(); j += 1) {\n num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );\n }\n }\n\n return qrPolynomial(num, 0);\n };\n\n _this.mod = function(e) {\n\n if (_this.getLength() - e.getLength() < 0) {\n return _this;\n }\n\n var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );\n\n var num = new Array(_this.getLength() );\n for (var i = 0; i < _this.getLength(); i += 1) {\n num[i] = _this.getAt(i);\n }\n\n for (var i = 0; i < e.getLength(); i += 1) {\n num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);\n }\n\n // recursive call\n return qrPolynomial(num, 0).mod(e);\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // QRRSBlock\n //---------------------------------------------------------------------\n\n var QRRSBlock = function() {\n\n var RS_BLOCK_TABLE = [\n\n // L\n // M\n // Q\n // H\n\n // 1\n [1, 26, 19],\n [1, 26, 16],\n [1, 26, 13],\n [1, 26, 9],\n\n // 2\n [1, 44, 34],\n [1, 44, 28],\n [1, 44, 22],\n [1, 44, 16],\n\n // 3\n [1, 70, 55],\n [1, 70, 44],\n [2, 35, 17],\n [2, 35, 13],\n\n // 4\n [1, 100, 80],\n [2, 50, 32],\n [2, 50, 24],\n [4, 25, 9],\n\n // 5\n [1, 134, 108],\n [2, 67, 43],\n [2, 33, 15, 2, 34, 16],\n [2, 33, 11, 2, 34, 12],\n\n // 6\n [2, 86, 68],\n [4, 43, 27],\n [4, 43, 19],\n [4, 43, 15],\n\n // 7\n [2, 98, 78],\n [4, 49, 31],\n [2, 32, 14, 4, 33, 15],\n [4, 39, 13, 1, 40, 14],\n\n // 8\n [2, 121, 97],\n [2, 60, 38, 2, 61, 39],\n [4, 40, 18, 2, 41, 19],\n [4, 40, 14, 2, 41, 15],\n\n // 9\n [2, 146, 116],\n [3, 58, 36, 2, 59, 37],\n [4, 36, 16, 4, 37, 17],\n [4, 36, 12, 4, 37, 13],\n\n // 10\n [2, 86, 68, 2, 87, 69],\n [4, 69, 43, 1, 70, 44],\n [6, 43, 19, 2, 44, 20],\n [6, 43, 15, 2, 44, 16],\n\n // 11\n [4, 101, 81],\n [1, 80, 50, 4, 81, 51],\n [4, 50, 22, 4, 51, 23],\n [3, 36, 12, 8, 37, 13],\n\n // 12\n [2, 116, 92, 2, 117, 93],\n [6, 58, 36, 2, 59, 37],\n [4, 46, 20, 6, 47, 21],\n [7, 42, 14, 4, 43, 15],\n\n // 13\n [4, 133, 107],\n [8, 59, 37, 1, 60, 38],\n [8, 44, 20, 4, 45, 21],\n [12, 33, 11, 4, 34, 12],\n\n // 14\n [3, 145, 115, 1, 146, 116],\n [4, 64, 40, 5, 65, 41],\n [11, 36, 16, 5, 37, 17],\n [11, 36, 12, 5, 37, 13],\n\n // 15\n [5, 109, 87, 1, 110, 88],\n [5, 65, 41, 5, 66, 42],\n [5, 54, 24, 7, 55, 25],\n [11, 36, 12, 7, 37, 13],\n\n // 16\n [5, 122, 98, 1, 123, 99],\n [7, 73, 45, 3, 74, 46],\n [15, 43, 19, 2, 44, 20],\n [3, 45, 15, 13, 46, 16],\n\n // 17\n [1, 135, 107, 5, 136, 108],\n [10, 74, 46, 1, 75, 47],\n [1, 50, 22, 15, 51, 23],\n [2, 42, 14, 17, 43, 15],\n\n // 18\n [5, 150, 120, 1, 151, 121],\n [9, 69, 43, 4, 70, 44],\n [17, 50, 22, 1, 51, 23],\n [2, 42, 14, 19, 43, 15],\n\n // 19\n [3, 141, 113, 4, 142, 114],\n [3, 70, 44, 11, 71, 45],\n [17, 47, 21, 4, 48, 22],\n [9, 39, 13, 16, 40, 14],\n\n // 20\n [3, 135, 107, 5, 136, 108],\n [3, 67, 41, 13, 68, 42],\n [15, 54, 24, 5, 55, 25],\n [15, 43, 15, 10, 44, 16],\n\n // 21\n [4, 144, 116, 4, 145, 117],\n [17, 68, 42],\n [17, 50, 22, 6, 51, 23],\n [19, 46, 16, 6, 47, 17],\n\n // 22\n [2, 139, 111, 7, 140, 112],\n [17, 74, 46],\n [7, 54, 24, 16, 55, 25],\n [34, 37, 13],\n\n // 23\n [4, 151, 121, 5, 152, 122],\n [4, 75, 47, 14, 76, 48],\n [11, 54, 24, 14, 55, 25],\n [16, 45, 15, 14, 46, 16],\n\n // 24\n [6, 147, 117, 4, 148, 118],\n [6, 73, 45, 14, 74, 46],\n [11, 54, 24, 16, 55, 25],\n [30, 46, 16, 2, 47, 17],\n\n // 25\n [8, 132, 106, 4, 133, 107],\n [8, 75, 47, 13, 76, 48],\n [7, 54, 24, 22, 55, 25],\n [22, 45, 15, 13, 46, 16],\n\n // 26\n [10, 142, 114, 2, 143, 115],\n [19, 74, 46, 4, 75, 47],\n [28, 50, 22, 6, 51, 23],\n [33, 46, 16, 4, 47, 17],\n\n // 27\n [8, 152, 122, 4, 153, 123],\n [22, 73, 45, 3, 74, 46],\n [8, 53, 23, 26, 54, 24],\n [12, 45, 15, 28, 46, 16],\n\n // 28\n [3, 147, 117, 10, 148, 118],\n [3, 73, 45, 23, 74, 46],\n [4, 54, 24, 31, 55, 25],\n [11, 45, 15, 31, 46, 16],\n\n // 29\n [7, 146, 116, 7, 147, 117],\n [21, 73, 45, 7, 74, 46],\n [1, 53, 23, 37, 54, 24],\n [19, 45, 15, 26, 46, 16],\n\n // 30\n [5, 145, 115, 10, 146, 116],\n [19, 75, 47, 10, 76, 48],\n [15, 54, 24, 25, 55, 25],\n [23, 45, 15, 25, 46, 16],\n\n // 31\n [13, 145, 115, 3, 146, 116],\n [2, 74, 46, 29, 75, 47],\n [42, 54, 24, 1, 55, 25],\n [23, 45, 15, 28, 46, 16],\n\n // 32\n [17, 145, 115],\n [10, 74, 46, 23, 75, 47],\n [10, 54, 24, 35, 55, 25],\n [19, 45, 15, 35, 46, 16],\n\n // 33\n [17, 145, 115, 1, 146, 116],\n [14, 74, 46, 21, 75, 47],\n [29, 54, 24, 19, 55, 25],\n [11, 45, 15, 46, 46, 16],\n\n // 34\n [13, 145, 115, 6, 146, 116],\n [14, 74, 46, 23, 75, 47],\n [44, 54, 24, 7, 55, 25],\n [59, 46, 16, 1, 47, 17],\n\n // 35\n [12, 151, 121, 7, 152, 122],\n [12, 75, 47, 26, 76, 48],\n [39, 54, 24, 14, 55, 25],\n [22, 45, 15, 41, 46, 16],\n\n // 36\n [6, 151, 121, 14, 152, 122],\n [6, 75, 47, 34, 76, 48],\n [46, 54, 24, 10, 55, 25],\n [2, 45, 15, 64, 46, 16],\n\n // 37\n [17, 152, 122, 4, 153, 123],\n [29, 74, 46, 14, 75, 47],\n [49, 54, 24, 10, 55, 25],\n [24, 45, 15, 46, 46, 16],\n\n // 38\n [4, 152, 122, 18, 153, 123],\n [13, 74, 46, 32, 75, 47],\n [48, 54, 24, 14, 55, 25],\n [42, 45, 15, 32, 46, 16],\n\n // 39\n [20, 147, 117, 4, 148, 118],\n [40, 75, 47, 7, 76, 48],\n [43, 54, 24, 22, 55, 25],\n [10, 45, 15, 67, 46, 16],\n\n // 40\n [19, 148, 118, 6, 149, 119],\n [18, 75, 47, 31, 76, 48],\n [34, 54, 24, 34, 55, 25],\n [20, 45, 15, 61, 46, 16]\n ];\n\n var qrRSBlock = function(totalCount, dataCount) {\n var _this = {};\n _this.totalCount = totalCount;\n _this.dataCount = dataCount;\n return _this;\n };\n\n var _this = {};\n\n var getRsBlockTable = function(typeNumber, errorCorrectionLevel) {\n\n switch(errorCorrectionLevel) {\n case QRErrorCorrectionLevel.L :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];\n case QRErrorCorrectionLevel.M :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];\n case QRErrorCorrectionLevel.Q :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];\n case QRErrorCorrectionLevel.H :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];\n default :\n return undefined;\n }\n };\n\n _this.getRSBlocks = function(typeNumber, errorCorrectionLevel) {\n\n var rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);\n\n if (typeof rsBlock == 'undefined') {\n throw 'bad rs block @ typeNumber:' + typeNumber +\n '/errorCorrectionLevel:' + errorCorrectionLevel;\n }\n\n var length = rsBlock.length / 3;\n\n var list = [];\n\n for (var i = 0; i < length; i += 1) {\n\n var count = rsBlock[i * 3 + 0];\n var totalCount = rsBlock[i * 3 + 1];\n var dataCount = rsBlock[i * 3 + 2];\n\n for (var j = 0; j < count; j += 1) {\n list.push(qrRSBlock(totalCount, dataCount) );\n }\n }\n\n return list;\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // qrBitBuffer\n //---------------------------------------------------------------------\n\n var qrBitBuffer = function() {\n\n var _buffer = [];\n var _length = 0;\n\n var _this = {};\n\n _this.getBuffer = function() {\n return _buffer;\n };\n\n _this.getAt = function(index) {\n var bufIndex = Math.floor(index / 8);\n return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;\n };\n\n _this.put = function(num, length) {\n for (var i = 0; i < length; i += 1) {\n _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);\n }\n };\n\n _this.getLengthInBits = function() {\n return _length;\n };\n\n _this.putBit = function(bit) {\n\n var bufIndex = Math.floor(_length / 8);\n if (_buffer.length <= bufIndex) {\n _buffer.push(0);\n }\n\n if (bit) {\n _buffer[bufIndex] |= (0x80 >>> (_length % 8) );\n }\n\n _length += 1;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrNumber\n //---------------------------------------------------------------------\n\n var qrNumber = function(data) {\n\n var _mode = QRMode.MODE_NUMBER;\n var _data = data;\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _data.length;\n };\n\n _this.write = function(buffer) {\n\n var data = _data;\n\n var i = 0;\n\n while (i + 2 < data.length) {\n buffer.put(strToNum(data.substring(i, i + 3) ), 10);\n i += 3;\n }\n\n if (i < data.length) {\n if (data.length - i == 1) {\n buffer.put(strToNum(data.substring(i, i + 1) ), 4);\n } else if (data.length - i == 2) {\n buffer.put(strToNum(data.substring(i, i + 2) ), 7);\n }\n }\n };\n\n var strToNum = function(s) {\n var num = 0;\n for (var i = 0; i < s.length; i += 1) {\n num = num * 10 + chatToNum(s.charAt(i) );\n }\n return num;\n };\n\n var chatToNum = function(c) {\n if ('0' <= c && c <= '9') {\n return c.charCodeAt(0) - '0'.charCodeAt(0);\n }\n throw 'illegal char :' + c;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrAlphaNum\n //---------------------------------------------------------------------\n\n var qrAlphaNum = function(data) {\n\n var _mode = QRMode.MODE_ALPHA_NUM;\n var _data = data;\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _data.length;\n };\n\n _this.write = function(buffer) {\n\n var s = _data;\n\n var i = 0;\n\n while (i + 1 < s.length) {\n buffer.put(\n getCode(s.charAt(i) ) * 45 +\n getCode(s.charAt(i + 1) ), 11);\n i += 2;\n }\n\n if (i < s.length) {\n buffer.put(getCode(s.charAt(i) ), 6);\n }\n };\n\n var getCode = function(c) {\n\n if ('0' <= c && c <= '9') {\n return c.charCodeAt(0) - '0'.charCodeAt(0);\n } else if ('A' <= c && c <= 'Z') {\n return c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;\n } else {\n switch (c) {\n case ' ' : return 36;\n case '$' : return 37;\n case '%' : return 38;\n case '*' : return 39;\n case '+' : return 40;\n case '-' : return 41;\n case '.' : return 42;\n case '/' : return 43;\n case ':' : return 44;\n default :\n throw 'illegal char :' + c;\n }\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qr8BitByte\n //---------------------------------------------------------------------\n\n var qr8BitByte = function(data) {\n\n var _mode = QRMode.MODE_8BIT_BYTE;\n var _data = data;\n var _bytes = qrcode.stringToBytes(data);\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _bytes.length;\n };\n\n _this.write = function(buffer) {\n for (var i = 0; i < _bytes.length; i += 1) {\n buffer.put(_bytes[i], 8);\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrKanji\n //---------------------------------------------------------------------\n\n var qrKanji = function(data) {\n\n var _mode = QRMode.MODE_KANJI;\n var _data = data;\n\n var stringToBytes = qrcode.stringToBytesFuncs['SJIS'];\n if (!stringToBytes) {\n throw 'sjis not supported.';\n }\n !function(c, code) {\n // self test for sjis support.\n var test = stringToBytes(c);\n if (test.length != 2 || ( (test[0] << 8) | test[1]) != code) {\n throw 'sjis not supported.';\n }\n }('\\u53cb', 0x9746);\n\n var _bytes = stringToBytes(data);\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return ~~(_bytes.length / 2);\n };\n\n _this.write = function(buffer) {\n\n var data = _bytes;\n\n var i = 0;\n\n while (i + 1 < data.length) {\n\n var c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);\n\n if (0x8140 <= c && c <= 0x9FFC) {\n c -= 0x8140;\n } else if (0xE040 <= c && c <= 0xEBBF) {\n c -= 0xC140;\n } else {\n throw 'illegal char at ' + (i + 1) + '/' + c;\n }\n\n c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);\n\n buffer.put(c, 13);\n\n i += 2;\n }\n\n if (i < data.length) {\n throw 'illegal char at ' + (i + 1);\n }\n };\n\n return _this;\n };\n\n //=====================================================================\n // GIF Support etc.\n //\n\n //---------------------------------------------------------------------\n // byteArrayOutputStream\n //---------------------------------------------------------------------\n\n var byteArrayOutputStream = function() {\n\n var _bytes = [];\n\n var _this = {};\n\n _this.writeByte = function(b) {\n _bytes.push(b & 0xff);\n };\n\n _this.writeShort = function(i) {\n _this.writeByte(i);\n _this.writeByte(i >>> 8);\n };\n\n _this.writeBytes = function(b, off, len) {\n off = off || 0;\n len = len || b.length;\n for (var i = 0; i < len; i += 1) {\n _this.writeByte(b[i + off]);\n }\n };\n\n _this.writeString = function(s) {\n for (var i = 0; i < s.length; i += 1) {\n _this.writeByte(s.charCodeAt(i) );\n }\n };\n\n _this.toByteArray = function() {\n return _bytes;\n };\n\n _this.toString = function() {\n var s = '';\n s += '[';\n for (var i = 0; i < _bytes.length; i += 1) {\n if (i > 0) {\n s += ',';\n }\n s += _bytes[i];\n }\n s += ']';\n return s;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // base64EncodeOutputStream\n //---------------------------------------------------------------------\n\n var base64EncodeOutputStream = function() {\n\n var _buffer = 0;\n var _buflen = 0;\n var _length = 0;\n var _base64 = '';\n\n var _this = {};\n\n var writeEncoded = function(b) {\n _base64 += String.fromCharCode(encode(b & 0x3f) );\n };\n\n var encode = function(n) {\n if (n < 0) {\n // error.\n } else if (n < 26) {\n return 0x41 + n;\n } else if (n < 52) {\n return 0x61 + (n - 26);\n } else if (n < 62) {\n return 0x30 + (n - 52);\n } else if (n == 62) {\n return 0x2b;\n } else if (n == 63) {\n return 0x2f;\n }\n throw 'n:' + n;\n };\n\n _this.writeByte = function(n) {\n\n _buffer = (_buffer << 8) | (n & 0xff);\n _buflen += 8;\n _length += 1;\n\n while (_buflen >= 6) {\n writeEncoded(_buffer >>> (_buflen - 6) );\n _buflen -= 6;\n }\n };\n\n _this.flush = function() {\n\n if (_buflen > 0) {\n writeEncoded(_buffer << (6 - _buflen) );\n _buffer = 0;\n _buflen = 0;\n }\n\n if (_length % 3 != 0) {\n // padding\n var padlen = 3 - _length % 3;\n for (var i = 0; i < padlen; i += 1) {\n _base64 += '=';\n }\n }\n };\n\n _this.toString = function() {\n return _base64;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // base64DecodeInputStream\n //---------------------------------------------------------------------\n\n var base64DecodeInputStream = function(str) {\n\n var _str = str;\n var _pos = 0;\n var _buffer = 0;\n var _buflen = 0;\n\n var _this = {};\n\n _this.read = function() {\n\n while (_buflen < 8) {\n\n if (_pos >= _str.length) {\n if (_buflen == 0) {\n return -1;\n }\n throw 'unexpected end of file./' + _buflen;\n }\n\n var c = _str.charAt(_pos);\n _pos += 1;\n\n if (c == '=') {\n _buflen = 0;\n return -1;\n } else if (c.match(/^\\s$/) ) {\n // ignore if whitespace.\n continue;\n }\n\n _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );\n _buflen += 6;\n }\n\n var n = (_buffer >>> (_buflen - 8) ) & 0xff;\n _buflen -= 8;\n return n;\n };\n\n var decode = function(c) {\n if (0x41 <= c && c <= 0x5a) {\n return c - 0x41;\n } else if (0x61 <= c && c <= 0x7a) {\n return c - 0x61 + 26;\n } else if (0x30 <= c && c <= 0x39) {\n return c - 0x30 + 52;\n } else if (c == 0x2b) {\n return 62;\n } else if (c == 0x2f) {\n return 63;\n } else {\n throw 'c:' + c;\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // gifImage (B/W)\n //---------------------------------------------------------------------\n\n var gifImage = function(width, height) {\n\n var _width = width;\n var _height = height;\n var _data = new Array(width * height);\n\n var _this = {};\n\n _this.setPixel = function(x, y, pixel) {\n _data[y * _width + x] = pixel;\n };\n\n _this.write = function(out) {\n\n //---------------------------------\n // GIF Signature\n\n out.writeString('GIF87a');\n\n //---------------------------------\n // Screen Descriptor\n\n out.writeShort(_width);\n out.writeShort(_height);\n\n out.writeByte(0x80); // 2bit\n out.writeByte(0);\n out.writeByte(0);\n\n //---------------------------------\n // Global Color Map\n\n // black\n out.writeByte(0x00);\n out.writeByte(0x00);\n out.writeByte(0x00);\n\n // white\n out.writeByte(0xff);\n out.writeByte(0xff);\n out.writeByte(0xff);\n\n //---------------------------------\n // Image Descriptor\n\n out.writeString(',');\n out.writeShort(0);\n out.writeShort(0);\n out.writeShort(_width);\n out.writeShort(_height);\n out.writeByte(0);\n\n //---------------------------------\n // Local Color Map\n\n //---------------------------------\n // Raster Data\n\n var lzwMinCodeSize = 2;\n var raster = getLZWRaster(lzwMinCodeSize);\n\n out.writeByte(lzwMinCodeSize);\n\n var offset = 0;\n\n while (raster.length - offset > 255) {\n out.writeByte(255);\n out.writeBytes(raster, offset, 255);\n offset += 255;\n }\n\n out.writeByte(raster.length - offset);\n out.writeBytes(raster, offset, raster.length - offset);\n out.writeByte(0x00);\n\n //---------------------------------\n // GIF Terminator\n out.writeString(';');\n };\n\n var bitOutputStream = function(out) {\n\n var _out = out;\n var _bitLength = 0;\n var _bitBuffer = 0;\n\n var _this = {};\n\n _this.write = function(data, length) {\n\n if ( (data >>> length) != 0) {\n throw 'length over';\n }\n\n while (_bitLength + length >= 8) {\n _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );\n length -= (8 - _bitLength);\n data >>>= (8 - _bitLength);\n _bitBuffer = 0;\n _bitLength = 0;\n }\n\n _bitBuffer = (data << _bitLength) | _bitBuffer;\n _bitLength = _bitLength + length;\n };\n\n _this.flush = function() {\n if (_bitLength > 0) {\n _out.writeByte(_bitBuffer);\n }\n };\n\n return _this;\n };\n\n var getLZWRaster = function(lzwMinCodeSize) {\n\n var clearCode = 1 << lzwMinCodeSize;\n var endCode = (1 << lzwMinCodeSize) + 1;\n var bitLength = lzwMinCodeSize + 1;\n\n // Setup LZWTable\n var table = lzwTable();\n\n for (var i = 0; i < clearCode; i += 1) {\n table.add(String.fromCharCode(i) );\n }\n table.add(String.fromCharCode(clearCode) );\n table.add(String.fromCharCode(endCode) );\n\n var byteOut = byteArrayOutputStream();\n var bitOut = bitOutputStream(byteOut);\n\n // clear code\n bitOut.write(clearCode, bitLength);\n\n var dataIndex = 0;\n\n var s = String.fromCharCode(_data[dataIndex]);\n dataIndex += 1;\n\n while (dataIndex < _data.length) {\n\n var c = String.fromCharCode(_data[dataIndex]);\n dataIndex += 1;\n\n if (table.contains(s + c) ) {\n\n s = s + c;\n\n } else {\n\n bitOut.write(table.indexOf(s), bitLength);\n\n if (table.size() < 0xfff) {\n\n if (table.size() == (1 << bitLength) ) {\n bitLength += 1;\n }\n\n table.add(s + c);\n }\n\n s = c;\n }\n }\n\n bitOut.write(table.indexOf(s), bitLength);\n\n // end code\n bitOut.write(endCode, bitLength);\n\n bitOut.flush();\n\n return byteOut.toByteArray();\n };\n\n var lzwTable = function() {\n\n var _map = {};\n var _size = 0;\n\n var _this = {};\n\n _this.add = function(key) {\n if (_this.contains(key) ) {\n throw 'dup key:' + key;\n }\n _map[key] = _size;\n _size += 1;\n };\n\n _this.size = function() {\n return _size;\n };\n\n _this.indexOf = function(key) {\n return _map[key];\n };\n\n _this.contains = function(key) {\n return typeof _map[key] != 'undefined';\n };\n\n return _this;\n };\n\n return _this;\n };\n\n var createDataURL = function(width, height, getPixel) {\n var gif = gifImage(width, height);\n for (var y = 0; y < height; y += 1) {\n for (var x = 0; x < width; x += 1) {\n gif.setPixel(x, y, getPixel(x, y) );\n }\n }\n\n var b = byteArrayOutputStream();\n gif.write(b);\n\n var base64 = base64EncodeOutputStream();\n var bytes = b.toByteArray();\n for (var i = 0; i < bytes.length; i += 1) {\n base64.writeByte(bytes[i]);\n }\n base64.flush();\n\n return 'data:image/gif;base64,' + base64;\n };\n\n //---------------------------------------------------------------------\n // returns qrcode function.\n\n return qrcode;\n}();\n\n// multibyte support\n!function() {\n\n qrcode.stringToBytesFuncs['UTF-8'] = function(s) {\n // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array\n function toUTF8Array(str) {\n var utf8 = [];\n for (var i=0; i < str.length; i++) {\n var charcode = str.charCodeAt(i);\n if (charcode < 0x80) utf8.push(charcode);\n else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6),\n 0x80 | (charcode & 0x3f));\n }\n else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(0xe0 | (charcode >> 12),\n 0x80 | ((charcode>>6) & 0x3f),\n 0x80 | (charcode & 0x3f));\n }\n // surrogate pair\n else {\n i++;\n // UTF-16 encodes 0x10000-0x10FFFF by\n // subtracting 0x10000 and splitting the\n // 20 bits of 0x0-0xFFFFF into two halves\n charcode = 0x10000 + (((charcode & 0x3ff)<<10)\n | (str.charCodeAt(i) & 0x3ff));\n utf8.push(0xf0 | (charcode >>18),\n 0x80 | ((charcode>>12) & 0x3f),\n 0x80 | ((charcode>>6) & 0x3f),\n 0x80 | (charcode & 0x3f));\n }\n }\n return utf8;\n }\n return toUTF8Array(s);\n };\n\n}();\n\n(function (factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n }\n}(function () {\n return qrcode;\n}));\n", "import { createElement, Ref, VNode } from \"preact\";\nimport { MutableRef, useEffect, useRef } from \"preact/hooks\";\n\nexport type StateFunc = (p: S) => VNode;\n\nexport type StateViewMap = {\n [S in StateType as S[\"status\"]]: StateFunc;\n};\n\nexport type RecursiveState = S | (() => RecursiveState);\n\nexport function compose(\n hook: (p: PType) => RecursiveState,\n viewMap: StateViewMap,\n): (p: PType) => VNode {\n function withHook(stateHook: () => RecursiveState): () => VNode {\n function ComposedComponent(): VNode {\n const state = stateHook();\n\n if (typeof state === \"function\") {\n const subComponent = withHook(state);\n return createElement(subComponent, {});\n }\n\n const statusName = state.status as unknown as SType[\"status\"];\n const viewComponent = viewMap[statusName] as unknown as StateFunc;\n return createElement(viewComponent, state);\n }\n\n return ComposedComponent;\n }\n\n return (p: PType) => {\n const h = withHook(() => hook(p));\n return h();\n };\n}\n\nexport function recursive(\n hook: (p: PType) => RecursiveState,\n): (p: PType) => VNode {\n function withHook(stateHook: () => RecursiveState): () => VNode {\n function ComposedComponent(): VNode {\n const state = stateHook();\n\n if (typeof state === \"function\") {\n const subComponent = withHook(state);\n return createElement(subComponent, {});\n }\n\n return state;\n }\n\n return ComposedComponent;\n }\n\n return (p: PType) => {\n const h = withHook(() => hook(p));\n return h();\n };\n}\n\n/**\n * Call `callback` only once.\n *\n * Callback can be a closure with binding to the current caller context. This helper\n * will always take the latest `callback`\n *\n * @param callback\n */\nexport function onComponentUnload(callback: () => void) {\n /**\n * we use a ref to avoid evaluating the effect function\n * on every render and so the unload is called only once\n */\n const ref = useRef();\n ref.current = callback;\n\n useEffect(() => {\n return () => {\n ref.current!();\n };\n }, []);\n}\n\nconst ownerDocument = typeof document === \"undefined\" ? null : document;\nconst preconnectsSet: Set = new Set();\n\nexport type Preconnect = {\n rel: \"preconnect\" | \"dns-prefetch\";\n href: string;\n crossOrigin: string;\n};\n\nexport function preconnectAs(pre: Preconnect[]) {\n if (ownerDocument) {\n pre.forEach(({ rel, href, crossOrigin }) => {\n const key = `${rel}${href}${crossOrigin}`;\n if (preconnectsSet.has(key)) return;\n preconnectsSet.add(key);\n const instance = ownerDocument.createElement(\"link\");\n instance.setAttribute(\"rel\", rel);\n instance.setAttribute(\"crossOrigin\", crossOrigin);\n instance.setAttribute(\"href\", href);\n ownerDocument.head.appendChild(instance);\n });\n }\n}\n\nexport function composeRef(...fn: ((e: T | null) => void)[]) {\n return (element: T | null) => {\n fn.forEach((handler) => {\n handler(element);\n });\n };\n}\n\nexport function saveRef(ref: MutableRef) {\n return (element: T | null) => {\n if (element) {\n ref.current = element;\n }\n };\n}\n/**\n * Show the element when the load ended\n * @param element\n */\nexport function doAutoFocus(\n element: T | null | undefined,\n) {\n if (element) {\n setTimeout(() => {\n element.focus({ preventScroll: true });\n }, 100);\n }\n}\n\n/**\n * Show the element when the load ended\n * @param element\n */\nexport function doAutoFocusWithScroll(element: HTMLElement | null) {\n if (element) {\n setTimeout(() => {\n element.focus({ preventScroll: true });\n element.scrollIntoView({\n behavior: \"smooth\",\n block: \"center\",\n inline: \"center\",\n });\n }, 100);\n }\n}\n\n/**\n *\n * @param obj VNode\n * @returns\n */\nexport function saveVNodeForInspection(obj: T): T {\n // @ts-ignore\n window[\"showVNodeInfo\"] = function showVNodeInfo() {\n inspect(obj);\n };\n return obj;\n}\nfunction inspect(obj: any) {\n if (!obj) return;\n if (obj.__c && obj.__c.__H) {\n const componentName = obj.__c.constructor.name;\n const hookState = obj.__c.__H;\n const stateList = hookState.__ as Array;\n console.log(\"==============\", componentName);\n stateList.forEach((hook) => {\n const { __: value, c: context, __h: factory, __H: args } = hook;\n if (typeof context !== \"undefined\") {\n const { __c: contextId } = context;\n console.log(\"context:\", contextId, hook);\n } else if (typeof factory === \"function\") {\n console.log(\"memo:\", value, \"deps:\", args);\n } else if (typeof value === \"function\") {\n const effectName = value.name;\n console.log(\"effect:\", effectName, \"deps:\", args);\n } else if (typeof value.current !== \"undefined\") {\n const ref = value.current;\n console.log(\"ref:\", ref instanceof Element ? ref.outerHTML : ref);\n } else if (value instanceof Array) {\n console.log(\"state:\", value[0]);\n } else {\n console.log(hook);\n }\n });\n }\n const children = obj.__k;\n if (children instanceof Array) {\n children.forEach((e) => inspect(e));\n } else {\n inspect(children);\n }\n}\n", "import {\n Duration,\n TranslatedString,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport { ComponentChildren, Fragment, VNode, h } from \"preact\";\n\ninterface Props {\n type?: \"info\" | \"success\" | \"warning\" | \"danger\" | \"low\";\n onClose?: () => void;\n title: TranslatedString | VNode;\n children?: ComponentChildren;\n timeout?: Duration;\n}\nexport function Attention({\n type = \"info\",\n title,\n children,\n onClose,\n timeout = Duration.getForever(),\n}: Props): VNode {\n return (\n
\n {/* {timeout.d_ms === \"forever\" ? undefined : \n } */}\n\n \n
\n
\n {type === \"low\" ? undefined : (\n \n {(() => {\n switch (type) {\n case \"info\":\n return (\n \n );\n case \"warning\":\n return (\n \n );\n case \"danger\":\n return (\n \n );\n case \"success\":\n return (\n \n );\n default:\n assertUnreachable(type);\n }\n })()}\n \n )}\n
\n
\n

\n {title}\n

\n
\n {children}\n
\n
\n {onClose && (\n
\n {\n e.preventDefault();\n onClose();\n }}\n >\n \n \n \n \n
\n )}\n
\n
\n {timeout.d_ms === \"forever\" ? undefined : (\n
\n \n \n \n
\n )}\n \n );\n}\n", "import { ComponentChildren, h, VNode } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\n\nexport function CopyIcon(): VNode {\n return (\n \n \n \n );\n}\n\nexport function CopiedIcon(): VNode {\n return (\n \n \n \n );\n}\n\nexport function CopyButton({\n class: clazz,\n children,\n getContent,\n}: {\n children?: ComponentChildren;\n class: string;\n getContent: () => string;\n}): VNode {\n const [copied, setCopied] = useState(false);\n function copyText(): void {\n if (!navigator.clipboard && !window.isSecureContext) {\n prompt(\n \"Clipboard is not available on insecure context (http).\",\n getContent(),\n );\n }\n if (navigator.clipboard) {\n navigator.clipboard.writeText(getContent() || \"\");\n setCopied(true);\n }\n }\n useEffect(() => {\n if (copied) {\n setTimeout(() => {\n setCopied(false);\n }, 1000);\n }\n }, [copied]);\n\n if (!copied) {\n return (\n {\n e.preventDefault();\n copyText();\n }}\n >\n \n {children}\n \n );\n }\n return (\n \n );\n}\n", "/*\n/*\n This file is part of GNU Taler\n (C) 2022 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n TalerError,\n TalerErrorCode,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport { Fragment, VNode, h } from \"preact\";\nimport {\n useCommonPreferences,\n useTranslationContext,\n} from \"../index.browser.js\";\nimport { Attention } from \"./Attention.js\";\n\nexport function DebugInfo({ error }: { error: any }): VNode {\n const { i18n } = useTranslationContext();\n const [{ showDebugInfo }, update] = useCommonPreferences();\n return (\n
\n \n {showDebugInfo && (\n
\n          {JSON.stringify(error, undefined, 2)}\n        
\n )}\n
\n );\n}\nexport function ErrorLoading({ error }: { error: TalerError }): VNode {\n const { i18n } = useTranslationContext();\n switch (error.errorDetail.code) {\n //////////////////\n // Every error that can be produce in a Http Request\n //////////////////\n case TalerErrorCode.GENERIC_TIMEOUT: {\n if (error.hasErrorCode(TalerErrorCode.GENERIC_TIMEOUT)) {\n return (\n \n {error.message}\n \n \n );\n }\n assertUnreachable(1 as never);\n }\n case TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR: {\n if (error.hasErrorCode(TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR)) {\n const { requestMethod, requestUrl, timeoutMs } = error.errorDetail;\n return (\n \n {error.message}\n \n \n );\n }\n assertUnreachable(1 as never);\n }\n case TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT: {\n if (\n error.hasErrorCode(TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT)\n ) {\n const { requestMethod, requestUrl, timeoutMs } = error.errorDetail;\n return (\n \n {error.message}\n \n \n );\n }\n assertUnreachable(1 as never);\n }\n case TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED: {\n if (error.hasErrorCode(TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED)) {\n const { requestMethod, requestUrl, throttleStats } = error.errorDetail;\n return (\n \n {error.message}\n \n \n );\n }\n assertUnreachable(1 as never);\n }\n case TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE: {\n if (\n error.hasErrorCode(TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE)\n ) {\n const { requestMethod, requestUrl, httpStatusCode, validationError } =\n error.errorDetail;\n return (\n \n {error.message}\n \n \n );\n }\n assertUnreachable(1 as never);\n }\n case TalerErrorCode.WALLET_NETWORK_ERROR: {\n if (error.hasErrorCode(TalerErrorCode.WALLET_NETWORK_ERROR)) {\n const { requestMethod, requestUrl } = error.errorDetail;\n return (\n \n {error.message}\n \n \n );\n }\n assertUnreachable(1 as never);\n }\n case TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR: {\n if (error.hasErrorCode(TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR)) {\n const { requestMethod, requestUrl, httpStatusCode, errorResponse } =\n error.errorDetail;\n return (\n \n {error.message}\n \n \n );\n }\n assertUnreachable(1 as never);\n }\n //////////////////\n // Every other error\n //////////////////\n // case TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR: {\n // return \n // \n // }\n //////////////////\n // Default message for unhandled case\n //////////////////\n default:\n return (\n \n {error.message}\n \n \n );\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nimport { Fragment, h, VNode } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\n// import { strings as messages } from \"../i18n/strings.js\";\nimport langIcon from \"../assets/lang.svg\";\nimport { useTranslationContext } from \"../index.browser.js\";\n\ntype LangsNames = {\n [P: string]: string;\n};\n\nconst names: LangsNames = {\n uk: \"\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430 [uk]\",\n tr: \"T\u00FCrk\u00E7e [tr]\",\n ru: \"\u0420\u0443\u0301\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u0301\u043A [ru]\",\n sv: \"Svenska [sv]\",\n it: \"Italiano [it]\",\n fr: \"Fran\u00E7ais [fr]\",\n es: \"Espa\u00F1ol [es]\",\n de: \"Deutsch [de]\",\n en: \"English [en]\",\n};\n\nfunction getLangName(s: keyof LangsNames | string): string {\n if (names[s]) return names[s];\n return String(s);\n}\n\nexport function LangSelector({\n type = \"select\",\n}: {\n type?: \"select\" | \"icon\";\n}): VNode {\n const { lang, changeLanguage, completeness, supportedLang } =\n useTranslationContext();\n const [hidden, setHidden] = useState(true);\n\n useEffect(() => {\n function bodyKeyPress(event: KeyboardEvent) {\n if (event.code === \"Escape\") setHidden(true);\n }\n function bodyOnClick(event: Event) {\n setHidden(true);\n }\n document.body.addEventListener(\"click\", bodyOnClick);\n document.body.addEventListener(\"keydown\", bodyKeyPress as any);\n return () => {\n document.body.removeEventListener(\"keydown\", bodyKeyPress as any);\n document.body.removeEventListener(\"click\", bodyOnClick);\n };\n }, []);\n return (\n
\n {(function () {\n switch (type) {\n case \"select\": {\n return (\n {\n setHidden(!hidden);\n e.stopPropagation();\n }}\n >\n \n \n {getLangName(lang)}\n \n \n \n \n \n \n \n );\n }\n case \"icon\": {\n return (\n {\n setHidden(!hidden);\n e.stopPropagation();\n }}\n >\n
\n \n {/* {lang} */}\n
\n \n );\n }\n }\n })()}\n\n {!hidden && (\n \n {type === \"icon\" ? (\n \n \n \n {getLangName(lang)}\n {(completeness as any)[lang]}%\n \n\n \n {/* \n \n */}\n \n \n \n ) : (\n \n )}\n {Object.keys(supportedLang)\n .filter((l) => l !== lang)\n .map((lang) => (\n {\n changeLanguage(lang);\n setHidden(true);\n }}\n >\n \n {getLangName(lang)}\n {(completeness as any)[lang]}%\n \n\n \n {/* \n \n */}\n \n \n ))}\n \n )}\n
\n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { h, VNode } from \"preact\";\n\nexport function Loading(): VNode {\n return (\n \n \n \n );\n}\n\nfunction Spinner(): VNode {\n return (\n
\n
\n
\n
\n
\n
\n );\n}\n", "import { ComponentChildren, Fragment, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport logo from \"../assets/taler-logo-white.png\";\nimport {\n LangSelector,\n useNotifications,\n useTranslationContext,\n} from \"../index.browser.js\";\n\ninterface Props {\n title: string;\n iconLinkURL: string;\n profileURL?: string;\n notificationURL?: string;\n children?: ComponentChildren;\n onLogout: (() => void) | undefined;\n sites: Array>;\n}\n\nexport function Header({\n title,\n profileURL,\n notificationURL,\n iconLinkURL,\n sites,\n onLogout,\n children,\n}: Props): VNode {\n const { i18n } = useTranslationContext();\n const [open, setOpen] = useState(false);\n const ns = useNotifications();\n return (\n \n
\n
\n
\n
\n \n \"GNU\n \n
\n \n {title}\n \n
\n
\n
\n {sites.map((site) => {\n if (site.length !== 2) return;\n const [name, url] = site;\n return (\n \n {name}\n \n );\n })}\n
\n
\n
\n {!notificationURL ? undefined : (\n \n \n \n Show notifications\n \n {ns.length > 0 ? (\n \n \n \n \n ) : (\n \n \n \n )}\n \n )}\n {!profileURL ? undefined : (\n \n \n \n Open profile\n \n \n \n \n \n )}\n \n\n {\n setOpen(!open);\n }}\n >\n \n \n Open settings\n \n \n \n \n \n
\n
\n
\n\n {open && (\n {\n setOpen(false);\n }}\n >\n
\n\n
\n
\n
\n
\n {\n //do not trigger close if clicking inside the sidebar\n e.stopPropagation();\n }}\n >\n
\n
\n \n Menu\n \n
\n {\n setOpen(false);\n }}\n >\n \n \n Close panel\n \n \n \n \n \n
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n
\n )}\n \n );\n}\n", "import { useTranslationContext } from \"../index.browser.js\";\nimport { h } from \"preact\";\n\nexport function Footer({\n testingUrlKey,\n VERSION,\n GIT_HASH,\n}: {\n VERSION?: string;\n GIT_HASH?: string;\n testingUrlKey?: string;\n}) {\n const { i18n } = useTranslationContext();\n\n const testingUrl =\n testingUrlKey &&\n typeof localStorage !== \"undefined\" &&\n localStorage.getItem(testingUrlKey)\n ? (localStorage.getItem(testingUrlKey) ?? undefined)\n : undefined;\n const versionText = VERSION ? (\n GIT_HASH ? (\n \n Version {VERSION} ({GIT_HASH.substring(0, 8)})\n \n ) : (\n VERSION\n )\n ) : (\n \"\"\n );\n return (\n
\n
\n

\n \n Learn more about{\" \"}\n \n GNU Taler\n \n \n

\n
\n
\n

\n Copyright © 2014—2025 Taler Systems SA. {versionText}{\" \"}\n

\n {testingUrlKey && testingUrl && (\n

\n Testing with {testingUrl}{\" \"}\n {\n e.preventDefault();\n localStorage.removeItem(testingUrlKey);\n window.location.reload();\n }}\n >\n stop testing\n \n

\n )}\n
\n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { Fragment, VNode, h } from \"preact\";\nimport { HTMLAttributes, useState } from \"preact/compat\";\nimport {\n SafeHandlerTemplate,\n useTranslationContext,\n} from \"../index.browser.js\";\nimport { doAutoFocus } from \"./utils.js\";\n\nexport interface ButtonHandler {\n onClick: (() => Promise) | undefined;\n}\n\ninterface Props extends HTMLAttributes {\n handler: ButtonHandler | undefined;\n}\n\n/**\n * This button accept an async function and report a notification\n * on error or success.\n *\n * When the async function is running the inner text will change into\n * a \"loading\" animation.\n *\n * @deprecated use ButtonBetter\n *\n * @param param0\n * @returns\n */\nexport function Button({\n handler,\n children,\n disabled,\n onClick: clickEvent,\n ...rest\n}: Props): VNode {\n const { i18n } = useTranslationContext();\n const [running, setRunning] = useState(false);\n return (\n {\n e.preventDefault();\n if (!handler || !handler.onClick) {\n return;\n }\n setRunning(true);\n handler.onClick().finally(() => {\n setRunning(false);\n });\n }}\n >\n {running ? : children}\n \n );\n}\n\ntype PropsBetter = Omit<\n Omit, \"type\">,\n \"onClick\"\n> & {\n type: \"button\" | \"submit\";\n onClick: SafeHandlerTemplate | undefined;\n focus?: boolean;\n};\n/**\n * FIXME: removed deprecated and change for this one\n * @param param0\n * @returns\n */\nexport function ButtonBetter({\n children,\n focus,\n onClick,\n disabled,\n ...rest\n}: PropsBetter): VNode {\n const [running, setRunning] = useState(false);\n return (\n {\n e.preventDefault();\n if (!onClick || !onClick.args) {\n return;\n }\n setRunning(true);\n onClick.call().finally(() => {\n setRunning(false);\n });\n }}\n >\n {running ? : children}\n \n );\n}\n/**\n * we should have a button-type and a submit-type\n * submit tpye should not have focus sin the focus in the form\n * submit should only be used on forms and there should be only one\n */\n// FIXME: we should stop using bulma css and remove all of this support\nexport function ButtonBetterBulma({\n children,\n focus,\n disabled,\n onClick,\n ...rest\n}: PropsBetter & { \"data-tooltip\"?: string }): VNode {\n const [running, setRunning] = useState(false);\n if (onClick) {\n {\n const prev = onClick.onStart;\n onClick.onStart = () => {\n setRunning(true);\n prev();\n };\n }\n {\n const prev = onClick.onSuccess;\n onClick.onSuccess = (...args) => {\n setRunning(false);\n return prev(...args);\n };\n }\n {\n const prev = onClick.onFail;\n onClick.onFail = (...args) => {\n setRunning(false);\n return prev(...args);\n };\n }\n }\n return (\n {\n e.preventDefault();\n if (!onClick || !onClick.args) {\n return;\n }\n onClick.call();\n }}\n >\n {running ? : children}\n \n );\n}\n\nfunction Spinner(): VNode {\n return (\n \n
\n
\n
\n
\n
\n
\n
\n );\n}\n\nfunction Wait(): VNode {\n return (\n \n
\n \n \n \n \n Loading...\n
\n
\n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { Fragment, h, VNode } from \"preact\";\n\nexport function ShowInputErrorLabel({\n isDirty,\n message,\n}: {\n message: string | undefined;\n isDirty: boolean;\n}): VNode {\n if (message && isDirty)\n return (\n
\n {message}\n
\n );\n return
;\n}\n", "import { Fragment, h, VNode } from \"preact\";\nimport { useState } from \"preact/compat\";\nimport {\n Notification,\n useCommonPreferences,\n useTranslationContext,\n} from \"../index.browser.js\";\nimport { Attention } from \"./Attention.js\";\n\nexport function LocalNotificationBanner({\n notification,\n}: {\n notification?: Notification;\n}): VNode {\n const { i18n } = useTranslationContext();\n const [{ showDebugInfo }] = useCommonPreferences();\n const [moreInfo, setMoreInfo] = useState(false);\n if (!notification) return ;\n switch (notification.message.type) {\n case \"error\":\n const desc = notification.message.description;\n return (\n
\n
\n {\n notification.acknowledge();\n }}\n >\n {desc &&\n desc.length &&\n (moreInfo ? (\n desc.map((d) => {\n return
{d}
;\n })\n ) : (\n
{desc[0]}
\n ))}\n\n
\n
\n {moreInfo || (desc && desc.length < 2) ? undefined : (\n \n )}\n
\n
\n {showDebugInfo && (\n
\n                  {JSON.stringify(notification.message.debug, undefined, 2)}\n                
\n )}\n \n
\n
\n );\n case \"info\":\n return (\n
\n
\n {\n notification.acknowledge();\n }}\n />\n
\n
\n );\n }\n}\n\nexport function LocalNotificationBannerBulma({\n notification,\n}: {\n notification?: Notification;\n}): VNode {\n const { i18n } = useTranslationContext();\n const [{ showDebugInfo }] = useCommonPreferences();\n const [moreInfo, setMoreInfo] = useState(showDebugInfo);\n if (!notification) return ;\n const msg = notification.message;\n switch (msg.type) {\n case \"error\":\n return (\n
\n \n
\n
\n
\n
\n
\n

{msg.title}

\n notification.acknowledge()}\n />\n
\n {msg.description && msg.description.length && (\n
\n {moreInfo ? (\n msg.description.map((d) => {\n return
{d}
;\n })\n ) : (\n
{msg.description[0]}
\n )}\n {moreInfo ||\n msg.description.length === 1 ? undefined : (\n setMoreInfo(true)}\n type=\"button\"\n style={{ justifySelf: \"right\", color: \"gray\" }}\n >\n show more info\n \n )}\n {showDebugInfo && msg.debug && (\n
 {JSON.stringify(msg.debug, undefined, 2)}
\n )}\n
\n )}\n
\n
\n
\n
\n
\n
\n );\n case \"info\":\n return (\n
\n \n
\n
\n
\n
\n
\n

{msg.title}

\n
\n
\n
\n
\n
\n
\n
\n );\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport { Fragment, VNode, h } from \"preact\";\nimport {\n Attention,\n GLOBAL_NOTIFICATION_TIMEOUT as GLOBAL_TOAST_TIMEOUT,\n Notification,\n useNotifications,\n} from \"../index.browser.js\";\nimport { Duration } from \"@gnu-taler/taler-util\";\n\n/**\n * Toasts should be considered when displaying these types of information to the user:\n *\n * Low attention messages that do not require user action\n * Singular status updates\n * Confirmations\n * Information that does not need to be followed up\n *\n * Do not use toasts if the information contains the following:\n *\n * High attention and crtitical information\n * Time-sensitive information\n * Requires user action or input\n * Batch updates\n *\n * @returns\n */\nexport function ToastBanner({ debug }: { debug?: boolean }): VNode {\n const notifs = useNotifications();\n if (notifs.length === 0) return ;\n const show = notifs.filter((e) => !e.message.ack && !e.message.timeout);\n if (show.length === 0) return ;\n return ;\n}\n\nfunction AttentionByType({\n msg,\n debug,\n}: {\n debug?: boolean;\n msg: Notification;\n}) {\n switch (msg.message.type) {\n case \"error\":\n return (\n {\n msg.acknowledge();\n }}\n timeout={debug ? Duration.getForever() : GLOBAL_TOAST_TIMEOUT}\n >\n {msg.message.description && (\n
\n {msg.message.description}\n
\n )}\n {!debug ? undefined :
{msg.message.debug}
}\n \n );\n case \"info\":\n return (\n {\n msg.acknowledge();\n }}\n timeout={GLOBAL_TOAST_TIMEOUT}\n />\n );\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { AbsoluteTime, Duration } from \"@gnu-taler/taler-util\";\nimport {\n formatISO,\n format,\n formatDuration,\n intervalToDuration,\n} from \"date-fns\";\nimport { Fragment, h, VNode } from \"preact\";\nimport { useTranslationContext } from \"../index.browser.js\";\n\n/**\n *\n * @param timestamp time to be formatted\n * @param relative duration threshold, if the difference is lower\n * the timestamp will be formatted as relative time from \"now\"\n *\n * @returns\n */\nexport function Time({\n timestamp,\n relative,\n format: formatString,\n}: {\n timestamp: AbsoluteTime | undefined;\n relative?: Duration;\n format: string;\n}): VNode {\n const { i18n, dateLocale } = useTranslationContext();\n if (!timestamp) return ;\n\n if (timestamp.t_ms === \"never\") {\n return ;\n }\n\n const now = AbsoluteTime.now();\n const diff = AbsoluteTime.difference(now, timestamp);\n if (relative && now.t_ms !== \"never\" && Duration.cmp(diff, relative) === -1) {\n const d = intervalToDuration({\n start: now.t_ms,\n end: timestamp.t_ms,\n });\n d.seconds = 0;\n const duration = formatDuration(d, { locale: dateLocale });\n const isFuture = AbsoluteTime.cmp(now, timestamp) < 0;\n if (isFuture) {\n return (\n \n );\n } else {\n return (\n \n );\n }\n }\n return (\n \n );\n}\n", "export default function toInteger(dirtyNumber) {\n if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {\n return NaN;\n }\n\n var number = Number(dirtyNumber);\n\n if (isNaN(number)) {\n return number;\n }\n\n return number < 0 ? Math.ceil(number) : Math.floor(number);\n}", "export default function requiredArgs(required, args) {\n if (args.length < required) {\n throw new TypeError(required + ' argument' + (required > 1 ? 's' : '') + ' required, but only ' + args.length + ' present');\n }\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name toDate\n * @category Common Helpers\n * @summary Convert the given argument to an instance of Date.\n *\n * @description\n * Convert the given argument to an instance of Date.\n *\n * If the argument is an instance of Date, the function returns its clone.\n *\n * If the argument is a number, it is treated as a timestamp.\n *\n * If the argument is none of the above, the function returns Invalid Date.\n *\n * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.\n *\n * @param {Date|Number} argument - the value to convert\n * @returns {Date} the parsed date in the local time zone\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Clone the date:\n * const result = toDate(new Date(2014, 1, 11, 11, 30, 30))\n * //=> Tue Feb 11 2014 11:30:30\n *\n * @example\n * // Convert the timestamp to date:\n * const result = toDate(1392098430000)\n * //=> Tue Feb 11 2014 11:30:30\n */\n\nexport default function toDate(argument) {\n requiredArgs(1, arguments);\n var argStr = Object.prototype.toString.call(argument); // Clone the date\n\n if (argument instanceof Date || _typeof(argument) === 'object' && argStr === '[object Date]') {\n // Prevent the date to lose the milliseconds when passed to new Date() in IE10\n return new Date(argument.getTime());\n } else if (typeof argument === 'number' || argStr === '[object Number]') {\n return new Date(argument);\n } else {\n if ((typeof argument === 'string' || argStr === '[object String]') && typeof console !== 'undefined') {\n // eslint-disable-next-line no-console\n console.warn(\"Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#string-arguments\"); // eslint-disable-next-line no-console\n\n console.warn(new Error().stack);\n }\n\n return new Date(NaN);\n }\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name addDays\n * @category Day Helpers\n * @summary Add the specified number of days to the given date.\n *\n * @description\n * Add the specified number of days to the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of days to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} - the new date with the days added\n * @throws {TypeError} - 2 arguments required\n *\n * @example\n * // Add 10 days to 1 September 2014:\n * const result = addDays(new Date(2014, 8, 1), 10)\n * //=> Thu Sep 11 2014 00:00:00\n */\n\nexport default function addDays(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var date = toDate(dirtyDate);\n var amount = toInteger(dirtyAmount);\n\n if (isNaN(amount)) {\n return new Date(NaN);\n }\n\n if (!amount) {\n // If 0 days, no-op to avoid changing times in the hour before end of DST\n return date;\n }\n\n date.setDate(date.getDate() + amount);\n return date;\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name addMonths\n * @category Month Helpers\n * @summary Add the specified number of months to the given date.\n *\n * @description\n * Add the specified number of months to the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of months to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the months added\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Add 5 months to 1 September 2014:\n * const result = addMonths(new Date(2014, 8, 1), 5)\n * //=> Sun Feb 01 2015 00:00:00\n */\n\nexport default function addMonths(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var date = toDate(dirtyDate);\n var amount = toInteger(dirtyAmount);\n\n if (isNaN(amount)) {\n return new Date(NaN);\n }\n\n if (!amount) {\n // If 0 months, no-op to avoid changing times in the hour before end of DST\n return date;\n }\n\n var dayOfMonth = date.getDate(); // The JS Date object supports date math by accepting out-of-bounds values for\n // month, day, etc. For example, new Date(2020, 0, 0) returns 31 Dec 2019 and\n // new Date(2020, 13, 1) returns 1 Feb 2021. This is *almost* the behavior we\n // want except that dates will wrap around the end of a month, meaning that\n // new Date(2020, 13, 31) will return 3 Mar 2021 not 28 Feb 2021 as desired. So\n // we'll default to the end of the desired month by adding 1 to the desired\n // month and using a date of 0 to back up one day to the end of the desired\n // month.\n\n var endOfDesiredMonth = new Date(date.getTime());\n endOfDesiredMonth.setMonth(date.getMonth() + amount + 1, 0);\n var daysInMonth = endOfDesiredMonth.getDate();\n\n if (dayOfMonth >= daysInMonth) {\n // If we're already at the end of the month, then this is the correct date\n // and we're done.\n return endOfDesiredMonth;\n } else {\n // Otherwise, we now know that setting the original day-of-month value won't\n // cause an overflow, so set the desired day-of-month. Note that we can't\n // just set the date of `endOfDesiredMonth` because that object may have had\n // its time changed in the unusual case where where a DST transition was on\n // the last day of the month and its local time was in the hour skipped or\n // repeated next to a DST transition. So we use `date` instead which is\n // guaranteed to still have the original time.\n date.setFullYear(endOfDesiredMonth.getFullYear(), endOfDesiredMonth.getMonth(), dayOfMonth);\n return date;\n }\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nimport addDays from \"../addDays/index.js\";\nimport addMonths from \"../addMonths/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\n\n/**\n * @name add\n * @category Common Helpers\n * @summary Add the specified years, months, weeks, days, hours, minutes and seconds to the given date.\n *\n * @description\n * Add the specified years, months, weeks, days, hours, minutes and seconds to the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Duration} duration - the object with years, months, weeks, days, hours, minutes and seconds to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n *\n * | Key | Description |\n * |----------------|------------------------------------|\n * | years | Amount of years to be added |\n * | months | Amount of months to be added |\n * | weeks | Amount of weeks to be added |\n * | days | Amount of days to be added |\n * | hours | Amount of hours to be added |\n * | minutes | Amount of minutes to be added |\n * | seconds | Amount of seconds to be added |\n *\n * All values default to 0\n *\n * @returns {Date} the new date with the seconds added\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Add the following duration to 1 September 2014, 10:19:50\n * const result = add(new Date(2014, 8, 1, 10, 19, 50), {\n * years: 2,\n * months: 9,\n * weeks: 1,\n * days: 7,\n * hours: 5,\n * minutes: 9,\n * seconds: 30,\n * })\n * //=> Thu Jun 15 2017 15:29:20\n */\nexport default function add(dirtyDate, duration) {\n requiredArgs(2, arguments);\n if (!duration || _typeof(duration) !== 'object') return new Date(NaN);\n var years = duration.years ? toInteger(duration.years) : 0;\n var months = duration.months ? toInteger(duration.months) : 0;\n var weeks = duration.weeks ? toInteger(duration.weeks) : 0;\n var days = duration.days ? toInteger(duration.days) : 0;\n var hours = duration.hours ? toInteger(duration.hours) : 0;\n var minutes = duration.minutes ? toInteger(duration.minutes) : 0;\n var seconds = duration.seconds ? toInteger(duration.seconds) : 0; // Add years and months\n\n var date = toDate(dirtyDate);\n var dateWithMonths = months || years ? addMonths(date, months + years * 12) : date; // Add weeks and days\n\n var dateWithDays = days || weeks ? addDays(dateWithMonths, days + weeks * 7) : dateWithMonths; // Add days, hours, minutes and seconds\n\n var minutesToAdd = minutes + hours * 60;\n var secondsToAdd = seconds + minutesToAdd * 60;\n var msToAdd = secondsToAdd * 1000;\n var finalDate = new Date(dateWithDays.getTime() + msToAdd);\n return finalDate;\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name addMilliseconds\n * @category Millisecond Helpers\n * @summary Add the specified number of milliseconds to the given date.\n *\n * @description\n * Add the specified number of milliseconds to the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of milliseconds to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the milliseconds added\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Add 750 milliseconds to 10 July 2014 12:45:30.000:\n * const result = addMilliseconds(new Date(2014, 6, 10, 12, 45, 30, 0), 750)\n * //=> Thu Jul 10 2014 12:45:30.750\n */\n\nexport default function addMilliseconds(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var timestamp = toDate(dirtyDate).getTime();\n var amount = toInteger(dirtyAmount);\n return new Date(timestamp + amount);\n}", "var defaultOptions = {};\nexport function getDefaultOptions() {\n return defaultOptions;\n}\nexport function setDefaultOptions(newOptions) {\n defaultOptions = newOptions;\n}", "import toDate from \"../toDate/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport { getDefaultOptions } from \"../_lib/defaultOptions/index.js\";\n/**\n * @name startOfWeek\n * @category Week Helpers\n * @summary Return the start of a week for the given date.\n *\n * @description\n * Return the start of a week for the given date.\n * The result will be in the local timezone.\n *\n * @param {Date|Number} date - the original date\n * @param {Object} [options] - an object with options.\n * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}\n * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)\n * @returns {Date} the start of a week\n * @throws {TypeError} 1 argument required\n * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6\n *\n * @example\n * // The start of a week for 2 September 2014 11:55:00:\n * const result = startOfWeek(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Sun Aug 31 2014 00:00:00\n *\n * @example\n * // If the week starts on Monday, the start of the week for 2 September 2014 11:55:00:\n * const result = startOfWeek(new Date(2014, 8, 2, 11, 55, 0), { weekStartsOn: 1 })\n * //=> Mon Sep 01 2014 00:00:00\n */\n\nexport default function startOfWeek(dirtyDate, options) {\n var _ref, _ref2, _ref3, _options$weekStartsOn, _options$locale, _options$locale$optio, _defaultOptions$local, _defaultOptions$local2;\n\n requiredArgs(1, arguments);\n var defaultOptions = getDefaultOptions();\n var weekStartsOn = toInteger((_ref = (_ref2 = (_ref3 = (_options$weekStartsOn = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.weekStartsOn) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.weekStartsOn) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.weekStartsOn) !== null && _ref !== void 0 ? _ref : 0); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN\n\n if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {\n throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');\n }\n\n var date = toDate(dirtyDate);\n var day = date.getDay();\n var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;\n date.setDate(date.getDate() - diff);\n date.setHours(0, 0, 0, 0);\n return date;\n}", "/**\n * Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.\n * They usually appear for dates that denote time before the timezones were introduced\n * (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891\n * and GMT+01:00:00 after that date)\n *\n * Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,\n * which would lead to incorrect calculations.\n *\n * This function returns the timezone offset in milliseconds that takes seconds in account.\n */\nexport default function getTimezoneOffsetInMilliseconds(date) {\n var utcDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()));\n utcDate.setUTCFullYear(date.getFullYear());\n return date.getTime() - utcDate.getTime();\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name startOfDay\n * @category Day Helpers\n * @summary Return the start of a day for the given date.\n *\n * @description\n * Return the start of a day for the given date.\n * The result will be in the local timezone.\n *\n * @param {Date|Number} date - the original date\n * @returns {Date} the start of a day\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // The start of a day for 2 September 2014 11:55:00:\n * const result = startOfDay(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Tue Sep 02 2014 00:00:00\n */\n\nexport default function startOfDay(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n date.setHours(0, 0, 0, 0);\n return date;\n}", "import getTimezoneOffsetInMilliseconds from \"../_lib/getTimezoneOffsetInMilliseconds/index.js\";\nimport startOfDay from \"../startOfDay/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nvar MILLISECONDS_IN_DAY = 86400000;\n/**\n * @name differenceInCalendarDays\n * @category Day Helpers\n * @summary Get the number of calendar days between the given dates.\n *\n * @description\n * Get the number of calendar days between the given dates. This means that the times are removed\n * from the dates and then the difference in days is calculated.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of calendar days\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many calendar days are between\n * // 2 July 2011 23:00:00 and 2 July 2012 00:00:00?\n * const result = differenceInCalendarDays(\n * new Date(2012, 6, 2, 0, 0),\n * new Date(2011, 6, 2, 23, 0)\n * )\n * //=> 366\n * // How many calendar days are between\n * // 2 July 2011 23:59:00 and 3 July 2011 00:01:00?\n * const result = differenceInCalendarDays(\n * new Date(2011, 6, 3, 0, 1),\n * new Date(2011, 6, 2, 23, 59)\n * )\n * //=> 1\n */\n\nexport default function differenceInCalendarDays(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var startOfDayLeft = startOfDay(dirtyDateLeft);\n var startOfDayRight = startOfDay(dirtyDateRight);\n var timestampLeft = startOfDayLeft.getTime() - getTimezoneOffsetInMilliseconds(startOfDayLeft);\n var timestampRight = startOfDayRight.getTime() - getTimezoneOffsetInMilliseconds(startOfDayRight); // Round the number of days to the nearest integer\n // because the number of milliseconds in a day is not constant\n // (e.g. it's different in the day of the daylight saving time clock shift)\n\n return Math.round((timestampLeft - timestampRight) / MILLISECONDS_IN_DAY);\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name compareAsc\n * @category Common Helpers\n * @summary Compare the two dates and return -1, 0 or 1.\n *\n * @description\n * Compare the two dates and return 1 if the first date is after the second,\n * -1 if the first date is before the second or 0 if dates are equal.\n *\n * @param {Date|Number} dateLeft - the first date to compare\n * @param {Date|Number} dateRight - the second date to compare\n * @returns {Number} the result of the comparison\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Compare 11 February 1987 and 10 July 1989:\n * const result = compareAsc(new Date(1987, 1, 11), new Date(1989, 6, 10))\n * //=> -1\n *\n * @example\n * // Sort the array of dates:\n * const result = [\n * new Date(1995, 6, 2),\n * new Date(1987, 1, 11),\n * new Date(1989, 6, 10)\n * ].sort(compareAsc)\n * //=> [\n * // Wed Feb 11 1987 00:00:00,\n * // Mon Jul 10 1989 00:00:00,\n * // Sun Jul 02 1995 00:00:00\n * // ]\n */\n\nexport default function compareAsc(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n var diff = dateLeft.getTime() - dateRight.getTime();\n\n if (diff < 0) {\n return -1;\n } else if (diff > 0) {\n return 1; // Return 0 if diff is 0; return NaN if diff is NaN\n } else {\n return diff;\n }\n}", "/**\n * Days in 1 week.\n *\n * @name daysInWeek\n * @constant\n * @type {number}\n * @default\n */\nexport var daysInWeek = 7;\n/**\n * Days in 1 year\n * One years equals 365.2425 days according to the formula:\n *\n * > Leap year occures every 4 years, except for years that are divisable by 100 and not divisable by 400.\n * > 1 mean year = (365+1/4-1/100+1/400) days = 365.2425 days\n *\n * @name daysInYear\n * @constant\n * @type {number}\n * @default\n */\n\nexport var daysInYear = 365.2425;\n/**\n * Maximum allowed time.\n *\n * @name maxTime\n * @constant\n * @type {number}\n * @default\n */\n\nexport var maxTime = Math.pow(10, 8) * 24 * 60 * 60 * 1000;\n/**\n * Milliseconds in 1 minute\n *\n * @name millisecondsInMinute\n * @constant\n * @type {number}\n * @default\n */\n\nexport var millisecondsInMinute = 60000;\n/**\n * Milliseconds in 1 hour\n *\n * @name millisecondsInHour\n * @constant\n * @type {number}\n * @default\n */\n\nexport var millisecondsInHour = 3600000;\n/**\n * Milliseconds in 1 second\n *\n * @name millisecondsInSecond\n * @constant\n * @type {number}\n * @default\n */\n\nexport var millisecondsInSecond = 1000;\n/**\n * Minimum allowed time.\n *\n * @name minTime\n * @constant\n * @type {number}\n * @default\n */\n\nexport var minTime = -maxTime;\n/**\n * Minutes in 1 hour\n *\n * @name minutesInHour\n * @constant\n * @type {number}\n * @default\n */\n\nexport var minutesInHour = 60;\n/**\n * Months in 1 quarter\n *\n * @name monthsInQuarter\n * @constant\n * @type {number}\n * @default\n */\n\nexport var monthsInQuarter = 3;\n/**\n * Months in 1 year\n *\n * @name monthsInYear\n * @constant\n * @type {number}\n * @default\n */\n\nexport var monthsInYear = 12;\n/**\n * Quarters in 1 year\n *\n * @name quartersInYear\n * @constant\n * @type {number}\n * @default\n */\n\nexport var quartersInYear = 4;\n/**\n * Seconds in 1 hour\n *\n * @name secondsInHour\n * @constant\n * @type {number}\n * @default\n */\n\nexport var secondsInHour = 3600;\n/**\n * Seconds in 1 minute\n *\n * @name secondsInMinute\n * @constant\n * @type {number}\n * @default\n */\n\nexport var secondsInMinute = 60;\n/**\n * Seconds in 1 day\n *\n * @name secondsInDay\n * @constant\n * @type {number}\n * @default\n */\n\nexport var secondsInDay = secondsInHour * 24;\n/**\n * Seconds in 1 week\n *\n * @name secondsInWeek\n * @constant\n * @type {number}\n * @default\n */\n\nexport var secondsInWeek = secondsInDay * 7;\n/**\n * Seconds in 1 year\n *\n * @name secondsInYear\n * @constant\n * @type {number}\n * @default\n */\n\nexport var secondsInYear = secondsInDay * daysInYear;\n/**\n * Seconds in 1 month\n *\n * @name secondsInMonth\n * @constant\n * @type {number}\n * @default\n */\n\nexport var secondsInMonth = secondsInYear / 12;\n/**\n * Seconds in 1 quarter\n *\n * @name secondsInQuarter\n * @constant\n * @type {number}\n * @default\n */\n\nexport var secondsInQuarter = secondsInMonth * 3;", "import startOfDay from \"../startOfDay/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isSameDay\n * @category Day Helpers\n * @summary Are the given dates in the same day (and year and month)?\n *\n * @description\n * Are the given dates in the same day (and year and month)?\n *\n * @param {Date|Number} dateLeft - the first date to check\n * @param {Date|Number} dateRight - the second date to check\n * @returns {Boolean} the dates are in the same day (and year and month)\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Are 4 September 06:00:00 and 4 September 18:00:00 in the same day?\n * const result = isSameDay(new Date(2014, 8, 4, 6, 0), new Date(2014, 8, 4, 18, 0))\n * //=> true\n *\n * @example\n * // Are 4 September and 4 October in the same day?\n * const result = isSameDay(new Date(2014, 8, 4), new Date(2014, 9, 4))\n * //=> false\n *\n * @example\n * // Are 4 September, 2014 and 4 September, 2015 in the same day?\n * const result = isSameDay(new Date(2014, 8, 4), new Date(2015, 8, 4))\n * //=> false\n */\n\nexport default function isSameDay(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeftStartOfDay = startOfDay(dirtyDateLeft);\n var dateRightStartOfDay = startOfDay(dirtyDateRight);\n return dateLeftStartOfDay.getTime() === dateRightStartOfDay.getTime();\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isDate\n * @category Common Helpers\n * @summary Is the given value a date?\n *\n * @description\n * Returns true if the given value is an instance of Date. The function works for dates transferred across iframes.\n *\n * @param {*} value - the value to check\n * @returns {boolean} true if the given value is a date\n * @throws {TypeError} 1 arguments required\n *\n * @example\n * // For a valid date:\n * const result = isDate(new Date())\n * //=> true\n *\n * @example\n * // For an invalid date:\n * const result = isDate(new Date(NaN))\n * //=> true\n *\n * @example\n * // For some value:\n * const result = isDate('2014-02-31')\n * //=> false\n *\n * @example\n * // For an object:\n * const result = isDate({})\n * //=> false\n */\n\nexport default function isDate(value) {\n requiredArgs(1, arguments);\n return value instanceof Date || _typeof(value) === 'object' && Object.prototype.toString.call(value) === '[object Date]';\n}", "import isDate from \"../isDate/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isValid\n * @category Common Helpers\n * @summary Is the given date valid?\n *\n * @description\n * Returns false if argument is Invalid Date and true otherwise.\n * Argument is converted to Date using `toDate`. See [toDate]{@link https://date-fns.org/docs/toDate}\n * Invalid Date is a Date, whose time value is NaN.\n *\n * Time value of Date: http://es5.github.io/#x15.9.1.1\n *\n * @param {*} date - the date to check\n * @returns {Boolean} the date is valid\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // For the valid date:\n * const result = isValid(new Date(2014, 1, 31))\n * //=> true\n *\n * @example\n * // For the value, convertable into a date:\n * const result = isValid(1393804800000)\n * //=> true\n *\n * @example\n * // For the invalid date:\n * const result = isValid(new Date(''))\n * //=> false\n */\n\nexport default function isValid(dirtyDate) {\n requiredArgs(1, arguments);\n\n if (!isDate(dirtyDate) && typeof dirtyDate !== 'number') {\n return false;\n }\n\n var date = toDate(dirtyDate);\n return !isNaN(Number(date));\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInCalendarMonths\n * @category Month Helpers\n * @summary Get the number of calendar months between the given dates.\n *\n * @description\n * Get the number of calendar months between the given dates.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of calendar months\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many calendar months are between 31 January 2014 and 1 September 2014?\n * const result = differenceInCalendarMonths(\n * new Date(2014, 8, 1),\n * new Date(2014, 0, 31)\n * )\n * //=> 8\n */\n\nexport default function differenceInCalendarMonths(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n var yearDiff = dateLeft.getFullYear() - dateRight.getFullYear();\n var monthDiff = dateLeft.getMonth() - dateRight.getMonth();\n return yearDiff * 12 + monthDiff;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInCalendarYears\n * @category Year Helpers\n * @summary Get the number of calendar years between the given dates.\n *\n * @description\n * Get the number of calendar years between the given dates.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of calendar years\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many calendar years are between 31 December 2013 and 11 February 2015?\n * const result = differenceInCalendarYears(\n * new Date(2015, 1, 11),\n * new Date(2013, 11, 31)\n * )\n * //=> 2\n */\n\nexport default function differenceInCalendarYears(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n return dateLeft.getFullYear() - dateRight.getFullYear();\n}", "import toDate from \"../toDate/index.js\";\nimport differenceInCalendarDays from \"../differenceInCalendarDays/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\"; // Like `compareAsc` but uses local time not UTC, which is needed\n// for accurate equality comparisons of UTC timestamps that end up\n// having the same representation in local time, e.g. one hour before\n// DST ends vs. the instant that DST ends.\n\nfunction compareLocalAsc(dateLeft, dateRight) {\n var diff = dateLeft.getFullYear() - dateRight.getFullYear() || dateLeft.getMonth() - dateRight.getMonth() || dateLeft.getDate() - dateRight.getDate() || dateLeft.getHours() - dateRight.getHours() || dateLeft.getMinutes() - dateRight.getMinutes() || dateLeft.getSeconds() - dateRight.getSeconds() || dateLeft.getMilliseconds() - dateRight.getMilliseconds();\n\n if (diff < 0) {\n return -1;\n } else if (diff > 0) {\n return 1; // Return 0 if diff is 0; return NaN if diff is NaN\n } else {\n return diff;\n }\n}\n/**\n * @name differenceInDays\n * @category Day Helpers\n * @summary Get the number of full days between the given dates.\n *\n * @description\n * Get the number of full day periods between two dates. Fractional days are\n * truncated towards zero.\n *\n * One \"full day\" is the distance between a local time in one day to the same\n * local time on the next or previous day. A full day can sometimes be less than\n * or more than 24 hours if a daylight savings change happens between two dates.\n *\n * To ignore DST and only measure exact 24-hour periods, use this instead:\n * `Math.floor(differenceInHours(dateLeft, dateRight)/24)|0`.\n *\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of full days according to the local timezone\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many full days are between\n * // 2 July 2011 23:00:00 and 2 July 2012 00:00:00?\n * const result = differenceInDays(\n * new Date(2012, 6, 2, 0, 0),\n * new Date(2011, 6, 2, 23, 0)\n * )\n * //=> 365\n * // How many full days are between\n * // 2 July 2011 23:59:00 and 3 July 2011 00:01:00?\n * const result = differenceInDays(\n * new Date(2011, 6, 3, 0, 1),\n * new Date(2011, 6, 2, 23, 59)\n * )\n * //=> 0\n * // How many full days are between\n * // 1 March 2020 0:00 and 1 June 2020 0:00 ?\n * // Note: because local time is used, the\n * // result will always be 92 days, even in\n * // time zones where DST starts and the\n * // period has only 92*24-1 hours.\n * const result = differenceInDays(\n * new Date(2020, 5, 1),\n * new Date(2020, 2, 1)\n * )\n//=> 92\n */\n\n\nexport default function differenceInDays(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n var sign = compareLocalAsc(dateLeft, dateRight);\n var difference = Math.abs(differenceInCalendarDays(dateLeft, dateRight));\n dateLeft.setDate(dateLeft.getDate() - sign * difference); // Math.abs(diff in full days - diff in calendar days) === 1 if last calendar day is not full\n // If so, result must be decreased by 1 in absolute value\n\n var isLastDayNotFull = Number(compareLocalAsc(dateLeft, dateRight) === -sign);\n var result = sign * (difference - isLastDayNotFull); // Prevent negative zero\n\n return result === 0 ? 0 : result;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInMilliseconds\n * @category Millisecond Helpers\n * @summary Get the number of milliseconds between the given dates.\n *\n * @description\n * Get the number of milliseconds between the given dates.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of milliseconds\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many milliseconds are between\n * // 2 July 2014 12:30:20.600 and 2 July 2014 12:30:21.700?\n * const result = differenceInMilliseconds(\n * new Date(2014, 6, 2, 12, 30, 21, 700),\n * new Date(2014, 6, 2, 12, 30, 20, 600)\n * )\n * //=> 1100\n */\n\nexport default function differenceInMilliseconds(dateLeft, dateRight) {\n requiredArgs(2, arguments);\n return toDate(dateLeft).getTime() - toDate(dateRight).getTime();\n}", "var roundingMap = {\n ceil: Math.ceil,\n round: Math.round,\n floor: Math.floor,\n trunc: function trunc(value) {\n return value < 0 ? Math.ceil(value) : Math.floor(value);\n } // Math.trunc is not supported by IE\n\n};\nvar defaultRoundingMethod = 'trunc';\nexport function getRoundingMethod(method) {\n return method ? roundingMap[method] : roundingMap[defaultRoundingMethod];\n}", "import { millisecondsInHour } from \"../constants/index.js\";\nimport differenceInMilliseconds from \"../differenceInMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport { getRoundingMethod } from \"../_lib/roundingMethods/index.js\";\n/**\n * @name differenceInHours\n * @category Hour Helpers\n * @summary Get the number of hours between the given dates.\n *\n * @description\n * Get the number of hours between the given dates.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @param {Object} [options] - an object with options.\n * @param {String} [options.roundingMethod='trunc'] - a rounding method (`ceil`, `floor`, `round` or `trunc`)\n * @returns {Number} the number of hours\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many hours are between 2 July 2014 06:50:00 and 2 July 2014 19:00:00?\n * const result = differenceInHours(\n * new Date(2014, 6, 2, 19, 0),\n * new Date(2014, 6, 2, 6, 50)\n * )\n * //=> 12\n */\n\nexport default function differenceInHours(dateLeft, dateRight, options) {\n requiredArgs(2, arguments);\n var diff = differenceInMilliseconds(dateLeft, dateRight) / millisecondsInHour;\n return getRoundingMethod(options === null || options === void 0 ? void 0 : options.roundingMethod)(diff);\n}", "import { millisecondsInMinute } from \"../constants/index.js\";\nimport differenceInMilliseconds from \"../differenceInMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport { getRoundingMethod } from \"../_lib/roundingMethods/index.js\";\n/**\n * @name differenceInMinutes\n * @category Minute Helpers\n * @summary Get the number of minutes between the given dates.\n *\n * @description\n * Get the signed number of full (rounded towards 0) minutes between the given dates.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @param {Object} [options] - an object with options.\n * @param {String} [options.roundingMethod='trunc'] - a rounding method (`ceil`, `floor`, `round` or `trunc`)\n * @returns {Number} the number of minutes\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many minutes are between 2 July 2014 12:07:59 and 2 July 2014 12:20:00?\n * const result = differenceInMinutes(\n * new Date(2014, 6, 2, 12, 20, 0),\n * new Date(2014, 6, 2, 12, 7, 59)\n * )\n * //=> 12\n *\n * @example\n * // How many minutes are between 10:01:59 and 10:00:00\n * const result = differenceInMinutes(\n * new Date(2000, 0, 1, 10, 0, 0),\n * new Date(2000, 0, 1, 10, 1, 59)\n * )\n * //=> -1\n */\n\nexport default function differenceInMinutes(dateLeft, dateRight, options) {\n requiredArgs(2, arguments);\n var diff = differenceInMilliseconds(dateLeft, dateRight) / millisecondsInMinute;\n return getRoundingMethod(options === null || options === void 0 ? void 0 : options.roundingMethod)(diff);\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name endOfDay\n * @category Day Helpers\n * @summary Return the end of a day for the given date.\n *\n * @description\n * Return the end of a day for the given date.\n * The result will be in the local timezone.\n *\n * @param {Date|Number} date - the original date\n * @returns {Date} the end of a day\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // The end of a day for 2 September 2014 11:55:00:\n * const result = endOfDay(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Tue Sep 02 2014 23:59:59.999\n */\n\nexport default function endOfDay(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n date.setHours(23, 59, 59, 999);\n return date;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name endOfMonth\n * @category Month Helpers\n * @summary Return the end of a month for the given date.\n *\n * @description\n * Return the end of a month for the given date.\n * The result will be in the local timezone.\n *\n * @param {Date|Number} date - the original date\n * @returns {Date} the end of a month\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // The end of a month for 2 September 2014 11:55:00:\n * const result = endOfMonth(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Tue Sep 30 2014 23:59:59.999\n */\n\nexport default function endOfMonth(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var month = date.getMonth();\n date.setFullYear(date.getFullYear(), month + 1, 0);\n date.setHours(23, 59, 59, 999);\n return date;\n}", "import toDate from \"../toDate/index.js\";\nimport endOfDay from \"../endOfDay/index.js\";\nimport endOfMonth from \"../endOfMonth/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isLastDayOfMonth\n * @category Month Helpers\n * @summary Is the given date the last day of a month?\n *\n * @description\n * Is the given date the last day of a month?\n *\n * @param {Date|Number} date - the date to check\n * @returns {Boolean} the date is the last day of a month\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Is 28 February 2014 the last day of a month?\n * const result = isLastDayOfMonth(new Date(2014, 1, 28))\n * //=> true\n */\n\nexport default function isLastDayOfMonth(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n return endOfDay(date).getTime() === endOfMonth(date).getTime();\n}", "import toDate from \"../toDate/index.js\";\nimport differenceInCalendarMonths from \"../differenceInCalendarMonths/index.js\";\nimport compareAsc from \"../compareAsc/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport isLastDayOfMonth from \"../isLastDayOfMonth/index.js\";\n/**\n * @name differenceInMonths\n * @category Month Helpers\n * @summary Get the number of full months between the given dates.\n *\n * @description\n * Get the number of full months between the given dates using trunc as a default rounding method.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of full months\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many full months are between 31 January 2014 and 1 September 2014?\n * const result = differenceInMonths(new Date(2014, 8, 1), new Date(2014, 0, 31))\n * //=> 7\n */\n\nexport default function differenceInMonths(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n var sign = compareAsc(dateLeft, dateRight);\n var difference = Math.abs(differenceInCalendarMonths(dateLeft, dateRight));\n var result; // Check for the difference of less than month\n\n if (difference < 1) {\n result = 0;\n } else {\n if (dateLeft.getMonth() === 1 && dateLeft.getDate() > 27) {\n // This will check if the date is end of Feb and assign a higher end of month date\n // to compare it with Jan\n dateLeft.setDate(30);\n }\n\n dateLeft.setMonth(dateLeft.getMonth() - sign * difference); // Math.abs(diff in full months - diff in calendar months) === 1 if last calendar month is not full\n // If so, result must be decreased by 1 in absolute value\n\n var isLastMonthNotFull = compareAsc(dateLeft, dateRight) === -sign; // Check for cases of one full calendar month\n\n if (isLastDayOfMonth(toDate(dirtyDateLeft)) && difference === 1 && compareAsc(dirtyDateLeft, dateRight) === 1) {\n isLastMonthNotFull = false;\n }\n\n result = sign * (difference - Number(isLastMonthNotFull));\n } // Prevent negative zero\n\n\n return result === 0 ? 0 : result;\n}", "import differenceInMilliseconds from \"../differenceInMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport { getRoundingMethod } from \"../_lib/roundingMethods/index.js\";\n/**\n * @name differenceInSeconds\n * @category Second Helpers\n * @summary Get the number of seconds between the given dates.\n *\n * @description\n * Get the number of seconds between the given dates.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @param {Object} [options] - an object with options.\n * @param {String} [options.roundingMethod='trunc'] - a rounding method (`ceil`, `floor`, `round` or `trunc`)\n * @returns {Number} the number of seconds\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many seconds are between\n * // 2 July 2014 12:30:07.999 and 2 July 2014 12:30:20.000?\n * const result = differenceInSeconds(\n * new Date(2014, 6, 2, 12, 30, 20, 0),\n * new Date(2014, 6, 2, 12, 30, 7, 999)\n * )\n * //=> 12\n */\n\nexport default function differenceInSeconds(dateLeft, dateRight, options) {\n requiredArgs(2, arguments);\n var diff = differenceInMilliseconds(dateLeft, dateRight) / 1000;\n return getRoundingMethod(options === null || options === void 0 ? void 0 : options.roundingMethod)(diff);\n}", "import toDate from \"../toDate/index.js\";\nimport differenceInCalendarYears from \"../differenceInCalendarYears/index.js\";\nimport compareAsc from \"../compareAsc/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInYears\n * @category Year Helpers\n * @summary Get the number of full years between the given dates.\n *\n * @description\n * Get the number of full years between the given dates.\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of full years\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many full years are between 31 December 2013 and 11 February 2015?\n * const result = differenceInYears(new Date(2015, 1, 11), new Date(2013, 11, 31))\n * //=> 1\n */\n\nexport default function differenceInYears(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n var sign = compareAsc(dateLeft, dateRight);\n var difference = Math.abs(differenceInCalendarYears(dateLeft, dateRight)); // Set both dates to a valid leap year for accurate comparison when dealing\n // with leap days\n\n dateLeft.setFullYear(1584);\n dateRight.setFullYear(1584); // Math.abs(diff in full years - diff in calendar years) === 1 if last calendar year is not full\n // If so, result must be decreased by 1 in absolute value\n\n var isLastYearNotFull = compareAsc(dateLeft, dateRight) === -sign;\n var result = sign * (difference - Number(isLastYearNotFull)); // Prevent negative zero\n\n return result === 0 ? 0 : result;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name eachDayOfInterval\n * @category Interval Helpers\n * @summary Return the array of dates within the specified time interval.\n *\n * @description\n * Return the array of dates within the specified time interval.\n *\n * @param {Interval} interval - the interval. See [Interval]{@link https://date-fns.org/docs/Interval}\n * @param {Object} [options] - an object with options.\n * @param {Number} [options.step=1] - the step to increment by. The value should be more than 1.\n * @returns {Date[]} the array with starts of days from the day of the interval start to the day of the interval end\n * @throws {TypeError} 1 argument required\n * @throws {RangeError} `options.step` must be a number greater than 1\n * @throws {RangeError} The start of an interval cannot be after its end\n * @throws {RangeError} Date in interval cannot be `Invalid Date`\n *\n * @example\n * // Each day between 6 October 2014 and 10 October 2014:\n * const result = eachDayOfInterval({\n * start: new Date(2014, 9, 6),\n * end: new Date(2014, 9, 10)\n * })\n * //=> [\n * // Mon Oct 06 2014 00:00:00,\n * // Tue Oct 07 2014 00:00:00,\n * // Wed Oct 08 2014 00:00:00,\n * // Thu Oct 09 2014 00:00:00,\n * // Fri Oct 10 2014 00:00:00\n * // ]\n */\n\nexport default function eachDayOfInterval(dirtyInterval, options) {\n var _options$step;\n\n requiredArgs(1, arguments);\n var interval = dirtyInterval || {};\n var startDate = toDate(interval.start);\n var endDate = toDate(interval.end);\n var endTime = endDate.getTime(); // Throw an exception if start date is after end date or if any date is `Invalid Date`\n\n if (!(startDate.getTime() <= endTime)) {\n throw new RangeError('Invalid interval');\n }\n\n var dates = [];\n var currentDate = startDate;\n currentDate.setHours(0, 0, 0, 0);\n var step = Number((_options$step = options === null || options === void 0 ? void 0 : options.step) !== null && _options$step !== void 0 ? _options$step : 1);\n if (step < 1 || isNaN(step)) throw new RangeError('`options.step` must be a number greater than 1');\n\n while (currentDate.getTime() <= endTime) {\n dates.push(toDate(currentDate));\n currentDate.setDate(currentDate.getDate() + step);\n currentDate.setHours(0, 0, 0, 0);\n }\n\n return dates;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name startOfMonth\n * @category Month Helpers\n * @summary Return the start of a month for the given date.\n *\n * @description\n * Return the start of a month for the given date.\n * The result will be in the local timezone.\n *\n * @param {Date|Number} date - the original date\n * @returns {Date} the start of a month\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // The start of a month for 2 September 2014 11:55:00:\n * const result = startOfMonth(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Mon Sep 01 2014 00:00:00\n */\n\nexport default function startOfMonth(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n date.setDate(1);\n date.setHours(0, 0, 0, 0);\n return date;\n}", "import { getDefaultOptions } from \"../_lib/defaultOptions/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n\n/**\n * @name endOfWeek\n * @category Week Helpers\n * @summary Return the end of a week for the given date.\n *\n * @description\n * Return the end of a week for the given date.\n * The result will be in the local timezone.\n *\n * @param {Date|Number} date - the original date\n * @param {Object} [options] - an object with options.\n * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}\n * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)\n * @returns {Date} the end of a week\n * @throws {TypeError} 1 argument required\n * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6\n *\n * @example\n * // The end of a week for 2 September 2014 11:55:00:\n * const result = endOfWeek(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Sat Sep 06 2014 23:59:59.999\n *\n * @example\n * // If the week starts on Monday, the end of the week for 2 September 2014 11:55:00:\n * const result = endOfWeek(new Date(2014, 8, 2, 11, 55, 0), { weekStartsOn: 1 })\n * //=> Sun Sep 07 2014 23:59:59.999\n */\nexport default function endOfWeek(dirtyDate, options) {\n var _ref, _ref2, _ref3, _options$weekStartsOn, _options$locale, _options$locale$optio, _defaultOptions$local, _defaultOptions$local2;\n\n requiredArgs(1, arguments);\n var defaultOptions = getDefaultOptions();\n var weekStartsOn = toInteger((_ref = (_ref2 = (_ref3 = (_options$weekStartsOn = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.weekStartsOn) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.weekStartsOn) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.weekStartsOn) !== null && _ref !== void 0 ? _ref : 0); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN\n\n if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {\n throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');\n }\n\n var date = toDate(dirtyDate);\n var day = date.getDay();\n var diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn);\n date.setDate(date.getDate() + diff);\n date.setHours(23, 59, 59, 999);\n return date;\n}", "import addMilliseconds from \"../addMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\n/**\n * @name subMilliseconds\n * @category Millisecond Helpers\n * @summary Subtract the specified number of milliseconds from the given date.\n *\n * @description\n * Subtract the specified number of milliseconds from the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of milliseconds to be subtracted. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the milliseconds subtracted\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Subtract 750 milliseconds from 10 July 2014 12:45:30.000:\n * const result = subMilliseconds(new Date(2014, 6, 10, 12, 45, 30, 0), 750)\n * //=> Thu Jul 10 2014 12:45:29.250\n */\n\nexport default function subMilliseconds(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var amount = toInteger(dirtyAmount);\n return addMilliseconds(dirtyDate, -amount);\n}", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nvar MILLISECONDS_IN_DAY = 86400000;\nexport default function getUTCDayOfYear(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var timestamp = date.getTime();\n date.setUTCMonth(0, 1);\n date.setUTCHours(0, 0, 0, 0);\n var startOfYearTimestamp = date.getTime();\n var difference = timestamp - startOfYearTimestamp;\n return Math.floor(difference / MILLISECONDS_IN_DAY) + 1;\n}", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nexport default function startOfUTCISOWeek(dirtyDate) {\n requiredArgs(1, arguments);\n var weekStartsOn = 1;\n var date = toDate(dirtyDate);\n var day = date.getUTCDay();\n var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;\n date.setUTCDate(date.getUTCDate() - diff);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n}", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nimport startOfUTCISOWeek from \"../startOfUTCISOWeek/index.js\";\nexport default function getUTCISOWeekYear(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var year = date.getUTCFullYear();\n var fourthOfJanuaryOfNextYear = new Date(0);\n fourthOfJanuaryOfNextYear.setUTCFullYear(year + 1, 0, 4);\n fourthOfJanuaryOfNextYear.setUTCHours(0, 0, 0, 0);\n var startOfNextYear = startOfUTCISOWeek(fourthOfJanuaryOfNextYear);\n var fourthOfJanuaryOfThisYear = new Date(0);\n fourthOfJanuaryOfThisYear.setUTCFullYear(year, 0, 4);\n fourthOfJanuaryOfThisYear.setUTCHours(0, 0, 0, 0);\n var startOfThisYear = startOfUTCISOWeek(fourthOfJanuaryOfThisYear);\n\n if (date.getTime() >= startOfNextYear.getTime()) {\n return year + 1;\n } else if (date.getTime() >= startOfThisYear.getTime()) {\n return year;\n } else {\n return year - 1;\n }\n}", "import getUTCISOWeekYear from \"../getUTCISOWeekYear/index.js\";\nimport startOfUTCISOWeek from \"../startOfUTCISOWeek/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nexport default function startOfUTCISOWeekYear(dirtyDate) {\n requiredArgs(1, arguments);\n var year = getUTCISOWeekYear(dirtyDate);\n var fourthOfJanuary = new Date(0);\n fourthOfJanuary.setUTCFullYear(year, 0, 4);\n fourthOfJanuary.setUTCHours(0, 0, 0, 0);\n var date = startOfUTCISOWeek(fourthOfJanuary);\n return date;\n}", "import toDate from \"../../toDate/index.js\";\nimport startOfUTCISOWeek from \"../startOfUTCISOWeek/index.js\";\nimport startOfUTCISOWeekYear from \"../startOfUTCISOWeekYear/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nvar MILLISECONDS_IN_WEEK = 604800000;\nexport default function getUTCISOWeek(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var diff = startOfUTCISOWeek(date).getTime() - startOfUTCISOWeekYear(date).getTime(); // Round the number of days to the nearest integer\n // because the number of milliseconds in a week is not constant\n // (e.g. it's different in the week of the daylight saving time clock shift)\n\n return Math.round(diff / MILLISECONDS_IN_WEEK) + 1;\n}", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nimport toInteger from \"../toInteger/index.js\";\nimport { getDefaultOptions } from \"../defaultOptions/index.js\";\nexport default function startOfUTCWeek(dirtyDate, options) {\n var _ref, _ref2, _ref3, _options$weekStartsOn, _options$locale, _options$locale$optio, _defaultOptions$local, _defaultOptions$local2;\n\n requiredArgs(1, arguments);\n var defaultOptions = getDefaultOptions();\n var weekStartsOn = toInteger((_ref = (_ref2 = (_ref3 = (_options$weekStartsOn = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.weekStartsOn) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.weekStartsOn) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.weekStartsOn) !== null && _ref !== void 0 ? _ref : 0); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN\n\n if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {\n throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');\n }\n\n var date = toDate(dirtyDate);\n var day = date.getUTCDay();\n var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;\n date.setUTCDate(date.getUTCDate() - diff);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n}", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nimport startOfUTCWeek from \"../startOfUTCWeek/index.js\";\nimport toInteger from \"../toInteger/index.js\";\nimport { getDefaultOptions } from \"../defaultOptions/index.js\";\nexport default function getUTCWeekYear(dirtyDate, options) {\n var _ref, _ref2, _ref3, _options$firstWeekCon, _options$locale, _options$locale$optio, _defaultOptions$local, _defaultOptions$local2;\n\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var year = date.getUTCFullYear();\n var defaultOptions = getDefaultOptions();\n var firstWeekContainsDate = toInteger((_ref = (_ref2 = (_ref3 = (_options$firstWeekCon = options === null || options === void 0 ? void 0 : options.firstWeekContainsDate) !== null && _options$firstWeekCon !== void 0 ? _options$firstWeekCon : options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.firstWeekContainsDate) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.firstWeekContainsDate) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.firstWeekContainsDate) !== null && _ref !== void 0 ? _ref : 1); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN\n\n if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {\n throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');\n }\n\n var firstWeekOfNextYear = new Date(0);\n firstWeekOfNextYear.setUTCFullYear(year + 1, 0, firstWeekContainsDate);\n firstWeekOfNextYear.setUTCHours(0, 0, 0, 0);\n var startOfNextYear = startOfUTCWeek(firstWeekOfNextYear, options);\n var firstWeekOfThisYear = new Date(0);\n firstWeekOfThisYear.setUTCFullYear(year, 0, firstWeekContainsDate);\n firstWeekOfThisYear.setUTCHours(0, 0, 0, 0);\n var startOfThisYear = startOfUTCWeek(firstWeekOfThisYear, options);\n\n if (date.getTime() >= startOfNextYear.getTime()) {\n return year + 1;\n } else if (date.getTime() >= startOfThisYear.getTime()) {\n return year;\n } else {\n return year - 1;\n }\n}", "import getUTCWeekYear from \"../getUTCWeekYear/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nimport startOfUTCWeek from \"../startOfUTCWeek/index.js\";\nimport toInteger from \"../toInteger/index.js\";\nimport { getDefaultOptions } from \"../defaultOptions/index.js\";\nexport default function startOfUTCWeekYear(dirtyDate, options) {\n var _ref, _ref2, _ref3, _options$firstWeekCon, _options$locale, _options$locale$optio, _defaultOptions$local, _defaultOptions$local2;\n\n requiredArgs(1, arguments);\n var defaultOptions = getDefaultOptions();\n var firstWeekContainsDate = toInteger((_ref = (_ref2 = (_ref3 = (_options$firstWeekCon = options === null || options === void 0 ? void 0 : options.firstWeekContainsDate) !== null && _options$firstWeekCon !== void 0 ? _options$firstWeekCon : options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.firstWeekContainsDate) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.firstWeekContainsDate) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.firstWeekContainsDate) !== null && _ref !== void 0 ? _ref : 1);\n var year = getUTCWeekYear(dirtyDate, options);\n var firstWeek = new Date(0);\n firstWeek.setUTCFullYear(year, 0, firstWeekContainsDate);\n firstWeek.setUTCHours(0, 0, 0, 0);\n var date = startOfUTCWeek(firstWeek, options);\n return date;\n}", "import toDate from \"../../toDate/index.js\";\nimport startOfUTCWeek from \"../startOfUTCWeek/index.js\";\nimport startOfUTCWeekYear from \"../startOfUTCWeekYear/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nvar MILLISECONDS_IN_WEEK = 604800000;\nexport default function getUTCWeek(dirtyDate, options) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var diff = startOfUTCWeek(date, options).getTime() - startOfUTCWeekYear(date, options).getTime(); // Round the number of days to the nearest integer\n // because the number of milliseconds in a week is not constant\n // (e.g. it's different in the week of the daylight saving time clock shift)\n\n return Math.round(diff / MILLISECONDS_IN_WEEK) + 1;\n}", "export default function addLeadingZeros(number, targetLength) {\n var sign = number < 0 ? '-' : '';\n var output = Math.abs(number).toString();\n\n while (output.length < targetLength) {\n output = '0' + output;\n }\n\n return sign + output;\n}", "import addLeadingZeros from \"../../addLeadingZeros/index.js\";\n/*\n * | | Unit | | Unit |\n * |-----|--------------------------------|-----|--------------------------------|\n * | a | AM, PM | A* | |\n * | d | Day of month | D | |\n * | h | Hour [1-12] | H | Hour [0-23] |\n * | m | Minute | M | Month |\n * | s | Second | S | Fraction of second |\n * | y | Year (abs) | Y | |\n *\n * Letters marked by * are not implemented but reserved by Unicode standard.\n */\n\nvar formatters = {\n // Year\n y: function y(date, token) {\n // From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_tokens\n // | Year | y | yy | yyy | yyyy | yyyyy |\n // |----------|-------|----|-------|-------|-------|\n // | AD 1 | 1 | 01 | 001 | 0001 | 00001 |\n // | AD 12 | 12 | 12 | 012 | 0012 | 00012 |\n // | AD 123 | 123 | 23 | 123 | 0123 | 00123 |\n // | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |\n // | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |\n var signedYear = date.getUTCFullYear(); // Returns 1 for 1 BC (which is year 0 in JavaScript)\n\n var year = signedYear > 0 ? signedYear : 1 - signedYear;\n return addLeadingZeros(token === 'yy' ? year % 100 : year, token.length);\n },\n // Month\n M: function M(date, token) {\n var month = date.getUTCMonth();\n return token === 'M' ? String(month + 1) : addLeadingZeros(month + 1, 2);\n },\n // Day of the month\n d: function d(date, token) {\n return addLeadingZeros(date.getUTCDate(), token.length);\n },\n // AM or PM\n a: function a(date, token) {\n var dayPeriodEnumValue = date.getUTCHours() / 12 >= 1 ? 'pm' : 'am';\n\n switch (token) {\n case 'a':\n case 'aa':\n return dayPeriodEnumValue.toUpperCase();\n\n case 'aaa':\n return dayPeriodEnumValue;\n\n case 'aaaaa':\n return dayPeriodEnumValue[0];\n\n case 'aaaa':\n default:\n return dayPeriodEnumValue === 'am' ? 'a.m.' : 'p.m.';\n }\n },\n // Hour [1-12]\n h: function h(date, token) {\n return addLeadingZeros(date.getUTCHours() % 12 || 12, token.length);\n },\n // Hour [0-23]\n H: function H(date, token) {\n return addLeadingZeros(date.getUTCHours(), token.length);\n },\n // Minute\n m: function m(date, token) {\n return addLeadingZeros(date.getUTCMinutes(), token.length);\n },\n // Second\n s: function s(date, token) {\n return addLeadingZeros(date.getUTCSeconds(), token.length);\n },\n // Fraction of second\n S: function S(date, token) {\n var numberOfDigits = token.length;\n var milliseconds = date.getUTCMilliseconds();\n var fractionalSeconds = Math.floor(milliseconds * Math.pow(10, numberOfDigits - 3));\n return addLeadingZeros(fractionalSeconds, token.length);\n }\n};\nexport default formatters;", "import getUTCDayOfYear from \"../../../_lib/getUTCDayOfYear/index.js\";\nimport getUTCISOWeek from \"../../../_lib/getUTCISOWeek/index.js\";\nimport getUTCISOWeekYear from \"../../../_lib/getUTCISOWeekYear/index.js\";\nimport getUTCWeek from \"../../../_lib/getUTCWeek/index.js\";\nimport getUTCWeekYear from \"../../../_lib/getUTCWeekYear/index.js\";\nimport addLeadingZeros from \"../../addLeadingZeros/index.js\";\nimport lightFormatters from \"../lightFormatters/index.js\";\nvar dayPeriodEnum = {\n am: 'am',\n pm: 'pm',\n midnight: 'midnight',\n noon: 'noon',\n morning: 'morning',\n afternoon: 'afternoon',\n evening: 'evening',\n night: 'night'\n};\n\n/*\n * | | Unit | | Unit |\n * |-----|--------------------------------|-----|--------------------------------|\n * | a | AM, PM | A* | Milliseconds in day |\n * | b | AM, PM, noon, midnight | B | Flexible day period |\n * | c | Stand-alone local day of week | C* | Localized hour w/ day period |\n * | d | Day of month | D | Day of year |\n * | e | Local day of week | E | Day of week |\n * | f | | F* | Day of week in month |\n * | g* | Modified Julian day | G | Era |\n * | h | Hour [1-12] | H | Hour [0-23] |\n * | i! | ISO day of week | I! | ISO week of year |\n * | j* | Localized hour w/ day period | J* | Localized hour w/o day period |\n * | k | Hour [1-24] | K | Hour [0-11] |\n * | l* | (deprecated) | L | Stand-alone month |\n * | m | Minute | M | Month |\n * | n | | N | |\n * | o! | Ordinal number modifier | O | Timezone (GMT) |\n * | p! | Long localized time | P! | Long localized date |\n * | q | Stand-alone quarter | Q | Quarter |\n * | r* | Related Gregorian year | R! | ISO week-numbering year |\n * | s | Second | S | Fraction of second |\n * | t! | Seconds timestamp | T! | Milliseconds timestamp |\n * | u | Extended year | U* | Cyclic year |\n * | v* | Timezone (generic non-locat.) | V* | Timezone (location) |\n * | w | Local week of year | W* | Week of month |\n * | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |\n * | y | Year (abs) | Y | Local week-numbering year |\n * | z | Timezone (specific non-locat.) | Z* | Timezone (aliases) |\n *\n * Letters marked by * are not implemented but reserved by Unicode standard.\n *\n * Letters marked by ! are non-standard, but implemented by date-fns:\n * - `o` modifies the previous token to turn it into an ordinal (see `format` docs)\n * - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,\n * i.e. 7 for Sunday, 1 for Monday, etc.\n * - `I` is ISO week of year, as opposed to `w` which is local week of year.\n * - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.\n * `R` is supposed to be used in conjunction with `I` and `i`\n * for universal ISO week-numbering date, whereas\n * `Y` is supposed to be used in conjunction with `w` and `e`\n * for week-numbering date specific to the locale.\n * - `P` is long localized date format\n * - `p` is long localized time format\n */\nvar formatters = {\n // Era\n G: function G(date, token, localize) {\n var era = date.getUTCFullYear() > 0 ? 1 : 0;\n\n switch (token) {\n // AD, BC\n case 'G':\n case 'GG':\n case 'GGG':\n return localize.era(era, {\n width: 'abbreviated'\n });\n // A, B\n\n case 'GGGGG':\n return localize.era(era, {\n width: 'narrow'\n });\n // Anno Domini, Before Christ\n\n case 'GGGG':\n default:\n return localize.era(era, {\n width: 'wide'\n });\n }\n },\n // Year\n y: function y(date, token, localize) {\n // Ordinal number\n if (token === 'yo') {\n var signedYear = date.getUTCFullYear(); // Returns 1 for 1 BC (which is year 0 in JavaScript)\n\n var year = signedYear > 0 ? signedYear : 1 - signedYear;\n return localize.ordinalNumber(year, {\n unit: 'year'\n });\n }\n\n return lightFormatters.y(date, token);\n },\n // Local week-numbering year\n Y: function Y(date, token, localize, options) {\n var signedWeekYear = getUTCWeekYear(date, options); // Returns 1 for 1 BC (which is year 0 in JavaScript)\n\n var weekYear = signedWeekYear > 0 ? signedWeekYear : 1 - signedWeekYear; // Two digit year\n\n if (token === 'YY') {\n var twoDigitYear = weekYear % 100;\n return addLeadingZeros(twoDigitYear, 2);\n } // Ordinal number\n\n\n if (token === 'Yo') {\n return localize.ordinalNumber(weekYear, {\n unit: 'year'\n });\n } // Padding\n\n\n return addLeadingZeros(weekYear, token.length);\n },\n // ISO week-numbering year\n R: function R(date, token) {\n var isoWeekYear = getUTCISOWeekYear(date); // Padding\n\n return addLeadingZeros(isoWeekYear, token.length);\n },\n // Extended year. This is a single number designating the year of this calendar system.\n // The main difference between `y` and `u` localizers are B.C. years:\n // | Year | `y` | `u` |\n // |------|-----|-----|\n // | AC 1 | 1 | 1 |\n // | BC 1 | 1 | 0 |\n // | BC 2 | 2 | -1 |\n // Also `yy` always returns the last two digits of a year,\n // while `uu` pads single digit years to 2 characters and returns other years unchanged.\n u: function u(date, token) {\n var year = date.getUTCFullYear();\n return addLeadingZeros(year, token.length);\n },\n // Quarter\n Q: function Q(date, token, localize) {\n var quarter = Math.ceil((date.getUTCMonth() + 1) / 3);\n\n switch (token) {\n // 1, 2, 3, 4\n case 'Q':\n return String(quarter);\n // 01, 02, 03, 04\n\n case 'QQ':\n return addLeadingZeros(quarter, 2);\n // 1st, 2nd, 3rd, 4th\n\n case 'Qo':\n return localize.ordinalNumber(quarter, {\n unit: 'quarter'\n });\n // Q1, Q2, Q3, Q4\n\n case 'QQQ':\n return localize.quarter(quarter, {\n width: 'abbreviated',\n context: 'formatting'\n });\n // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n\n case 'QQQQQ':\n return localize.quarter(quarter, {\n width: 'narrow',\n context: 'formatting'\n });\n // 1st quarter, 2nd quarter, ...\n\n case 'QQQQ':\n default:\n return localize.quarter(quarter, {\n width: 'wide',\n context: 'formatting'\n });\n }\n },\n // Stand-alone quarter\n q: function q(date, token, localize) {\n var quarter = Math.ceil((date.getUTCMonth() + 1) / 3);\n\n switch (token) {\n // 1, 2, 3, 4\n case 'q':\n return String(quarter);\n // 01, 02, 03, 04\n\n case 'qq':\n return addLeadingZeros(quarter, 2);\n // 1st, 2nd, 3rd, 4th\n\n case 'qo':\n return localize.ordinalNumber(quarter, {\n unit: 'quarter'\n });\n // Q1, Q2, Q3, Q4\n\n case 'qqq':\n return localize.quarter(quarter, {\n width: 'abbreviated',\n context: 'standalone'\n });\n // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n\n case 'qqqqq':\n return localize.quarter(quarter, {\n width: 'narrow',\n context: 'standalone'\n });\n // 1st quarter, 2nd quarter, ...\n\n case 'qqqq':\n default:\n return localize.quarter(quarter, {\n width: 'wide',\n context: 'standalone'\n });\n }\n },\n // Month\n M: function M(date, token, localize) {\n var month = date.getUTCMonth();\n\n switch (token) {\n case 'M':\n case 'MM':\n return lightFormatters.M(date, token);\n // 1st, 2nd, ..., 12th\n\n case 'Mo':\n return localize.ordinalNumber(month + 1, {\n unit: 'month'\n });\n // Jan, Feb, ..., Dec\n\n case 'MMM':\n return localize.month(month, {\n width: 'abbreviated',\n context: 'formatting'\n });\n // J, F, ..., D\n\n case 'MMMMM':\n return localize.month(month, {\n width: 'narrow',\n context: 'formatting'\n });\n // January, February, ..., December\n\n case 'MMMM':\n default:\n return localize.month(month, {\n width: 'wide',\n context: 'formatting'\n });\n }\n },\n // Stand-alone month\n L: function L(date, token, localize) {\n var month = date.getUTCMonth();\n\n switch (token) {\n // 1, 2, ..., 12\n case 'L':\n return String(month + 1);\n // 01, 02, ..., 12\n\n case 'LL':\n return addLeadingZeros(month + 1, 2);\n // 1st, 2nd, ..., 12th\n\n case 'Lo':\n return localize.ordinalNumber(month + 1, {\n unit: 'month'\n });\n // Jan, Feb, ..., Dec\n\n case 'LLL':\n return localize.month(month, {\n width: 'abbreviated',\n context: 'standalone'\n });\n // J, F, ..., D\n\n case 'LLLLL':\n return localize.month(month, {\n width: 'narrow',\n context: 'standalone'\n });\n // January, February, ..., December\n\n case 'LLLL':\n default:\n return localize.month(month, {\n width: 'wide',\n context: 'standalone'\n });\n }\n },\n // Local week of year\n w: function w(date, token, localize, options) {\n var week = getUTCWeek(date, options);\n\n if (token === 'wo') {\n return localize.ordinalNumber(week, {\n unit: 'week'\n });\n }\n\n return addLeadingZeros(week, token.length);\n },\n // ISO week of year\n I: function I(date, token, localize) {\n var isoWeek = getUTCISOWeek(date);\n\n if (token === 'Io') {\n return localize.ordinalNumber(isoWeek, {\n unit: 'week'\n });\n }\n\n return addLeadingZeros(isoWeek, token.length);\n },\n // Day of the month\n d: function d(date, token, localize) {\n if (token === 'do') {\n return localize.ordinalNumber(date.getUTCDate(), {\n unit: 'date'\n });\n }\n\n return lightFormatters.d(date, token);\n },\n // Day of year\n D: function D(date, token, localize) {\n var dayOfYear = getUTCDayOfYear(date);\n\n if (token === 'Do') {\n return localize.ordinalNumber(dayOfYear, {\n unit: 'dayOfYear'\n });\n }\n\n return addLeadingZeros(dayOfYear, token.length);\n },\n // Day of week\n E: function E(date, token, localize) {\n var dayOfWeek = date.getUTCDay();\n\n switch (token) {\n // Tue\n case 'E':\n case 'EE':\n case 'EEE':\n return localize.day(dayOfWeek, {\n width: 'abbreviated',\n context: 'formatting'\n });\n // T\n\n case 'EEEEE':\n return localize.day(dayOfWeek, {\n width: 'narrow',\n context: 'formatting'\n });\n // Tu\n\n case 'EEEEEE':\n return localize.day(dayOfWeek, {\n width: 'short',\n context: 'formatting'\n });\n // Tuesday\n\n case 'EEEE':\n default:\n return localize.day(dayOfWeek, {\n width: 'wide',\n context: 'formatting'\n });\n }\n },\n // Local day of week\n e: function e(date, token, localize, options) {\n var dayOfWeek = date.getUTCDay();\n var localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;\n\n switch (token) {\n // Numerical value (Nth day of week with current locale or weekStartsOn)\n case 'e':\n return String(localDayOfWeek);\n // Padded numerical value\n\n case 'ee':\n return addLeadingZeros(localDayOfWeek, 2);\n // 1st, 2nd, ..., 7th\n\n case 'eo':\n return localize.ordinalNumber(localDayOfWeek, {\n unit: 'day'\n });\n\n case 'eee':\n return localize.day(dayOfWeek, {\n width: 'abbreviated',\n context: 'formatting'\n });\n // T\n\n case 'eeeee':\n return localize.day(dayOfWeek, {\n width: 'narrow',\n context: 'formatting'\n });\n // Tu\n\n case 'eeeeee':\n return localize.day(dayOfWeek, {\n width: 'short',\n context: 'formatting'\n });\n // Tuesday\n\n case 'eeee':\n default:\n return localize.day(dayOfWeek, {\n width: 'wide',\n context: 'formatting'\n });\n }\n },\n // Stand-alone local day of week\n c: function c(date, token, localize, options) {\n var dayOfWeek = date.getUTCDay();\n var localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;\n\n switch (token) {\n // Numerical value (same as in `e`)\n case 'c':\n return String(localDayOfWeek);\n // Padded numerical value\n\n case 'cc':\n return addLeadingZeros(localDayOfWeek, token.length);\n // 1st, 2nd, ..., 7th\n\n case 'co':\n return localize.ordinalNumber(localDayOfWeek, {\n unit: 'day'\n });\n\n case 'ccc':\n return localize.day(dayOfWeek, {\n width: 'abbreviated',\n context: 'standalone'\n });\n // T\n\n case 'ccccc':\n return localize.day(dayOfWeek, {\n width: 'narrow',\n context: 'standalone'\n });\n // Tu\n\n case 'cccccc':\n return localize.day(dayOfWeek, {\n width: 'short',\n context: 'standalone'\n });\n // Tuesday\n\n case 'cccc':\n default:\n return localize.day(dayOfWeek, {\n width: 'wide',\n context: 'standalone'\n });\n }\n },\n // ISO day of week\n i: function i(date, token, localize) {\n var dayOfWeek = date.getUTCDay();\n var isoDayOfWeek = dayOfWeek === 0 ? 7 : dayOfWeek;\n\n switch (token) {\n // 2\n case 'i':\n return String(isoDayOfWeek);\n // 02\n\n case 'ii':\n return addLeadingZeros(isoDayOfWeek, token.length);\n // 2nd\n\n case 'io':\n return localize.ordinalNumber(isoDayOfWeek, {\n unit: 'day'\n });\n // Tue\n\n case 'iii':\n return localize.day(dayOfWeek, {\n width: 'abbreviated',\n context: 'formatting'\n });\n // T\n\n case 'iiiii':\n return localize.day(dayOfWeek, {\n width: 'narrow',\n context: 'formatting'\n });\n // Tu\n\n case 'iiiiii':\n return localize.day(dayOfWeek, {\n width: 'short',\n context: 'formatting'\n });\n // Tuesday\n\n case 'iiii':\n default:\n return localize.day(dayOfWeek, {\n width: 'wide',\n context: 'formatting'\n });\n }\n },\n // AM or PM\n a: function a(date, token, localize) {\n var hours = date.getUTCHours();\n var dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am';\n\n switch (token) {\n case 'a':\n case 'aa':\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'abbreviated',\n context: 'formatting'\n });\n\n case 'aaa':\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'abbreviated',\n context: 'formatting'\n }).toLowerCase();\n\n case 'aaaaa':\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'aaaa':\n default:\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'wide',\n context: 'formatting'\n });\n }\n },\n // AM, PM, midnight, noon\n b: function b(date, token, localize) {\n var hours = date.getUTCHours();\n var dayPeriodEnumValue;\n\n if (hours === 12) {\n dayPeriodEnumValue = dayPeriodEnum.noon;\n } else if (hours === 0) {\n dayPeriodEnumValue = dayPeriodEnum.midnight;\n } else {\n dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am';\n }\n\n switch (token) {\n case 'b':\n case 'bb':\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'abbreviated',\n context: 'formatting'\n });\n\n case 'bbb':\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'abbreviated',\n context: 'formatting'\n }).toLowerCase();\n\n case 'bbbbb':\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'bbbb':\n default:\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'wide',\n context: 'formatting'\n });\n }\n },\n // in the morning, in the afternoon, in the evening, at night\n B: function B(date, token, localize) {\n var hours = date.getUTCHours();\n var dayPeriodEnumValue;\n\n if (hours >= 17) {\n dayPeriodEnumValue = dayPeriodEnum.evening;\n } else if (hours >= 12) {\n dayPeriodEnumValue = dayPeriodEnum.afternoon;\n } else if (hours >= 4) {\n dayPeriodEnumValue = dayPeriodEnum.morning;\n } else {\n dayPeriodEnumValue = dayPeriodEnum.night;\n }\n\n switch (token) {\n case 'B':\n case 'BB':\n case 'BBB':\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'abbreviated',\n context: 'formatting'\n });\n\n case 'BBBBB':\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'BBBB':\n default:\n return localize.dayPeriod(dayPeriodEnumValue, {\n width: 'wide',\n context: 'formatting'\n });\n }\n },\n // Hour [1-12]\n h: function h(date, token, localize) {\n if (token === 'ho') {\n var hours = date.getUTCHours() % 12;\n if (hours === 0) hours = 12;\n return localize.ordinalNumber(hours, {\n unit: 'hour'\n });\n }\n\n return lightFormatters.h(date, token);\n },\n // Hour [0-23]\n H: function H(date, token, localize) {\n if (token === 'Ho') {\n return localize.ordinalNumber(date.getUTCHours(), {\n unit: 'hour'\n });\n }\n\n return lightFormatters.H(date, token);\n },\n // Hour [0-11]\n K: function K(date, token, localize) {\n var hours = date.getUTCHours() % 12;\n\n if (token === 'Ko') {\n return localize.ordinalNumber(hours, {\n unit: 'hour'\n });\n }\n\n return addLeadingZeros(hours, token.length);\n },\n // Hour [1-24]\n k: function k(date, token, localize) {\n var hours = date.getUTCHours();\n if (hours === 0) hours = 24;\n\n if (token === 'ko') {\n return localize.ordinalNumber(hours, {\n unit: 'hour'\n });\n }\n\n return addLeadingZeros(hours, token.length);\n },\n // Minute\n m: function m(date, token, localize) {\n if (token === 'mo') {\n return localize.ordinalNumber(date.getUTCMinutes(), {\n unit: 'minute'\n });\n }\n\n return lightFormatters.m(date, token);\n },\n // Second\n s: function s(date, token, localize) {\n if (token === 'so') {\n return localize.ordinalNumber(date.getUTCSeconds(), {\n unit: 'second'\n });\n }\n\n return lightFormatters.s(date, token);\n },\n // Fraction of second\n S: function S(date, token) {\n return lightFormatters.S(date, token);\n },\n // Timezone (ISO-8601. If offset is 0, output is always `'Z'`)\n X: function X(date, token, _localize, options) {\n var originalDate = options._originalDate || date;\n var timezoneOffset = originalDate.getTimezoneOffset();\n\n if (timezoneOffset === 0) {\n return 'Z';\n }\n\n switch (token) {\n // Hours and optional minutes\n case 'X':\n return formatTimezoneWithOptionalMinutes(timezoneOffset);\n // Hours, minutes and optional seconds without `:` delimiter\n // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets\n // so this token always has the same output as `XX`\n\n case 'XXXX':\n case 'XX':\n // Hours and minutes without `:` delimiter\n return formatTimezone(timezoneOffset);\n // Hours, minutes and optional seconds with `:` delimiter\n // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets\n // so this token always has the same output as `XXX`\n\n case 'XXXXX':\n case 'XXX': // Hours and minutes with `:` delimiter\n\n default:\n return formatTimezone(timezoneOffset, ':');\n }\n },\n // Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)\n x: function x(date, token, _localize, options) {\n var originalDate = options._originalDate || date;\n var timezoneOffset = originalDate.getTimezoneOffset();\n\n switch (token) {\n // Hours and optional minutes\n case 'x':\n return formatTimezoneWithOptionalMinutes(timezoneOffset);\n // Hours, minutes and optional seconds without `:` delimiter\n // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets\n // so this token always has the same output as `xx`\n\n case 'xxxx':\n case 'xx':\n // Hours and minutes without `:` delimiter\n return formatTimezone(timezoneOffset);\n // Hours, minutes and optional seconds with `:` delimiter\n // Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets\n // so this token always has the same output as `xxx`\n\n case 'xxxxx':\n case 'xxx': // Hours and minutes with `:` delimiter\n\n default:\n return formatTimezone(timezoneOffset, ':');\n }\n },\n // Timezone (GMT)\n O: function O(date, token, _localize, options) {\n var originalDate = options._originalDate || date;\n var timezoneOffset = originalDate.getTimezoneOffset();\n\n switch (token) {\n // Short\n case 'O':\n case 'OO':\n case 'OOO':\n return 'GMT' + formatTimezoneShort(timezoneOffset, ':');\n // Long\n\n case 'OOOO':\n default:\n return 'GMT' + formatTimezone(timezoneOffset, ':');\n }\n },\n // Timezone (specific non-location)\n z: function z(date, token, _localize, options) {\n var originalDate = options._originalDate || date;\n var timezoneOffset = originalDate.getTimezoneOffset();\n\n switch (token) {\n // Short\n case 'z':\n case 'zz':\n case 'zzz':\n return 'GMT' + formatTimezoneShort(timezoneOffset, ':');\n // Long\n\n case 'zzzz':\n default:\n return 'GMT' + formatTimezone(timezoneOffset, ':');\n }\n },\n // Seconds timestamp\n t: function t(date, token, _localize, options) {\n var originalDate = options._originalDate || date;\n var timestamp = Math.floor(originalDate.getTime() / 1000);\n return addLeadingZeros(timestamp, token.length);\n },\n // Milliseconds timestamp\n T: function T(date, token, _localize, options) {\n var originalDate = options._originalDate || date;\n var timestamp = originalDate.getTime();\n return addLeadingZeros(timestamp, token.length);\n }\n};\n\nfunction formatTimezoneShort(offset, dirtyDelimiter) {\n var sign = offset > 0 ? '-' : '+';\n var absOffset = Math.abs(offset);\n var hours = Math.floor(absOffset / 60);\n var minutes = absOffset % 60;\n\n if (minutes === 0) {\n return sign + String(hours);\n }\n\n var delimiter = dirtyDelimiter || '';\n return sign + String(hours) + delimiter + addLeadingZeros(minutes, 2);\n}\n\nfunction formatTimezoneWithOptionalMinutes(offset, dirtyDelimiter) {\n if (offset % 60 === 0) {\n var sign = offset > 0 ? '-' : '+';\n return sign + addLeadingZeros(Math.abs(offset) / 60, 2);\n }\n\n return formatTimezone(offset, dirtyDelimiter);\n}\n\nfunction formatTimezone(offset, dirtyDelimiter) {\n var delimiter = dirtyDelimiter || '';\n var sign = offset > 0 ? '-' : '+';\n var absOffset = Math.abs(offset);\n var hours = addLeadingZeros(Math.floor(absOffset / 60), 2);\n var minutes = addLeadingZeros(absOffset % 60, 2);\n return sign + hours + delimiter + minutes;\n}\n\nexport default formatters;", "var dateLongFormatter = function dateLongFormatter(pattern, formatLong) {\n switch (pattern) {\n case 'P':\n return formatLong.date({\n width: 'short'\n });\n\n case 'PP':\n return formatLong.date({\n width: 'medium'\n });\n\n case 'PPP':\n return formatLong.date({\n width: 'long'\n });\n\n case 'PPPP':\n default:\n return formatLong.date({\n width: 'full'\n });\n }\n};\n\nvar timeLongFormatter = function timeLongFormatter(pattern, formatLong) {\n switch (pattern) {\n case 'p':\n return formatLong.time({\n width: 'short'\n });\n\n case 'pp':\n return formatLong.time({\n width: 'medium'\n });\n\n case 'ppp':\n return formatLong.time({\n width: 'long'\n });\n\n case 'pppp':\n default:\n return formatLong.time({\n width: 'full'\n });\n }\n};\n\nvar dateTimeLongFormatter = function dateTimeLongFormatter(pattern, formatLong) {\n var matchResult = pattern.match(/(P+)(p+)?/) || [];\n var datePattern = matchResult[1];\n var timePattern = matchResult[2];\n\n if (!timePattern) {\n return dateLongFormatter(pattern, formatLong);\n }\n\n var dateTimeFormat;\n\n switch (datePattern) {\n case 'P':\n dateTimeFormat = formatLong.dateTime({\n width: 'short'\n });\n break;\n\n case 'PP':\n dateTimeFormat = formatLong.dateTime({\n width: 'medium'\n });\n break;\n\n case 'PPP':\n dateTimeFormat = formatLong.dateTime({\n width: 'long'\n });\n break;\n\n case 'PPPP':\n default:\n dateTimeFormat = formatLong.dateTime({\n width: 'full'\n });\n break;\n }\n\n return dateTimeFormat.replace('{{date}}', dateLongFormatter(datePattern, formatLong)).replace('{{time}}', timeLongFormatter(timePattern, formatLong));\n};\n\nvar longFormatters = {\n p: timeLongFormatter,\n P: dateTimeLongFormatter\n};\nexport default longFormatters;", "var protectedDayOfYearTokens = ['D', 'DD'];\nvar protectedWeekYearTokens = ['YY', 'YYYY'];\nexport function isProtectedDayOfYearToken(token) {\n return protectedDayOfYearTokens.indexOf(token) !== -1;\n}\nexport function isProtectedWeekYearToken(token) {\n return protectedWeekYearTokens.indexOf(token) !== -1;\n}\nexport function throwProtectedError(token, format, input) {\n if (token === 'YYYY') {\n throw new RangeError(\"Use `yyyy` instead of `YYYY` (in `\".concat(format, \"`) for formatting years to the input `\").concat(input, \"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\"));\n } else if (token === 'YY') {\n throw new RangeError(\"Use `yy` instead of `YY` (in `\".concat(format, \"`) for formatting years to the input `\").concat(input, \"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\"));\n } else if (token === 'D') {\n throw new RangeError(\"Use `d` instead of `D` (in `\".concat(format, \"`) for formatting days of the month to the input `\").concat(input, \"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\"));\n } else if (token === 'DD') {\n throw new RangeError(\"Use `dd` instead of `DD` (in `\".concat(format, \"`) for formatting days of the month to the input `\").concat(input, \"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\"));\n }\n}", "var formatDistanceLocale = {\n lessThanXSeconds: {\n one: 'less than a second',\n other: 'less than {{count}} seconds'\n },\n xSeconds: {\n one: '1 second',\n other: '{{count}} seconds'\n },\n halfAMinute: 'half a minute',\n lessThanXMinutes: {\n one: 'less than a minute',\n other: 'less than {{count}} minutes'\n },\n xMinutes: {\n one: '1 minute',\n other: '{{count}} minutes'\n },\n aboutXHours: {\n one: 'about 1 hour',\n other: 'about {{count}} hours'\n },\n xHours: {\n one: '1 hour',\n other: '{{count}} hours'\n },\n xDays: {\n one: '1 day',\n other: '{{count}} days'\n },\n aboutXWeeks: {\n one: 'about 1 week',\n other: 'about {{count}} weeks'\n },\n xWeeks: {\n one: '1 week',\n other: '{{count}} weeks'\n },\n aboutXMonths: {\n one: 'about 1 month',\n other: 'about {{count}} months'\n },\n xMonths: {\n one: '1 month',\n other: '{{count}} months'\n },\n aboutXYears: {\n one: 'about 1 year',\n other: 'about {{count}} years'\n },\n xYears: {\n one: '1 year',\n other: '{{count}} years'\n },\n overXYears: {\n one: 'over 1 year',\n other: 'over {{count}} years'\n },\n almostXYears: {\n one: 'almost 1 year',\n other: 'almost {{count}} years'\n }\n};\n\nvar formatDistance = function formatDistance(token, count, options) {\n var result;\n var tokenValue = formatDistanceLocale[token];\n\n if (typeof tokenValue === 'string') {\n result = tokenValue;\n } else if (count === 1) {\n result = tokenValue.one;\n } else {\n result = tokenValue.other.replace('{{count}}', count.toString());\n }\n\n if (options !== null && options !== void 0 && options.addSuffix) {\n if (options.comparison && options.comparison > 0) {\n return 'in ' + result;\n } else {\n return result + ' ago';\n }\n }\n\n return result;\n};\n\nexport default formatDistance;", "export default function buildFormatLongFn(args) {\n return function () {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // TODO: Remove String()\n var width = options.width ? String(options.width) : args.defaultWidth;\n var format = args.formats[width] || args.formats[args.defaultWidth];\n return format;\n };\n}", "import buildFormatLongFn from \"../../../_lib/buildFormatLongFn/index.js\";\nvar dateFormats = {\n full: 'EEEE, MMMM do, y',\n long: 'MMMM do, y',\n medium: 'MMM d, y',\n short: 'MM/dd/yyyy'\n};\nvar timeFormats = {\n full: 'h:mm:ss a zzzz',\n long: 'h:mm:ss a z',\n medium: 'h:mm:ss a',\n short: 'h:mm a'\n};\nvar dateTimeFormats = {\n full: \"{{date}} 'at' {{time}}\",\n long: \"{{date}} 'at' {{time}}\",\n medium: '{{date}}, {{time}}',\n short: '{{date}}, {{time}}'\n};\nvar formatLong = {\n date: buildFormatLongFn({\n formats: dateFormats,\n defaultWidth: 'full'\n }),\n time: buildFormatLongFn({\n formats: timeFormats,\n defaultWidth: 'full'\n }),\n dateTime: buildFormatLongFn({\n formats: dateTimeFormats,\n defaultWidth: 'full'\n })\n};\nexport default formatLong;", "var formatRelativeLocale = {\n lastWeek: \"'last' eeee 'at' p\",\n yesterday: \"'yesterday at' p\",\n today: \"'today at' p\",\n tomorrow: \"'tomorrow at' p\",\n nextWeek: \"eeee 'at' p\",\n other: 'P'\n};\n\nvar formatRelative = function formatRelative(token, _date, _baseDate, _options) {\n return formatRelativeLocale[token];\n};\n\nexport default formatRelative;", "export default function buildLocalizeFn(args) {\n return function (dirtyIndex, options) {\n var context = options !== null && options !== void 0 && options.context ? String(options.context) : 'standalone';\n var valuesArray;\n\n if (context === 'formatting' && args.formattingValues) {\n var defaultWidth = args.defaultFormattingWidth || args.defaultWidth;\n var width = options !== null && options !== void 0 && options.width ? String(options.width) : defaultWidth;\n valuesArray = args.formattingValues[width] || args.formattingValues[defaultWidth];\n } else {\n var _defaultWidth = args.defaultWidth;\n\n var _width = options !== null && options !== void 0 && options.width ? String(options.width) : args.defaultWidth;\n\n valuesArray = args.values[_width] || args.values[_defaultWidth];\n }\n\n var index = args.argumentCallback ? args.argumentCallback(dirtyIndex) : dirtyIndex; // @ts-ignore: For some reason TypeScript just don't want to match it, no matter how hard we try. I challenge you to try to remove it!\n\n return valuesArray[index];\n };\n}", "import buildLocalizeFn from \"../../../_lib/buildLocalizeFn/index.js\";\nvar eraValues = {\n narrow: ['B', 'A'],\n abbreviated: ['BC', 'AD'],\n wide: ['Before Christ', 'Anno Domini']\n};\nvar quarterValues = {\n narrow: ['1', '2', '3', '4'],\n abbreviated: ['Q1', 'Q2', 'Q3', 'Q4'],\n wide: ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter']\n}; // Note: in English, the names of days of the week and months are capitalized.\n// If you are making a new locale based on this one, check if the same is true for the language you're working on.\n// Generally, formatted dates should look like they are in the middle of a sentence,\n// e.g. in Spanish language the weekdays and months should be in the lowercase.\n\nvar monthValues = {\n narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],\n abbreviated: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n wide: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']\n};\nvar dayValues = {\n narrow: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],\n short: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n abbreviated: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n wide: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']\n};\nvar dayPeriodValues = {\n narrow: {\n am: 'a',\n pm: 'p',\n midnight: 'mi',\n noon: 'n',\n morning: 'morning',\n afternoon: 'afternoon',\n evening: 'evening',\n night: 'night'\n },\n abbreviated: {\n am: 'AM',\n pm: 'PM',\n midnight: 'midnight',\n noon: 'noon',\n morning: 'morning',\n afternoon: 'afternoon',\n evening: 'evening',\n night: 'night'\n },\n wide: {\n am: 'a.m.',\n pm: 'p.m.',\n midnight: 'midnight',\n noon: 'noon',\n morning: 'morning',\n afternoon: 'afternoon',\n evening: 'evening',\n night: 'night'\n }\n};\nvar formattingDayPeriodValues = {\n narrow: {\n am: 'a',\n pm: 'p',\n midnight: 'mi',\n noon: 'n',\n morning: 'in the morning',\n afternoon: 'in the afternoon',\n evening: 'in the evening',\n night: 'at night'\n },\n abbreviated: {\n am: 'AM',\n pm: 'PM',\n midnight: 'midnight',\n noon: 'noon',\n morning: 'in the morning',\n afternoon: 'in the afternoon',\n evening: 'in the evening',\n night: 'at night'\n },\n wide: {\n am: 'a.m.',\n pm: 'p.m.',\n midnight: 'midnight',\n noon: 'noon',\n morning: 'in the morning',\n afternoon: 'in the afternoon',\n evening: 'in the evening',\n night: 'at night'\n }\n};\n\nvar ordinalNumber = function ordinalNumber(dirtyNumber, _options) {\n var number = Number(dirtyNumber); // If ordinal numbers depend on context, for example,\n // if they are different for different grammatical genders,\n // use `options.unit`.\n //\n // `unit` can be 'year', 'quarter', 'month', 'week', 'date', 'dayOfYear',\n // 'day', 'hour', 'minute', 'second'.\n\n var rem100 = number % 100;\n\n if (rem100 > 20 || rem100 < 10) {\n switch (rem100 % 10) {\n case 1:\n return number + 'st';\n\n case 2:\n return number + 'nd';\n\n case 3:\n return number + 'rd';\n }\n }\n\n return number + 'th';\n};\n\nvar localize = {\n ordinalNumber: ordinalNumber,\n era: buildLocalizeFn({\n values: eraValues,\n defaultWidth: 'wide'\n }),\n quarter: buildLocalizeFn({\n values: quarterValues,\n defaultWidth: 'wide',\n argumentCallback: function argumentCallback(quarter) {\n return quarter - 1;\n }\n }),\n month: buildLocalizeFn({\n values: monthValues,\n defaultWidth: 'wide'\n }),\n day: buildLocalizeFn({\n values: dayValues,\n defaultWidth: 'wide'\n }),\n dayPeriod: buildLocalizeFn({\n values: dayPeriodValues,\n defaultWidth: 'wide',\n formattingValues: formattingDayPeriodValues,\n defaultFormattingWidth: 'wide'\n })\n};\nexport default localize;", "export default function buildMatchFn(args) {\n return function (string) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var width = options.width;\n var matchPattern = width && args.matchPatterns[width] || args.matchPatterns[args.defaultMatchWidth];\n var matchResult = string.match(matchPattern);\n\n if (!matchResult) {\n return null;\n }\n\n var matchedString = matchResult[0];\n var parsePatterns = width && args.parsePatterns[width] || args.parsePatterns[args.defaultParseWidth];\n var key = Array.isArray(parsePatterns) ? findIndex(parsePatterns, function (pattern) {\n return pattern.test(matchedString);\n }) : findKey(parsePatterns, function (pattern) {\n return pattern.test(matchedString);\n });\n var value;\n value = args.valueCallback ? args.valueCallback(key) : key;\n value = options.valueCallback ? options.valueCallback(value) : value;\n var rest = string.slice(matchedString.length);\n return {\n value: value,\n rest: rest\n };\n };\n}\n\nfunction findKey(object, predicate) {\n for (var key in object) {\n if (object.hasOwnProperty(key) && predicate(object[key])) {\n return key;\n }\n }\n\n return undefined;\n}\n\nfunction findIndex(array, predicate) {\n for (var key = 0; key < array.length; key++) {\n if (predicate(array[key])) {\n return key;\n }\n }\n\n return undefined;\n}", "export default function buildMatchPatternFn(args) {\n return function (string) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var matchResult = string.match(args.matchPattern);\n if (!matchResult) return null;\n var matchedString = matchResult[0];\n var parseResult = string.match(args.parsePattern);\n if (!parseResult) return null;\n var value = args.valueCallback ? args.valueCallback(parseResult[0]) : parseResult[0];\n value = options.valueCallback ? options.valueCallback(value) : value;\n var rest = string.slice(matchedString.length);\n return {\n value: value,\n rest: rest\n };\n };\n}", "import buildMatchFn from \"../../../_lib/buildMatchFn/index.js\";\nimport buildMatchPatternFn from \"../../../_lib/buildMatchPatternFn/index.js\";\nvar matchOrdinalNumberPattern = /^(\\d+)(th|st|nd|rd)?/i;\nvar parseOrdinalNumberPattern = /\\d+/i;\nvar matchEraPatterns = {\n narrow: /^(b|a)/i,\n abbreviated: /^(b\\.?\\s?c\\.?|b\\.?\\s?c\\.?\\s?e\\.?|a\\.?\\s?d\\.?|c\\.?\\s?e\\.?)/i,\n wide: /^(before christ|before common era|anno domini|common era)/i\n};\nvar parseEraPatterns = {\n any: [/^b/i, /^(a|c)/i]\n};\nvar matchQuarterPatterns = {\n narrow: /^[1234]/i,\n abbreviated: /^q[1234]/i,\n wide: /^[1234](th|st|nd|rd)? quarter/i\n};\nvar parseQuarterPatterns = {\n any: [/1/i, /2/i, /3/i, /4/i]\n};\nvar matchMonthPatterns = {\n narrow: /^[jfmasond]/i,\n abbreviated: /^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,\n wide: /^(january|february|march|april|may|june|july|august|september|october|november|december)/i\n};\nvar parseMonthPatterns = {\n narrow: [/^j/i, /^f/i, /^m/i, /^a/i, /^m/i, /^j/i, /^j/i, /^a/i, /^s/i, /^o/i, /^n/i, /^d/i],\n any: [/^ja/i, /^f/i, /^mar/i, /^ap/i, /^may/i, /^jun/i, /^jul/i, /^au/i, /^s/i, /^o/i, /^n/i, /^d/i]\n};\nvar matchDayPatterns = {\n narrow: /^[smtwf]/i,\n short: /^(su|mo|tu|we|th|fr|sa)/i,\n abbreviated: /^(sun|mon|tue|wed|thu|fri|sat)/i,\n wide: /^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i\n};\nvar parseDayPatterns = {\n narrow: [/^s/i, /^m/i, /^t/i, /^w/i, /^t/i, /^f/i, /^s/i],\n any: [/^su/i, /^m/i, /^tu/i, /^w/i, /^th/i, /^f/i, /^sa/i]\n};\nvar matchDayPeriodPatterns = {\n narrow: /^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,\n any: /^([ap]\\.?\\s?m\\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i\n};\nvar parseDayPeriodPatterns = {\n any: {\n am: /^a/i,\n pm: /^p/i,\n midnight: /^mi/i,\n noon: /^no/i,\n morning: /morning/i,\n afternoon: /afternoon/i,\n evening: /evening/i,\n night: /night/i\n }\n};\nvar match = {\n ordinalNumber: buildMatchPatternFn({\n matchPattern: matchOrdinalNumberPattern,\n parsePattern: parseOrdinalNumberPattern,\n valueCallback: function valueCallback(value) {\n return parseInt(value, 10);\n }\n }),\n era: buildMatchFn({\n matchPatterns: matchEraPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseEraPatterns,\n defaultParseWidth: 'any'\n }),\n quarter: buildMatchFn({\n matchPatterns: matchQuarterPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseQuarterPatterns,\n defaultParseWidth: 'any',\n valueCallback: function valueCallback(index) {\n return index + 1;\n }\n }),\n month: buildMatchFn({\n matchPatterns: matchMonthPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseMonthPatterns,\n defaultParseWidth: 'any'\n }),\n day: buildMatchFn({\n matchPatterns: matchDayPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseDayPatterns,\n defaultParseWidth: 'any'\n }),\n dayPeriod: buildMatchFn({\n matchPatterns: matchDayPeriodPatterns,\n defaultMatchWidth: 'any',\n parsePatterns: parseDayPeriodPatterns,\n defaultParseWidth: 'any'\n })\n};\nexport default match;", "import formatDistance from \"./_lib/formatDistance/index.js\";\nimport formatLong from \"./_lib/formatLong/index.js\";\nimport formatRelative from \"./_lib/formatRelative/index.js\";\nimport localize from \"./_lib/localize/index.js\";\nimport match from \"./_lib/match/index.js\";\n\n/**\n * @type {Locale}\n * @category Locales\n * @summary English locale (United States).\n * @language English\n * @iso-639-2 eng\n * @author Sasha Koss [@kossnocorp]{@link https://github.com/kossnocorp}\n * @author Lesha Koss [@leshakoss]{@link https://github.com/leshakoss}\n */\nvar locale = {\n code: 'en-US',\n formatDistance: formatDistance,\n formatLong: formatLong,\n formatRelative: formatRelative,\n localize: localize,\n match: match,\n options: {\n weekStartsOn: 0\n /* Sunday */\n ,\n firstWeekContainsDate: 1\n }\n};\nexport default locale;", "import defaultLocale from \"../../locale/en-US/index.js\";\nexport default defaultLocale;", "import isValid from \"../isValid/index.js\";\nimport subMilliseconds from \"../subMilliseconds/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport formatters from \"../_lib/format/formatters/index.js\";\nimport longFormatters from \"../_lib/format/longFormatters/index.js\";\nimport getTimezoneOffsetInMilliseconds from \"../_lib/getTimezoneOffsetInMilliseconds/index.js\";\nimport { isProtectedDayOfYearToken, isProtectedWeekYearToken, throwProtectedError } from \"../_lib/protectedTokens/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport { getDefaultOptions } from \"../_lib/defaultOptions/index.js\";\nimport defaultLocale from \"../_lib/defaultLocale/index.js\"; // This RegExp consists of three parts separated by `|`:\n// - [yYQqMLwIdDecihHKkms]o matches any available ordinal number token\n// (one of the certain letters followed by `o`)\n// - (\\w)\\1* matches any sequences of the same letter\n// - '' matches two quote characters in a row\n// - '(''|[^'])+('|$) matches anything surrounded by two quote characters ('),\n// except a single quote symbol, which ends the sequence.\n// Two quote characters do not end the sequence.\n// If there is no matching single quote\n// then the sequence will continue until the end of the string.\n// - . matches any single character unmatched by previous parts of the RegExps\n\nvar formattingTokensRegExp = /[yYQqMLwIdDecihHKkms]o|(\\w)\\1*|''|'(''|[^'])+('|$)|./g; // This RegExp catches symbols escaped by quotes, and also\n// sequences of symbols P, p, and the combinations like `PPPPPPPppppp`\n\nvar longFormattingTokensRegExp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;\nvar escapedStringRegExp = /^'([^]*?)'?$/;\nvar doubleQuoteRegExp = /''/g;\nvar unescapedLatinCharacterRegExp = /[a-zA-Z]/;\n/**\n * @name format\n * @category Common Helpers\n * @summary Format the date.\n *\n * @description\n * Return the formatted date string in the given format. The result may vary by locale.\n *\n * > \u26A0\uFE0F Please note that the `format` tokens differ from Moment.js and other libraries.\n * > See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * The characters wrapped between two single quotes characters (') are escaped.\n * Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.\n * (see the last example)\n *\n * Format of the string is based on Unicode Technical Standard #35:\n * https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * with a few additions (see note 7 below the table).\n *\n * Accepted patterns:\n * | Unit | Pattern | Result examples | Notes |\n * |---------------------------------|---------|-----------------------------------|-------|\n * | Era | G..GGG | AD, BC | |\n * | | GGGG | Anno Domini, Before Christ | 2 |\n * | | GGGGG | A, B | |\n * | Calendar year | y | 44, 1, 1900, 2017 | 5 |\n * | | yo | 44th, 1st, 0th, 17th | 5,7 |\n * | | yy | 44, 01, 00, 17 | 5 |\n * | | yyy | 044, 001, 1900, 2017 | 5 |\n * | | yyyy | 0044, 0001, 1900, 2017 | 5 |\n * | | yyyyy | ... | 3,5 |\n * | Local week-numbering year | Y | 44, 1, 1900, 2017 | 5 |\n * | | Yo | 44th, 1st, 1900th, 2017th | 5,7 |\n * | | YY | 44, 01, 00, 17 | 5,8 |\n * | | YYY | 044, 001, 1900, 2017 | 5 |\n * | | YYYY | 0044, 0001, 1900, 2017 | 5,8 |\n * | | YYYYY | ... | 3,5 |\n * | ISO week-numbering year | R | -43, 0, 1, 1900, 2017 | 5,7 |\n * | | RR | -43, 00, 01, 1900, 2017 | 5,7 |\n * | | RRR | -043, 000, 001, 1900, 2017 | 5,7 |\n * | | RRRR | -0043, 0000, 0001, 1900, 2017 | 5,7 |\n * | | RRRRR | ... | 3,5,7 |\n * | Extended year | u | -43, 0, 1, 1900, 2017 | 5 |\n * | | uu | -43, 01, 1900, 2017 | 5 |\n * | | uuu | -043, 001, 1900, 2017 | 5 |\n * | | uuuu | -0043, 0001, 1900, 2017 | 5 |\n * | | uuuuu | ... | 3,5 |\n * | Quarter (formatting) | Q | 1, 2, 3, 4 | |\n * | | Qo | 1st, 2nd, 3rd, 4th | 7 |\n * | | QQ | 01, 02, 03, 04 | |\n * | | QQQ | Q1, Q2, Q3, Q4 | |\n * | | QQQQ | 1st quarter, 2nd quarter, ... | 2 |\n * | | QQQQQ | 1, 2, 3, 4 | 4 |\n * | Quarter (stand-alone) | q | 1, 2, 3, 4 | |\n * | | qo | 1st, 2nd, 3rd, 4th | 7 |\n * | | qq | 01, 02, 03, 04 | |\n * | | qqq | Q1, Q2, Q3, Q4 | |\n * | | qqqq | 1st quarter, 2nd quarter, ... | 2 |\n * | | qqqqq | 1, 2, 3, 4 | 4 |\n * | Month (formatting) | M | 1, 2, ..., 12 | |\n * | | Mo | 1st, 2nd, ..., 12th | 7 |\n * | | MM | 01, 02, ..., 12 | |\n * | | MMM | Jan, Feb, ..., Dec | |\n * | | MMMM | January, February, ..., December | 2 |\n * | | MMMMM | J, F, ..., D | |\n * | Month (stand-alone) | L | 1, 2, ..., 12 | |\n * | | Lo | 1st, 2nd, ..., 12th | 7 |\n * | | LL | 01, 02, ..., 12 | |\n * | | LLL | Jan, Feb, ..., Dec | |\n * | | LLLL | January, February, ..., December | 2 |\n * | | LLLLL | J, F, ..., D | |\n * | Local week of year | w | 1, 2, ..., 53 | |\n * | | wo | 1st, 2nd, ..., 53th | 7 |\n * | | ww | 01, 02, ..., 53 | |\n * | ISO week of year | I | 1, 2, ..., 53 | 7 |\n * | | Io | 1st, 2nd, ..., 53th | 7 |\n * | | II | 01, 02, ..., 53 | 7 |\n * | Day of month | d | 1, 2, ..., 31 | |\n * | | do | 1st, 2nd, ..., 31st | 7 |\n * | | dd | 01, 02, ..., 31 | |\n * | Day of year | D | 1, 2, ..., 365, 366 | 9 |\n * | | Do | 1st, 2nd, ..., 365th, 366th | 7 |\n * | | DD | 01, 02, ..., 365, 366 | 9 |\n * | | DDD | 001, 002, ..., 365, 366 | |\n * | | DDDD | ... | 3 |\n * | Day of week (formatting) | E..EEE | Mon, Tue, Wed, ..., Sun | |\n * | | EEEE | Monday, Tuesday, ..., Sunday | 2 |\n * | | EEEEE | M, T, W, T, F, S, S | |\n * | | EEEEEE | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | ISO day of week (formatting) | i | 1, 2, 3, ..., 7 | 7 |\n * | | io | 1st, 2nd, ..., 7th | 7 |\n * | | ii | 01, 02, ..., 07 | 7 |\n * | | iii | Mon, Tue, Wed, ..., Sun | 7 |\n * | | iiii | Monday, Tuesday, ..., Sunday | 2,7 |\n * | | iiiii | M, T, W, T, F, S, S | 7 |\n * | | iiiiii | Mo, Tu, We, Th, Fr, Sa, Su | 7 |\n * | Local day of week (formatting) | e | 2, 3, 4, ..., 1 | |\n * | | eo | 2nd, 3rd, ..., 1st | 7 |\n * | | ee | 02, 03, ..., 01 | |\n * | | eee | Mon, Tue, Wed, ..., Sun | |\n * | | eeee | Monday, Tuesday, ..., Sunday | 2 |\n * | | eeeee | M, T, W, T, F, S, S | |\n * | | eeeeee | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | Local day of week (stand-alone) | c | 2, 3, 4, ..., 1 | |\n * | | co | 2nd, 3rd, ..., 1st | 7 |\n * | | cc | 02, 03, ..., 01 | |\n * | | ccc | Mon, Tue, Wed, ..., Sun | |\n * | | cccc | Monday, Tuesday, ..., Sunday | 2 |\n * | | ccccc | M, T, W, T, F, S, S | |\n * | | cccccc | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | AM, PM | a..aa | AM, PM | |\n * | | aaa | am, pm | |\n * | | aaaa | a.m., p.m. | 2 |\n * | | aaaaa | a, p | |\n * | AM, PM, noon, midnight | b..bb | AM, PM, noon, midnight | |\n * | | bbb | am, pm, noon, midnight | |\n * | | bbbb | a.m., p.m., noon, midnight | 2 |\n * | | bbbbb | a, p, n, mi | |\n * | Flexible day period | B..BBB | at night, in the morning, ... | |\n * | | BBBB | at night, in the morning, ... | 2 |\n * | | BBBBB | at night, in the morning, ... | |\n * | Hour [1-12] | h | 1, 2, ..., 11, 12 | |\n * | | ho | 1st, 2nd, ..., 11th, 12th | 7 |\n * | | hh | 01, 02, ..., 11, 12 | |\n * | Hour [0-23] | H | 0, 1, 2, ..., 23 | |\n * | | Ho | 0th, 1st, 2nd, ..., 23rd | 7 |\n * | | HH | 00, 01, 02, ..., 23 | |\n * | Hour [0-11] | K | 1, 2, ..., 11, 0 | |\n * | | Ko | 1st, 2nd, ..., 11th, 0th | 7 |\n * | | KK | 01, 02, ..., 11, 00 | |\n * | Hour [1-24] | k | 24, 1, 2, ..., 23 | |\n * | | ko | 24th, 1st, 2nd, ..., 23rd | 7 |\n * | | kk | 24, 01, 02, ..., 23 | |\n * | Minute | m | 0, 1, ..., 59 | |\n * | | mo | 0th, 1st, ..., 59th | 7 |\n * | | mm | 00, 01, ..., 59 | |\n * | Second | s | 0, 1, ..., 59 | |\n * | | so | 0th, 1st, ..., 59th | 7 |\n * | | ss | 00, 01, ..., 59 | |\n * | Fraction of second | S | 0, 1, ..., 9 | |\n * | | SS | 00, 01, ..., 99 | |\n * | | SSS | 000, 001, ..., 999 | |\n * | | SSSS | ... | 3 |\n * | Timezone (ISO-8601 w/ Z) | X | -08, +0530, Z | |\n * | | XX | -0800, +0530, Z | |\n * | | XXX | -08:00, +05:30, Z | |\n * | | XXXX | -0800, +0530, Z, +123456 | 2 |\n * | | XXXXX | -08:00, +05:30, Z, +12:34:56 | |\n * | Timezone (ISO-8601 w/o Z) | x | -08, +0530, +00 | |\n * | | xx | -0800, +0530, +0000 | |\n * | | xxx | -08:00, +05:30, +00:00 | 2 |\n * | | xxxx | -0800, +0530, +0000, +123456 | |\n * | | xxxxx | -08:00, +05:30, +00:00, +12:34:56 | |\n * | Timezone (GMT) | O...OOO | GMT-8, GMT+5:30, GMT+0 | |\n * | | OOOO | GMT-08:00, GMT+05:30, GMT+00:00 | 2 |\n * | Timezone (specific non-locat.) | z...zzz | GMT-8, GMT+5:30, GMT+0 | 6 |\n * | | zzzz | GMT-08:00, GMT+05:30, GMT+00:00 | 2,6 |\n * | Seconds timestamp | t | 512969520 | 7 |\n * | | tt | ... | 3,7 |\n * | Milliseconds timestamp | T | 512969520900 | 7 |\n * | | TT | ... | 3,7 |\n * | Long localized date | P | 04/29/1453 | 7 |\n * | | PP | Apr 29, 1453 | 7 |\n * | | PPP | April 29th, 1453 | 7 |\n * | | PPPP | Friday, April 29th, 1453 | 2,7 |\n * | Long localized time | p | 12:00 AM | 7 |\n * | | pp | 12:00:00 AM | 7 |\n * | | ppp | 12:00:00 AM GMT+2 | 7 |\n * | | pppp | 12:00:00 AM GMT+02:00 | 2,7 |\n * | Combination of date and time | Pp | 04/29/1453, 12:00 AM | 7 |\n * | | PPpp | Apr 29, 1453, 12:00:00 AM | 7 |\n * | | PPPppp | April 29th, 1453 at ... | 7 |\n * | | PPPPpppp| Friday, April 29th, 1453 at ... | 2,7 |\n * Notes:\n * 1. \"Formatting\" units (e.g. formatting quarter) in the default en-US locale\n * are the same as \"stand-alone\" units, but are different in some languages.\n * \"Formatting\" units are declined according to the rules of the language\n * in the context of a date. \"Stand-alone\" units are always nominative singular:\n *\n * `format(new Date(2017, 10, 6), 'do LLLL', {locale: cs}) //=> '6. listopad'`\n *\n * `format(new Date(2017, 10, 6), 'do MMMM', {locale: cs}) //=> '6. listopadu'`\n *\n * 2. Any sequence of the identical letters is a pattern, unless it is escaped by\n * the single quote characters (see below).\n * If the sequence is longer than listed in table (e.g. `EEEEEEEEEEE`)\n * the output will be the same as default pattern for this unit, usually\n * the longest one (in case of ISO weekdays, `EEEE`). Default patterns for units\n * are marked with \"2\" in the last column of the table.\n *\n * `format(new Date(2017, 10, 6), 'MMM') //=> 'Nov'`\n *\n * `format(new Date(2017, 10, 6), 'MMMM') //=> 'November'`\n *\n * `format(new Date(2017, 10, 6), 'MMMMM') //=> 'N'`\n *\n * `format(new Date(2017, 10, 6), 'MMMMMM') //=> 'November'`\n *\n * `format(new Date(2017, 10, 6), 'MMMMMMM') //=> 'November'`\n *\n * 3. Some patterns could be unlimited length (such as `yyyyyyyy`).\n * The output will be padded with zeros to match the length of the pattern.\n *\n * `format(new Date(2017, 10, 6), 'yyyyyyyy') //=> '00002017'`\n *\n * 4. `QQQQQ` and `qqqqq` could be not strictly numerical in some locales.\n * These tokens represent the shortest form of the quarter.\n *\n * 5. The main difference between `y` and `u` patterns are B.C. years:\n *\n * | Year | `y` | `u` |\n * |------|-----|-----|\n * | AC 1 | 1 | 1 |\n * | BC 1 | 1 | 0 |\n * | BC 2 | 2 | -1 |\n *\n * Also `yy` always returns the last two digits of a year,\n * while `uu` pads single digit years to 2 characters and returns other years unchanged:\n *\n * | Year | `yy` | `uu` |\n * |------|------|------|\n * | 1 | 01 | 01 |\n * | 14 | 14 | 14 |\n * | 376 | 76 | 376 |\n * | 1453 | 53 | 1453 |\n *\n * The same difference is true for local and ISO week-numbering years (`Y` and `R`),\n * except local week-numbering years are dependent on `options.weekStartsOn`\n * and `options.firstWeekContainsDate` (compare [getISOWeekYear]{@link https://date-fns.org/docs/getISOWeekYear}\n * and [getWeekYear]{@link https://date-fns.org/docs/getWeekYear}).\n *\n * 6. Specific non-location timezones are currently unavailable in `date-fns`,\n * so right now these tokens fall back to GMT timezones.\n *\n * 7. These patterns are not in the Unicode Technical Standard #35:\n * - `i`: ISO day of week\n * - `I`: ISO week of year\n * - `R`: ISO week-numbering year\n * - `t`: seconds timestamp\n * - `T`: milliseconds timestamp\n * - `o`: ordinal number modifier\n * - `P`: long localized date\n * - `p`: long localized time\n *\n * 8. `YY` and `YYYY` tokens represent week-numbering years but they are often confused with years.\n * You should enable `options.useAdditionalWeekYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * 9. `D` and `DD` tokens represent days of the year but they are often confused with days of the month.\n * You should enable `options.useAdditionalDayOfYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * @param {Date|Number} date - the original date\n * @param {String} format - the string of tokens\n * @param {Object} [options] - an object with options.\n * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}\n * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)\n * @param {Number} [options.firstWeekContainsDate=1] - the day of January, which is\n * @param {Boolean} [options.useAdditionalWeekYearTokens=false] - if true, allows usage of the week-numbering year tokens `YY` and `YYYY`;\n * see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @param {Boolean} [options.useAdditionalDayOfYearTokens=false] - if true, allows usage of the day of year tokens `D` and `DD`;\n * see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @returns {String} the formatted date string\n * @throws {TypeError} 2 arguments required\n * @throws {RangeError} `date` must not be Invalid Date\n * @throws {RangeError} `options.locale` must contain `localize` property\n * @throws {RangeError} `options.locale` must contain `formatLong` property\n * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6\n * @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7\n * @throws {RangeError} use `yyyy` instead of `YYYY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws {RangeError} use `yy` instead of `YY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws {RangeError} use `d` instead of `D` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws {RangeError} use `dd` instead of `DD` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws {RangeError} format string contains an unescaped latin alphabet character\n *\n * @example\n * // Represent 11 February 2014 in middle-endian format:\n * const result = format(new Date(2014, 1, 11), 'MM/dd/yyyy')\n * //=> '02/11/2014'\n *\n * @example\n * // Represent 2 July 2014 in Esperanto:\n * import { eoLocale } from 'date-fns/locale/eo'\n * const result = format(new Date(2014, 6, 2), \"do 'de' MMMM yyyy\", {\n * locale: eoLocale\n * })\n * //=> '2-a de julio 2014'\n *\n * @example\n * // Escape string by single quote characters:\n * const result = format(new Date(2014, 6, 2, 15), \"h 'o''clock'\")\n * //=> \"3 o'clock\"\n */\n\nexport default function format(dirtyDate, dirtyFormatStr, options) {\n var _ref, _options$locale, _ref2, _ref3, _ref4, _options$firstWeekCon, _options$locale2, _options$locale2$opti, _defaultOptions$local, _defaultOptions$local2, _ref5, _ref6, _ref7, _options$weekStartsOn, _options$locale3, _options$locale3$opti, _defaultOptions$local3, _defaultOptions$local4;\n\n requiredArgs(2, arguments);\n var formatStr = String(dirtyFormatStr);\n var defaultOptions = getDefaultOptions();\n var locale = (_ref = (_options$locale = options === null || options === void 0 ? void 0 : options.locale) !== null && _options$locale !== void 0 ? _options$locale : defaultOptions.locale) !== null && _ref !== void 0 ? _ref : defaultLocale;\n var firstWeekContainsDate = toInteger((_ref2 = (_ref3 = (_ref4 = (_options$firstWeekCon = options === null || options === void 0 ? void 0 : options.firstWeekContainsDate) !== null && _options$firstWeekCon !== void 0 ? _options$firstWeekCon : options === null || options === void 0 ? void 0 : (_options$locale2 = options.locale) === null || _options$locale2 === void 0 ? void 0 : (_options$locale2$opti = _options$locale2.options) === null || _options$locale2$opti === void 0 ? void 0 : _options$locale2$opti.firstWeekContainsDate) !== null && _ref4 !== void 0 ? _ref4 : defaultOptions.firstWeekContainsDate) !== null && _ref3 !== void 0 ? _ref3 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.firstWeekContainsDate) !== null && _ref2 !== void 0 ? _ref2 : 1); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN\n\n if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {\n throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');\n }\n\n var weekStartsOn = toInteger((_ref5 = (_ref6 = (_ref7 = (_options$weekStartsOn = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : options === null || options === void 0 ? void 0 : (_options$locale3 = options.locale) === null || _options$locale3 === void 0 ? void 0 : (_options$locale3$opti = _options$locale3.options) === null || _options$locale3$opti === void 0 ? void 0 : _options$locale3$opti.weekStartsOn) !== null && _ref7 !== void 0 ? _ref7 : defaultOptions.weekStartsOn) !== null && _ref6 !== void 0 ? _ref6 : (_defaultOptions$local3 = defaultOptions.locale) === null || _defaultOptions$local3 === void 0 ? void 0 : (_defaultOptions$local4 = _defaultOptions$local3.options) === null || _defaultOptions$local4 === void 0 ? void 0 : _defaultOptions$local4.weekStartsOn) !== null && _ref5 !== void 0 ? _ref5 : 0); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN\n\n if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {\n throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');\n }\n\n if (!locale.localize) {\n throw new RangeError('locale must contain localize property');\n }\n\n if (!locale.formatLong) {\n throw new RangeError('locale must contain formatLong property');\n }\n\n var originalDate = toDate(dirtyDate);\n\n if (!isValid(originalDate)) {\n throw new RangeError('Invalid time value');\n } // Convert the date in system timezone to the same date in UTC+00:00 timezone.\n // This ensures that when UTC functions will be implemented, locales will be compatible with them.\n // See an issue about UTC functions: https://github.com/date-fns/date-fns/issues/376\n\n\n var timezoneOffset = getTimezoneOffsetInMilliseconds(originalDate);\n var utcDate = subMilliseconds(originalDate, timezoneOffset);\n var formatterOptions = {\n firstWeekContainsDate: firstWeekContainsDate,\n weekStartsOn: weekStartsOn,\n locale: locale,\n _originalDate: originalDate\n };\n var result = formatStr.match(longFormattingTokensRegExp).map(function (substring) {\n var firstCharacter = substring[0];\n\n if (firstCharacter === 'p' || firstCharacter === 'P') {\n var longFormatter = longFormatters[firstCharacter];\n return longFormatter(substring, locale.formatLong);\n }\n\n return substring;\n }).join('').match(formattingTokensRegExp).map(function (substring) {\n // Replace two single quote characters with one single quote character\n if (substring === \"''\") {\n return \"'\";\n }\n\n var firstCharacter = substring[0];\n\n if (firstCharacter === \"'\") {\n return cleanEscapedString(substring);\n }\n\n var formatter = formatters[firstCharacter];\n\n if (formatter) {\n if (!(options !== null && options !== void 0 && options.useAdditionalWeekYearTokens) && isProtectedWeekYearToken(substring)) {\n throwProtectedError(substring, dirtyFormatStr, String(dirtyDate));\n }\n\n if (!(options !== null && options !== void 0 && options.useAdditionalDayOfYearTokens) && isProtectedDayOfYearToken(substring)) {\n throwProtectedError(substring, dirtyFormatStr, String(dirtyDate));\n }\n\n return formatter(utcDate, substring, locale.localize, formatterOptions);\n }\n\n if (firstCharacter.match(unescapedLatinCharacterRegExp)) {\n throw new RangeError('Format string contains an unescaped latin alphabet character `' + firstCharacter + '`');\n }\n\n return substring;\n }).join('');\n return result;\n}\n\nfunction cleanEscapedString(input) {\n var matched = input.match(escapedStringRegExp);\n\n if (!matched) {\n return input;\n }\n\n return matched[1].replace(doubleQuoteRegExp, \"'\");\n}", "export default function assign(target, object) {\n if (target == null) {\n throw new TypeError('assign requires that input parameter not be null or undefined');\n }\n\n for (var property in object) {\n if (Object.prototype.hasOwnProperty.call(object, property)) {\n ;\n target[property] = object[property];\n }\n }\n\n return target;\n}", "import { getDefaultOptions } from \"../_lib/defaultOptions/index.js\";\nimport defaultLocale from \"../_lib/defaultLocale/index.js\";\nvar defaultFormat = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'];\n/**\n * @name formatDuration\n * @category Common Helpers\n * @summary Formats a duration in human-readable format\n *\n * @description\n * Return human-readable duration string i.e. \"9 months 2 days\"\n *\n * @param {Duration} duration - the duration to format\n * @param {Object} [options] - an object with options.\n * @param {string[]} [options.format=['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds']] - the array of units to format\n * @param {boolean} [options.zero=false] - should zeros be included in the output?\n * @param {string} [options.delimiter=' '] - delimiter string\n * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}\n * @returns {string} the formatted date string\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Format full duration\n * formatDuration({\n * years: 2,\n * months: 9,\n * weeks: 1,\n * days: 7,\n * hours: 5,\n * minutes: 9,\n * seconds: 30\n * })\n * //=> '2 years 9 months 1 week 7 days 5 hours 9 minutes 30 seconds'\n *\n * @example\n * // Format partial duration\n * formatDuration({ months: 9, days: 2 })\n * //=> '9 months 2 days'\n *\n * @example\n * // Customize the format\n * formatDuration(\n * {\n * years: 2,\n * months: 9,\n * weeks: 1,\n * days: 7,\n * hours: 5,\n * minutes: 9,\n * seconds: 30\n * },\n * { format: ['months', 'weeks'] }\n * ) === '9 months 1 week'\n *\n * @example\n * // Customize the zeros presence\n * formatDuration({ years: 0, months: 9 })\n * //=> '9 months'\n * formatDuration({ years: 0, months: 9 }, { zero: true })\n * //=> '0 years 9 months'\n *\n * @example\n * // Customize the delimiter\n * formatDuration({ years: 2, months: 9, weeks: 3 }, { delimiter: ', ' })\n * //=> '2 years, 9 months, 3 weeks'\n */\n\nexport default function formatDuration(duration, options) {\n var _ref, _options$locale, _options$format, _options$zero, _options$delimiter;\n\n if (arguments.length < 1) {\n throw new TypeError(\"1 argument required, but only \".concat(arguments.length, \" present\"));\n }\n\n var defaultOptions = getDefaultOptions();\n var locale = (_ref = (_options$locale = options === null || options === void 0 ? void 0 : options.locale) !== null && _options$locale !== void 0 ? _options$locale : defaultOptions.locale) !== null && _ref !== void 0 ? _ref : defaultLocale;\n var format = (_options$format = options === null || options === void 0 ? void 0 : options.format) !== null && _options$format !== void 0 ? _options$format : defaultFormat;\n var zero = (_options$zero = options === null || options === void 0 ? void 0 : options.zero) !== null && _options$zero !== void 0 ? _options$zero : false;\n var delimiter = (_options$delimiter = options === null || options === void 0 ? void 0 : options.delimiter) !== null && _options$delimiter !== void 0 ? _options$delimiter : ' ';\n\n if (!locale.formatDistance) {\n return '';\n }\n\n var result = format.reduce(function (acc, unit) {\n var token = \"x\".concat(unit.replace(/(^.)/, function (m) {\n return m.toUpperCase();\n }));\n var value = duration[unit];\n\n if (typeof value === 'number' && (zero || duration[unit])) {\n return acc.concat(locale.formatDistance(token, value));\n }\n\n return acc;\n }, []).join(delimiter);\n return result;\n}", "import toDate from \"../toDate/index.js\";\nimport addLeadingZeros from \"../_lib/addLeadingZeros/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name formatISO\n * @category Common Helpers\n * @summary Format the date according to the ISO 8601 standard (https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003169814.htm).\n *\n * @description\n * Return the formatted date string in ISO 8601 format. Options may be passed to control the parts and notations of the date.\n *\n * @param {Date|Number} date - the original date\n * @param {Object} [options] - an object with options.\n * @param {'extended'|'basic'} [options.format='extended'] - if 'basic', hide delimiters between date and time values.\n * @param {'complete'|'date'|'time'} [options.representation='complete'] - format date, time with local time zone, or both.\n * @returns {String} the formatted date string (in local time zone)\n * @throws {TypeError} 1 argument required\n * @throws {RangeError} `date` must not be Invalid Date\n * @throws {RangeError} `options.format` must be 'extended' or 'basic'\n * @throws {RangeError} `options.representation` must be 'date', 'time' or 'complete'\n *\n * @example\n * // Represent 18 September 2019 in ISO 8601 format (local time zone is UTC):\n * const result = formatISO(new Date(2019, 8, 18, 19, 0, 52))\n * //=> '2019-09-18T19:00:52Z'\n *\n * @example\n * // Represent 18 September 2019 in ISO 8601, short format (local time zone is UTC):\n * const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { format: 'basic' })\n * //=> '20190918T190052'\n *\n * @example\n * // Represent 18 September 2019 in ISO 8601 format, date only:\n * const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { representation: 'date' })\n * //=> '2019-09-18'\n *\n * @example\n * // Represent 18 September 2019 in ISO 8601 format, time only (local time zone is UTC):\n * const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { representation: 'time' })\n * //=> '19:00:52Z'\n */\n\nexport default function formatISO(date, options) {\n var _options$format, _options$representati;\n\n requiredArgs(1, arguments);\n var originalDate = toDate(date);\n\n if (isNaN(originalDate.getTime())) {\n throw new RangeError('Invalid time value');\n }\n\n var format = String((_options$format = options === null || options === void 0 ? void 0 : options.format) !== null && _options$format !== void 0 ? _options$format : 'extended');\n var representation = String((_options$representati = options === null || options === void 0 ? void 0 : options.representation) !== null && _options$representati !== void 0 ? _options$representati : 'complete');\n\n if (format !== 'extended' && format !== 'basic') {\n throw new RangeError(\"format must be 'extended' or 'basic'\");\n }\n\n if (representation !== 'date' && representation !== 'time' && representation !== 'complete') {\n throw new RangeError(\"representation must be 'date', 'time', or 'complete'\");\n }\n\n var result = '';\n var tzOffset = '';\n var dateDelimiter = format === 'extended' ? '-' : '';\n var timeDelimiter = format === 'extended' ? ':' : ''; // Representation is either 'date' or 'complete'\n\n if (representation !== 'time') {\n var day = addLeadingZeros(originalDate.getDate(), 2);\n var month = addLeadingZeros(originalDate.getMonth() + 1, 2);\n var year = addLeadingZeros(originalDate.getFullYear(), 4); // yyyyMMdd or yyyy-MM-dd.\n\n result = \"\".concat(year).concat(dateDelimiter).concat(month).concat(dateDelimiter).concat(day);\n } // Representation is either 'time' or 'complete'\n\n\n if (representation !== 'date') {\n // Add the timezone.\n var offset = originalDate.getTimezoneOffset();\n\n if (offset !== 0) {\n var absoluteOffset = Math.abs(offset);\n var hourOffset = addLeadingZeros(Math.floor(absoluteOffset / 60), 2);\n var minuteOffset = addLeadingZeros(absoluteOffset % 60, 2); // If less than 0, the sign is +, because it is ahead of time.\n\n var sign = offset < 0 ? '+' : '-';\n tzOffset = \"\".concat(sign).concat(hourOffset, \":\").concat(minuteOffset);\n } else {\n tzOffset = 'Z';\n }\n\n var hour = addLeadingZeros(originalDate.getHours(), 2);\n var minute = addLeadingZeros(originalDate.getMinutes(), 2);\n var second = addLeadingZeros(originalDate.getSeconds(), 2); // If there's also date, separate it with time with 'T'\n\n var separator = result === '' ? '' : 'T'; // Creates a time string consisting of hour, minute, and second, separated by delimiters, if defined.\n\n var time = [hour, minute, second].join(timeDelimiter); // HHmmss or HH:mm:ss.\n\n result = \"\".concat(result).concat(separator).concat(time).concat(tzOffset);\n }\n\n return result;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name getHours\n * @category Hour Helpers\n * @summary Get the hours of the given date.\n *\n * @description\n * Get the hours of the given date.\n *\n * @param {Date|Number} date - the given date\n * @returns {Number} the hours\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Get the hours of 29 February 2012 11:45:00:\n * const result = getHours(new Date(2012, 1, 29, 11, 45))\n * //=> 11\n */\n\nexport default function getHours(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var hours = date.getHours();\n return hours;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name getMinutes\n * @category Minute Helpers\n * @summary Get the minutes of the given date.\n *\n * @description\n * Get the minutes of the given date.\n *\n * @param {Date|Number} date - the given date\n * @returns {Number} the minutes\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Get the minutes of 29 February 2012 11:45:05:\n * const result = getMinutes(new Date(2012, 1, 29, 11, 45, 5))\n * //=> 45\n */\n\nexport default function getMinutes(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var minutes = date.getMinutes();\n return minutes;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name getMonth\n * @category Month Helpers\n * @summary Get the month of the given date.\n *\n * @description\n * Get the month of the given date.\n *\n * @param {Date|Number} date - the given date\n * @returns {Number} the month\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Which month is 29 February 2012?\n * const result = getMonth(new Date(2012, 1, 29))\n * //=> 1\n */\n\nexport default function getMonth(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var month = date.getMonth();\n return month;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name getSeconds\n * @category Second Helpers\n * @summary Get the seconds of the given date.\n *\n * @description\n * Get the seconds of the given date.\n *\n * @param {Date|Number} date - the given date\n * @returns {Number} the seconds\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Get the seconds of 29 February 2012 11:45:05.123:\n * const result = getSeconds(new Date(2012, 1, 29, 11, 45, 5, 123))\n * //=> 5\n */\n\nexport default function getSeconds(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var seconds = date.getSeconds();\n return seconds;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name getYear\n * @category Year Helpers\n * @summary Get the year of the given date.\n *\n * @description\n * Get the year of the given date.\n *\n * @param {Date|Number} date - the given date\n * @returns {Number} the year\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Which year is 2 July 2014?\n * const result = getYear(new Date(2014, 6, 2))\n * //=> 2014\n */\n\nexport default function getYear(dirtyDate) {\n requiredArgs(1, arguments);\n return toDate(dirtyDate).getFullYear();\n}", "import compareAsc from \"../compareAsc/index.js\";\nimport add from \"../add/index.js\";\nimport differenceInDays from \"../differenceInDays/index.js\";\nimport differenceInHours from \"../differenceInHours/index.js\";\nimport differenceInMinutes from \"../differenceInMinutes/index.js\";\nimport differenceInMonths from \"../differenceInMonths/index.js\";\nimport differenceInSeconds from \"../differenceInSeconds/index.js\";\nimport differenceInYears from \"../differenceInYears/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name intervalToDuration\n * @category Common Helpers\n * @summary Convert interval to duration\n *\n * @description\n * Convert a interval object to a duration object.\n *\n * @param {Interval} interval - the interval to convert to duration\n *\n * @returns {Duration} The duration Object\n * @throws {TypeError} Requires 2 arguments\n * @throws {RangeError} `start` must not be Invalid Date\n * @throws {RangeError} `end` must not be Invalid Date\n *\n * @example\n * // Get the duration between January 15, 1929 and April 4, 1968.\n * intervalToDuration({\n * start: new Date(1929, 0, 15, 12, 0, 0),\n * end: new Date(1968, 3, 4, 19, 5, 0)\n * })\n * // => { years: 39, months: 2, days: 20, hours: 7, minutes: 5, seconds: 0 }\n */\n\nexport default function intervalToDuration(interval) {\n requiredArgs(1, arguments);\n var start = toDate(interval.start);\n var end = toDate(interval.end);\n if (isNaN(start.getTime())) throw new RangeError('Start Date is invalid');\n if (isNaN(end.getTime())) throw new RangeError('End Date is invalid');\n var duration = {};\n duration.years = Math.abs(differenceInYears(end, start));\n var sign = compareAsc(end, start);\n var remainingMonths = add(start, {\n years: sign * duration.years\n });\n duration.months = Math.abs(differenceInMonths(end, remainingMonths));\n var remainingDays = add(remainingMonths, {\n months: sign * duration.months\n });\n duration.days = Math.abs(differenceInDays(end, remainingDays));\n var remainingHours = add(remainingDays, {\n days: sign * duration.days\n });\n duration.hours = Math.abs(differenceInHours(end, remainingHours));\n var remainingMinutes = add(remainingHours, {\n hours: sign * duration.hours\n });\n duration.minutes = Math.abs(differenceInMinutes(end, remainingMinutes));\n var remainingSeconds = add(remainingMinutes, {\n minutes: sign * duration.minutes\n });\n duration.seconds = Math.abs(differenceInSeconds(end, remainingSeconds));\n return duration;\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isFuture\n * @category Common Helpers\n * @summary Is the given date in the future?\n * @pure false\n *\n * @description\n * Is the given date in the future?\n *\n * > \u26A0\uFE0F Please note that this function is not present in the FP submodule as\n * > it uses `Date.now()` internally hence impure and can't be safely curried.\n *\n * @param {Date|Number} date - the date to check\n * @returns {Boolean} the date is in the future\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // If today is 6 October 2014, is 31 December 2014 in the future?\n * const result = isFuture(new Date(2014, 11, 31))\n * //=> true\n */\n\nexport default function isFuture(dirtyDate) {\n requiredArgs(1, arguments);\n return toDate(dirtyDate).getTime() > Date.now();\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nvar TIMEZONE_UNIT_PRIORITY = 10;\nexport var Setter = /*#__PURE__*/function () {\n function Setter() {\n _classCallCheck(this, Setter);\n\n _defineProperty(this, \"subPriority\", 0);\n }\n\n _createClass(Setter, [{\n key: \"validate\",\n value: function validate(_utcDate, _options) {\n return true;\n }\n }]);\n\n return Setter;\n}();\nexport var ValueSetter = /*#__PURE__*/function (_Setter) {\n _inherits(ValueSetter, _Setter);\n\n var _super = _createSuper(ValueSetter);\n\n function ValueSetter(value, validateValue, setValue, priority, subPriority) {\n var _this;\n\n _classCallCheck(this, ValueSetter);\n\n _this = _super.call(this);\n _this.value = value;\n _this.validateValue = validateValue;\n _this.setValue = setValue;\n _this.priority = priority;\n\n if (subPriority) {\n _this.subPriority = subPriority;\n }\n\n return _this;\n }\n\n _createClass(ValueSetter, [{\n key: \"validate\",\n value: function validate(utcDate, options) {\n return this.validateValue(utcDate, this.value, options);\n }\n }, {\n key: \"set\",\n value: function set(utcDate, flags, options) {\n return this.setValue(utcDate, flags, this.value, options);\n }\n }]);\n\n return ValueSetter;\n}(Setter);\nexport var DateToSystemTimezoneSetter = /*#__PURE__*/function (_Setter2) {\n _inherits(DateToSystemTimezoneSetter, _Setter2);\n\n var _super2 = _createSuper(DateToSystemTimezoneSetter);\n\n function DateToSystemTimezoneSetter() {\n var _this2;\n\n _classCallCheck(this, DateToSystemTimezoneSetter);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this2 = _super2.call.apply(_super2, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this2), \"priority\", TIMEZONE_UNIT_PRIORITY);\n\n _defineProperty(_assertThisInitialized(_this2), \"subPriority\", -1);\n\n return _this2;\n }\n\n _createClass(DateToSystemTimezoneSetter, [{\n key: \"set\",\n value: function set(date, flags) {\n if (flags.timestampIsSet) {\n return date;\n }\n\n var convertedDate = new Date(0);\n convertedDate.setFullYear(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());\n convertedDate.setHours(date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());\n return convertedDate;\n }\n }]);\n\n return DateToSystemTimezoneSetter;\n}(Setter);", "function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nimport { ValueSetter } from \"./Setter.js\";\nexport var Parser = /*#__PURE__*/function () {\n function Parser() {\n _classCallCheck(this, Parser);\n }\n\n _createClass(Parser, [{\n key: \"run\",\n value: function run(dateString, token, match, options) {\n var result = this.parse(dateString, token, match, options);\n\n if (!result) {\n return null;\n }\n\n return {\n setter: new ValueSetter(result.value, this.validate, this.set, this.priority, this.subPriority),\n rest: result.rest\n };\n }\n }, {\n key: \"validate\",\n value: function validate(_utcDate, _value, _options) {\n return true;\n }\n }]);\n\n return Parser;\n}();", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nexport var EraParser = /*#__PURE__*/function (_Parser) {\n _inherits(EraParser, _Parser);\n\n var _super = _createSuper(EraParser);\n\n function EraParser() {\n var _this;\n\n _classCallCheck(this, EraParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 140);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['R', 'u', 't', 'T']);\n\n return _this;\n }\n\n _createClass(EraParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n // AD, BC\n case 'G':\n case 'GG':\n case 'GGG':\n return match.era(dateString, {\n width: 'abbreviated'\n }) || match.era(dateString, {\n width: 'narrow'\n });\n // A, B\n\n case 'GGGGG':\n return match.era(dateString, {\n width: 'narrow'\n });\n // Anno Domini, Before Christ\n\n case 'GGGG':\n default:\n return match.era(dateString, {\n width: 'wide'\n }) || match.era(dateString, {\n width: 'abbreviated'\n }) || match.era(dateString, {\n width: 'narrow'\n });\n }\n }\n }, {\n key: \"set\",\n value: function set(date, flags, value) {\n flags.era = value;\n date.setUTCFullYear(value, 0, 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return EraParser;\n}(Parser);", "export var numericPatterns = {\n month: /^(1[0-2]|0?\\d)/,\n // 0 to 12\n date: /^(3[0-1]|[0-2]?\\d)/,\n // 0 to 31\n dayOfYear: /^(36[0-6]|3[0-5]\\d|[0-2]?\\d?\\d)/,\n // 0 to 366\n week: /^(5[0-3]|[0-4]?\\d)/,\n // 0 to 53\n hour23h: /^(2[0-3]|[0-1]?\\d)/,\n // 0 to 23\n hour24h: /^(2[0-4]|[0-1]?\\d)/,\n // 0 to 24\n hour11h: /^(1[0-1]|0?\\d)/,\n // 0 to 11\n hour12h: /^(1[0-2]|0?\\d)/,\n // 0 to 12\n minute: /^[0-5]?\\d/,\n // 0 to 59\n second: /^[0-5]?\\d/,\n // 0 to 59\n singleDigit: /^\\d/,\n // 0 to 9\n twoDigits: /^\\d{1,2}/,\n // 0 to 99\n threeDigits: /^\\d{1,3}/,\n // 0 to 999\n fourDigits: /^\\d{1,4}/,\n // 0 to 9999\n anyDigitsSigned: /^-?\\d+/,\n singleDigitSigned: /^-?\\d/,\n // 0 to 9, -0 to -9\n twoDigitsSigned: /^-?\\d{1,2}/,\n // 0 to 99, -0 to -99\n threeDigitsSigned: /^-?\\d{1,3}/,\n // 0 to 999, -0 to -999\n fourDigitsSigned: /^-?\\d{1,4}/ // 0 to 9999, -0 to -9999\n\n};\nexport var timezonePatterns = {\n basicOptionalMinutes: /^([+-])(\\d{2})(\\d{2})?|Z/,\n basic: /^([+-])(\\d{2})(\\d{2})|Z/,\n basicOptionalSeconds: /^([+-])(\\d{2})(\\d{2})((\\d{2}))?|Z/,\n extended: /^([+-])(\\d{2}):(\\d{2})|Z/,\n extendedOptionalSeconds: /^([+-])(\\d{2}):(\\d{2})(:(\\d{2}))?|Z/\n};", "import { millisecondsInHour, millisecondsInMinute, millisecondsInSecond } from \"../../constants/index.js\";\nimport { numericPatterns } from \"./constants.js\";\nexport function mapValue(parseFnResult, mapFn) {\n if (!parseFnResult) {\n return parseFnResult;\n }\n\n return {\n value: mapFn(parseFnResult.value),\n rest: parseFnResult.rest\n };\n}\nexport function parseNumericPattern(pattern, dateString) {\n var matchResult = dateString.match(pattern);\n\n if (!matchResult) {\n return null;\n }\n\n return {\n value: parseInt(matchResult[0], 10),\n rest: dateString.slice(matchResult[0].length)\n };\n}\nexport function parseTimezonePattern(pattern, dateString) {\n var matchResult = dateString.match(pattern);\n\n if (!matchResult) {\n return null;\n } // Input is 'Z'\n\n\n if (matchResult[0] === 'Z') {\n return {\n value: 0,\n rest: dateString.slice(1)\n };\n }\n\n var sign = matchResult[1] === '+' ? 1 : -1;\n var hours = matchResult[2] ? parseInt(matchResult[2], 10) : 0;\n var minutes = matchResult[3] ? parseInt(matchResult[3], 10) : 0;\n var seconds = matchResult[5] ? parseInt(matchResult[5], 10) : 0;\n return {\n value: sign * (hours * millisecondsInHour + minutes * millisecondsInMinute + seconds * millisecondsInSecond),\n rest: dateString.slice(matchResult[0].length)\n };\n}\nexport function parseAnyDigitsSigned(dateString) {\n return parseNumericPattern(numericPatterns.anyDigitsSigned, dateString);\n}\nexport function parseNDigits(n, dateString) {\n switch (n) {\n case 1:\n return parseNumericPattern(numericPatterns.singleDigit, dateString);\n\n case 2:\n return parseNumericPattern(numericPatterns.twoDigits, dateString);\n\n case 3:\n return parseNumericPattern(numericPatterns.threeDigits, dateString);\n\n case 4:\n return parseNumericPattern(numericPatterns.fourDigits, dateString);\n\n default:\n return parseNumericPattern(new RegExp('^\\\\d{1,' + n + '}'), dateString);\n }\n}\nexport function parseNDigitsSigned(n, dateString) {\n switch (n) {\n case 1:\n return parseNumericPattern(numericPatterns.singleDigitSigned, dateString);\n\n case 2:\n return parseNumericPattern(numericPatterns.twoDigitsSigned, dateString);\n\n case 3:\n return parseNumericPattern(numericPatterns.threeDigitsSigned, dateString);\n\n case 4:\n return parseNumericPattern(numericPatterns.fourDigitsSigned, dateString);\n\n default:\n return parseNumericPattern(new RegExp('^-?\\\\d{1,' + n + '}'), dateString);\n }\n}\nexport function dayPeriodEnumToHours(dayPeriod) {\n switch (dayPeriod) {\n case 'morning':\n return 4;\n\n case 'evening':\n return 17;\n\n case 'pm':\n case 'noon':\n case 'afternoon':\n return 12;\n\n case 'am':\n case 'midnight':\n case 'night':\n default:\n return 0;\n }\n}\nexport function normalizeTwoDigitYear(twoDigitYear, currentYear) {\n var isCommonEra = currentYear > 0; // Absolute number of the current year:\n // 1 -> 1 AC\n // 0 -> 1 BC\n // -1 -> 2 BC\n\n var absCurrentYear = isCommonEra ? currentYear : 1 - currentYear;\n var result;\n\n if (absCurrentYear <= 50) {\n result = twoDigitYear || 100;\n } else {\n var rangeEnd = absCurrentYear + 50;\n var rangeEndCentury = Math.floor(rangeEnd / 100) * 100;\n var isPreviousCentury = twoDigitYear >= rangeEnd % 100;\n result = twoDigitYear + rangeEndCentury - (isPreviousCentury ? 100 : 0);\n }\n\n return isCommonEra ? result : 1 - result;\n}\nexport function isLeapYearIndex(year) {\n return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { mapValue, normalizeTwoDigitYear, parseNDigits } from \"../utils.js\";\n// From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns\n// | Year | y | yy | yyy | yyyy | yyyyy |\n// |----------|-------|----|-------|-------|-------|\n// | AD 1 | 1 | 01 | 001 | 0001 | 00001 |\n// | AD 12 | 12 | 12 | 012 | 0012 | 00012 |\n// | AD 123 | 123 | 23 | 123 | 0123 | 00123 |\n// | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |\n// | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |\nexport var YearParser = /*#__PURE__*/function (_Parser) {\n _inherits(YearParser, _Parser);\n\n var _super = _createSuper(YearParser);\n\n function YearParser() {\n var _this;\n\n _classCallCheck(this, YearParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 130);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['Y', 'R', 'u', 'w', 'I', 'i', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(YearParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n var valueCallback = function valueCallback(year) {\n return {\n year: year,\n isTwoDigitYear: token === 'yy'\n };\n };\n\n switch (token) {\n case 'y':\n return mapValue(parseNDigits(4, dateString), valueCallback);\n\n case 'yo':\n return mapValue(match.ordinalNumber(dateString, {\n unit: 'year'\n }), valueCallback);\n\n default:\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value.isTwoDigitYear || value.year > 0;\n }\n }, {\n key: \"set\",\n value: function set(date, flags, value) {\n var currentYear = date.getUTCFullYear();\n\n if (value.isTwoDigitYear) {\n var normalizedTwoDigitYear = normalizeTwoDigitYear(value.year, currentYear);\n date.setUTCFullYear(normalizedTwoDigitYear, 0, 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n\n var year = !('era' in flags) || flags.era === 1 ? value.year : 1 - value.year;\n date.setUTCFullYear(year, 0, 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return YearParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { parseNDigits, normalizeTwoDigitYear, mapValue } from \"../utils.js\";\nimport getUTCWeekYear from \"../../../_lib/getUTCWeekYear/index.js\";\nimport startOfUTCWeek from \"../../../_lib/startOfUTCWeek/index.js\";\n// Local week-numbering year\nexport var LocalWeekYearParser = /*#__PURE__*/function (_Parser) {\n _inherits(LocalWeekYearParser, _Parser);\n\n var _super = _createSuper(LocalWeekYearParser);\n\n function LocalWeekYearParser() {\n var _this;\n\n _classCallCheck(this, LocalWeekYearParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 130);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['y', 'R', 'u', 'Q', 'q', 'M', 'L', 'I', 'd', 'D', 'i', 't', 'T']);\n\n return _this;\n }\n\n _createClass(LocalWeekYearParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n var valueCallback = function valueCallback(year) {\n return {\n year: year,\n isTwoDigitYear: token === 'YY'\n };\n };\n\n switch (token) {\n case 'Y':\n return mapValue(parseNDigits(4, dateString), valueCallback);\n\n case 'Yo':\n return mapValue(match.ordinalNumber(dateString, {\n unit: 'year'\n }), valueCallback);\n\n default:\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value.isTwoDigitYear || value.year > 0;\n }\n }, {\n key: \"set\",\n value: function set(date, flags, value, options) {\n var currentYear = getUTCWeekYear(date, options);\n\n if (value.isTwoDigitYear) {\n var normalizedTwoDigitYear = normalizeTwoDigitYear(value.year, currentYear);\n date.setUTCFullYear(normalizedTwoDigitYear, 0, options.firstWeekContainsDate);\n date.setUTCHours(0, 0, 0, 0);\n return startOfUTCWeek(date, options);\n }\n\n var year = !('era' in flags) || flags.era === 1 ? value.year : 1 - value.year;\n date.setUTCFullYear(year, 0, options.firstWeekContainsDate);\n date.setUTCHours(0, 0, 0, 0);\n return startOfUTCWeek(date, options);\n }\n }]);\n\n return LocalWeekYearParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { parseNDigitsSigned } from \"../utils.js\";\nimport startOfUTCISOWeek from \"../../../_lib/startOfUTCISOWeek/index.js\"; // ISO week-numbering year\n\nexport var ISOWeekYearParser = /*#__PURE__*/function (_Parser) {\n _inherits(ISOWeekYearParser, _Parser);\n\n var _super = _createSuper(ISOWeekYearParser);\n\n function ISOWeekYearParser() {\n var _this;\n\n _classCallCheck(this, ISOWeekYearParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 130);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['G', 'y', 'Y', 'u', 'Q', 'q', 'M', 'L', 'w', 'd', 'D', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(ISOWeekYearParser, [{\n key: \"parse\",\n value: function parse(dateString, token) {\n if (token === 'R') {\n return parseNDigitsSigned(4, dateString);\n }\n\n return parseNDigitsSigned(token.length, dateString);\n }\n }, {\n key: \"set\",\n value: function set(_date, _flags, value) {\n var firstWeekOfYear = new Date(0);\n firstWeekOfYear.setUTCFullYear(value, 0, 4);\n firstWeekOfYear.setUTCHours(0, 0, 0, 0);\n return startOfUTCISOWeek(firstWeekOfYear);\n }\n }]);\n\n return ISOWeekYearParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { parseNDigitsSigned } from \"../utils.js\";\nexport var ExtendedYearParser = /*#__PURE__*/function (_Parser) {\n _inherits(ExtendedYearParser, _Parser);\n\n var _super = _createSuper(ExtendedYearParser);\n\n function ExtendedYearParser() {\n var _this;\n\n _classCallCheck(this, ExtendedYearParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 130);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['G', 'y', 'Y', 'R', 'w', 'I', 'i', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(ExtendedYearParser, [{\n key: \"parse\",\n value: function parse(dateString, token) {\n if (token === 'u') {\n return parseNDigitsSigned(4, dateString);\n }\n\n return parseNDigitsSigned(token.length, dateString);\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCFullYear(value, 0, 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return ExtendedYearParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { parseNDigits } from \"../utils.js\";\nexport var QuarterParser = /*#__PURE__*/function (_Parser) {\n _inherits(QuarterParser, _Parser);\n\n var _super = _createSuper(QuarterParser);\n\n function QuarterParser() {\n var _this;\n\n _classCallCheck(this, QuarterParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 120);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['Y', 'R', 'q', 'M', 'L', 'w', 'I', 'd', 'D', 'i', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(QuarterParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n // 1, 2, 3, 4\n case 'Q':\n case 'QQ':\n // 01, 02, 03, 04\n return parseNDigits(token.length, dateString);\n // 1st, 2nd, 3rd, 4th\n\n case 'Qo':\n return match.ordinalNumber(dateString, {\n unit: 'quarter'\n });\n // Q1, Q2, Q3, Q4\n\n case 'QQQ':\n return match.quarter(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.quarter(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n\n case 'QQQQQ':\n return match.quarter(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // 1st quarter, 2nd quarter, ...\n\n case 'QQQQ':\n default:\n return match.quarter(dateString, {\n width: 'wide',\n context: 'formatting'\n }) || match.quarter(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.quarter(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 1 && value <= 4;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCMonth((value - 1) * 3, 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return QuarterParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { parseNDigits } from \"../utils.js\";\nexport var StandAloneQuarterParser = /*#__PURE__*/function (_Parser) {\n _inherits(StandAloneQuarterParser, _Parser);\n\n var _super = _createSuper(StandAloneQuarterParser);\n\n function StandAloneQuarterParser() {\n var _this;\n\n _classCallCheck(this, StandAloneQuarterParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 120);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['Y', 'R', 'Q', 'M', 'L', 'w', 'I', 'd', 'D', 'i', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(StandAloneQuarterParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n // 1, 2, 3, 4\n case 'q':\n case 'qq':\n // 01, 02, 03, 04\n return parseNDigits(token.length, dateString);\n // 1st, 2nd, 3rd, 4th\n\n case 'qo':\n return match.ordinalNumber(dateString, {\n unit: 'quarter'\n });\n // Q1, Q2, Q3, Q4\n\n case 'qqq':\n return match.quarter(dateString, {\n width: 'abbreviated',\n context: 'standalone'\n }) || match.quarter(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n // 1, 2, 3, 4 (narrow quarter; could be not numerical)\n\n case 'qqqqq':\n return match.quarter(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n // 1st quarter, 2nd quarter, ...\n\n case 'qqqq':\n default:\n return match.quarter(dateString, {\n width: 'wide',\n context: 'standalone'\n }) || match.quarter(dateString, {\n width: 'abbreviated',\n context: 'standalone'\n }) || match.quarter(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 1 && value <= 4;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCMonth((value - 1) * 3, 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return StandAloneQuarterParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { mapValue, parseNDigits, parseNumericPattern } from \"../utils.js\";\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nexport var MonthParser = /*#__PURE__*/function (_Parser) {\n _inherits(MonthParser, _Parser);\n\n var _super = _createSuper(MonthParser);\n\n function MonthParser() {\n var _this;\n\n _classCallCheck(this, MonthParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['Y', 'R', 'q', 'Q', 'L', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']);\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 110);\n\n return _this;\n }\n\n _createClass(MonthParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n var valueCallback = function valueCallback(value) {\n return value - 1;\n };\n\n switch (token) {\n // 1, 2, ..., 12\n case 'M':\n return mapValue(parseNumericPattern(numericPatterns.month, dateString), valueCallback);\n // 01, 02, ..., 12\n\n case 'MM':\n return mapValue(parseNDigits(2, dateString), valueCallback);\n // 1st, 2nd, ..., 12th\n\n case 'Mo':\n return mapValue(match.ordinalNumber(dateString, {\n unit: 'month'\n }), valueCallback);\n // Jan, Feb, ..., Dec\n\n case 'MMM':\n return match.month(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.month(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // J, F, ..., D\n\n case 'MMMMM':\n return match.month(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // January, February, ..., December\n\n case 'MMMM':\n default:\n return match.month(dateString, {\n width: 'wide',\n context: 'formatting'\n }) || match.month(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.month(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCMonth(value, 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return MonthParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits, mapValue } from \"../utils.js\";\nexport var StandAloneMonthParser = /*#__PURE__*/function (_Parser) {\n _inherits(StandAloneMonthParser, _Parser);\n\n var _super = _createSuper(StandAloneMonthParser);\n\n function StandAloneMonthParser() {\n var _this;\n\n _classCallCheck(this, StandAloneMonthParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 110);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['Y', 'R', 'q', 'Q', 'M', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(StandAloneMonthParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n var valueCallback = function valueCallback(value) {\n return value - 1;\n };\n\n switch (token) {\n // 1, 2, ..., 12\n case 'L':\n return mapValue(parseNumericPattern(numericPatterns.month, dateString), valueCallback);\n // 01, 02, ..., 12\n\n case 'LL':\n return mapValue(parseNDigits(2, dateString), valueCallback);\n // 1st, 2nd, ..., 12th\n\n case 'Lo':\n return mapValue(match.ordinalNumber(dateString, {\n unit: 'month'\n }), valueCallback);\n // Jan, Feb, ..., Dec\n\n case 'LLL':\n return match.month(dateString, {\n width: 'abbreviated',\n context: 'standalone'\n }) || match.month(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n // J, F, ..., D\n\n case 'LLLLL':\n return match.month(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n // January, February, ..., December\n\n case 'LLLL':\n default:\n return match.month(dateString, {\n width: 'wide',\n context: 'standalone'\n }) || match.month(dateString, {\n width: 'abbreviated',\n context: 'standalone'\n }) || match.month(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCMonth(value, 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return StandAloneMonthParser;\n}(Parser);", "import toInteger from \"../toInteger/index.js\";\nimport toDate from \"../../toDate/index.js\";\nimport getUTCWeek from \"../getUTCWeek/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nexport default function setUTCWeek(dirtyDate, dirtyWeek, options) {\n requiredArgs(2, arguments);\n var date = toDate(dirtyDate);\n var week = toInteger(dirtyWeek);\n var diff = getUTCWeek(date, options) - week;\n date.setUTCDate(date.getUTCDate() - diff * 7);\n return date;\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits } from \"../utils.js\";\nimport setUTCWeek from \"../../../_lib/setUTCWeek/index.js\";\nimport startOfUTCWeek from \"../../../_lib/startOfUTCWeek/index.js\"; // Local week of year\n\nexport var LocalWeekParser = /*#__PURE__*/function (_Parser) {\n _inherits(LocalWeekParser, _Parser);\n\n var _super = _createSuper(LocalWeekParser);\n\n function LocalWeekParser() {\n var _this;\n\n _classCallCheck(this, LocalWeekParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 100);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'i', 't', 'T']);\n\n return _this;\n }\n\n _createClass(LocalWeekParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'w':\n return parseNumericPattern(numericPatterns.week, dateString);\n\n case 'wo':\n return match.ordinalNumber(dateString, {\n unit: 'week'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 1 && value <= 53;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value, options) {\n return startOfUTCWeek(setUTCWeek(date, value, options), options);\n }\n }]);\n\n return LocalWeekParser;\n}(Parser);", "import toInteger from \"../toInteger/index.js\";\nimport toDate from \"../../toDate/index.js\";\nimport getUTCISOWeek from \"../getUTCISOWeek/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nexport default function setUTCISOWeek(dirtyDate, dirtyISOWeek) {\n requiredArgs(2, arguments);\n var date = toDate(dirtyDate);\n var isoWeek = toInteger(dirtyISOWeek);\n var diff = getUTCISOWeek(date) - isoWeek;\n date.setUTCDate(date.getUTCDate() - diff * 7);\n return date;\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits } from \"../utils.js\";\nimport setUTCISOWeek from \"../../../_lib/setUTCISOWeek/index.js\";\nimport startOfUTCISOWeek from \"../../../_lib/startOfUTCISOWeek/index.js\"; // ISO week of year\n\nexport var ISOWeekParser = /*#__PURE__*/function (_Parser) {\n _inherits(ISOWeekParser, _Parser);\n\n var _super = _createSuper(ISOWeekParser);\n\n function ISOWeekParser() {\n var _this;\n\n _classCallCheck(this, ISOWeekParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 100);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['y', 'Y', 'u', 'q', 'Q', 'M', 'L', 'w', 'd', 'D', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(ISOWeekParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'I':\n return parseNumericPattern(numericPatterns.week, dateString);\n\n case 'Io':\n return match.ordinalNumber(dateString, {\n unit: 'week'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 1 && value <= 53;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n return startOfUTCISOWeek(setUTCISOWeek(date, value));\n }\n }]);\n\n return ISOWeekParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { isLeapYearIndex, parseNDigits, parseNumericPattern } from \"../utils.js\";\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nvar DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\nvar DAYS_IN_MONTH_LEAP_YEAR = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // Day of the month\n\nexport var DateParser = /*#__PURE__*/function (_Parser) {\n _inherits(DateParser, _Parser);\n\n var _super = _createSuper(DateParser);\n\n function DateParser() {\n var _this;\n\n _classCallCheck(this, DateParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 90);\n\n _defineProperty(_assertThisInitialized(_this), \"subPriority\", 1);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['Y', 'R', 'q', 'Q', 'w', 'I', 'D', 'i', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(DateParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'd':\n return parseNumericPattern(numericPatterns.date, dateString);\n\n case 'do':\n return match.ordinalNumber(dateString, {\n unit: 'date'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(date, value) {\n var year = date.getUTCFullYear();\n var isLeapYear = isLeapYearIndex(year);\n var month = date.getUTCMonth();\n\n if (isLeapYear) {\n return value >= 1 && value <= DAYS_IN_MONTH_LEAP_YEAR[month];\n } else {\n return value >= 1 && value <= DAYS_IN_MONTH[month];\n }\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCDate(value);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return DateParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits, isLeapYearIndex } from \"../utils.js\";\nexport var DayOfYearParser = /*#__PURE__*/function (_Parser) {\n _inherits(DayOfYearParser, _Parser);\n\n var _super = _createSuper(DayOfYearParser);\n\n function DayOfYearParser() {\n var _this;\n\n _classCallCheck(this, DayOfYearParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 90);\n\n _defineProperty(_assertThisInitialized(_this), \"subpriority\", 1);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['Y', 'R', 'q', 'Q', 'M', 'L', 'w', 'I', 'd', 'E', 'i', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(DayOfYearParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'D':\n case 'DD':\n return parseNumericPattern(numericPatterns.dayOfYear, dateString);\n\n case 'Do':\n return match.ordinalNumber(dateString, {\n unit: 'date'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(date, value) {\n var year = date.getUTCFullYear();\n var isLeapYear = isLeapYearIndex(year);\n\n if (isLeapYear) {\n return value >= 1 && value <= 366;\n } else {\n return value >= 1 && value <= 365;\n }\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCMonth(0, value);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return DayOfYearParser;\n}(Parser);", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nimport toInteger from \"../toInteger/index.js\";\nimport { getDefaultOptions } from \"../defaultOptions/index.js\";\nexport default function setUTCDay(dirtyDate, dirtyDay, options) {\n var _ref, _ref2, _ref3, _options$weekStartsOn, _options$locale, _options$locale$optio, _defaultOptions$local, _defaultOptions$local2;\n\n requiredArgs(2, arguments);\n var defaultOptions = getDefaultOptions();\n var weekStartsOn = toInteger((_ref = (_ref2 = (_ref3 = (_options$weekStartsOn = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : options === null || options === void 0 ? void 0 : (_options$locale = options.locale) === null || _options$locale === void 0 ? void 0 : (_options$locale$optio = _options$locale.options) === null || _options$locale$optio === void 0 ? void 0 : _options$locale$optio.weekStartsOn) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.weekStartsOn) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.weekStartsOn) !== null && _ref !== void 0 ? _ref : 0); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN\n\n if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {\n throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');\n }\n\n var date = toDate(dirtyDate);\n var day = toInteger(dirtyDay);\n var currentDay = date.getUTCDay();\n var remainder = day % 7;\n var dayIndex = (remainder + 7) % 7;\n var diff = (dayIndex < weekStartsOn ? 7 : 0) + day - currentDay;\n date.setUTCDate(date.getUTCDate() + diff);\n return date;\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport setUTCDay from \"../../../_lib/setUTCDay/index.js\"; // Day of week\n\nexport var DayParser = /*#__PURE__*/function (_Parser) {\n _inherits(DayParser, _Parser);\n\n var _super = _createSuper(DayParser);\n\n function DayParser() {\n var _this;\n\n _classCallCheck(this, DayParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 90);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['D', 'i', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(DayParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n // Tue\n case 'E':\n case 'EE':\n case 'EEE':\n return match.day(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // T\n\n case 'EEEEE':\n return match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // Tu\n\n case 'EEEEEE':\n return match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // Tuesday\n\n case 'EEEE':\n default:\n return match.day(dateString, {\n width: 'wide',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value, options) {\n date = setUTCDay(date, value, options);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return DayParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { mapValue, parseNDigits } from \"../utils.js\";\nimport setUTCDay from \"../../../_lib/setUTCDay/index.js\"; // Local day of week\n\nexport var LocalDayParser = /*#__PURE__*/function (_Parser) {\n _inherits(LocalDayParser, _Parser);\n\n var _super = _createSuper(LocalDayParser);\n\n function LocalDayParser() {\n var _this;\n\n _classCallCheck(this, LocalDayParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 90);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'E', 'i', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(LocalDayParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match, options) {\n var valueCallback = function valueCallback(value) {\n var wholeWeekDays = Math.floor((value - 1) / 7) * 7;\n return (value + options.weekStartsOn + 6) % 7 + wholeWeekDays;\n };\n\n switch (token) {\n // 3\n case 'e':\n case 'ee':\n // 03\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n // 3rd\n\n case 'eo':\n return mapValue(match.ordinalNumber(dateString, {\n unit: 'day'\n }), valueCallback);\n // Tue\n\n case 'eee':\n return match.day(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // T\n\n case 'eeeee':\n return match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // Tu\n\n case 'eeeeee':\n return match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n // Tuesday\n\n case 'eeee':\n default:\n return match.day(dateString, {\n width: 'wide',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value, options) {\n date = setUTCDay(date, value, options);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return LocalDayParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { mapValue, parseNDigits } from \"../utils.js\";\nimport setUTCDay from \"../../../_lib/setUTCDay/index.js\"; // Stand-alone local day of week\n\nexport var StandAloneLocalDayParser = /*#__PURE__*/function (_Parser) {\n _inherits(StandAloneLocalDayParser, _Parser);\n\n var _super = _createSuper(StandAloneLocalDayParser);\n\n function StandAloneLocalDayParser() {\n var _this;\n\n _classCallCheck(this, StandAloneLocalDayParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 90);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['y', 'R', 'u', 'q', 'Q', 'M', 'L', 'I', 'd', 'D', 'E', 'i', 'e', 't', 'T']);\n\n return _this;\n }\n\n _createClass(StandAloneLocalDayParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match, options) {\n var valueCallback = function valueCallback(value) {\n var wholeWeekDays = Math.floor((value - 1) / 7) * 7;\n return (value + options.weekStartsOn + 6) % 7 + wholeWeekDays;\n };\n\n switch (token) {\n // 3\n case 'c':\n case 'cc':\n // 03\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n // 3rd\n\n case 'co':\n return mapValue(match.ordinalNumber(dateString, {\n unit: 'day'\n }), valueCallback);\n // Tue\n\n case 'ccc':\n return match.day(dateString, {\n width: 'abbreviated',\n context: 'standalone'\n }) || match.day(dateString, {\n width: 'short',\n context: 'standalone'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n // T\n\n case 'ccccc':\n return match.day(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n // Tu\n\n case 'cccccc':\n return match.day(dateString, {\n width: 'short',\n context: 'standalone'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n // Tuesday\n\n case 'cccc':\n default:\n return match.day(dateString, {\n width: 'wide',\n context: 'standalone'\n }) || match.day(dateString, {\n width: 'abbreviated',\n context: 'standalone'\n }) || match.day(dateString, {\n width: 'short',\n context: 'standalone'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'standalone'\n });\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 6;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value, options) {\n date = setUTCDay(date, value, options);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return StandAloneLocalDayParser;\n}(Parser);", "import toDate from \"../../toDate/index.js\";\nimport requiredArgs from \"../requiredArgs/index.js\";\nimport toInteger from \"../toInteger/index.js\";\nexport default function setUTCISODay(dirtyDate, dirtyDay) {\n requiredArgs(2, arguments);\n var day = toInteger(dirtyDay);\n\n if (day % 7 === 0) {\n day = day - 7;\n }\n\n var weekStartsOn = 1;\n var date = toDate(dirtyDate);\n var currentDay = date.getUTCDay();\n var remainder = day % 7;\n var dayIndex = (remainder + 7) % 7;\n var diff = (dayIndex < weekStartsOn ? 7 : 0) + day - currentDay;\n date.setUTCDate(date.getUTCDate() + diff);\n return date;\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { mapValue, parseNDigits } from \"../utils.js\";\nimport setUTCISODay from \"../../../_lib/setUTCISODay/index.js\"; // ISO day of week\n\nexport var ISODayParser = /*#__PURE__*/function (_Parser) {\n _inherits(ISODayParser, _Parser);\n\n var _super = _createSuper(ISODayParser);\n\n function ISODayParser() {\n var _this;\n\n _classCallCheck(this, ISODayParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 90);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['y', 'Y', 'u', 'q', 'Q', 'M', 'L', 'w', 'd', 'D', 'E', 'e', 'c', 't', 'T']);\n\n return _this;\n }\n\n _createClass(ISODayParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n var valueCallback = function valueCallback(value) {\n if (value === 0) {\n return 7;\n }\n\n return value;\n };\n\n switch (token) {\n // 2\n case 'i':\n case 'ii':\n // 02\n return parseNDigits(token.length, dateString);\n // 2nd\n\n case 'io':\n return match.ordinalNumber(dateString, {\n unit: 'day'\n });\n // Tue\n\n case 'iii':\n return mapValue(match.day(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n }), valueCallback);\n // T\n\n case 'iiiii':\n return mapValue(match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n }), valueCallback);\n // Tu\n\n case 'iiiiii':\n return mapValue(match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n }), valueCallback);\n // Tuesday\n\n case 'iiii':\n default:\n return mapValue(match.day(dateString, {\n width: 'wide',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'short',\n context: 'formatting'\n }) || match.day(dateString, {\n width: 'narrow',\n context: 'formatting'\n }), valueCallback);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 1 && value <= 7;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date = setUTCISODay(date, value);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n }]);\n\n return ISODayParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { dayPeriodEnumToHours } from \"../utils.js\";\nexport var AMPMParser = /*#__PURE__*/function (_Parser) {\n _inherits(AMPMParser, _Parser);\n\n var _super = _createSuper(AMPMParser);\n\n function AMPMParser() {\n var _this;\n\n _classCallCheck(this, AMPMParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 80);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['b', 'B', 'H', 'k', 't', 'T']);\n\n return _this;\n }\n\n _createClass(AMPMParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'a':\n case 'aa':\n case 'aaa':\n return match.dayPeriod(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'aaaaa':\n return match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'aaaa':\n default:\n return match.dayPeriod(dateString, {\n width: 'wide',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n }\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n }]);\n\n return AMPMParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { dayPeriodEnumToHours } from \"../utils.js\";\nexport var AMPMMidnightParser = /*#__PURE__*/function (_Parser) {\n _inherits(AMPMMidnightParser, _Parser);\n\n var _super = _createSuper(AMPMMidnightParser);\n\n function AMPMMidnightParser() {\n var _this;\n\n _classCallCheck(this, AMPMMidnightParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 80);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['a', 'B', 'H', 'k', 't', 'T']);\n\n return _this;\n }\n\n _createClass(AMPMMidnightParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'b':\n case 'bb':\n case 'bbb':\n return match.dayPeriod(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'bbbbb':\n return match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'bbbb':\n default:\n return match.dayPeriod(dateString, {\n width: 'wide',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n }\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n }]);\n\n return AMPMMidnightParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { dayPeriodEnumToHours } from \"../utils.js\"; // in the morning, in the afternoon, in the evening, at night\n\nexport var DayPeriodParser = /*#__PURE__*/function (_Parser) {\n _inherits(DayPeriodParser, _Parser);\n\n var _super = _createSuper(DayPeriodParser);\n\n function DayPeriodParser() {\n var _this;\n\n _classCallCheck(this, DayPeriodParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 80);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['a', 'b', 't', 'T']);\n\n return _this;\n }\n\n _createClass(DayPeriodParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'B':\n case 'BB':\n case 'BBB':\n return match.dayPeriod(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'BBBBB':\n return match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n\n case 'BBBB':\n default:\n return match.dayPeriod(dateString, {\n width: 'wide',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'abbreviated',\n context: 'formatting'\n }) || match.dayPeriod(dateString, {\n width: 'narrow',\n context: 'formatting'\n });\n }\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCHours(dayPeriodEnumToHours(value), 0, 0, 0);\n return date;\n }\n }]);\n\n return DayPeriodParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits } from \"../utils.js\";\nexport var Hour1to12Parser = /*#__PURE__*/function (_Parser) {\n _inherits(Hour1to12Parser, _Parser);\n\n var _super = _createSuper(Hour1to12Parser);\n\n function Hour1to12Parser() {\n var _this;\n\n _classCallCheck(this, Hour1to12Parser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 70);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['H', 'K', 'k', 't', 'T']);\n\n return _this;\n }\n\n _createClass(Hour1to12Parser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'h':\n return parseNumericPattern(numericPatterns.hour12h, dateString);\n\n case 'ho':\n return match.ordinalNumber(dateString, {\n unit: 'hour'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 1 && value <= 12;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n var isPM = date.getUTCHours() >= 12;\n\n if (isPM && value < 12) {\n date.setUTCHours(value + 12, 0, 0, 0);\n } else if (!isPM && value === 12) {\n date.setUTCHours(0, 0, 0, 0);\n } else {\n date.setUTCHours(value, 0, 0, 0);\n }\n\n return date;\n }\n }]);\n\n return Hour1to12Parser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits } from \"../utils.js\";\nexport var Hour0to23Parser = /*#__PURE__*/function (_Parser) {\n _inherits(Hour0to23Parser, _Parser);\n\n var _super = _createSuper(Hour0to23Parser);\n\n function Hour0to23Parser() {\n var _this;\n\n _classCallCheck(this, Hour0to23Parser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 70);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['a', 'b', 'h', 'K', 'k', 't', 'T']);\n\n return _this;\n }\n\n _createClass(Hour0to23Parser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'H':\n return parseNumericPattern(numericPatterns.hour23h, dateString);\n\n case 'Ho':\n return match.ordinalNumber(dateString, {\n unit: 'hour'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 23;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCHours(value, 0, 0, 0);\n return date;\n }\n }]);\n\n return Hour0to23Parser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits } from \"../utils.js\";\nexport var Hour0To11Parser = /*#__PURE__*/function (_Parser) {\n _inherits(Hour0To11Parser, _Parser);\n\n var _super = _createSuper(Hour0To11Parser);\n\n function Hour0To11Parser() {\n var _this;\n\n _classCallCheck(this, Hour0To11Parser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 70);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['h', 'H', 'k', 't', 'T']);\n\n return _this;\n }\n\n _createClass(Hour0To11Parser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'K':\n return parseNumericPattern(numericPatterns.hour11h, dateString);\n\n case 'Ko':\n return match.ordinalNumber(dateString, {\n unit: 'hour'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 11;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n var isPM = date.getUTCHours() >= 12;\n\n if (isPM && value < 12) {\n date.setUTCHours(value + 12, 0, 0, 0);\n } else {\n date.setUTCHours(value, 0, 0, 0);\n }\n\n return date;\n }\n }]);\n\n return Hour0To11Parser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits } from \"../utils.js\";\nexport var Hour1To24Parser = /*#__PURE__*/function (_Parser) {\n _inherits(Hour1To24Parser, _Parser);\n\n var _super = _createSuper(Hour1To24Parser);\n\n function Hour1To24Parser() {\n var _this;\n\n _classCallCheck(this, Hour1To24Parser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 70);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['a', 'b', 'h', 'H', 'K', 't', 'T']);\n\n return _this;\n }\n\n _createClass(Hour1To24Parser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'k':\n return parseNumericPattern(numericPatterns.hour24h, dateString);\n\n case 'ko':\n return match.ordinalNumber(dateString, {\n unit: 'hour'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 1 && value <= 24;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n var hours = value <= 24 ? value % 24 : value;\n date.setUTCHours(hours, 0, 0, 0);\n return date;\n }\n }]);\n\n return Hour1To24Parser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits } from \"../utils.js\";\nexport var MinuteParser = /*#__PURE__*/function (_Parser) {\n _inherits(MinuteParser, _Parser);\n\n var _super = _createSuper(MinuteParser);\n\n function MinuteParser() {\n var _this;\n\n _classCallCheck(this, MinuteParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 60);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['t', 'T']);\n\n return _this;\n }\n\n _createClass(MinuteParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 'm':\n return parseNumericPattern(numericPatterns.minute, dateString);\n\n case 'mo':\n return match.ordinalNumber(dateString, {\n unit: 'minute'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 59;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCMinutes(value, 0, 0);\n return date;\n }\n }]);\n\n return MinuteParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { numericPatterns } from \"../constants.js\";\nimport { parseNumericPattern, parseNDigits } from \"../utils.js\";\nexport var SecondParser = /*#__PURE__*/function (_Parser) {\n _inherits(SecondParser, _Parser);\n\n var _super = _createSuper(SecondParser);\n\n function SecondParser() {\n var _this;\n\n _classCallCheck(this, SecondParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 50);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['t', 'T']);\n\n return _this;\n }\n\n _createClass(SecondParser, [{\n key: \"parse\",\n value: function parse(dateString, token, match) {\n switch (token) {\n case 's':\n return parseNumericPattern(numericPatterns.second, dateString);\n\n case 'so':\n return match.ordinalNumber(dateString, {\n unit: 'second'\n });\n\n default:\n return parseNDigits(token.length, dateString);\n }\n }\n }, {\n key: \"validate\",\n value: function validate(_date, value) {\n return value >= 0 && value <= 59;\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCSeconds(value, 0);\n return date;\n }\n }]);\n\n return SecondParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { mapValue, parseNDigits } from \"../utils.js\";\nexport var FractionOfSecondParser = /*#__PURE__*/function (_Parser) {\n _inherits(FractionOfSecondParser, _Parser);\n\n var _super = _createSuper(FractionOfSecondParser);\n\n function FractionOfSecondParser() {\n var _this;\n\n _classCallCheck(this, FractionOfSecondParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 30);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['t', 'T']);\n\n return _this;\n }\n\n _createClass(FractionOfSecondParser, [{\n key: \"parse\",\n value: function parse(dateString, token) {\n var valueCallback = function valueCallback(value) {\n return Math.floor(value * Math.pow(10, -token.length + 3));\n };\n\n return mapValue(parseNDigits(token.length, dateString), valueCallback);\n }\n }, {\n key: \"set\",\n value: function set(date, _flags, value) {\n date.setUTCMilliseconds(value);\n return date;\n }\n }]);\n\n return FractionOfSecondParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { timezonePatterns } from \"../constants.js\";\nimport { parseTimezonePattern } from \"../utils.js\"; // Timezone (ISO-8601. +00:00 is `'Z'`)\n\nexport var ISOTimezoneWithZParser = /*#__PURE__*/function (_Parser) {\n _inherits(ISOTimezoneWithZParser, _Parser);\n\n var _super = _createSuper(ISOTimezoneWithZParser);\n\n function ISOTimezoneWithZParser() {\n var _this;\n\n _classCallCheck(this, ISOTimezoneWithZParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 10);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['t', 'T', 'x']);\n\n return _this;\n }\n\n _createClass(ISOTimezoneWithZParser, [{\n key: \"parse\",\n value: function parse(dateString, token) {\n switch (token) {\n case 'X':\n return parseTimezonePattern(timezonePatterns.basicOptionalMinutes, dateString);\n\n case 'XX':\n return parseTimezonePattern(timezonePatterns.basic, dateString);\n\n case 'XXXX':\n return parseTimezonePattern(timezonePatterns.basicOptionalSeconds, dateString);\n\n case 'XXXXX':\n return parseTimezonePattern(timezonePatterns.extendedOptionalSeconds, dateString);\n\n case 'XXX':\n default:\n return parseTimezonePattern(timezonePatterns.extended, dateString);\n }\n }\n }, {\n key: \"set\",\n value: function set(date, flags, value) {\n if (flags.timestampIsSet) {\n return date;\n }\n\n return new Date(date.getTime() - value);\n }\n }]);\n\n return ISOTimezoneWithZParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { timezonePatterns } from \"../constants.js\";\nimport { parseTimezonePattern } from \"../utils.js\"; // Timezone (ISO-8601)\n\nexport var ISOTimezoneParser = /*#__PURE__*/function (_Parser) {\n _inherits(ISOTimezoneParser, _Parser);\n\n var _super = _createSuper(ISOTimezoneParser);\n\n function ISOTimezoneParser() {\n var _this;\n\n _classCallCheck(this, ISOTimezoneParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 10);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", ['t', 'T', 'X']);\n\n return _this;\n }\n\n _createClass(ISOTimezoneParser, [{\n key: \"parse\",\n value: function parse(dateString, token) {\n switch (token) {\n case 'x':\n return parseTimezonePattern(timezonePatterns.basicOptionalMinutes, dateString);\n\n case 'xx':\n return parseTimezonePattern(timezonePatterns.basic, dateString);\n\n case 'xxxx':\n return parseTimezonePattern(timezonePatterns.basicOptionalSeconds, dateString);\n\n case 'xxxxx':\n return parseTimezonePattern(timezonePatterns.extendedOptionalSeconds, dateString);\n\n case 'xxx':\n default:\n return parseTimezonePattern(timezonePatterns.extended, dateString);\n }\n }\n }, {\n key: \"set\",\n value: function set(date, flags, value) {\n if (flags.timestampIsSet) {\n return date;\n }\n\n return new Date(date.getTime() - value);\n }\n }]);\n\n return ISOTimezoneParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { parseAnyDigitsSigned } from \"../utils.js\";\nexport var TimestampSecondsParser = /*#__PURE__*/function (_Parser) {\n _inherits(TimestampSecondsParser, _Parser);\n\n var _super = _createSuper(TimestampSecondsParser);\n\n function TimestampSecondsParser() {\n var _this;\n\n _classCallCheck(this, TimestampSecondsParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 40);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", '*');\n\n return _this;\n }\n\n _createClass(TimestampSecondsParser, [{\n key: \"parse\",\n value: function parse(dateString) {\n return parseAnyDigitsSigned(dateString);\n }\n }, {\n key: \"set\",\n value: function set(_date, _flags, value) {\n return [new Date(value * 1000), {\n timestampIsSet: true\n }];\n }\n }]);\n\n return TimestampSecondsParser;\n}(Parser);", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nimport { Parser } from \"../Parser.js\";\nimport { parseAnyDigitsSigned } from \"../utils.js\";\nexport var TimestampMillisecondsParser = /*#__PURE__*/function (_Parser) {\n _inherits(TimestampMillisecondsParser, _Parser);\n\n var _super = _createSuper(TimestampMillisecondsParser);\n\n function TimestampMillisecondsParser() {\n var _this;\n\n _classCallCheck(this, TimestampMillisecondsParser);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _super.call.apply(_super, [this].concat(args));\n\n _defineProperty(_assertThisInitialized(_this), \"priority\", 20);\n\n _defineProperty(_assertThisInitialized(_this), \"incompatibleTokens\", '*');\n\n return _this;\n }\n\n _createClass(TimestampMillisecondsParser, [{\n key: \"parse\",\n value: function parse(dateString) {\n return parseAnyDigitsSigned(dateString);\n }\n }, {\n key: \"set\",\n value: function set(_date, _flags, value) {\n return [new Date(value), {\n timestampIsSet: true\n }];\n }\n }]);\n\n return TimestampMillisecondsParser;\n}(Parser);", "import { EraParser } from \"./EraParser.js\";\nimport { YearParser } from \"./YearParser.js\";\nimport { LocalWeekYearParser } from \"./LocalWeekYearParser.js\";\nimport { ISOWeekYearParser } from \"./ISOWeekYearParser.js\";\nimport { ExtendedYearParser } from \"./ExtendedYearParser.js\";\nimport { QuarterParser } from \"./QuarterParser.js\";\nimport { StandAloneQuarterParser } from \"./StandAloneQuarterParser.js\";\nimport { MonthParser } from \"./MonthParser.js\";\nimport { StandAloneMonthParser } from \"./StandAloneMonthParser.js\";\nimport { LocalWeekParser } from \"./LocalWeekParser.js\";\nimport { ISOWeekParser } from \"./ISOWeekParser.js\";\nimport { DateParser } from \"./DateParser.js\";\nimport { DayOfYearParser } from \"./DayOfYearParser.js\";\nimport { DayParser } from \"./DayParser.js\";\nimport { LocalDayParser } from \"./LocalDayParser.js\";\nimport { StandAloneLocalDayParser } from \"./StandAloneLocalDayParser.js\";\nimport { ISODayParser } from \"./ISODayParser.js\";\nimport { AMPMParser } from \"./AMPMParser.js\";\nimport { AMPMMidnightParser } from \"./AMPMMidnightParser.js\";\nimport { DayPeriodParser } from \"./DayPeriodParser.js\";\nimport { Hour1to12Parser } from \"./Hour1to12Parser.js\";\nimport { Hour0to23Parser } from \"./Hour0to23Parser.js\";\nimport { Hour0To11Parser } from \"./Hour0To11Parser.js\";\nimport { Hour1To24Parser } from \"./Hour1To24Parser.js\";\nimport { MinuteParser } from \"./MinuteParser.js\";\nimport { SecondParser } from \"./SecondParser.js\";\nimport { FractionOfSecondParser } from \"./FractionOfSecondParser.js\";\nimport { ISOTimezoneWithZParser } from \"./ISOTimezoneWithZParser.js\";\nimport { ISOTimezoneParser } from \"./ISOTimezoneParser.js\";\nimport { TimestampSecondsParser } from \"./TimestampSecondsParser.js\";\nimport { TimestampMillisecondsParser } from \"./TimestampMillisecondsParser.js\";\n/*\n * | | Unit | | Unit |\n * |-----|--------------------------------|-----|--------------------------------|\n * | a | AM, PM | A* | Milliseconds in day |\n * | b | AM, PM, noon, midnight | B | Flexible day period |\n * | c | Stand-alone local day of week | C* | Localized hour w/ day period |\n * | d | Day of month | D | Day of year |\n * | e | Local day of week | E | Day of week |\n * | f | | F* | Day of week in month |\n * | g* | Modified Julian day | G | Era |\n * | h | Hour [1-12] | H | Hour [0-23] |\n * | i! | ISO day of week | I! | ISO week of year |\n * | j* | Localized hour w/ day period | J* | Localized hour w/o day period |\n * | k | Hour [1-24] | K | Hour [0-11] |\n * | l* | (deprecated) | L | Stand-alone month |\n * | m | Minute | M | Month |\n * | n | | N | |\n * | o! | Ordinal number modifier | O* | Timezone (GMT) |\n * | p | | P | |\n * | q | Stand-alone quarter | Q | Quarter |\n * | r* | Related Gregorian year | R! | ISO week-numbering year |\n * | s | Second | S | Fraction of second |\n * | t! | Seconds timestamp | T! | Milliseconds timestamp |\n * | u | Extended year | U* | Cyclic year |\n * | v* | Timezone (generic non-locat.) | V* | Timezone (location) |\n * | w | Local week of year | W* | Week of month |\n * | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |\n * | y | Year (abs) | Y | Local week-numbering year |\n * | z* | Timezone (specific non-locat.) | Z* | Timezone (aliases) |\n *\n * Letters marked by * are not implemented but reserved by Unicode standard.\n *\n * Letters marked by ! are non-standard, but implemented by date-fns:\n * - `o` modifies the previous token to turn it into an ordinal (see `parse` docs)\n * - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,\n * i.e. 7 for Sunday, 1 for Monday, etc.\n * - `I` is ISO week of year, as opposed to `w` which is local week of year.\n * - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.\n * `R` is supposed to be used in conjunction with `I` and `i`\n * for universal ISO week-numbering date, whereas\n * `Y` is supposed to be used in conjunction with `w` and `e`\n * for week-numbering date specific to the locale.\n */\n\nexport var parsers = {\n G: new EraParser(),\n y: new YearParser(),\n Y: new LocalWeekYearParser(),\n R: new ISOWeekYearParser(),\n u: new ExtendedYearParser(),\n Q: new QuarterParser(),\n q: new StandAloneQuarterParser(),\n M: new MonthParser(),\n L: new StandAloneMonthParser(),\n w: new LocalWeekParser(),\n I: new ISOWeekParser(),\n d: new DateParser(),\n D: new DayOfYearParser(),\n E: new DayParser(),\n e: new LocalDayParser(),\n c: new StandAloneLocalDayParser(),\n i: new ISODayParser(),\n a: new AMPMParser(),\n b: new AMPMMidnightParser(),\n B: new DayPeriodParser(),\n h: new Hour1to12Parser(),\n H: new Hour0to23Parser(),\n K: new Hour0To11Parser(),\n k: new Hour1To24Parser(),\n m: new MinuteParser(),\n s: new SecondParser(),\n S: new FractionOfSecondParser(),\n X: new ISOTimezoneWithZParser(),\n x: new ISOTimezoneParser(),\n t: new TimestampSecondsParser(),\n T: new TimestampMillisecondsParser()\n};", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === \"undefined\" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nimport defaultLocale from \"../_lib/defaultLocale/index.js\";\nimport subMilliseconds from \"../subMilliseconds/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport assign from \"../_lib/assign/index.js\";\nimport longFormatters from \"../_lib/format/longFormatters/index.js\";\nimport getTimezoneOffsetInMilliseconds from \"../_lib/getTimezoneOffsetInMilliseconds/index.js\";\nimport { isProtectedDayOfYearToken, isProtectedWeekYearToken, throwProtectedError } from \"../_lib/protectedTokens/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport { DateToSystemTimezoneSetter } from \"./_lib/Setter.js\";\nimport { parsers } from \"./_lib/parsers/index.js\";\nimport { getDefaultOptions } from \"../_lib/defaultOptions/index.js\"; // This RegExp consists of three parts separated by `|`:\n// - [yYQqMLwIdDecihHKkms]o matches any available ordinal number token\n// (one of the certain letters followed by `o`)\n// - (\\w)\\1* matches any sequences of the same letter\n// - '' matches two quote characters in a row\n// - '(''|[^'])+('|$) matches anything surrounded by two quote characters ('),\n// except a single quote symbol, which ends the sequence.\n// Two quote characters do not end the sequence.\n// If there is no matching single quote\n// then the sequence will continue until the end of the string.\n// - . matches any single character unmatched by previous parts of the RegExps\n\nvar formattingTokensRegExp = /[yYQqMLwIdDecihHKkms]o|(\\w)\\1*|''|'(''|[^'])+('|$)|./g; // This RegExp catches symbols escaped by quotes, and also\n// sequences of symbols P, p, and the combinations like `PPPPPPPppppp`\n\nvar longFormattingTokensRegExp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;\nvar escapedStringRegExp = /^'([^]*?)'?$/;\nvar doubleQuoteRegExp = /''/g;\nvar notWhitespaceRegExp = /\\S/;\nvar unescapedLatinCharacterRegExp = /[a-zA-Z]/;\n/**\n * @name parse\n * @category Common Helpers\n * @summary Parse the date.\n *\n * @description\n * Return the date parsed from string using the given format string.\n *\n * > \u26A0\uFE0F Please note that the `format` tokens differ from Moment.js and other libraries.\n * > See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * The characters in the format string wrapped between two single quotes characters (') are escaped.\n * Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.\n *\n * Format of the format string is based on Unicode Technical Standard #35:\n * https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n * with a few additions (see note 5 below the table).\n *\n * Not all tokens are compatible. Combinations that don't make sense or could lead to bugs are prohibited\n * and will throw `RangeError`. For example usage of 24-hour format token with AM/PM token will throw an exception:\n *\n * ```javascript\n * parse('23 AM', 'HH a', new Date())\n * //=> RangeError: The format string mustn't contain `HH` and `a` at the same time\n * ```\n *\n * See the compatibility table: https://docs.google.com/spreadsheets/d/e/2PACX-1vQOPU3xUhplll6dyoMmVUXHKl_8CRDs6_ueLmex3SoqwhuolkuN3O05l4rqx5h1dKX8eb46Ul-CCSrq/pubhtml?gid=0&single=true\n *\n * Accepted format string patterns:\n * | Unit |Prior| Pattern | Result examples | Notes |\n * |---------------------------------|-----|---------|-----------------------------------|-------|\n * | Era | 140 | G..GGG | AD, BC | |\n * | | | GGGG | Anno Domini, Before Christ | 2 |\n * | | | GGGGG | A, B | |\n * | Calendar year | 130 | y | 44, 1, 1900, 2017, 9999 | 4 |\n * | | | yo | 44th, 1st, 1900th, 9999999th | 4,5 |\n * | | | yy | 44, 01, 00, 17 | 4 |\n * | | | yyy | 044, 001, 123, 999 | 4 |\n * | | | yyyy | 0044, 0001, 1900, 2017 | 4 |\n * | | | yyyyy | ... | 2,4 |\n * | Local week-numbering year | 130 | Y | 44, 1, 1900, 2017, 9000 | 4 |\n * | | | Yo | 44th, 1st, 1900th, 9999999th | 4,5 |\n * | | | YY | 44, 01, 00, 17 | 4,6 |\n * | | | YYY | 044, 001, 123, 999 | 4 |\n * | | | YYYY | 0044, 0001, 1900, 2017 | 4,6 |\n * | | | YYYYY | ... | 2,4 |\n * | ISO week-numbering year | 130 | R | -43, 1, 1900, 2017, 9999, -9999 | 4,5 |\n * | | | RR | -43, 01, 00, 17 | 4,5 |\n * | | | RRR | -043, 001, 123, 999, -999 | 4,5 |\n * | | | RRRR | -0043, 0001, 2017, 9999, -9999 | 4,5 |\n * | | | RRRRR | ... | 2,4,5 |\n * | Extended year | 130 | u | -43, 1, 1900, 2017, 9999, -999 | 4 |\n * | | | uu | -43, 01, 99, -99 | 4 |\n * | | | uuu | -043, 001, 123, 999, -999 | 4 |\n * | | | uuuu | -0043, 0001, 2017, 9999, -9999 | 4 |\n * | | | uuuuu | ... | 2,4 |\n * | Quarter (formatting) | 120 | Q | 1, 2, 3, 4 | |\n * | | | Qo | 1st, 2nd, 3rd, 4th | 5 |\n * | | | QQ | 01, 02, 03, 04 | |\n * | | | QQQ | Q1, Q2, Q3, Q4 | |\n * | | | QQQQ | 1st quarter, 2nd quarter, ... | 2 |\n * | | | QQQQQ | 1, 2, 3, 4 | 4 |\n * | Quarter (stand-alone) | 120 | q | 1, 2, 3, 4 | |\n * | | | qo | 1st, 2nd, 3rd, 4th | 5 |\n * | | | qq | 01, 02, 03, 04 | |\n * | | | qqq | Q1, Q2, Q3, Q4 | |\n * | | | qqqq | 1st quarter, 2nd quarter, ... | 2 |\n * | | | qqqqq | 1, 2, 3, 4 | 3 |\n * | Month (formatting) | 110 | M | 1, 2, ..., 12 | |\n * | | | Mo | 1st, 2nd, ..., 12th | 5 |\n * | | | MM | 01, 02, ..., 12 | |\n * | | | MMM | Jan, Feb, ..., Dec | |\n * | | | MMMM | January, February, ..., December | 2 |\n * | | | MMMMM | J, F, ..., D | |\n * | Month (stand-alone) | 110 | L | 1, 2, ..., 12 | |\n * | | | Lo | 1st, 2nd, ..., 12th | 5 |\n * | | | LL | 01, 02, ..., 12 | |\n * | | | LLL | Jan, Feb, ..., Dec | |\n * | | | LLLL | January, February, ..., December | 2 |\n * | | | LLLLL | J, F, ..., D | |\n * | Local week of year | 100 | w | 1, 2, ..., 53 | |\n * | | | wo | 1st, 2nd, ..., 53th | 5 |\n * | | | ww | 01, 02, ..., 53 | |\n * | ISO week of year | 100 | I | 1, 2, ..., 53 | 5 |\n * | | | Io | 1st, 2nd, ..., 53th | 5 |\n * | | | II | 01, 02, ..., 53 | 5 |\n * | Day of month | 90 | d | 1, 2, ..., 31 | |\n * | | | do | 1st, 2nd, ..., 31st | 5 |\n * | | | dd | 01, 02, ..., 31 | |\n * | Day of year | 90 | D | 1, 2, ..., 365, 366 | 7 |\n * | | | Do | 1st, 2nd, ..., 365th, 366th | 5 |\n * | | | DD | 01, 02, ..., 365, 366 | 7 |\n * | | | DDD | 001, 002, ..., 365, 366 | |\n * | | | DDDD | ... | 2 |\n * | Day of week (formatting) | 90 | E..EEE | Mon, Tue, Wed, ..., Sun | |\n * | | | EEEE | Monday, Tuesday, ..., Sunday | 2 |\n * | | | EEEEE | M, T, W, T, F, S, S | |\n * | | | EEEEEE | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | ISO day of week (formatting) | 90 | i | 1, 2, 3, ..., 7 | 5 |\n * | | | io | 1st, 2nd, ..., 7th | 5 |\n * | | | ii | 01, 02, ..., 07 | 5 |\n * | | | iii | Mon, Tue, Wed, ..., Sun | 5 |\n * | | | iiii | Monday, Tuesday, ..., Sunday | 2,5 |\n * | | | iiiii | M, T, W, T, F, S, S | 5 |\n * | | | iiiiii | Mo, Tu, We, Th, Fr, Sa, Su | 5 |\n * | Local day of week (formatting) | 90 | e | 2, 3, 4, ..., 1 | |\n * | | | eo | 2nd, 3rd, ..., 1st | 5 |\n * | | | ee | 02, 03, ..., 01 | |\n * | | | eee | Mon, Tue, Wed, ..., Sun | |\n * | | | eeee | Monday, Tuesday, ..., Sunday | 2 |\n * | | | eeeee | M, T, W, T, F, S, S | |\n * | | | eeeeee | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | Local day of week (stand-alone) | 90 | c | 2, 3, 4, ..., 1 | |\n * | | | co | 2nd, 3rd, ..., 1st | 5 |\n * | | | cc | 02, 03, ..., 01 | |\n * | | | ccc | Mon, Tue, Wed, ..., Sun | |\n * | | | cccc | Monday, Tuesday, ..., Sunday | 2 |\n * | | | ccccc | M, T, W, T, F, S, S | |\n * | | | cccccc | Mo, Tu, We, Th, Fr, Sa, Su | |\n * | AM, PM | 80 | a..aaa | AM, PM | |\n * | | | aaaa | a.m., p.m. | 2 |\n * | | | aaaaa | a, p | |\n * | AM, PM, noon, midnight | 80 | b..bbb | AM, PM, noon, midnight | |\n * | | | bbbb | a.m., p.m., noon, midnight | 2 |\n * | | | bbbbb | a, p, n, mi | |\n * | Flexible day period | 80 | B..BBB | at night, in the morning, ... | |\n * | | | BBBB | at night, in the morning, ... | 2 |\n * | | | BBBBB | at night, in the morning, ... | |\n * | Hour [1-12] | 70 | h | 1, 2, ..., 11, 12 | |\n * | | | ho | 1st, 2nd, ..., 11th, 12th | 5 |\n * | | | hh | 01, 02, ..., 11, 12 | |\n * | Hour [0-23] | 70 | H | 0, 1, 2, ..., 23 | |\n * | | | Ho | 0th, 1st, 2nd, ..., 23rd | 5 |\n * | | | HH | 00, 01, 02, ..., 23 | |\n * | Hour [0-11] | 70 | K | 1, 2, ..., 11, 0 | |\n * | | | Ko | 1st, 2nd, ..., 11th, 0th | 5 |\n * | | | KK | 01, 02, ..., 11, 00 | |\n * | Hour [1-24] | 70 | k | 24, 1, 2, ..., 23 | |\n * | | | ko | 24th, 1st, 2nd, ..., 23rd | 5 |\n * | | | kk | 24, 01, 02, ..., 23 | |\n * | Minute | 60 | m | 0, 1, ..., 59 | |\n * | | | mo | 0th, 1st, ..., 59th | 5 |\n * | | | mm | 00, 01, ..., 59 | |\n * | Second | 50 | s | 0, 1, ..., 59 | |\n * | | | so | 0th, 1st, ..., 59th | 5 |\n * | | | ss | 00, 01, ..., 59 | |\n * | Seconds timestamp | 40 | t | 512969520 | |\n * | | | tt | ... | 2 |\n * | Fraction of second | 30 | S | 0, 1, ..., 9 | |\n * | | | SS | 00, 01, ..., 99 | |\n * | | | SSS | 000, 001, ..., 999 | |\n * | | | SSSS | ... | 2 |\n * | Milliseconds timestamp | 20 | T | 512969520900 | |\n * | | | TT | ... | 2 |\n * | Timezone (ISO-8601 w/ Z) | 10 | X | -08, +0530, Z | |\n * | | | XX | -0800, +0530, Z | |\n * | | | XXX | -08:00, +05:30, Z | |\n * | | | XXXX | -0800, +0530, Z, +123456 | 2 |\n * | | | XXXXX | -08:00, +05:30, Z, +12:34:56 | |\n * | Timezone (ISO-8601 w/o Z) | 10 | x | -08, +0530, +00 | |\n * | | | xx | -0800, +0530, +0000 | |\n * | | | xxx | -08:00, +05:30, +00:00 | 2 |\n * | | | xxxx | -0800, +0530, +0000, +123456 | |\n * | | | xxxxx | -08:00, +05:30, +00:00, +12:34:56 | |\n * | Long localized date | NA | P | 05/29/1453 | 5,8 |\n * | | | PP | May 29, 1453 | |\n * | | | PPP | May 29th, 1453 | |\n * | | | PPPP | Sunday, May 29th, 1453 | 2,5,8 |\n * | Long localized time | NA | p | 12:00 AM | 5,8 |\n * | | | pp | 12:00:00 AM | |\n * | Combination of date and time | NA | Pp | 05/29/1453, 12:00 AM | |\n * | | | PPpp | May 29, 1453, 12:00:00 AM | |\n * | | | PPPpp | May 29th, 1453 at ... | |\n * | | | PPPPpp | Sunday, May 29th, 1453 at ... | 2,5,8 |\n * Notes:\n * 1. \"Formatting\" units (e.g. formatting quarter) in the default en-US locale\n * are the same as \"stand-alone\" units, but are different in some languages.\n * \"Formatting\" units are declined according to the rules of the language\n * in the context of a date. \"Stand-alone\" units are always nominative singular.\n * In `format` function, they will produce different result:\n *\n * `format(new Date(2017, 10, 6), 'do LLLL', {locale: cs}) //=> '6. listopad'`\n *\n * `format(new Date(2017, 10, 6), 'do MMMM', {locale: cs}) //=> '6. listopadu'`\n *\n * `parse` will try to match both formatting and stand-alone units interchangably.\n *\n * 2. Any sequence of the identical letters is a pattern, unless it is escaped by\n * the single quote characters (see below).\n * If the sequence is longer than listed in table:\n * - for numerical units (`yyyyyyyy`) `parse` will try to match a number\n * as wide as the sequence\n * - for text units (`MMMMMMMM`) `parse` will try to match the widest variation of the unit.\n * These variations are marked with \"2\" in the last column of the table.\n *\n * 3. `QQQQQ` and `qqqqq` could be not strictly numerical in some locales.\n * These tokens represent the shortest form of the quarter.\n *\n * 4. The main difference between `y` and `u` patterns are B.C. years:\n *\n * | Year | `y` | `u` |\n * |------|-----|-----|\n * | AC 1 | 1 | 1 |\n * | BC 1 | 1 | 0 |\n * | BC 2 | 2 | -1 |\n *\n * Also `yy` will try to guess the century of two digit year by proximity with `referenceDate`:\n *\n * `parse('50', 'yy', new Date(2018, 0, 1)) //=> Sat Jan 01 2050 00:00:00`\n *\n * `parse('75', 'yy', new Date(2018, 0, 1)) //=> Wed Jan 01 1975 00:00:00`\n *\n * while `uu` will just assign the year as is:\n *\n * `parse('50', 'uu', new Date(2018, 0, 1)) //=> Sat Jan 01 0050 00:00:00`\n *\n * `parse('75', 'uu', new Date(2018, 0, 1)) //=> Tue Jan 01 0075 00:00:00`\n *\n * The same difference is true for local and ISO week-numbering years (`Y` and `R`),\n * except local week-numbering years are dependent on `options.weekStartsOn`\n * and `options.firstWeekContainsDate` (compare [setISOWeekYear]{@link https://date-fns.org/docs/setISOWeekYear}\n * and [setWeekYear]{@link https://date-fns.org/docs/setWeekYear}).\n *\n * 5. These patterns are not in the Unicode Technical Standard #35:\n * - `i`: ISO day of week\n * - `I`: ISO week of year\n * - `R`: ISO week-numbering year\n * - `o`: ordinal number modifier\n * - `P`: long localized date\n * - `p`: long localized time\n *\n * 6. `YY` and `YYYY` tokens represent week-numbering years but they are often confused with years.\n * You should enable `options.useAdditionalWeekYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * 7. `D` and `DD` tokens represent days of the year but they are ofthen confused with days of the month.\n * You should enable `options.useAdditionalDayOfYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n *\n * 8. `P+` tokens do not have a defined priority since they are merely aliases to other tokens based\n * on the given locale.\n *\n * using `en-US` locale: `P` => `MM/dd/yyyy`\n * using `en-US` locale: `p` => `hh:mm a`\n * using `pt-BR` locale: `P` => `dd/MM/yyyy`\n * using `pt-BR` locale: `p` => `HH:mm`\n *\n * Values will be assigned to the date in the descending order of its unit's priority.\n * Units of an equal priority overwrite each other in the order of appearance.\n *\n * If no values of higher priority are parsed (e.g. when parsing string 'January 1st' without a year),\n * the values will be taken from 3rd argument `referenceDate` which works as a context of parsing.\n *\n * `referenceDate` must be passed for correct work of the function.\n * If you're not sure which `referenceDate` to supply, create a new instance of Date:\n * `parse('02/11/2014', 'MM/dd/yyyy', new Date())`\n * In this case parsing will be done in the context of the current date.\n * If `referenceDate` is `Invalid Date` or a value not convertible to valid `Date`,\n * then `Invalid Date` will be returned.\n *\n * The result may vary by locale.\n *\n * If `formatString` matches with `dateString` but does not provides tokens, `referenceDate` will be returned.\n *\n * If parsing failed, `Invalid Date` will be returned.\n * Invalid Date is a Date, whose time value is NaN.\n * Time value of Date: http://es5.github.io/#x15.9.1.1\n *\n * @param {String} dateString - the string to parse\n * @param {String} formatString - the string of tokens\n * @param {Date|Number} referenceDate - defines values missing from the parsed dateString\n * @param {Object} [options] - an object with options.\n * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}\n * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)\n * @param {1|2|3|4|5|6|7} [options.firstWeekContainsDate=1] - the day of January, which is always in the first week of the year\n * @param {Boolean} [options.useAdditionalWeekYearTokens=false] - if true, allows usage of the week-numbering year tokens `YY` and `YYYY`;\n * see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @param {Boolean} [options.useAdditionalDayOfYearTokens=false] - if true, allows usage of the day of year tokens `D` and `DD`;\n * see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @returns {Date} the parsed date\n * @throws {TypeError} 3 arguments required\n * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6\n * @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7\n * @throws {RangeError} `options.locale` must contain `match` property\n * @throws {RangeError} use `yyyy` instead of `YYYY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws {RangeError} use `yy` instead of `YY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws {RangeError} use `d` instead of `D` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws {RangeError} use `dd` instead of `DD` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md\n * @throws {RangeError} format string contains an unescaped latin alphabet character\n *\n * @example\n * // Parse 11 February 2014 from middle-endian format:\n * var result = parse('02/11/2014', 'MM/dd/yyyy', new Date())\n * //=> Tue Feb 11 2014 00:00:00\n *\n * @example\n * // Parse 28th of February in Esperanto locale in the context of 2010 year:\n * import eo from 'date-fns/locale/eo'\n * var result = parse('28-a de februaro', \"do 'de' MMMM\", new Date(2010, 0, 1), {\n * locale: eo\n * })\n * //=> Sun Feb 28 2010 00:00:00\n */\n\nexport default function parse(dirtyDateString, dirtyFormatString, dirtyReferenceDate, options) {\n var _ref, _options$locale, _ref2, _ref3, _ref4, _options$firstWeekCon, _options$locale2, _options$locale2$opti, _defaultOptions$local, _defaultOptions$local2, _ref5, _ref6, _ref7, _options$weekStartsOn, _options$locale3, _options$locale3$opti, _defaultOptions$local3, _defaultOptions$local4;\n\n requiredArgs(3, arguments);\n var dateString = String(dirtyDateString);\n var formatString = String(dirtyFormatString);\n var defaultOptions = getDefaultOptions();\n var locale = (_ref = (_options$locale = options === null || options === void 0 ? void 0 : options.locale) !== null && _options$locale !== void 0 ? _options$locale : defaultOptions.locale) !== null && _ref !== void 0 ? _ref : defaultLocale;\n\n if (!locale.match) {\n throw new RangeError('locale must contain match property');\n }\n\n var firstWeekContainsDate = toInteger((_ref2 = (_ref3 = (_ref4 = (_options$firstWeekCon = options === null || options === void 0 ? void 0 : options.firstWeekContainsDate) !== null && _options$firstWeekCon !== void 0 ? _options$firstWeekCon : options === null || options === void 0 ? void 0 : (_options$locale2 = options.locale) === null || _options$locale2 === void 0 ? void 0 : (_options$locale2$opti = _options$locale2.options) === null || _options$locale2$opti === void 0 ? void 0 : _options$locale2$opti.firstWeekContainsDate) !== null && _ref4 !== void 0 ? _ref4 : defaultOptions.firstWeekContainsDate) !== null && _ref3 !== void 0 ? _ref3 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.firstWeekContainsDate) !== null && _ref2 !== void 0 ? _ref2 : 1); // Test if weekStartsOn is between 1 and 7 _and_ is not NaN\n\n if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {\n throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');\n }\n\n var weekStartsOn = toInteger((_ref5 = (_ref6 = (_ref7 = (_options$weekStartsOn = options === null || options === void 0 ? void 0 : options.weekStartsOn) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : options === null || options === void 0 ? void 0 : (_options$locale3 = options.locale) === null || _options$locale3 === void 0 ? void 0 : (_options$locale3$opti = _options$locale3.options) === null || _options$locale3$opti === void 0 ? void 0 : _options$locale3$opti.weekStartsOn) !== null && _ref7 !== void 0 ? _ref7 : defaultOptions.weekStartsOn) !== null && _ref6 !== void 0 ? _ref6 : (_defaultOptions$local3 = defaultOptions.locale) === null || _defaultOptions$local3 === void 0 ? void 0 : (_defaultOptions$local4 = _defaultOptions$local3.options) === null || _defaultOptions$local4 === void 0 ? void 0 : _defaultOptions$local4.weekStartsOn) !== null && _ref5 !== void 0 ? _ref5 : 0); // Test if weekStartsOn is between 0 and 6 _and_ is not NaN\n\n if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {\n throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');\n }\n\n if (formatString === '') {\n if (dateString === '') {\n return toDate(dirtyReferenceDate);\n } else {\n return new Date(NaN);\n }\n }\n\n var subFnOptions = {\n firstWeekContainsDate: firstWeekContainsDate,\n weekStartsOn: weekStartsOn,\n locale: locale\n }; // If timezone isn't specified, it will be set to the system timezone\n\n var setters = [new DateToSystemTimezoneSetter()];\n var tokens = formatString.match(longFormattingTokensRegExp).map(function (substring) {\n var firstCharacter = substring[0];\n\n if (firstCharacter in longFormatters) {\n var longFormatter = longFormatters[firstCharacter];\n return longFormatter(substring, locale.formatLong);\n }\n\n return substring;\n }).join('').match(formattingTokensRegExp);\n var usedTokens = [];\n\n var _iterator = _createForOfIteratorHelper(tokens),\n _step;\n\n try {\n var _loop = function _loop() {\n var token = _step.value;\n\n if (!(options !== null && options !== void 0 && options.useAdditionalWeekYearTokens) && isProtectedWeekYearToken(token)) {\n throwProtectedError(token, formatString, dirtyDateString);\n }\n\n if (!(options !== null && options !== void 0 && options.useAdditionalDayOfYearTokens) && isProtectedDayOfYearToken(token)) {\n throwProtectedError(token, formatString, dirtyDateString);\n }\n\n var firstCharacter = token[0];\n var parser = parsers[firstCharacter];\n\n if (parser) {\n var incompatibleTokens = parser.incompatibleTokens;\n\n if (Array.isArray(incompatibleTokens)) {\n var incompatibleToken = usedTokens.find(function (usedToken) {\n return incompatibleTokens.includes(usedToken.token) || usedToken.token === firstCharacter;\n });\n\n if (incompatibleToken) {\n throw new RangeError(\"The format string mustn't contain `\".concat(incompatibleToken.fullToken, \"` and `\").concat(token, \"` at the same time\"));\n }\n } else if (parser.incompatibleTokens === '*' && usedTokens.length > 0) {\n throw new RangeError(\"The format string mustn't contain `\".concat(token, \"` and any other token at the same time\"));\n }\n\n usedTokens.push({\n token: firstCharacter,\n fullToken: token\n });\n var parseResult = parser.run(dateString, token, locale.match, subFnOptions);\n\n if (!parseResult) {\n return {\n v: new Date(NaN)\n };\n }\n\n setters.push(parseResult.setter);\n dateString = parseResult.rest;\n } else {\n if (firstCharacter.match(unescapedLatinCharacterRegExp)) {\n throw new RangeError('Format string contains an unescaped latin alphabet character `' + firstCharacter + '`');\n } // Replace two single quote characters with one single quote character\n\n\n if (token === \"''\") {\n token = \"'\";\n } else if (firstCharacter === \"'\") {\n token = cleanEscapedString(token);\n } // Cut token from string, or, if string doesn't match the token, return Invalid Date\n\n\n if (dateString.indexOf(token) === 0) {\n dateString = dateString.slice(token.length);\n } else {\n return {\n v: new Date(NaN)\n };\n }\n }\n };\n\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var _ret = _loop();\n\n if (_typeof(_ret) === \"object\") return _ret.v;\n } // Check if the remaining input contains something other than whitespace\n\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n\n if (dateString.length > 0 && notWhitespaceRegExp.test(dateString)) {\n return new Date(NaN);\n }\n\n var uniquePrioritySetters = setters.map(function (setter) {\n return setter.priority;\n }).sort(function (a, b) {\n return b - a;\n }).filter(function (priority, index, array) {\n return array.indexOf(priority) === index;\n }).map(function (priority) {\n return setters.filter(function (setter) {\n return setter.priority === priority;\n }).sort(function (a, b) {\n return b.subPriority - a.subPriority;\n });\n }).map(function (setterArray) {\n return setterArray[0];\n });\n var date = toDate(dirtyReferenceDate);\n\n if (isNaN(date.getTime())) {\n return new Date(NaN);\n } // Convert the date in system timezone to the same date in UTC+00:00 timezone.\n\n\n var utcDate = subMilliseconds(date, getTimezoneOffsetInMilliseconds(date));\n var flags = {};\n\n var _iterator2 = _createForOfIteratorHelper(uniquePrioritySetters),\n _step2;\n\n try {\n for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n var setter = _step2.value;\n\n if (!setter.validate(utcDate, subFnOptions)) {\n return new Date(NaN);\n }\n\n var result = setter.set(utcDate, flags, subFnOptions); // Result is tuple (date, flags)\n\n if (Array.isArray(result)) {\n utcDate = result[0];\n assign(flags, result[1]); // Result is date\n } else {\n utcDate = result;\n }\n }\n } catch (err) {\n _iterator2.e(err);\n } finally {\n _iterator2.f();\n }\n\n return utcDate;\n}\n\nfunction cleanEscapedString(input) {\n return input.match(escapedStringRegExp)[1].replace(doubleQuoteRegExp, \"'\");\n}", "import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isSameMonth\n * @category Month Helpers\n * @summary Are the given dates in the same month (and year)?\n *\n * @description\n * Are the given dates in the same month (and year)?\n *\n * @param {Date|Number} dateLeft - the first date to check\n * @param {Date|Number} dateRight - the second date to check\n * @returns {Boolean} the dates are in the same month (and year)\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Are 2 September 2014 and 25 September 2014 in the same month?\n * const result = isSameMonth(new Date(2014, 8, 2), new Date(2014, 8, 25))\n * //=> true\n *\n * @example\n * // Are 2 September 2014 and 25 September 2015 in the same month?\n * const result = isSameMonth(new Date(2014, 8, 2), new Date(2015, 8, 25))\n * //=> false\n */\n\nexport default function isSameMonth(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n return dateLeft.getFullYear() === dateRight.getFullYear() && dateLeft.getMonth() === dateRight.getMonth();\n}", "import addDays from \"../addDays/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\n/**\n * @name subDays\n * @category Day Helpers\n * @summary Subtract the specified number of days from the given date.\n *\n * @description\n * Subtract the specified number of days from the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of days to be subtracted. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the days subtracted\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Subtract 10 days from 1 September 2014:\n * const result = subDays(new Date(2014, 8, 1), 10)\n * //=> Fri Aug 22 2014 00:00:00\n */\n\nexport default function subDays(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var amount = toInteger(dirtyAmount);\n return addDays(dirtyDate, -amount);\n}", "import { millisecondsInHour, millisecondsInMinute } from \"../constants/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\n/**\n * @name parseISO\n * @category Common Helpers\n * @summary Parse ISO string\n *\n * @description\n * Parse the given string in ISO 8601 format and return an instance of Date.\n *\n * Function accepts complete ISO 8601 formats as well as partial implementations.\n * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601\n *\n * If the argument isn't a string, the function cannot parse the string or\n * the values are invalid, it returns Invalid Date.\n *\n * @param {String} argument - the value to convert\n * @param {Object} [options] - an object with options.\n * @param {0|1|2} [options.additionalDigits=2] - the additional number of digits in the extended year format\n * @returns {Date} the parsed date in the local time zone\n * @throws {TypeError} 1 argument required\n * @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2\n *\n * @example\n * // Convert string '2014-02-11T11:30:30' to date:\n * const result = parseISO('2014-02-11T11:30:30')\n * //=> Tue Feb 11 2014 11:30:30\n *\n * @example\n * // Convert string '+02014101' to date,\n * // if the additional number of digits in the extended year format is 1:\n * const result = parseISO('+02014101', { additionalDigits: 1 })\n * //=> Fri Apr 11 2014 00:00:00\n */\n\nexport default function parseISO(argument, options) {\n var _options$additionalDi;\n\n requiredArgs(1, arguments);\n var additionalDigits = toInteger((_options$additionalDi = options === null || options === void 0 ? void 0 : options.additionalDigits) !== null && _options$additionalDi !== void 0 ? _options$additionalDi : 2);\n\n if (additionalDigits !== 2 && additionalDigits !== 1 && additionalDigits !== 0) {\n throw new RangeError('additionalDigits must be 0, 1 or 2');\n }\n\n if (!(typeof argument === 'string' || Object.prototype.toString.call(argument) === '[object String]')) {\n return new Date(NaN);\n }\n\n var dateStrings = splitDateString(argument);\n var date;\n\n if (dateStrings.date) {\n var parseYearResult = parseYear(dateStrings.date, additionalDigits);\n date = parseDate(parseYearResult.restDateString, parseYearResult.year);\n }\n\n if (!date || isNaN(date.getTime())) {\n return new Date(NaN);\n }\n\n var timestamp = date.getTime();\n var time = 0;\n var offset;\n\n if (dateStrings.time) {\n time = parseTime(dateStrings.time);\n\n if (isNaN(time)) {\n return new Date(NaN);\n }\n }\n\n if (dateStrings.timezone) {\n offset = parseTimezone(dateStrings.timezone);\n\n if (isNaN(offset)) {\n return new Date(NaN);\n }\n } else {\n var dirtyDate = new Date(timestamp + time); // js parsed string assuming it's in UTC timezone\n // but we need it to be parsed in our timezone\n // so we use utc values to build date in our timezone.\n // Year values from 0 to 99 map to the years 1900 to 1999\n // so set year explicitly with setFullYear.\n\n var result = new Date(0);\n result.setFullYear(dirtyDate.getUTCFullYear(), dirtyDate.getUTCMonth(), dirtyDate.getUTCDate());\n result.setHours(dirtyDate.getUTCHours(), dirtyDate.getUTCMinutes(), dirtyDate.getUTCSeconds(), dirtyDate.getUTCMilliseconds());\n return result;\n }\n\n return new Date(timestamp + time + offset);\n}\nvar patterns = {\n dateTimeDelimiter: /[T ]/,\n timeZoneDelimiter: /[Z ]/i,\n timezone: /([Z+-].*)$/\n};\nvar dateRegex = /^-?(?:(\\d{3})|(\\d{2})(?:-?(\\d{2}))?|W(\\d{2})(?:-?(\\d{1}))?|)$/;\nvar timeRegex = /^(\\d{2}(?:[.,]\\d*)?)(?::?(\\d{2}(?:[.,]\\d*)?))?(?::?(\\d{2}(?:[.,]\\d*)?))?$/;\nvar timezoneRegex = /^([+-])(\\d{2})(?::?(\\d{2}))?$/;\n\nfunction splitDateString(dateString) {\n var dateStrings = {};\n var array = dateString.split(patterns.dateTimeDelimiter);\n var timeString; // The regex match should only return at maximum two array elements.\n // [date], [time], or [date, time].\n\n if (array.length > 2) {\n return dateStrings;\n }\n\n if (/:/.test(array[0])) {\n timeString = array[0];\n } else {\n dateStrings.date = array[0];\n timeString = array[1];\n\n if (patterns.timeZoneDelimiter.test(dateStrings.date)) {\n dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];\n timeString = dateString.substr(dateStrings.date.length, dateString.length);\n }\n }\n\n if (timeString) {\n var token = patterns.timezone.exec(timeString);\n\n if (token) {\n dateStrings.time = timeString.replace(token[1], '');\n dateStrings.timezone = token[1];\n } else {\n dateStrings.time = timeString;\n }\n }\n\n return dateStrings;\n}\n\nfunction parseYear(dateString, additionalDigits) {\n var regex = new RegExp('^(?:(\\\\d{4}|[+-]\\\\d{' + (4 + additionalDigits) + '})|(\\\\d{2}|[+-]\\\\d{' + (2 + additionalDigits) + '})$)');\n var captures = dateString.match(regex); // Invalid ISO-formatted year\n\n if (!captures) return {\n year: NaN,\n restDateString: ''\n };\n var year = captures[1] ? parseInt(captures[1]) : null;\n var century = captures[2] ? parseInt(captures[2]) : null; // either year or century is null, not both\n\n return {\n year: century === null ? year : century * 100,\n restDateString: dateString.slice((captures[1] || captures[2]).length)\n };\n}\n\nfunction parseDate(dateString, year) {\n // Invalid ISO-formatted year\n if (year === null) return new Date(NaN);\n var captures = dateString.match(dateRegex); // Invalid ISO-formatted string\n\n if (!captures) return new Date(NaN);\n var isWeekDate = !!captures[4];\n var dayOfYear = parseDateUnit(captures[1]);\n var month = parseDateUnit(captures[2]) - 1;\n var day = parseDateUnit(captures[3]);\n var week = parseDateUnit(captures[4]);\n var dayOfWeek = parseDateUnit(captures[5]) - 1;\n\n if (isWeekDate) {\n if (!validateWeekDate(year, week, dayOfWeek)) {\n return new Date(NaN);\n }\n\n return dayOfISOWeekYear(year, week, dayOfWeek);\n } else {\n var date = new Date(0);\n\n if (!validateDate(year, month, day) || !validateDayOfYearDate(year, dayOfYear)) {\n return new Date(NaN);\n }\n\n date.setUTCFullYear(year, month, Math.max(dayOfYear, day));\n return date;\n }\n}\n\nfunction parseDateUnit(value) {\n return value ? parseInt(value) : 1;\n}\n\nfunction parseTime(timeString) {\n var captures = timeString.match(timeRegex);\n if (!captures) return NaN; // Invalid ISO-formatted time\n\n var hours = parseTimeUnit(captures[1]);\n var minutes = parseTimeUnit(captures[2]);\n var seconds = parseTimeUnit(captures[3]);\n\n if (!validateTime(hours, minutes, seconds)) {\n return NaN;\n }\n\n return hours * millisecondsInHour + minutes * millisecondsInMinute + seconds * 1000;\n}\n\nfunction parseTimeUnit(value) {\n return value && parseFloat(value.replace(',', '.')) || 0;\n}\n\nfunction parseTimezone(timezoneString) {\n if (timezoneString === 'Z') return 0;\n var captures = timezoneString.match(timezoneRegex);\n if (!captures) return 0;\n var sign = captures[1] === '+' ? -1 : 1;\n var hours = parseInt(captures[2]);\n var minutes = captures[3] && parseInt(captures[3]) || 0;\n\n if (!validateTimezone(hours, minutes)) {\n return NaN;\n }\n\n return sign * (hours * millisecondsInHour + minutes * millisecondsInMinute);\n}\n\nfunction dayOfISOWeekYear(isoWeekYear, week, day) {\n var date = new Date(0);\n date.setUTCFullYear(isoWeekYear, 0, 4);\n var fourthOfJanuaryDay = date.getUTCDay() || 7;\n var diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;\n date.setUTCDate(date.getUTCDate() + diff);\n return date;\n} // Validation functions\n// February is null to handle the leap year (using ||)\n\n\nvar daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\nfunction isLeapYearIndex(year) {\n return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;\n}\n\nfunction validateDate(year, month, date) {\n return month >= 0 && month <= 11 && date >= 1 && date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28));\n}\n\nfunction validateDayOfYearDate(year, dayOfYear) {\n return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);\n}\n\nfunction validateWeekDate(_year, week, day) {\n return week >= 1 && week <= 53 && day >= 0 && day <= 6;\n}\n\nfunction validateTime(hours, minutes, seconds) {\n if (hours === 24) {\n return minutes === 0 && seconds === 0;\n }\n\n return seconds >= 0 && seconds < 60 && minutes >= 0 && minutes < 60 && hours >= 0 && hours < 25;\n}\n\nfunction validateTimezone(_hours, minutes) {\n return minutes >= 0 && minutes <= 59;\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name setHours\n * @category Hour Helpers\n * @summary Set the hours to the given date.\n *\n * @description\n * Set the hours to the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} hours - the hours of the new date\n * @returns {Date} the new date with the hours set\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Set 4 hours to 1 September 2014 11:30:00:\n * const result = setHours(new Date(2014, 8, 1, 11, 30), 4)\n * //=> Mon Sep 01 2014 04:30:00\n */\n\nexport default function setHours(dirtyDate, dirtyHours) {\n requiredArgs(2, arguments);\n var date = toDate(dirtyDate);\n var hours = toInteger(dirtyHours);\n date.setHours(hours);\n return date;\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name setYear\n * @category Year Helpers\n * @summary Set the year to the given date.\n *\n * @description\n * Set the year to the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} year - the year of the new date\n * @returns {Date} the new date with the year set\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Set year 2013 to 1 September 2014:\n * const result = setYear(new Date(2014, 8, 1), 2013)\n * //=> Sun Sep 01 2013 00:00:00\n */\n\nexport default function setYear(dirtyDate, dirtyYear) {\n requiredArgs(2, arguments);\n var date = toDate(dirtyDate);\n var year = toInteger(dirtyYear); // Check if date is Invalid Date because Date.prototype.setFullYear ignores the value of Invalid Date\n\n if (isNaN(date.getTime())) {\n return new Date(NaN);\n }\n\n date.setFullYear(year);\n return date;\n}", "import toInteger from \"../_lib/toInteger/index.js\";\nimport addMonths from \"../addMonths/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name subMonths\n * @category Month Helpers\n * @summary Subtract the specified number of months from the given date.\n *\n * @description\n * Subtract the specified number of months from the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of months to be subtracted. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the months subtracted\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Subtract 5 months from 1 February 2015:\n * const result = subMonths(new Date(2015, 1, 1), 5)\n * //=> Mon Sep 01 2014 00:00:00\n */\n\nexport default function subMonths(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var amount = toInteger(dirtyAmount);\n return addMonths(dirtyDate, -amount);\n}", "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nimport subDays from \"../subDays/index.js\";\nimport subMonths from \"../subMonths/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport toInteger from \"../_lib/toInteger/index.js\";\n/**\n * @name sub\n * @category Common Helpers\n * @summary Subtract the specified years, months, weeks, days, hours, minutes and seconds from the given date.\n *\n * @description\n * Subtract the specified years, months, weeks, days, hours, minutes and seconds from the given date.\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Duration} duration - the object with years, months, weeks, days, hours, minutes and seconds to be subtracted\n *\n * | Key | Description |\n * |---------|------------------------------------|\n * | years | Amount of years to be subtracted |\n * | months | Amount of months to be subtracted |\n * | weeks | Amount of weeks to be subtracted |\n * | days | Amount of days to be subtracted |\n * | hours | Amount of hours to be subtracted |\n * | minutes | Amount of minutes to be subtracted |\n * | seconds | Amount of seconds to be subtracted |\n *\n * All values default to 0\n *\n * @returns {Date} the new date with the seconds subtracted\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Subtract the following duration from 15 June 2017 15:29:20\n * const result = sub(new Date(2017, 5, 15, 15, 29, 20), {\n * years: 2,\n * months: 9,\n * weeks: 1,\n * days: 7,\n * hours: 5,\n * minutes: 9,\n * seconds: 30\n * })\n * //=> Mon Sep 1 2014 10:19:50\n */\n\nexport default function sub(date, duration) {\n requiredArgs(2, arguments);\n if (!duration || _typeof(duration) !== 'object') return new Date(NaN);\n var years = duration.years ? toInteger(duration.years) : 0;\n var months = duration.months ? toInteger(duration.months) : 0;\n var weeks = duration.weeks ? toInteger(duration.weeks) : 0;\n var days = duration.days ? toInteger(duration.days) : 0;\n var hours = duration.hours ? toInteger(duration.hours) : 0;\n var minutes = duration.minutes ? toInteger(duration.minutes) : 0;\n var seconds = duration.seconds ? toInteger(duration.seconds) : 0; // Subtract years and months\n\n var dateWithoutMonths = subMonths(date, months + years * 12); // Subtract weeks and days\n\n var dateWithoutDays = subDays(dateWithoutMonths, days + weeks * 7); // Subtract hours, minutes and seconds\n\n var minutestoSub = minutes + hours * 60;\n var secondstoSub = seconds + minutestoSub * 60;\n var mstoSub = secondstoSub * 1000;\n var finalDate = new Date(dateWithoutDays.getTime() - mstoSub);\n return finalDate;\n}", "import {\n AmountJson,\n Amounts,\n CurrencySpecification,\n} from \"@gnu-taler/taler-util\";\nimport { h, VNode } from \"preact\";\n\n/**\n * Common way to render amount\n *\n * @param value the amount to be rendered\n * @param spec currency specification\n * @param specMap currency specification by currency name\n * @param hideSmall don't show very tiny value\n * @param negative if the value specified by amount is negative\n * @param withColor show negative as red and positive as green\n * @param withSign include a minus for negatives\n * @returns\n */\nexport function RenderAmount({\n value,\n spec,\n specMap,\n negative,\n withColor,\n withSign,\n hideSmall,\n}: {\n spec?: CurrencySpecification;\n specMap?: Record;\n value: AmountJson;\n hideSmall?: boolean;\n negative?: boolean;\n withColor?: boolean;\n withSign?: boolean;\n}): VNode {\n const neg = !!negative; // convert to true or false\n\n const currentSpec = spec ?? (!specMap ? undefined : specMap[value.currency]);\n if (!currentSpec) {\n throw Error(\"missing currency spec\");\n }\n const { currency, normal, small } = Amounts.stringifyValueWithSpec(\n value,\n currentSpec,\n );\n\n return (\n \n {withSign && negative ? \"- \" : undefined}\n {currency} {normal}{\" \"}\n {!hideSmall && small && {small}}\n \n );\n}\n\nexport function RenderAmountBulma({\n value,\n spec,\n specMap,\n negative,\n withColor,\n withSign,\n hideSmall,\n}: {\n spec?: CurrencySpecification;\n specMap?: Record;\n value: AmountJson;\n hideSmall?: boolean;\n negative?: boolean;\n withColor?: boolean;\n withSign?: boolean;\n}): VNode {\n const neg = !!negative;\n\n const currentSpec = spec ?? (!specMap ? undefined : specMap[value.currency]);\n if (!currentSpec) {\n throw Error(\"missing currency spec\");\n }\n\n const { currency, normal, small } = Amounts.stringifyValueWithSpec(\n value,\n currentSpec,\n );\n\n return (\n \n {withSign && negative ? \"- \" : undefined}\n {currency} {normal}{\" \"}\n {!hideSmall && small && {small}}\n \n );\n}\n", "import { h } from \"preact\";\nimport { useTranslationContext } from \"../index.browser.js\";\n\n/**\n * Common pagination footer for tables.\n *\n * @param param0\n * @returns\n */\nexport function Pagination({\n onFirstPage,\n onNext,\n}: {\n onFirstPage?: () => void;\n onNext?: () => void;\n}) {\n const { i18n } = useTranslationContext();\n return (\n \n
\n \n First page\n \n \n Next\n \n
\n \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2021-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport logo from \"@assets/svg/logo/qr-logo.svg\";\nimport chFlag from \"@assets/svg/swiss-qr-flag.svg\";\nimport { TalerUri, TalerUris, TranslatedString } from \"@gnu-taler/taler-util\";\nimport { h, VNode } from \"preact\";\nimport qrcode from \"qrcode-generator\";\n\nfunction generate_qr(\n text: string,\n params: {\n typeNumber?: TypeNumber;\n errorCorrectionLevel?: ErrorCorrectionLevel;\n } = {},\n) {\n const qr = qrcode(\n params.typeNumber ?? 0,\n (params.errorCorrectionLevel = \"H\"),\n );\n qr.addData(text, \"Byte\");\n qr.make();\n const image = qr.createSvgTag({\n scalable: true,\n margin: 0,\n });\n return `data:image/svg+xml,${encodeURIComponent(image)}`;\n}\n\nexport function QR_Taler({ uri }: { uri: TalerUri }): VNode {\n const stringUri = TalerUris.toString(uri);\n return (\n \n \n \n
\n \n \n
\n
\n );\n}\n\nexport function QR_TOTP({ otpAuthURI }: { otpAuthURI: string }): VNode {\n return (\n \n \n \n \n\n \n \n T-OTP\n \n \n \n );\n}\n\nexport function QR_Generic({\n content,\n title,\n}: {\n content: string;\n title?: string;\n}): VNode {\n return (\n \n \n \n \n\n {title === undefined ? undefined : (\n \n \n {title}\n \n \n )}\n \n );\n}\n/**\n * Based on the definition of Swiss Implementation Guidelines\n * for the QR-bill\n * @param param0\n * @returns\n */\nexport function QR_SwissBank({ text }: { text: string }): VNode {\n return (\n \n \n \n \n\n \n \n \n \n \n \n );\n}\n\nexport function QR_Bank({\n text,\n label,\n}: {\n text: string;\n label: TranslatedString;\n}): VNode {\n return (\n \n \n \n \n\n \n \n {label}\n \n \n \n );\n}\n", "import { h, VNode } from \"preact\";\n\nexport type MessageType = \"INFO\" | \"WARN\" | \"ERROR\" | \"SUCCESS\";\nexport interface NotificationCard {\n message: string;\n description?: string | VNode;\n details?: string | VNode | string;\n type: MessageType;\n}\n\ninterface Props {\n notification?: NotificationCard;\n}\n\nexport function NotificationCardBulma({\n notification: n,\n}: Props): VNode | null {\n if (!n) return null;\n return (\n
\n
\n
\n \n
\n

{n.message}

\n
\n {n.description && (\n
\n
{n.description}
\n {n.details &&
{n.details}
}\n
\n )}\n \n
\n
\n
\n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2021-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nimport {\n TalerBankIntegrationHttpClient,\n TalerCoreBankHttpClient,\n TalerRevenueHttpClient,\n TalerWireGatewayHttpClient,\n} from \"@gnu-taler/taler-util\";\nimport { ComponentChildren, createContext, h, VNode } from \"preact\";\nimport { useContext } from \"preact/hooks\";\nimport { defaultRequestHandler } from \"../utils/request.js\";\n\ninterface Type {\n /**\n * @deprecated this show not be used\n */\n request: typeof defaultRequestHandler;\n bankCore: TalerCoreBankHttpClient;\n bankIntegration: TalerBankIntegrationHttpClient;\n bankWire: TalerWireGatewayHttpClient;\n bankRevenue: TalerRevenueHttpClient;\n}\n\nconst Context = createContext({ request: defaultRequestHandler } as any);\n\nexport const useApiContext = (): Type => useContext(Context);\nexport const ApiContextProvider = ({\n children,\n value,\n}: {\n value: Type;\n children: ComponentChildren;\n}): VNode => {\n return h(Context.Provider, { value, children });\n};\n", "/*\n This file is part of GNU Taler\n (C) 2021-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { decodeCrock, encodeCrock } from \"@gnu-taler/taler-util\";\n\nconst utf8Encoder = new TextEncoder();\nconst utf8Decoder = new TextDecoder(\"utf-8\", { ignoreBOM: true });\n\nexport function encodeCrockForURI(string: string): string {\n return encodeCrock(utf8Encoder.encode(string));\n}\n\nexport function decodeCrockFromURI(enc: string): string {\n return utf8Decoder.decode(decodeCrock(enc));\n}\n\nexport function base64encode(str: string): string {\n return base64EncArr(strToUTF8Arr(str));\n}\n\nexport function base64decode(str: string): string {\n return UTF8ArrToStr(base64DecToArr(str));\n}\n\n// from https://developer.mozilla.org/en-US/docs/Glossary/Base64\n\n// Array of bytes to Base64 string decoding\nfunction b64ToUint6(nChr: number): number {\n return nChr > 64 && nChr < 91\n ? nChr - 65\n : nChr > 96 && nChr < 123\n ? nChr - 71\n : nChr > 47 && nChr < 58\n ? nChr + 4\n : nChr === 43\n ? 62\n : nChr === 47\n ? 63\n : 0;\n}\n\nfunction base64DecToArr(sBase64: string, nBlocksSize?: number): Uint8Array {\n const sB64Enc = sBase64.replace(/[^A-Za-z0-9+/]/g, \"\"); // Only necessary if the base64 includes whitespace such as line breaks.\n const nInLen = sB64Enc.length;\n const nOutLen = nBlocksSize\n ? Math.ceil(((nInLen * 3 + 1) >> 2) / nBlocksSize) * nBlocksSize\n : (nInLen * 3 + 1) >> 2;\n const taBytes = new Uint8Array(nOutLen);\n\n let nMod3;\n let nMod4;\n let nUint24 = 0;\n let nOutIdx = 0;\n for (let nInIdx = 0; nInIdx < nInLen; nInIdx++) {\n nMod4 = nInIdx & 3;\n nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4));\n if (nMod4 === 3 || nInLen - nInIdx === 1) {\n nMod3 = 0;\n while (nMod3 < 3 && nOutIdx < nOutLen) {\n taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255;\n nMod3++;\n nOutIdx++;\n }\n nUint24 = 0;\n }\n }\n\n return taBytes;\n}\n\n/* Base64 string to array encoding */\nfunction uint6ToB64(nUint6: number): number {\n return nUint6 < 26\n ? nUint6 + 65\n : nUint6 < 52\n ? nUint6 + 71\n : nUint6 < 62\n ? nUint6 - 4\n : nUint6 === 62\n ? 43\n : nUint6 === 63\n ? 47\n : 65;\n}\n\nfunction base64EncArr(aBytes: Uint8Array): string {\n let nMod3 = 2;\n let sB64Enc = \"\";\n\n const nLen = aBytes.length;\n let nUint24 = 0;\n for (let nIdx = 0; nIdx < nLen; nIdx++) {\n nMod3 = nIdx % 3;\n // To break your base64 into several 80-character lines, add:\n // if (nIdx > 0 && ((nIdx * 4) / 3) % 76 === 0) {\n // sB64Enc += \"\\r\\n\";\n // }\n\n nUint24 |= aBytes[nIdx] << ((16 >>> nMod3) & 24);\n if (nMod3 === 2 || aBytes.length - nIdx === 1) {\n sB64Enc += String.fromCodePoint(\n uint6ToB64((nUint24 >>> 18) & 63),\n uint6ToB64((nUint24 >>> 12) & 63),\n uint6ToB64((nUint24 >>> 6) & 63),\n uint6ToB64(nUint24 & 63),\n );\n nUint24 = 0;\n }\n }\n return (\n sB64Enc.substring(0, sB64Enc.length - 2 + nMod3) +\n (nMod3 === 2 ? \"\" : nMod3 === 1 ? \"=\" : \"==\")\n );\n}\n\n/**\n * UTF-8 array to JS string and vice versa\n *\n * @param aBytes\n * @deprecated use textEncoder\n * @returns\n */\nfunction UTF8ArrToStr(aBytes: Uint8Array): string {\n let sView = \"\";\n let nPart;\n const nLen = aBytes.length;\n for (let nIdx = 0; nIdx < nLen; nIdx++) {\n nPart = aBytes[nIdx];\n sView += String.fromCodePoint(\n nPart > 251 && nPart < 254 && nIdx + 5 < nLen /* six bytes */\n ? /* (nPart - 252 << 30) may be not so safe in ECMAScript! So\u2026: */\n (nPart - 252) * 1073741824 +\n ((aBytes[++nIdx] - 128) << 24) +\n ((aBytes[++nIdx] - 128) << 18) +\n ((aBytes[++nIdx] - 128) << 12) +\n ((aBytes[++nIdx] - 128) << 6) +\n aBytes[++nIdx] -\n 128\n : nPart > 247 && nPart < 252 && nIdx + 4 < nLen /* five bytes */\n ? ((nPart - 248) << 24) +\n ((aBytes[++nIdx] - 128) << 18) +\n ((aBytes[++nIdx] - 128) << 12) +\n ((aBytes[++nIdx] - 128) << 6) +\n aBytes[++nIdx] -\n 128\n : nPart > 239 && nPart < 248 && nIdx + 3 < nLen /* four bytes */\n ? ((nPart - 240) << 18) +\n ((aBytes[++nIdx] - 128) << 12) +\n ((aBytes[++nIdx] - 128) << 6) +\n aBytes[++nIdx] -\n 128\n : nPart > 223 && nPart < 240 && nIdx + 2 < nLen /* three bytes */\n ? ((nPart - 224) << 12) +\n ((aBytes[++nIdx] - 128) << 6) +\n aBytes[++nIdx] -\n 128\n : nPart > 191 && nPart < 224 && nIdx + 1 < nLen /* two bytes */\n ? ((nPart - 192) << 6) + aBytes[++nIdx] - 128\n : /* nPart < 127 ? */ /* one byte */\n nPart,\n );\n }\n return sView;\n}\n\n/**\n *\n * @param sDOMStr\n * @deprecated use textEncoder\n * @returns\n */\nfunction strToUTF8Arr(sDOMStr: string): Uint8Array {\n let nChr;\n const nStrLen = sDOMStr.length;\n let nArrLen = 0;\n\n /* mapping\u2026 */\n for (let nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) {\n nChr = sDOMStr.codePointAt(nMapIdx);\n if (nChr === undefined) {\n throw Error(\n `No char at ${nMapIdx} on string with length: ${sDOMStr.length}`,\n );\n }\n\n if (nChr >= 0x10000) {\n nMapIdx++;\n }\n\n nArrLen +=\n nChr < 0x80\n ? 1\n : nChr < 0x800\n ? 2\n : nChr < 0x10000\n ? 3\n : nChr < 0x200000\n ? 4\n : nChr < 0x4000000\n ? 5\n : 6;\n }\n\n const aBytes = new Uint8Array(nArrLen);\n\n /* transcription\u2026 */\n let nIdx = 0;\n let nChrIdx = 0;\n while (nIdx < nArrLen) {\n nChr = sDOMStr.codePointAt(nChrIdx);\n if (nChr === undefined) {\n throw Error(\n `No char at ${nChrIdx} on string with length: ${sDOMStr.length}`,\n );\n }\n if (nChr < 128) {\n /* one byte */\n aBytes[nIdx++] = nChr;\n } else if (nChr < 0x800) {\n /* two bytes */\n aBytes[nIdx++] = 192 + (nChr >>> 6);\n aBytes[nIdx++] = 128 + (nChr & 63);\n } else if (nChr < 0x10000) {\n /* three bytes */\n aBytes[nIdx++] = 224 + (nChr >>> 12);\n aBytes[nIdx++] = 128 + ((nChr >>> 6) & 63);\n aBytes[nIdx++] = 128 + (nChr & 63);\n } else if (nChr < 0x200000) {\n /* four bytes */\n aBytes[nIdx++] = 240 + (nChr >>> 18);\n aBytes[nIdx++] = 128 + ((nChr >>> 12) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 6) & 63);\n aBytes[nIdx++] = 128 + (nChr & 63);\n nChrIdx++;\n } else if (nChr < 0x4000000) {\n /* five bytes */\n aBytes[nIdx++] = 248 + (nChr >>> 24);\n aBytes[nIdx++] = 128 + ((nChr >>> 18) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 12) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 6) & 63);\n aBytes[nIdx++] = 128 + (nChr & 63);\n nChrIdx++;\n } /* if (nChr <= 0x7fffffff) */ else {\n /* six bytes */\n aBytes[nIdx++] = 252 + (nChr >>> 30);\n aBytes[nIdx++] = 128 + ((nChr >>> 24) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 18) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 12) & 63);\n aBytes[nIdx++] = 128 + ((nChr >>> 6) & 63);\n aBytes[nIdx++] = 128 + (nChr & 63);\n nChrIdx++;\n }\n nChrIdx++;\n }\n\n return aBytes;\n}\n", "/*\n This file is part of GNU Taler\n (C) 2021-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { HttpStatusCode } from \"@gnu-taler/taler-util\";\nimport { base64encode } from \"./base64.js\";\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport enum ErrorType {\n CLIENT,\n SERVER,\n UNREADABLE,\n TIMEOUT,\n UNEXPECTED,\n}\n\n/**\n *\n * @param baseUrl URL where the service is located\n * @param endpoint endpoint of the service to be called\n * @param options auth, method and params\n * @deprecated do not use it, it will be removed\n * @returns\n */\nexport async function defaultRequestHandler(\n baseUrl: string,\n endpoint: string,\n options: RequestOptions = {},\n): Promise> {\n const requestHeaders: Record = {};\n if (options.token) {\n requestHeaders.Authorization = `Bearer secret-token:${options.token}`;\n } else if (options.basicAuth) {\n requestHeaders.Authorization = `Basic ${base64encode(\n `${options.basicAuth.username}:${options.basicAuth.password}`,\n )}`;\n }\n\n requestHeaders[\"Content-Type\"] =\n !options.contentType || options.contentType === \"json\"\n ? \"application/json\"\n : \"text/plain\";\n\n if (options.talerAmlOfficerSignature) {\n requestHeaders[\"Taler-AML-Officer-Signature\"] =\n options.talerAmlOfficerSignature;\n }\n\n const requestMethod = options?.method ?? \"GET\";\n const requestBody = options?.data;\n const requestTimeout = options?.timeout ?? 5 * 1000;\n const requestParams = options.params ?? {};\n const requestPreventCache = options.preventCache ?? false;\n const requestPreventCors = options.preventCors ?? false;\n\n const validURL = validateURL(baseUrl, endpoint);\n\n if (!validURL) {\n const error: HttpResponseUnexpectedError = {\n info: {\n url: `${baseUrl}${endpoint}`,\n payload: {},\n hasToken: !!options.token,\n status: 0,\n options,\n },\n type: ErrorType.UNEXPECTED,\n exception: undefined,\n loading: false,\n message: `invalid URL: \"${baseUrl}${endpoint}\"`,\n };\n throw new RequestError(error);\n }\n\n Object.entries(requestParams).forEach(([key, value]) => {\n validURL.searchParams.set(key, String(value));\n });\n\n let payload: BodyInit | undefined = undefined;\n if (requestBody != null) {\n if (typeof requestBody === \"string\") {\n payload = requestBody;\n } else if (requestBody instanceof ArrayBuffer) {\n payload = requestBody;\n } else if (ArrayBuffer.isView(requestBody)) {\n payload = new Uint8Array(\n requestBody.buffer,\n requestBody.byteOffset,\n requestBody.byteLength,\n ) as Uint8Array;\n } else if (typeof requestBody === \"object\") {\n payload = JSON.stringify(requestBody);\n } else {\n const error: HttpResponseUnexpectedError = {\n info: {\n url: validURL.href,\n payload: {},\n hasToken: !!options.token,\n status: 0,\n options,\n },\n type: ErrorType.UNEXPECTED,\n exception: undefined,\n loading: false,\n message: `unsupported request body type: \"${typeof requestBody}\"`,\n };\n throw new RequestError(error);\n }\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort(\"HTTP_REQUEST_TIMEOUT\");\n }, requestTimeout);\n\n let response;\n try {\n response = await fetch(validURL.href, {\n headers: requestHeaders,\n method: requestMethod,\n credentials: \"omit\",\n mode: requestPreventCors ? \"no-cors\" : \"cors\",\n cache: requestPreventCache ? \"no-cache\" : \"default\",\n body: payload,\n signal: controller.signal,\n });\n } catch (ex) {\n const info: RequestInfo = {\n payload,\n url: validURL.href,\n hasToken: !!options.token,\n status: 0,\n options,\n };\n\n if (ex instanceof Error) {\n if (ex.message === \"HTTP_REQUEST_TIMEOUT\") {\n const error: HttpRequestTimeoutError = {\n info,\n type: ErrorType.TIMEOUT,\n message: \"request timeout\",\n };\n throw new RequestError(error);\n }\n }\n\n const error: HttpResponseUnexpectedError = {\n info,\n type: ErrorType.UNEXPECTED,\n exception: ex,\n loading: false,\n message: ex instanceof Error ? ex.message : \"\",\n };\n throw new RequestError(error);\n }\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n const headerMap = new Headers();\n response.headers.forEach((value, key) => {\n headerMap.set(key, value);\n });\n\n if (response.ok) {\n const result = await buildRequestOk(\n response,\n validURL.href,\n payload,\n !!options.token,\n options,\n );\n return result;\n } else {\n const dataTxt = await response.text();\n const error = buildRequestFailed(\n validURL.href,\n dataTxt,\n response.status,\n payload,\n options,\n );\n throw new RequestError(error);\n }\n}\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport type HttpResponse =\n | HttpResponseOk\n | HttpResponseLoading\n | HttpError;\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport type HttpResponsePaginated =\n | HttpResponseOkPaginated\n | HttpResponseLoading\n | HttpError;\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport interface RequestInfo {\n url: string;\n hasToken: boolean;\n payload: any;\n status: number;\n options: RequestOptions;\n}\n\ninterface HttpResponseLoading {\n ok?: false;\n loading: true;\n clientError?: false;\n serverError?: false;\n\n data?: T;\n}\n/**\n * @deprecated do not use it, it will be removed\n */\nexport interface HttpResponseOk {\n ok: true;\n loading?: false;\n clientError?: false;\n serverError?: false;\n\n data: T;\n info?: RequestInfo;\n}\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport type HttpResponseOkPaginated = HttpResponseOk & WithPagination;\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport interface WithPagination {\n loadMore: () => void;\n loadMorePrev: () => void;\n isReachingEnd?: boolean;\n isReachingStart?: boolean;\n}\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport type HttpError =\n | HttpRequestTimeoutError\n | HttpResponseClientError\n | HttpResponseServerError\n | HttpResponseUnreadableError\n | HttpResponseUnexpectedError;\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport interface HttpResponseServerError {\n ok?: false;\n loading?: false;\n type: ErrorType.SERVER;\n payload: ErrorDetail;\n status: HttpStatusCode;\n message: string;\n info: RequestInfo;\n}\ninterface HttpRequestTimeoutError {\n ok?: false;\n loading?: false;\n type: ErrorType.TIMEOUT;\n\n info: RequestInfo;\n\n message: string;\n}\ninterface HttpResponseClientError {\n ok?: false;\n loading?: false;\n type: ErrorType.CLIENT;\n\n info: RequestInfo;\n status: HttpStatusCode;\n payload: ErrorDetail;\n message: string;\n}\n\ninterface HttpResponseUnexpectedError {\n ok?: false;\n loading: false;\n type: ErrorType.UNEXPECTED;\n\n info: RequestInfo;\n status?: HttpStatusCode;\n exception: unknown;\n message: string;\n}\n\ninterface HttpResponseUnreadableError {\n ok?: false;\n loading: false;\n type: ErrorType.UNREADABLE;\n\n info: RequestInfo;\n status: HttpStatusCode;\n exception: unknown;\n body: string;\n message: string;\n}\n/**\n * @deprecated do not use it, it will be removed\n */\nexport class RequestError extends Error {\n /**\n * @deprecated use cause\n */\n info: HttpError;\n cause: HttpError;\n constructor(d: HttpError) {\n super(d.message);\n this.info = d;\n this.cause = d;\n }\n}\n\ntype Methods = \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\" | \"PUT\";\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport interface RequestOptions {\n method?: Methods;\n token?: string;\n basicAuth?: {\n username: string;\n password: string;\n };\n preventCache?: boolean;\n preventCors?: boolean;\n data?: any;\n params?: unknown;\n timeout?: number;\n contentType?: \"text\" | \"json\";\n talerAmlOfficerSignature?: string;\n}\n\n/**\n * @deprecated do not use it, it will be removed\n */\nasync function buildRequestOk(\n response: Response,\n url: string,\n payload: any,\n hasToken: boolean,\n options: RequestOptions,\n): Promise> {\n const dataTxt = await response.text();\n const data = dataTxt ? JSON.parse(dataTxt) : undefined;\n return {\n ok: true,\n data,\n info: {\n payload,\n url,\n hasToken,\n options,\n status: response.status,\n },\n };\n}\n\n/**\n * @deprecated do not use it, it will be removed\n */\nexport function buildRequestFailed(\n url: string,\n dataTxt: string,\n status: number,\n payload: any,\n maybeOptions?: RequestOptions,\n):\n | HttpResponseClientError\n | HttpResponseServerError\n | HttpResponseUnreadableError\n | HttpResponseUnexpectedError {\n const options = maybeOptions ?? {};\n const info: RequestInfo = {\n payload,\n url,\n hasToken: !!options.token,\n options,\n status: status || 0,\n };\n\n // const dataTxt = await response.text();\n try {\n const data = dataTxt ? JSON.parse(dataTxt) : undefined;\n const errorCode = !data || !data.code ? \"\" : `(code: ${data.code})`;\n const errorHint =\n !data || !data.hint ? \"Not hint.\" : `${data.hint} ${errorCode}`;\n\n if (status && status >= 400 && status < 500) {\n const message =\n data === undefined\n ? `Client error (${status}) without data.`\n : errorHint;\n\n const error: HttpResponseClientError = {\n type: ErrorType.CLIENT,\n status,\n info,\n message,\n payload: data,\n };\n return error;\n }\n if (status && status >= 500 && status < 600) {\n const message =\n data === undefined\n ? `Server error (${status}) without data.`\n : errorHint;\n const error: HttpResponseServerError = {\n type: ErrorType.SERVER,\n status,\n info,\n message,\n payload: data,\n };\n return error;\n }\n return {\n info,\n loading: false,\n type: ErrorType.UNEXPECTED,\n status,\n exception: undefined,\n message: `http status code not handled: ${status}`,\n };\n } catch (ex) {\n const error: HttpResponseUnreadableError = {\n info,\n loading: false,\n status,\n type: ErrorType.UNREADABLE,\n exception: ex,\n body: dataTxt,\n message: \"Could not parse body as json\",\n };\n\n return error;\n }\n}\n\n/**\n * @deprecated do not use it, it will be removed\n */\nfunction validateURL(baseUrl: string, endpoint: string): URL | undefined {\n try {\n return new URL(`${baseUrl}${endpoint}`);\n } catch (ex) {\n return undefined;\n }\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { i18n, setupI18n } from \"@gnu-taler/taler-util\";\nimport { ComponentChildren, createContext, h, VNode } from \"preact\";\nimport { useContext, useEffect } from \"preact/hooks\";\nimport { useLang } from \"../hooks/index.js\";\nimport { Locale } from \"date-fns\";\nimport {\n es as esLocale,\n enGB as enLocale,\n fr as frLocale,\n de as deLocale,\n} from \"date-fns/locale\";\n\nexport type InternationalizationAPI = typeof i18n;\n\ninterface Type {\n lang: string;\n supportedLang: { [id in keyof typeof SUPPORTED_LANGS]: string };\n changeLanguage: (l: string) => void;\n i18n: InternationalizationAPI;\n dateLocale: Locale;\n completeness: Record;\n}\n\nconst SUPPORTED_LANGS = {\n es: \"Espanol [es]\",\n en: \"English [en]\",\n fr: \"Francais [fr]\",\n de: \"Deutsch [de]\",\n // sv: \"Svenska [sv]\",\n // it: \"Italiane [it]\",\n};\n\nconst initial: Type = {\n lang: \"en\",\n supportedLang: SUPPORTED_LANGS,\n changeLanguage: () => {\n // do not change anything\n },\n i18n,\n dateLocale: enLocale,\n completeness: {\n de: 0,\n en: 0,\n es: 0,\n fr: 0,\n },\n};\nconst Context = createContext(initial);\n\ninterface LangInfo {\n lang: string;\n completeness: number;\n}\ninterface Props {\n initial?: string;\n children: ComponentChildren;\n /** ONLY USER FOR TESTING */\n forceLang__testing?: string;\n source: Record;\n}\n\n// Outmost UI wrapper.\nexport const TranslationProvider = ({\n initial,\n children,\n forceLang__testing: forceLang,\n source,\n}: Props): VNode => {\n const completeness = Object.keys(SUPPORTED_LANGS).reduce(\n (map, lang) => {\n if (lang !== \"en\" && source[lang] && source[lang].completeness) {\n map[lang] = source[lang].completeness;\n }\n return map;\n },\n { en: 100 } as Record,\n );\n\n const { value: lang, update: changeLanguage } = useLang(\n initial,\n completeness,\n );\n\n useEffect(() => {\n if (forceLang) {\n changeLanguage(forceLang);\n }\n }, [forceLang]);\n useEffect(() => {\n setupI18n(lang, source);\n }, [lang]);\n if (forceLang) {\n setupI18n(forceLang, source);\n } else {\n setupI18n(lang, source);\n }\n\n const dateLocale =\n lang === \"es\"\n ? esLocale\n : lang === \"fr\"\n ? frLocale\n : lang === \"de\"\n ? deLocale\n : enLocale;\n\n return h(Context.Provider, {\n value: {\n lang,\n changeLanguage,\n supportedLang: SUPPORTED_LANGS,\n i18n,\n dateLocale,\n completeness,\n },\n children,\n });\n};\n\nexport const useTranslationContext = (): Type => useContext(Context);\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport { CancellationToken, TalerError } from \"@gnu-taler/taler-util\";\nimport { error } from \"console\";\nimport { useCallback, useEffect, useRef, useState } from \"preact/hooks\";\n\n/**\n * convert the async function into preact hook\n *\n * @param callback the async function\n *\n * @returns operation status\n */\nexport function useAsync(\n callback: (() => Promise) | undefined,\n deps: Array = [],\n) {\n const [data, setData] = useState();\n const [error, setError] = useState();\n\n useEffect(() => {\n let unloaded = false;\n if (callback) {\n callback()\n .then((resp) => {\n if (unloaded) return;\n setData(resp);\n })\n .catch((error: unknown) => {\n if (unloaded) return;\n if (error instanceof TalerError) {\n setError(error);\n } else {\n setError(TalerError.fromException(error));\n }\n });\n }\n return () => {\n unloaded = true;\n };\n }, deps);\n\n if (error) return error;\n if (!data) return undefined;\n return data;\n}\n\nexport const LONG_POLL_DELAY = 15000;\n\n// FIXME: the problem with this compared with useSWR is that\n// if the hook is called from more than one place then\n// you will have multiple request. This needs to be merged, maybe based on a\n// key\n/**\n * First start with `initial` value, if initial is undefined then finish.\n * Otherwise:\n * Based on `initial` check if it should do long-polling with `shouldRetryFn`\n * If the result is undefined then finish.\n * Otherwise:\n * Verify if the call is going to fast, if so slow down.\n *\n * Call `retryFn` as the long poll function.\n * The result will be the next `initial` value.\n *\n *\n *\n * @param initial what we already know about the state\n * @param shouldRetryFn verify if we need to do long poll based on what we know\n * @param retryFn the long polling function that should return the same type of initial value\n * @param deps\n * @returns\n */\nexport function useLongPolling(\n initial: Res,\n shouldRetryFn: (res: Res) => boolean,\n retryFn: (ct: CancellationToken, last: Res, deps: Array) => Promise,\n deps: Array = [],\n opts: { minTime?: number } = {},\n) {\n const minTime = opts?.minTime ?? 1000;\n\n const [result, setResult] = useState(initial);\n\n useEffect(() => {\n setResult(initial);\n }, [initial, ...deps]);\n\n const ct = useRef<{\n ct: CancellationToken.Source | undefined;\n unloaded: boolean;\n startMs: number;\n }>({ ct: undefined, unloaded: false, startMs: 0 });\n\n useEffect(() => {\n // if (result === undefined || result instanceof TalerError) return;\n\n const tk = CancellationToken.create();\n ct.current.ct = tk;\n\n const doWeRetry = shouldRetryFn(result);\n if (!doWeRetry) return;\n\n const diff = new Date().getTime() - ct.current.startMs;\n if (ct.current.startMs === 0 || diff > minTime) {\n ct.current.startMs = new Date().getTime();\n retryFn(tk.token, result, deps)\n .then((r) => {\n if (!tk.token.isCancelled) {\n setResult(r);\n }\n })\n .catch((error) => console.log(\"\"));\n } else {\n // calling too fast, wait whats left to reach minTime\n delayMs(minTime - diff).then(() => {\n if (ct.current.unloaded) return;\n ct.current.startMs = new Date().getTime();\n retryFn(tk.token, result, deps)\n .then((r) => {\n if (!tk.token.isCancelled) {\n setResult(r);\n }\n })\n .catch((error) => console.log(\"\"));\n });\n }\n\n return () => {};\n }, [result]);\n\n /**\n * the resultset is not needed anymore\n */\n useEffect(() => {\n return () => {\n ct.current.unloaded = true;\n ct.current.startMs = 0;\n };\n }, []);\n\n /**\n * request dependency changed\n * different resultset expected\n */\n useEffect(() => {\n return () => {\n ct.current.ct?.cancel();\n ct.current.unloaded = true;\n ct.current.startMs = 0;\n };\n }, deps);\n\n return result;\n}\n\n/**\n * this should be in taler-utils\n * @param ms\n * @returns\n */\nexport async function delayMs(ms: number): Promise {\n return new Promise((resolve, reject) => {\n setTimeout(() => resolve(), ms);\n });\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport { TalerErrorDetail, TalerHttpError } from \"@gnu-taler/taler-util\";\n// import { TalerError } from \"@gnu-taler/taler-wallet-core\";\nimport { useEffect, useMemo, useState } from \"preact/hooks\";\n\nexport interface HookOk {\n hasError: false;\n response: T;\n}\n\nexport type HookError = HookGenericError | HookOperationalError;\n\nexport interface HookGenericError {\n hasError: true;\n operational: false;\n message: string;\n}\n\nexport interface HookOperationalError {\n hasError: true;\n operational: true;\n details: TalerErrorDetail;\n}\n\ninterface WithRetry {\n retry: () => void;\n}\n\nexport type HookResponse = HookOk | HookError | undefined;\nexport type HookResponseWithRetry =\n | ((HookOk | HookError) & WithRetry)\n | undefined;\n\n/**\n * @deprecated use useAsyncWithRetry\n */\nexport function useAsyncAsHook(\n fn: () => Promise,\n deps?: any[],\n): HookResponseWithRetry {\n const [result, setHookResponse] = useState>(undefined);\n\n const args = useMemo(\n () => ({\n fn,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }),\n deps || [],\n );\n\n async function doAsync(): Promise {\n try {\n const response = await args.fn();\n if (response === false) return;\n setHookResponse({ hasError: false, response });\n } catch (e) {\n // if (e instanceof TalerError) {\n // setHookResponse({\n // hasError: true,\n // operational: true,\n // details: e.errorDetail,\n // });\n // } else\n if (e instanceof Error) {\n setHookResponse({\n hasError: true,\n operational: false,\n message: e.message,\n });\n }\n }\n }\n\n useEffect(() => {\n doAsync();\n }, [args]);\n\n if (!result) return undefined;\n return { ...result, retry: doAsync };\n}\n\n/**\n * @deprecated\n *\n * Convert an async function named $fetcher into a hook behavior\n * with a retry function condition.\n *\n * The $retry function is called every time $fetcher finalize\n * and if $retry returns true the $fetcher is called again\n *\n * @param fetcher\n * @param retry\n * @returns\n */\nexport function useAsyncWithRetry(\n fetcher: (() => Promise) | undefined,\n retry?: (res: Res | undefined, err?: TalerHttpError | undefined) => boolean,\n): { result: Res | undefined; error: TalerHttpError | undefined } {\n const [result, setResult] = useState();\n const [error, setError] = useState();\n const [retryCounter, setRetryCounter] = useState(0);\n\n let unloaded = false;\n useEffect(() => {\n if (fetcher) {\n fetcher()\n .then((resp) => {\n if (unloaded) return;\n setResult(resp);\n })\n .catch((error: TalerHttpError) => {\n if (unloaded) return;\n setError(error);\n });\n }\n\n return () => {\n unloaded = true;\n };\n }, [fetcher, retryCounter]);\n\n // retry on result or error\n // FIXME: why we need a second useEffect? this should be merged with the one above\n useEffect(() => {\n if (retry && retry(result, error)) {\n setRetryCounter((c) => c + 1);\n }\n return () => {\n unloaded = true;\n };\n }, [result, error]);\n\n return { result, error };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AbsoluteTime,\n AmountJson,\n assertUnreachable,\n TalerExchangeApi,\n TranslatedString,\n} from \"@gnu-taler/taler-util\";\nimport { useMemo, useState } from \"preact/hooks\";\nimport {\n FormDesign,\n FormMetadata,\n InternationalizationAPI,\n UIFieldHandler,\n UIFormElementConfig,\n useTranslationContext,\n} from \"../index.browser.js\";\n\n/**\n * Underlying state model for the form UI.\n */\nexport interface FormModel {\n /**\n * Get a handler for an UI field based on the field identifier.\n */\n getHandlerForUiField(fieldId: string): UIFieldHandler;\n\n /**\n * Get the field handler for an attribute.\n *\n * If there are multiple handlers for the same attribute path,\n * an arbitrary handler is returned.\n *\n * (In the future, this might be changed to return the only currently\n * visible handler.)\n */\n getHandlerForAttributeKey(attributeKey: string): UIFieldHandler;\n\n /**\n * Check if a section of the form is hidden.\n */\n isSectionHidden(sectionName: string): boolean;\n}\n\n/**\n * Implementation of {@link FormModel}.\n */\nclass FormModelImpl implements FormModel {\n public fieldHandlers: { [x: string]: UIFieldHandler } = {};\n public hiddenSections: Set = new Set();\n\n getHandlerForUiField(fieldId: string): UIFieldHandler {\n return this.fieldHandlers[fieldId];\n }\n\n getHandlerForAttributeKey(attributeKey: string): UIFieldHandler {\n for (const h of Object.values(this.fieldHandlers)) {\n if (h.name === attributeKey) {\n return h;\n }\n }\n throw Error(`no handler for attribute path ${attributeKey}`);\n }\n\n isSectionHidden(sectionName: string): boolean {\n return this.hiddenSections.has(sectionName);\n }\n}\n\nexport type FormValues = {\n [k in keyof T]: T[k] extends string ? string | undefined : FormValues;\n};\n\nexport type RecursivePartial = {\n [k in keyof T]?: T[k] extends string\n ? string\n : T[k] extends AmountJson\n ? T[k]\n : T[k] extends Array\n ? T[k]\n : T[k] extends TalerExchangeApi.AmlState\n ? T[k]\n : RecursivePartial;\n};\n\nexport type ErrorAndLabel = {\n message: TranslatedString;\n label: TranslatedString;\n section: TranslatedString | undefined;\n};\n\nexport type FormErrors = {\n [k in keyof T]?: T[k] extends string\n ? ErrorAndLabel\n : T[k] extends AmountJson\n ? ErrorAndLabel\n : T[k] extends AbsoluteTime\n ? ErrorAndLabel\n : T[k] extends TalerExchangeApi.AmlState\n ? ErrorAndLabel\n : FormErrors;\n};\n\nexport type FormStatus =\n | {\n status: \"ok\";\n result: T;\n errors: undefined;\n }\n | {\n status: \"fail\";\n result: RecursivePartial;\n errors: FormErrors;\n };\n\n/**\n * FIMXE: Consider renaming this to FormModel and folding the current FormModel into it.\n */\nexport type FormState = {\n design: FormDesign;\n model: FormModel;\n status: FormStatus;\n update: (f: FormValues) => void;\n};\n\n/**\n * Hook to instantiate a form from its metadata.\n */\nexport function useFormMeta(\n form: FormMetadata,\n formContext: any,\n initialValue: RecursivePartial>,\n): FormState {\n let formDesign: FormDesign;\n if (typeof form.config === \"function\") {\n const config = form.config;\n formDesign = useMemo(() => config(formContext), [form, formContext]);\n } else {\n formDesign = form.config;\n }\n return useForm(formDesign, initialValue);\n}\n\n/**\n * Hook to instantiate a form from its design.\n */\nexport function useForm(\n design: FormDesign,\n initialValue: RecursivePartial>,\n): FormState {\n const { i18n } = useTranslationContext();\n const [formValue, formUpdateHandler] =\n useState>>(initialValue);\n\n const { model, result, errors } = constructFormHandler(\n design,\n formValue,\n formUpdateHandler,\n i18n,\n );\n\n const status = {\n status: errors === undefined ? \"ok\" : \"fail\",\n result,\n errors,\n } as FormStatus;\n\n return {\n model,\n status,\n update: (f) => {\n formUpdateHandler(f as any);\n },\n design,\n };\n}\n\n/**\n * Use {@link path} to get the value of {@link object}.\n * Return {@link fallbackValue} if the target property is undefined\n */\nexport function getValueFromPath(\n object: any,\n path: string[],\n fallbackValue?: any,\n): any {\n if (path.length === 0) return object;\n const [head, ...rest] = path;\n if (!head) {\n return getValueFromPath(object, rest, fallbackValue);\n }\n if (object === undefined) {\n return fallbackValue;\n }\n return getValueFromPath(object[head], rest, fallbackValue);\n}\n\n/**\n * Use $path to set the value $value into $object\n * Don't modify $object, returns a new value\n * returns undefined if the object is empty\n */\nfunction setValueIntoPath(object: any, path: string[], value: any): any {\n if (path.length === 0) return value;\n const [head, ...rest] = path;\n if (!head) {\n return setValueIntoPath(object, rest, value);\n }\n if (object === undefined) {\n return undefinedIfEmpty({ [head]: setValueIntoPath({}, rest, value) });\n }\n return undefinedIfEmpty({\n ...object,\n [head]: setValueIntoPath(object[head] ?? {}, rest, value),\n });\n}\n\nexport function undefinedIfEmpty(\n obj: T,\n): T | undefined {\n if (obj === undefined) return undefined;\n return Object.keys(obj).some(\n (k) => (obj as Record)[k] !== undefined,\n )\n ? obj\n : undefined;\n}\n\nfunction checkFormFieldIsValid(\n formElement: UIFormElementConfig,\n currentValue: string | undefined,\n i18n: InternationalizationAPI,\n secitonTitle: string | undefined,\n form: any,\n): ErrorAndLabel | undefined {\n if (!(\"id\" in formElement)) {\n return undefined;\n }\n\n if (formElement.required && currentValue === undefined) {\n return {\n label: formElement.label as TranslatedString,\n message: i18n.str`required`,\n section: secitonTitle as TranslatedString,\n };\n } else if (formElement.validator) {\n try {\n const message = formElement.validator(currentValue as any, form);\n if (message !== undefined) {\n return {\n label: formElement.label as TranslatedString,\n message,\n section: secitonTitle as TranslatedString,\n };\n }\n } catch (e) {\n console.error(e);\n const message = i18n.str`Validation function failed. Contact developers ${String(\n e,\n )}`;\n console.log(message);\n return {\n label: formElement.label as TranslatedString,\n message,\n section: secitonTitle as TranslatedString,\n };\n }\n }\n return undefined;\n}\n\n/**\n * @param formValue Plain, unprocessed form contents.\n */\nfunction constructFormHandler(\n design: FormDesign,\n formValue: RecursivePartial>,\n onValueChange: (d: RecursivePartial>) => void,\n i18n: InternationalizationAPI,\n): {\n model: FormModel;\n result: FormStatus;\n errors: FormErrors | undefined;\n} {\n let model: FormModelImpl = new FormModelImpl();\n let result = {} as FormStatus;\n let errors: FormErrors | undefined = undefined;\n\n function createFieldHandler(\n formElement: UIFormElementConfig,\n hiddenSection: boolean | undefined,\n handlerUiPath: string,\n secitonTitle: string | undefined,\n ): void {\n let field: UIFieldHandler;\n\n if (\"id\" in formElement) {\n const path = formElement.id.split(\".\");\n\n const currentValue = getValueFromPath(formValue as any, path, undefined);\n\n // compute prop based on state\n const hidden =\n hiddenSection ||\n formElement.hidden ||\n (formElement.hide && formElement.hide(currentValue, result));\n\n const currentError: ErrorAndLabel | undefined = !hidden\n ? checkFormFieldIsValid(\n formElement,\n currentValue,\n i18n,\n secitonTitle,\n formValue,\n )\n : undefined;\n\n if (currentError !== undefined) {\n errors = setValueIntoPath(errors, path, currentError);\n }\n\n function updater(newValue: unknown) {\n const updated = setValueIntoPath(formValue, path, newValue) ?? {};\n onValueChange(updated);\n }\n\n field = {\n name: formElement.id,\n error: currentError?.message,\n value: currentValue,\n onChange: updater,\n formRootResult: result,\n hidden,\n };\n if (!hidden) {\n result = setValueIntoPath(result, path, field.value) ?? {};\n }\n } else {\n const hidden =\n hiddenSection ||\n formElement.hidden ||\n (formElement.hide && formElement.hide({}, result));\n field = {\n name: \"\",\n value: undefined,\n onChange: () => {},\n formRootResult: result,\n hidden,\n };\n }\n\n model.fieldHandlers[handlerUiPath] = field;\n }\n\n switch (design.type) {\n case \"double-column\": {\n design.sections.forEach((sec, secIndex) => {\n const hidden = sec.hide && sec.hide(result);\n if (hidden) {\n model.hiddenSections.add(`${secIndex}`);\n }\n\n sec.fields.forEach((f, fieldIndex) =>\n createFieldHandler(f, hidden, `${secIndex}.${fieldIndex}`, sec.title),\n );\n });\n break;\n }\n case \"single-column\": {\n design.fields.forEach((f, fieldIndex) =>\n createFieldHandler(f, undefined, `root.${fieldIndex}`, undefined),\n );\n break;\n }\n default: {\n assertUnreachable(design);\n }\n }\n\n return { model, result, errors };\n}\n", "/*\n This file is part of GNU Anastasis\n (C) 2021-2022 Anastasis SARL\n\n GNU Anastasis is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Anastasis; see the file COPYING. If not, see \n */\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nimport { AbsoluteTime, Codec, codecForString } from \"@gnu-taler/taler-util\";\nimport { useEffect, useState } from \"preact/hooks\";\nimport {\n ObservableMap,\n browserStorageMap,\n localStorageMap,\n memoryMap,\n} from \"../utils/observable.js\";\n\ndeclare const opaque_StorageKey: unique symbol;\n\nexport type StorageKey = {\n id: string;\n [opaque_StorageKey]: true;\n codec: Codec;\n};\n\nexport function buildStorageKey(\n name: string,\n codec: Codec,\n): StorageKey;\nexport function buildStorageKey(name: string): StorageKey;\nexport function buildStorageKey(\n name: string,\n codec?: Codec,\n): StorageKey {\n return {\n id: name,\n codec: codec ?? (codecForString() as Codec),\n } as StorageKey;\n}\n\nexport interface StorageState {\n value?: Type;\n update: (s: Type) => void;\n reset: () => void;\n}\n\nconst supportLocalStorage = typeof window !== \"undefined\";\nconst supportBrowserStorage =\n typeof chrome !== \"undefined\" && typeof chrome.storage !== \"undefined\";\n\n/**\n * Build setting storage\n */\nconst storage: ObservableMap = (function buildStorage() {\n if (supportBrowserStorage) {\n //browser storage is like local storage but\n //with app sync.\n //Works for almost every browser\n if (supportLocalStorage) {\n return browserStorageMap(localStorageMap());\n } else {\n // service worker doesn't have local storage\n return browserStorageMap(memoryMap());\n }\n } else if (supportLocalStorage) {\n // fallback if browser is too old\n return localStorageMap();\n } else {\n // new need to save settings somewhere\n return memoryMap();\n }\n})();\n//with initial value\nexport function useLocalStorage(\n key: StorageKey,\n defaultValue: Type,\n): Required>;\n//without initial value\nexport function useLocalStorage(\n key: StorageKey,\n): StorageState;\n// impl\nexport function useLocalStorage(\n key: StorageKey,\n defaultValue?: Type,\n): StorageState {\n const current = convert(storage.get(key.id), key, defaultValue);\n\n const [_, setStoredValue] = useState(AbsoluteTime.now().t_ms);\n\n useEffect(() => {\n return storage.onUpdate(key.id, () => {\n // const newValue = storage.get(key.id);\n setStoredValue(AbsoluteTime.now().t_ms);\n });\n }, [key.id]);\n\n const setValue = (value?: Type): void => {\n if (value === undefined) {\n storage.delete(key.id);\n } else {\n storage.set(\n key.id,\n key.codec ? JSON.stringify(value) : (value as string),\n );\n }\n };\n\n return {\n value: current,\n update: setValue,\n reset: () => {\n setValue(defaultValue);\n },\n };\n}\n\nfunction convert(\n updated: string | undefined,\n key: StorageKey,\n defaultValue?: Type,\n): Type | undefined {\n if (updated === undefined) return defaultValue; //optional\n try {\n return key.codec.decode(JSON.parse(updated));\n } catch (e) {\n console.error(\"Decoding error\", e);\n //decode error\n return defaultValue;\n }\n}\n", "import { isArrayBufferView } from \"util/types\";\n\nexport type ObservableMap = Map & {\n onAnyUpdate: (callback: () => void) => () => void;\n onUpdate: (key: string, callback: () => void) => () => void;\n};\n\n//FIXME: allow different type for different properties\nexport function memoryMap(\n backend: Map = new Map(),\n): ObservableMap {\n const obs = new EventTarget();\n const theMemoryMap: ObservableMap = {\n onAnyUpdate: (handler) => {\n obs.addEventListener(`update`, handler);\n obs.addEventListener(`clear`, handler);\n return () => {\n obs.removeEventListener(`update`, handler);\n obs.removeEventListener(`clear`, handler);\n };\n },\n onUpdate: (key, handler) => {\n obs.addEventListener(`update-${key}`, handler);\n obs.addEventListener(`clear`, handler);\n return () => {\n obs.removeEventListener(`update-${key}`, handler);\n obs.removeEventListener(`clear`, handler);\n };\n },\n delete: (key: string) => {\n const result = backend.delete(key);\n //@ts-ignore\n theMemoryMap.size = backend.length;\n obs.dispatchEvent(new Event(`update-${key}`));\n obs.dispatchEvent(new Event(`update`));\n return result;\n },\n set: (key: string, value: T) => {\n backend.set(key, value);\n //@ts-ignore\n theMemoryMap.size = backend.length;\n obs.dispatchEvent(new Event(`update-${key}`));\n obs.dispatchEvent(new Event(`update`));\n return theMemoryMap;\n },\n clear: () => {\n backend.clear();\n obs.dispatchEvent(new Event(`clear`));\n },\n entries: backend.entries.bind(backend),\n forEach: backend.forEach.bind(backend),\n get: backend.get.bind(backend),\n has: backend.has.bind(backend),\n keys: backend.keys.bind(backend),\n size: backend.size,\n values: backend.values.bind(backend),\n [Symbol.iterator]: backend[Symbol.iterator],\n [Symbol.toStringTag]: \"theMemoryMap\",\n };\n return theMemoryMap;\n}\n\n//FIXME: change this implementation to match the\n// browser storage. instead of creating a sync implementation\n// of observable map it should reuse the memoryMap and\n// sync the state with local storage\nexport function localStorageMap(): ObservableMap {\n const obs = new EventTarget();\n const theLocalStorageMap: ObservableMap = {\n onAnyUpdate: (handler) => {\n obs.addEventListener(`update`, handler);\n obs.addEventListener(`clear`, handler);\n window.addEventListener(\"storage\", handler);\n return () => {\n window.removeEventListener(\"storage\", handler);\n obs.removeEventListener(`update`, handler);\n obs.removeEventListener(`clear`, handler);\n };\n },\n onUpdate: (key, handler) => {\n obs.addEventListener(`update-${key}`, handler);\n obs.addEventListener(`clear`, handler);\n function handleStorageEvent(ev: StorageEvent) {\n if (ev.key === null || ev.key === key) {\n handler();\n }\n }\n window.addEventListener(\"storage\", handleStorageEvent);\n return () => {\n window.removeEventListener(\"storage\", handleStorageEvent);\n obs.removeEventListener(`update-${key}`, handler);\n obs.removeEventListener(`clear`, handler);\n };\n },\n delete: (key: string) => {\n const exists = localStorage.getItem(key) !== null;\n localStorage.removeItem(key);\n //@ts-ignore\n theLocalStorageMap.size = localStorage.length;\n obs.dispatchEvent(new Event(`update-${key}`));\n obs.dispatchEvent(new Event(`update`));\n return exists;\n },\n set: (key: string, v: string) => {\n localStorage.setItem(key, v);\n //@ts-ignore\n theLocalStorageMap.size = localStorage.length;\n obs.dispatchEvent(new Event(`update-${key}`));\n obs.dispatchEvent(new Event(`update`));\n return theLocalStorageMap;\n },\n clear: () => {\n localStorage.clear();\n obs.dispatchEvent(new Event(`clear`));\n },\n entries: (): IterableIterator<[string, string]> => {\n let index = 0;\n const total = localStorage.length;\n return {\n next() {\n if (index === total) return { done: true, value: undefined };\n const key = localStorage.key(index);\n if (key === null) {\n //we are going from 0 until last, this should not happen\n throw Error(\"key cant be null\");\n }\n const item = localStorage.getItem(key);\n if (item === null) {\n //the key exist, this should not happen\n throw Error(\"value cant be null\");\n }\n index = index + 1;\n return { done: false, value: [key, item] };\n },\n [Symbol.iterator]() {\n return this;\n },\n };\n },\n forEach: (cb) => {\n for (let index = 0; index < localStorage.length; index++) {\n const key = localStorage.key(index);\n if (key === null) {\n //we are going from 0 until last, this should not happen\n throw Error(\"key cant be null\");\n }\n const item = localStorage.getItem(key);\n if (item === null) {\n //the key exist, this should not happen\n throw Error(\"value cant be null\");\n }\n cb(key, item, theLocalStorageMap);\n }\n },\n get: (key: string) => {\n const item = localStorage.getItem(key);\n if (item === null) return undefined;\n return item;\n },\n has: (key: string) => {\n return localStorage.getItem(key) === null;\n },\n keys: () => {\n let index = 0;\n const total = localStorage.length;\n return {\n next() {\n if (index === total) return { done: true, value: undefined };\n const key = localStorage.key(index);\n if (key === null) {\n //we are going from 0 until last, this should not happen\n throw Error(\"key cant be null\");\n }\n index = index + 1;\n return { done: false, value: key };\n },\n [Symbol.iterator]() {\n return this;\n },\n };\n },\n size: localStorage.length,\n values: () => {\n let index = 0;\n const total = localStorage.length;\n return {\n next() {\n if (index === total) return { done: true, value: undefined };\n const key = localStorage.key(index);\n if (key === null) {\n //we are going from 0 until last, this should not happen\n throw Error(\"key cant be null\");\n }\n const item = localStorage.getItem(key);\n if (item === null) {\n //the key exist, this should not happen\n throw Error(\"value cant be null\");\n }\n index = index + 1;\n return { done: false, value: item };\n },\n [Symbol.iterator]() {\n return this;\n },\n };\n },\n [Symbol.iterator]: function (): IterableIterator<[string, string]> {\n return theLocalStorageMap.entries();\n },\n [Symbol.toStringTag]: \"theLocalStorageMap\",\n };\n return theLocalStorageMap;\n}\n\nconst isFirefox =\n typeof (window as any) !== \"undefined\" &&\n typeof (window as any)[\"InstallTrigger\"] !== \"undefined\";\n\nasync function getAllContent() {\n //Firefox and Chrome has different storage api\n if (isFirefox) {\n // @ts-ignore\n return browser.storage.local.get();\n } else {\n return chrome.storage.local.get();\n }\n}\n\nasync function updateContent(obj: Record) {\n if (isFirefox) {\n // @ts-ignore\n return browser.storage.local.set(obj);\n } else {\n return chrome.storage.local.set(obj);\n }\n}\ntype Changes = { [key: string]: { oldValue?: any; newValue?: any } };\nfunction onBrowserStorageUpdate(cb: (changes: Changes) => void): void {\n if (isFirefox) {\n // @ts-ignore\n browser.storage.local.onChanged.addListener(cb);\n } else {\n chrome.storage.local.onChanged.addListener(cb);\n }\n}\n\nexport function browserStorageMap(\n backend: ObservableMap,\n): ObservableMap {\n getAllContent().then((content) => {\n Object.entries(content ?? {}).forEach(([k, v]) => {\n backend.set(k, v as string);\n });\n });\n\n backend.onAnyUpdate(async () => {\n const result: Record = {};\n for (const [key, value] of backend.entries()) {\n result[key] = value;\n }\n await updateContent(result);\n });\n\n onBrowserStorageUpdate((changes) => {\n //another chrome instance made the change\n const changedItems = Object.keys(changes);\n if (changedItems.length === 0) {\n backend.clear();\n } else {\n for (const key of changedItems) {\n if (!changes[key].newValue) {\n backend.delete(key);\n } else {\n if (changes[key].newValue !== changes[key].oldValue) {\n backend.set(key, changes[key].newValue);\n }\n }\n }\n }\n });\n\n return backend;\n}\n", "/*\n This file is part of GNU Anastasis\n (C) 2021-2022 Anastasis SARL\n\n GNU Anastasis is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Anastasis; see the file COPYING. If not, see \n */\n\nimport {\n StorageState,\n buildStorageKey,\n useLocalStorage,\n} from \"./useLocalStorage.js\";\n\n/**\n * If the translation is under this threshold then\n * browser won't automatically switch to default lang.\n *\n */\nconst MIN_LANG_COVERAGE_THRESHOLD = 85;\n/**\n * choose the best from the browser config based on the completeness\n * on the translation\n */\nfunction getBrowserLang(\n completeness: Record,\n): string | undefined {\n if (typeof window === \"undefined\") return undefined;\n\n if (window.navigator.language) {\n if (\n completeness[window.navigator.language] >= MIN_LANG_COVERAGE_THRESHOLD\n ) {\n return window.navigator.language;\n }\n }\n if (window.navigator.languages) {\n const match = Object.entries(completeness)\n .filter(([code, value]) => {\n if (value < MIN_LANG_COVERAGE_THRESHOLD) return false; //do not consider langs below 90%\n return (\n window.navigator.languages.findIndex((l) => l.startsWith(code)) !== -1\n );\n })\n .map(([code, value]) => ({ code, value }));\n\n if (match.length > 0) {\n let max = match[0];\n match.forEach((v) => {\n if (v.value > max.value) {\n max = v;\n }\n });\n return max.code;\n }\n }\n\n return undefined;\n}\n\nconst langPreferenceKey = buildStorageKey(\"lang-preference\");\n\nexport function useLang(\n initial: string | undefined,\n completeness: Record,\n): Required {\n const defaultValue = (\n getBrowserLang(completeness) ||\n initial ||\n \"en\"\n ).substring(0, 2);\n return useLocalStorage(langPreferenceKey, defaultValue);\n}\n", "/*\n This file is part of GNU Taler\n (C) 2021-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nimport {\n Challenge,\n ChallengeRequestResponse,\n ChallengeResponse,\n} from \"@gnu-taler/taler-util\";\nimport { useState } from \"preact/hooks\";\nimport { SafeHandlerTemplate } from \"./useNotifications.js\";\n\n/**\n * State of the current MFA operation and handler to manage\n * the state and retry.\n *\n */\nexport interface MfaState {\n /**\n * If a mfa has been started this will contain\n * the challenge response.\n */\n pendingChallenge: ChallengeResponse | undefined;\n\n onChallengeRequired: (\n c: ChallengeResponse,\n repeat?: SafeHandlerTemplate<[ids: string[]], any>,\n ) => void;\n\n onChallengeRequiredWithInitial: (\n c: ChallengeResponse,\n initial: { request: Challenge; response: ChallengeRequestResponse },\n repeat?: SafeHandlerTemplate<[ids: string[]], any>,\n ) => void;\n /**\n * Cancel the current pending challenge.\n *\n * @returns\n */\n doCancelChallenge: () => void;\n\n repeatCall?: SafeHandlerTemplate<[string[]], any>;\n\n initial?: { request: Challenge; response: ChallengeRequestResponse };\n}\n\n/**\n * Handler to be used by the function performing the MFA\n * guarded operation\n */\nexport interface MfaHandler {\n /**\n * Callback handler to use when the operation fails with MFA required\n * @param challenge\n * @param params\n * @returns\n */\n onChallengeRequired: (challenge: ChallengeResponse, ...params: any[]) => void;\n /**\n * Challenges that are already solved and can be used for the operation.\n * If this is undefined it may mean that it is the first call.\n */\n ids: string[] | undefined;\n}\n\n/**\n * asd\n */\ntype CallbackFactory = (\n h: MfaHandler,\n) => (...args: T) => Promise;\n\n/**\n * @returns\n */\nexport function useChallengeHandler(): MfaState {\n const [state, setState] = useState<{\n challenge: ChallengeResponse;\n initial?: { request: Challenge; response: ChallengeRequestResponse };\n repeat?: SafeHandlerTemplate<[string[]], any>;\n }>();\n\n function reset() {\n setState(undefined);\n }\n\n function onChallengeRequired(\n challenge: ChallengeResponse,\n repeat?: SafeHandlerTemplate<[string[]], any>,\n ) {\n setState({ challenge, initial: undefined, repeat });\n }\n function onChallengeRequiredWithInitial(\n challenge: ChallengeResponse,\n initial: { request: Challenge; response: ChallengeRequestResponse },\n repeat?: SafeHandlerTemplate<[string[]], any>,\n ) {\n setState({ challenge, initial, repeat });\n }\n\n return {\n doCancelChallenge: reset,\n onChallengeRequired,\n onChallengeRequiredWithInitial,\n pendingChallenge: state?.challenge,\n repeatCall: state?.repeat,\n initial: state?.initial,\n };\n}\n", "/*\n This file is part of GNU Anastasis\n (C) 2021-2022 Anastasis SARL\n\n GNU Anastasis is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License along with\n GNU Anastasis; see the file COPYING. If not, see \n */\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nimport { useEffect, useState } from \"preact/hooks\";\nimport { ObservableMap, memoryMap } from \"../utils/observable.js\";\nimport { StorageState } from \"./useLocalStorage.js\";\n\nconst storage: ObservableMap = memoryMap();\n\n//with initial value\nexport function useMemoryStorage(\n key: string,\n defaultValue: Type,\n): Required>;\n//with initial value\nexport function useMemoryStorage(\n key: string,\n): StorageState;\n// impl\nexport function useMemoryStorage(\n key: string,\n defaultValue?: Type,\n): StorageState {\n const [storedValue, setStoredValue] = useState(\n (): Type | undefined => {\n const prev = storage.get(key);\n return prev === undefined ? defaultValue : prev;\n },\n );\n\n useEffect(() => {\n return storage.onUpdate(key, () => {\n const newValue = storage.get(key);\n setStoredValue(newValue === undefined ? defaultValue : newValue);\n });\n }, [key]);\n\n const setValue = (value?: Type): void => {\n if (value === undefined) {\n storage.delete(key);\n } else {\n storage.set(key, value);\n }\n };\n\n return {\n value: storedValue,\n update: setValue,\n reset: () => {\n setValue(defaultValue);\n },\n };\n}\n", "import {\n AbsoluteTime,\n assertUnreachable,\n Duration,\n OperationAlternative,\n OperationFail,\n OperationOk,\n OperationResult,\n TalerError,\n TalerErrorCode,\n TranslatedString,\n} from \"@gnu-taler/taler-util\";\nimport { useEffect, useState } from \"preact/hooks\";\nimport {\n InternationalizationAPI,\n memoryMap,\n useTranslationContext,\n} from \"../index.browser.js\";\n\nexport type NotificationMessage = ErrorNotification | InfoNotification;\n\nexport interface ErrorNotification {\n type: \"error\";\n title: TranslatedString;\n ack?: boolean;\n timeout?: boolean;\n description?: TranslatedString[];\n debug?: any;\n actions?: {};\n when: AbsoluteTime;\n}\nexport interface InfoNotification {\n type: \"info\";\n title: TranslatedString;\n ack?: boolean;\n timeout?: boolean;\n when: AbsoluteTime;\n}\n\nconst storage = memoryMap>();\nconst NOTIFICATION_KEY = \"notification\";\n\nexport const GLOBAL_NOTIFICATION_TIMEOUT = Duration.fromSpec({\n seconds: 5,\n});\n\nfunction updateInStorage(n: NotificationMessage) {\n const h = hash(n);\n const mem = storage.get(NOTIFICATION_KEY) ?? new Map();\n const newState = new Map(mem);\n newState.set(h, n);\n storage.set(NOTIFICATION_KEY, newState);\n}\n\nexport function notify(notif: NotificationMessage): void {\n const currentState: Map =\n storage.get(NOTIFICATION_KEY) ?? new Map();\n const newState = currentState.set(hash(notif), notif);\n\n if (GLOBAL_NOTIFICATION_TIMEOUT.d_ms !== \"forever\") {\n setTimeout(() => {\n notif.timeout = true;\n updateInStorage(notif);\n }, GLOBAL_NOTIFICATION_TIMEOUT.d_ms);\n }\n\n storage.set(NOTIFICATION_KEY, newState);\n}\nexport function notifyError(\n title: TranslatedString,\n description: TranslatedString | undefined,\n debug?: any,\n) {\n notify({\n type: \"error\" as const,\n title,\n description: description ? [description] : undefined,\n debug,\n when: AbsoluteTime.now(),\n });\n}\nexport function notifyException(title: TranslatedString, ex: Error) {\n notify({\n type: \"error\" as const,\n title,\n description: [ex.message as TranslatedString],\n debug: ex.stack,\n when: AbsoluteTime.now(),\n });\n}\nexport function notifyInfo(title: TranslatedString) {\n notify({\n type: \"info\" as const,\n title,\n when: AbsoluteTime.now(),\n });\n}\n\nexport type Notification = {\n message: NotificationMessage;\n acknowledge: () => void;\n};\n\nexport function useNotifications(): Notification[] {\n const [, setLastUpdate] = useState();\n const value = storage.get(NOTIFICATION_KEY) ?? new Map();\n\n useEffect(() => {\n return storage.onUpdate(NOTIFICATION_KEY, () => {\n setLastUpdate(Date.now());\n // const mem = storage.get(NOTIFICATION_KEY) ?? new Map();\n // setter(structuredClone(mem));\n });\n });\n\n return Array.from(value.values()).map((message, idx) => {\n return {\n message,\n acknowledge: () => {\n message.ack = true;\n updateInStorage(message);\n },\n };\n });\n}\n\nfunction hashCode(str: string): string {\n if (str.length === 0) return \"0\";\n let hash = 0;\n let chr;\n for (let i = 0; i < str.length; i++) {\n chr = str.charCodeAt(i);\n hash = (hash << 5) - hash + chr;\n hash |= 0; // Convert to 32bit integer\n }\n return hash.toString(16);\n}\n\nfunction hash(msg: NotificationMessage): string {\n let str = (msg.type + \":\" + msg.title) as string;\n if (msg.type === \"error\") {\n if (msg.description) {\n str += \":\" + msg.description;\n }\n if (msg.debug) {\n str += \":\" + msg.debug;\n }\n }\n return hashCode(str);\n}\n\n/**\n * A function that may fail and return a message to be shown\n * as a notification\n */\nexport type FunctionThatMayFail = (\n ...args: T\n) => Promise;\n\n/**\n * Initialize a notification handler.\n * @returns a tuple of notification and setter\n * 1) notification that may be set by a function when it fails.\n * 2) a error handling function that converts a function that returns a message\n * into a function that will set the notification.\n *\n */\nexport function useLocalNotificationBetter(): [\n Notification | undefined,\n >(\n opName: TranslatedString,\n doAction: (...args: Args) => Promise,\n args?: Args,\n ) => SafeHandlerTemplate,\n] {\n const [value, save] = useState();\n const notif = !value\n ? undefined\n : {\n message: value,\n acknowledge: () => {\n save(undefined);\n },\n };\n\n // FIXME: we should move this outside of logic\n const { i18n } = useTranslationContext();\n\n function safeFunctionHandler<\n Args extends any[],\n R extends OperationResult,\n >(\n opName: TranslatedString,\n doAction: (...args: Args) => Promise,\n args?: Args,\n ): SafeHandlerTemplate {\n function buildSafeHandler(\n a: Args | undefined,\n doAction: (...args: Args) => Promise,\n ): SafeHandlerTemplate {\n const thiz: SafeHandlerTemplate = {\n args: a,\n withArgs: (...newArgs) => {\n const r = buildSafeHandler(newArgs, doAction);\n r.onSuccess = thiz.onSuccess;\n r.onFail = thiz.onFail;\n return r;\n },\n lambda: (converter, init) => {\n type D = Parameters;\n type SH = SafeHandlerTemplate;\n\n const r = buildSafeHandler(\n init ? converter(...init) : undefined,\n doAction,\n );\n // @ts-expect-error\n r.withArgs = (...args: D) => {\n const d = converter(...args);\n if (!d) return thiz;\n const e = thiz.withArgs(...d);\n return e;\n };\n /**\n * FIXME: there is a problem with this\n *\n * adding onSuccess function after creating the lambda makes the withArgs\n * build handlers without onSuccess. consider this\n *\n * const h = safeHandler(handler).lambda((param) -> .. )\n * h.onSuccess = () => i18n.str`ok`\n * const button = h.withArgs(p);\n *\n * button.call()\n *\n * the onSuccess function is undefined when button is clicked.\n * But not if the lambda is created after the onSuccess assignment\n */\n r.onSuccess = thiz.onSuccess;\n r.onFail = thiz.onFail;\n return r as any as SH;\n },\n call: async (): Promise => {\n if (!thiz.args) return;\n try {\n thiz.onStart();\n const resp = await doAction(...thiz.args);\n switch (resp.type) {\n case \"ok\": {\n const msg = thiz.onSuccess(resp.body, ...thiz.args);\n if (msg) {\n save(successWithTitle(msg));\n }\n return;\n }\n case \"fail\": {\n const error = thiz.onFail(resp as any, ...thiz.args);\n if (error) {\n save(failWithTitle(i18n, opName, resp, error, thiz.args));\n }\n return;\n }\n default: {\n assertUnreachable(resp);\n }\n }\n } catch (error: unknown) {\n // This functions should not throw, this is a problem.\n logBugForDevelopers(error);\n onUnexpected(\n i18n,\n i18n.str`Unexpected error trying to ${opName}`,\n save,\n )(error, thiz.args);\n return;\n }\n },\n onFail: (fail, ...rest) =>\n i18n.str`Unhandled failure trying to ${opName}. Code ${fail.case}`,\n onSuccess: () => undefined,\n onStart: () => undefined,\n };\n return thiz;\n }\n return buildSafeHandler(args, doAction);\n }\n\n return [notif, safeFunctionHandler];\n}\n\nexport function logBugForDevelopers(error: unknown) {\n console.error(\n `Internal error, this is mostly a bug in the application. Please report: `,\n error,\n );\n}\n\nfunction describeErrorResponse(\n i18n: InternationalizationAPI,\n errorResponse: { code?: number; hint?: string },\n): TranslatedString | undefined {\n if (!errorResponse.code) return undefined;\n switch (errorResponse.code) {\n case TalerErrorCode.GENERIC_JSON_INVALID:\n return i18n.str`Looks like the JSON in the request was malformed.`;\n default:\n return undefined;\n }\n}\n\nfunction notUndefined(t: T | undefined): t is T {\n return !!t;\n}\n\nfunction translateTalerError(\n cause: TalerError,\n i18n: InternationalizationAPI,\n): TranslatedString[] {\n if (\n cause.hasErrorCode(TalerErrorCode.GENERIC_TIMEOUT) ||\n cause.hasErrorCode(TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT)\n ) {\n return [\n i18n.str`The request reached a timeout, check your connection.`,\n i18n.str`The ${cause.errorDetail.requestMethod} request to ${\n cause.errorDetail.requestUrl\n } failed after ${cause.errorDetail.timeoutMs / 1000} seconds.`,\n cause.errorDetail.when\n ? i18n.str`The last request time is ${AbsoluteTime.stringify(\n cause.errorDetail.when,\n )}`\n : undefined,\n ].filter(notUndefined);\n }\n if (cause.hasErrorCode(TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR)) {\n return [\n i18n.str`The request was cancelled.`,\n i18n.str`The ${cause.errorDetail.requestMethod} request ${cause.errorDetail.requestUrl} failed with code ${cause.errorDetail.httpStatusCode}.`,\n cause.errorDetail.when\n ? i18n.str`The request was made at ${AbsoluteTime.stringify(\n cause.errorDetail.when,\n )}`\n : undefined,\n ].filter(notUndefined);\n }\n if (cause.hasErrorCode(TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED)) {\n return [\n i18n.str`Too many requests were made to the server and this action was throttled.`,\n i18n.str`The request \"${cause.errorDetail.requestMethod} ${cause.errorDetail.requestUrl}\" failed with an code ${cause.errorDetail.httpStatusCode}`,\n cause.errorDetail.when\n ? i18n.str`The last request time is ${AbsoluteTime.stringify(\n cause.errorDetail.when,\n )}`\n : undefined,\n ].filter(notUndefined);\n }\n if (cause.hasErrorCode(TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE)) {\n return [\n i18n.str`The server's response was malformed.`,\n i18n.str`The response to \"${cause.errorDetail.requestMethod} ${cause.errorDetail.requestUrl}\" failed with an code ${cause.errorDetail.httpStatusCode}`,\n cause.errorDetail.when\n ? i18n.str`The request was made at ${AbsoluteTime.stringify(\n cause.errorDetail.when,\n )}`\n : undefined,\n cause.errorDetail.contentType\n ? i18n.str`The content type is ${cause.errorDetail.contentType}`\n : undefined,\n cause.errorDetail.validationError\n ? i18n.str`The validation error is \"${cause.errorDetail.validationError}\"`\n : undefined,\n cause.errorDetail.response\n ? (cause.errorDetail.response as TranslatedString)\n : undefined,\n ].filter(notUndefined);\n }\n if (cause.hasErrorCode(TalerErrorCode.WALLET_NETWORK_ERROR)) {\n return [\n i18n.str`Due to a network problem the request could not be finished.`,\n i18n.str`The ${cause.errorDetail.requestMethod} request to ${cause.errorDetail.requestUrl} failed.`,\n cause.errorDetail.when\n ? i18n.str`The request was made at ${AbsoluteTime.stringify(\n cause.errorDetail.when,\n )}`\n : undefined,\n ].filter(notUndefined);\n }\n if (cause.hasErrorCode(TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR)) {\n const hint =\n \"hint\" in cause.errorDetail.errorResponse\n ? cause.errorDetail.errorResponse.hint\n : undefined;\n return [\n i18n.str`The server's response was unexpected. This mean the client and the server are not in sync about the protocol.`,\n i18n.str`The ${cause.errorDetail.requestMethod} request to ${cause.errorDetail.requestUrl} failed with code ${cause.errorDetail.httpStatusCode}`,\n cause.errorDetail.when\n ? i18n.str`The request was made at ${AbsoluteTime.stringify(\n cause.errorDetail.when,\n )}`\n : undefined,\n describeErrorResponse(i18n, cause.errorDetail.errorResponse),\n hint ? i18n.str`And the server say: \"${hint}\"` : undefined,\n ].filter(notUndefined);\n }\n return [i18n.str`Unexpected error`, cause.message as TranslatedString];\n}\n\nfunction onUnexpected(\n i18n: InternationalizationAPI,\n title: TranslatedString,\n save: (m: NotificationMessage) => void,\n): (cause: unknown, args: any[]) => void {\n return (error, args) => {\n if (error instanceof TalerError) {\n save({\n title,\n type: \"error\",\n description: translateTalerError(error, i18n),\n debug: {\n error,\n stack: error instanceof Error ? error.stack : undefined,\n args: sanitizeFunctionArguments(args),\n when: AbsoluteTime.now(),\n },\n when: AbsoluteTime.now(),\n });\n } else {\n const description = (\n error instanceof Error ? error.message : String(error)\n ) as TranslatedString;\n\n save({\n title,\n type: \"error\",\n description: [\n i18n.str`Unexpected error, this is likely a bug. Please report `,\n ],\n debug: {\n error: String(error),\n stack: error instanceof Error ? error.stack : undefined,\n args: sanitizeFunctionArguments(args),\n when: AbsoluteTime.now(),\n },\n when: AbsoluteTime.now(),\n });\n }\n };\n}\n\nfunction sanitizeFunctionArguments(args: any[]): string {\n return args\n .map((d) =>\n typeof d === \"string\" && d.startsWith(\"secret-token:\")\n ? \"secret-token:...redacted...\"\n : typeof d === \"object\"\n ? JSON.stringify(d, undefined, 2)\n : d,\n )\n .join(\", \");\n}\n\ninterface AppEvents {\n \"on-success\": { userId: string; timestamp: number };\n \"on-fail\": undefined; // Or void if no payload\n}\n\n/**\n * A function converted into a safe handler.\n *\n *\n */\nexport interface SafeHandlerTemplate {\n readonly args: Args | undefined;\n /**\n * call the action with the arguments\n */\n call(): Promise;\n /**\n * creates another handler for the same actions but different arguments\n * @param e\n */\n lambda(\n e: (...d: OtherArgs) => Args | undefined,\n init?: OtherArgs,\n ): SafeHandlerTemplate;\n /**\n * creates another handler with new arguments\n * @param args\n */\n withArgs(...args: Args): SafeHandlerTemplate;\n\n onSuccess: OnOperationSuccesReturnType;\n onFail: OnOperationFailReturnType;\n onStart: () => void;\n}\n\nfunction successWithTitle(title: TranslatedString): NotificationMessage {\n return {\n title,\n type: \"info\",\n when: AbsoluteTime.now(),\n };\n}\n\nfunction failWithTitle(\n i18n: InternationalizationAPI,\n opName: TranslatedString,\n fail: OperationFail,\n description: TranslatedString,\n args: any[],\n): NotificationMessage {\n return {\n title: i18n.str`Unable to ${opName}.`,\n type: \"error\",\n description: [description],\n debug: {\n detail: fail.detail,\n case: fail.case,\n when: AbsoluteTime.now(),\n // args: sanitizeFunctionArguments(args),\n },\n when: AbsoluteTime.now(),\n };\n}\n\nexport type OnOperationSuccesReturnType = (\n result: T extends OperationOk ? B : never,\n ...args: K\n) => TranslatedString | undefined | void;\n\nexport type OnOperationFailReturnType = (\n d:\n | (T extends OperationFail ? T : never)\n | (T extends OperationAlternative ? T : never),\n ...args: K\n) => TranslatedString | undefined;\n\nexport type OnOperationUnexpectedFailReturnType = (e: unknown) => void;\n", "var formatDistanceLocale = {\n lessThanXSeconds: {\n standalone: {\n one: 'weniger als 1 Sekunde',\n other: 'weniger als {{count}} Sekunden'\n },\n withPreposition: {\n one: 'weniger als 1 Sekunde',\n other: 'weniger als {{count}} Sekunden'\n }\n },\n xSeconds: {\n standalone: {\n one: '1 Sekunde',\n other: '{{count}} Sekunden'\n },\n withPreposition: {\n one: '1 Sekunde',\n other: '{{count}} Sekunden'\n }\n },\n halfAMinute: {\n standalone: 'halbe Minute',\n withPreposition: 'halben Minute'\n },\n lessThanXMinutes: {\n standalone: {\n one: 'weniger als 1 Minute',\n other: 'weniger als {{count}} Minuten'\n },\n withPreposition: {\n one: 'weniger als 1 Minute',\n other: 'weniger als {{count}} Minuten'\n }\n },\n xMinutes: {\n standalone: {\n one: '1 Minute',\n other: '{{count}} Minuten'\n },\n withPreposition: {\n one: '1 Minute',\n other: '{{count}} Minuten'\n }\n },\n aboutXHours: {\n standalone: {\n one: 'etwa 1 Stunde',\n other: 'etwa {{count}} Stunden'\n },\n withPreposition: {\n one: 'etwa 1 Stunde',\n other: 'etwa {{count}} Stunden'\n }\n },\n xHours: {\n standalone: {\n one: '1 Stunde',\n other: '{{count}} Stunden'\n },\n withPreposition: {\n one: '1 Stunde',\n other: '{{count}} Stunden'\n }\n },\n xDays: {\n standalone: {\n one: '1 Tag',\n other: '{{count}} Tage'\n },\n withPreposition: {\n one: '1 Tag',\n other: '{{count}} Tagen'\n }\n },\n aboutXWeeks: {\n standalone: {\n one: 'etwa 1 Woche',\n other: 'etwa {{count}} Wochen'\n },\n withPreposition: {\n one: 'etwa 1 Woche',\n other: 'etwa {{count}} Wochen'\n }\n },\n xWeeks: {\n standalone: {\n one: '1 Woche',\n other: '{{count}} Wochen'\n },\n withPreposition: {\n one: '1 Woche',\n other: '{{count}} Wochen'\n }\n },\n aboutXMonths: {\n standalone: {\n one: 'etwa 1 Monat',\n other: 'etwa {{count}} Monate'\n },\n withPreposition: {\n one: 'etwa 1 Monat',\n other: 'etwa {{count}} Monaten'\n }\n },\n xMonths: {\n standalone: {\n one: '1 Monat',\n other: '{{count}} Monate'\n },\n withPreposition: {\n one: '1 Monat',\n other: '{{count}} Monaten'\n }\n },\n aboutXYears: {\n standalone: {\n one: 'etwa 1 Jahr',\n other: 'etwa {{count}} Jahre'\n },\n withPreposition: {\n one: 'etwa 1 Jahr',\n other: 'etwa {{count}} Jahren'\n }\n },\n xYears: {\n standalone: {\n one: '1 Jahr',\n other: '{{count}} Jahre'\n },\n withPreposition: {\n one: '1 Jahr',\n other: '{{count}} Jahren'\n }\n },\n overXYears: {\n standalone: {\n one: 'mehr als 1 Jahr',\n other: 'mehr als {{count}} Jahre'\n },\n withPreposition: {\n one: 'mehr als 1 Jahr',\n other: 'mehr als {{count}} Jahren'\n }\n },\n almostXYears: {\n standalone: {\n one: 'fast 1 Jahr',\n other: 'fast {{count}} Jahre'\n },\n withPreposition: {\n one: 'fast 1 Jahr',\n other: 'fast {{count}} Jahren'\n }\n }\n};\n\nvar formatDistance = function formatDistance(token, count, options) {\n var result;\n var tokenValue = options !== null && options !== void 0 && options.addSuffix ? formatDistanceLocale[token].withPreposition : formatDistanceLocale[token].standalone;\n\n if (typeof tokenValue === 'string') {\n result = tokenValue;\n } else if (count === 1) {\n result = tokenValue.one;\n } else {\n result = tokenValue.other.replace('{{count}}', String(count));\n }\n\n if (options !== null && options !== void 0 && options.addSuffix) {\n if (options.comparison && options.comparison > 0) {\n return 'in ' + result;\n } else {\n return 'vor ' + result;\n }\n }\n\n return result;\n};\n\nexport default formatDistance;", "import buildFormatLongFn from \"../../../_lib/buildFormatLongFn/index.js\";\n// DIN 5008: https://de.wikipedia.org/wiki/Datumsformat#DIN_5008\nvar dateFormats = {\n full: 'EEEE, do MMMM y',\n // Montag, 7. Januar 2018\n long: 'do MMMM y',\n // 7. Januar 2018\n medium: 'do MMM y',\n // 7. Jan. 2018\n short: 'dd.MM.y' // 07.01.2018\n\n};\nvar timeFormats = {\n full: 'HH:mm:ss zzzz',\n long: 'HH:mm:ss z',\n medium: 'HH:mm:ss',\n short: 'HH:mm'\n};\nvar dateTimeFormats = {\n full: \"{{date}} 'um' {{time}}\",\n long: \"{{date}} 'um' {{time}}\",\n medium: '{{date}} {{time}}',\n short: '{{date}} {{time}}'\n};\nvar formatLong = {\n date: buildFormatLongFn({\n formats: dateFormats,\n defaultWidth: 'full'\n }),\n time: buildFormatLongFn({\n formats: timeFormats,\n defaultWidth: 'full'\n }),\n dateTime: buildFormatLongFn({\n formats: dateTimeFormats,\n defaultWidth: 'full'\n })\n};\nexport default formatLong;", "var formatRelativeLocale = {\n lastWeek: \"'letzten' eeee 'um' p\",\n yesterday: \"'gestern um' p\",\n today: \"'heute um' p\",\n tomorrow: \"'morgen um' p\",\n nextWeek: \"eeee 'um' p\",\n other: 'P'\n};\n\nvar formatRelative = function formatRelative(token, _date, _baseDate, _options) {\n return formatRelativeLocale[token];\n};\n\nexport default formatRelative;", "import buildLocalizeFn from \"../../../_lib/buildLocalizeFn/index.js\";\nvar eraValues = {\n narrow: ['v.Chr.', 'n.Chr.'],\n abbreviated: ['v.Chr.', 'n.Chr.'],\n wide: ['vor Christus', 'nach Christus']\n};\nvar quarterValues = {\n narrow: ['1', '2', '3', '4'],\n abbreviated: ['Q1', 'Q2', 'Q3', 'Q4'],\n wide: ['1. Quartal', '2. Quartal', '3. Quartal', '4. Quartal']\n}; // Note: in German, the names of days of the week and months are capitalized.\n// If you are making a new locale based on this one, check if the same is true for the language you're working on.\n// Generally, formatted dates should look like they are in the middle of a sentence,\n// e.g. in Spanish language the weekdays and months should be in the lowercase.\n\nvar monthValues = {\n narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],\n abbreviated: ['Jan', 'Feb', 'M\u00E4r', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],\n wide: ['Januar', 'Februar', 'M\u00E4rz', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']\n}; // https://st.unicode.org/cldr-apps/v#/de/Gregorian/\n\nvar formattingMonthValues = {\n narrow: monthValues.narrow,\n abbreviated: ['Jan.', 'Feb.', 'M\u00E4rz', 'Apr.', 'Mai', 'Juni', 'Juli', 'Aug.', 'Sep.', 'Okt.', 'Nov.', 'Dez.'],\n wide: monthValues.wide\n};\nvar dayValues = {\n narrow: ['S', 'M', 'D', 'M', 'D', 'F', 'S'],\n short: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],\n abbreviated: ['So.', 'Mo.', 'Di.', 'Mi.', 'Do.', 'Fr.', 'Sa.'],\n wide: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag']\n}; // https://www.unicode.org/cldr/charts/32/summary/de.html#1881\n\nvar dayPeriodValues = {\n narrow: {\n am: 'vm.',\n pm: 'nm.',\n midnight: 'Mitternacht',\n noon: 'Mittag',\n morning: 'Morgen',\n afternoon: 'Nachm.',\n evening: 'Abend',\n night: 'Nacht'\n },\n abbreviated: {\n am: 'vorm.',\n pm: 'nachm.',\n midnight: 'Mitternacht',\n noon: 'Mittag',\n morning: 'Morgen',\n afternoon: 'Nachmittag',\n evening: 'Abend',\n night: 'Nacht'\n },\n wide: {\n am: 'vormittags',\n pm: 'nachmittags',\n midnight: 'Mitternacht',\n noon: 'Mittag',\n morning: 'Morgen',\n afternoon: 'Nachmittag',\n evening: 'Abend',\n night: 'Nacht'\n }\n};\nvar formattingDayPeriodValues = {\n narrow: {\n am: 'vm.',\n pm: 'nm.',\n midnight: 'Mitternacht',\n noon: 'Mittag',\n morning: 'morgens',\n afternoon: 'nachm.',\n evening: 'abends',\n night: 'nachts'\n },\n abbreviated: {\n am: 'vorm.',\n pm: 'nachm.',\n midnight: 'Mitternacht',\n noon: 'Mittag',\n morning: 'morgens',\n afternoon: 'nachmittags',\n evening: 'abends',\n night: 'nachts'\n },\n wide: {\n am: 'vormittags',\n pm: 'nachmittags',\n midnight: 'Mitternacht',\n noon: 'Mittag',\n morning: 'morgens',\n afternoon: 'nachmittags',\n evening: 'abends',\n night: 'nachts'\n }\n};\n\nvar ordinalNumber = function ordinalNumber(dirtyNumber) {\n var number = Number(dirtyNumber);\n return number + '.';\n};\n\nvar localize = {\n ordinalNumber: ordinalNumber,\n era: buildLocalizeFn({\n values: eraValues,\n defaultWidth: 'wide'\n }),\n quarter: buildLocalizeFn({\n values: quarterValues,\n defaultWidth: 'wide',\n argumentCallback: function argumentCallback(quarter) {\n return quarter - 1;\n }\n }),\n month: buildLocalizeFn({\n values: monthValues,\n formattingValues: formattingMonthValues,\n defaultWidth: 'wide'\n }),\n day: buildLocalizeFn({\n values: dayValues,\n defaultWidth: 'wide'\n }),\n dayPeriod: buildLocalizeFn({\n values: dayPeriodValues,\n defaultWidth: 'wide',\n formattingValues: formattingDayPeriodValues,\n defaultFormattingWidth: 'wide'\n })\n};\nexport default localize;", "import buildMatchFn from \"../../../_lib/buildMatchFn/index.js\";\nimport buildMatchPatternFn from \"../../../_lib/buildMatchPatternFn/index.js\";\nvar matchOrdinalNumberPattern = /^(\\d+)(\\.)?/i;\nvar parseOrdinalNumberPattern = /\\d+/i;\nvar matchEraPatterns = {\n narrow: /^(v\\.? ?Chr\\.?|n\\.? ?Chr\\.?)/i,\n abbreviated: /^(v\\.? ?Chr\\.?|n\\.? ?Chr\\.?)/i,\n wide: /^(vor Christus|vor unserer Zeitrechnung|nach Christus|unserer Zeitrechnung)/i\n};\nvar parseEraPatterns = {\n any: [/^v/i, /^n/i]\n};\nvar matchQuarterPatterns = {\n narrow: /^[1234]/i,\n abbreviated: /^q[1234]/i,\n wide: /^[1234](\\.)? Quartal/i\n};\nvar parseQuarterPatterns = {\n any: [/1/i, /2/i, /3/i, /4/i]\n};\nvar matchMonthPatterns = {\n narrow: /^[jfmasond]/i,\n abbreviated: /^(j[a\u00E4]n|feb|m\u00E4r[z]?|apr|mai|jun[i]?|jul[i]?|aug|sep|okt|nov|dez)\\.?/i,\n wide: /^(januar|februar|m\u00E4rz|april|mai|juni|juli|august|september|oktober|november|dezember)/i\n};\nvar parseMonthPatterns = {\n narrow: [/^j/i, /^f/i, /^m/i, /^a/i, /^m/i, /^j/i, /^j/i, /^a/i, /^s/i, /^o/i, /^n/i, /^d/i],\n any: [/^j[a\u00E4]/i, /^f/i, /^m\u00E4r/i, /^ap/i, /^mai/i, /^jun/i, /^jul/i, /^au/i, /^s/i, /^o/i, /^n/i, /^d/i]\n};\nvar matchDayPatterns = {\n narrow: /^[smdmf]/i,\n short: /^(so|mo|di|mi|do|fr|sa)/i,\n abbreviated: /^(son?|mon?|die?|mit?|don?|fre?|sam?)\\.?/i,\n wide: /^(sonntag|montag|dienstag|mittwoch|donnerstag|freitag|samstag)/i\n};\nvar parseDayPatterns = {\n any: [/^so/i, /^mo/i, /^di/i, /^mi/i, /^do/i, /^f/i, /^sa/i]\n};\nvar matchDayPeriodPatterns = {\n narrow: /^(vm\\.?|nm\\.?|Mitternacht|Mittag|morgens|nachm\\.?|abends|nachts)/i,\n abbreviated: /^(vorm\\.?|nachm\\.?|Mitternacht|Mittag|morgens|nachm\\.?|abends|nachts)/i,\n wide: /^(vormittags|nachmittags|Mitternacht|Mittag|morgens|nachmittags|abends|nachts)/i\n};\nvar parseDayPeriodPatterns = {\n any: {\n am: /^v/i,\n pm: /^n/i,\n midnight: /^Mitte/i,\n noon: /^Mitta/i,\n morning: /morgens/i,\n afternoon: /nachmittags/i,\n // will never be matched. Afternoon is matched by `pm`\n evening: /abends/i,\n night: /nachts/i // will never be matched. Night is matched by `pm`\n\n }\n};\nvar match = {\n ordinalNumber: buildMatchPatternFn({\n matchPattern: matchOrdinalNumberPattern,\n parsePattern: parseOrdinalNumberPattern,\n valueCallback: function valueCallback(value) {\n return parseInt(value);\n }\n }),\n era: buildMatchFn({\n matchPatterns: matchEraPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseEraPatterns,\n defaultParseWidth: 'any'\n }),\n quarter: buildMatchFn({\n matchPatterns: matchQuarterPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseQuarterPatterns,\n defaultParseWidth: 'any',\n valueCallback: function valueCallback(index) {\n return index + 1;\n }\n }),\n month: buildMatchFn({\n matchPatterns: matchMonthPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseMonthPatterns,\n defaultParseWidth: 'any'\n }),\n day: buildMatchFn({\n matchPatterns: matchDayPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseDayPatterns,\n defaultParseWidth: 'any'\n }),\n dayPeriod: buildMatchFn({\n matchPatterns: matchDayPeriodPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseDayPeriodPatterns,\n defaultParseWidth: 'any'\n })\n};\nexport default match;", "import formatDistance from \"./_lib/formatDistance/index.js\";\nimport formatLong from \"./_lib/formatLong/index.js\";\nimport formatRelative from \"./_lib/formatRelative/index.js\";\nimport localize from \"./_lib/localize/index.js\";\nimport match from \"./_lib/match/index.js\";\n\n/**\n * @type {Locale}\n * @category Locales\n * @summary German locale.\n * @language German\n * @iso-639-2 deu\n * @author Thomas Eilmsteiner [@DeMuu]{@link https://github.com/DeMuu}\n * @author Asia [@asia-t]{@link https://github.com/asia-t}\n * @author Van Vuong Ngo [@vanvuongngo]{@link https://github.com/vanvuongngo}\n * @author RomanErnst [@pex]{@link https://github.com/pex}\n * @author Philipp Keck [@Philipp91]{@link https://github.com/Philipp91}\n */\nvar locale = {\n code: 'de',\n formatDistance: formatDistance,\n formatLong: formatLong,\n formatRelative: formatRelative,\n localize: localize,\n match: match,\n options: {\n weekStartsOn: 1\n /* Monday */\n ,\n firstWeekContainsDate: 4\n }\n};\nexport default locale;", "import buildFormatLongFn from \"../../../_lib/buildFormatLongFn/index.js\";\nvar dateFormats = {\n full: 'EEEE, d MMMM yyyy',\n long: 'd MMMM yyyy',\n medium: 'd MMM yyyy',\n short: 'dd/MM/yyyy'\n};\nvar timeFormats = {\n full: 'HH:mm:ss zzzz',\n long: 'HH:mm:ss z',\n medium: 'HH:mm:ss',\n short: 'HH:mm'\n};\nvar dateTimeFormats = {\n full: \"{{date}} 'at' {{time}}\",\n long: \"{{date}} 'at' {{time}}\",\n medium: '{{date}}, {{time}}',\n short: '{{date}}, {{time}}'\n};\nvar formatLong = {\n date: buildFormatLongFn({\n formats: dateFormats,\n defaultWidth: 'full'\n }),\n time: buildFormatLongFn({\n formats: timeFormats,\n defaultWidth: 'full'\n }),\n dateTime: buildFormatLongFn({\n formats: dateTimeFormats,\n defaultWidth: 'full'\n })\n};\nexport default formatLong;", "import formatDistance from \"../en-US/_lib/formatDistance/index.js\";\nimport formatRelative from \"../en-US/_lib/formatRelative/index.js\";\nimport localize from \"../en-US/_lib/localize/index.js\";\nimport match from \"../en-US/_lib/match/index.js\";\nimport formatLong from \"./_lib/formatLong/index.js\";\n/**\n * @type {Locale}\n * @category Locales\n * @summary English locale (United Kingdom).\n * @language English\n * @iso-639-2 eng\n * @author Alex [@glintik]{@link https://github.com/glintik}\n */\n\nvar locale = {\n code: 'en-GB',\n formatDistance: formatDistance,\n formatLong: formatLong,\n formatRelative: formatRelative,\n localize: localize,\n match: match,\n options: {\n weekStartsOn: 1\n /* Monday */\n ,\n firstWeekContainsDate: 4\n }\n};\nexport default locale;", "var formatDistanceLocale = {\n lessThanXSeconds: {\n one: 'menos de un segundo',\n other: 'menos de {{count}} segundos'\n },\n xSeconds: {\n one: '1 segundo',\n other: '{{count}} segundos'\n },\n halfAMinute: 'medio minuto',\n lessThanXMinutes: {\n one: 'menos de un minuto',\n other: 'menos de {{count}} minutos'\n },\n xMinutes: {\n one: '1 minuto',\n other: '{{count}} minutos'\n },\n aboutXHours: {\n one: 'alrededor de 1 hora',\n other: 'alrededor de {{count}} horas'\n },\n xHours: {\n one: '1 hora',\n other: '{{count}} horas'\n },\n xDays: {\n one: '1 d\u00EDa',\n other: '{{count}} d\u00EDas'\n },\n aboutXWeeks: {\n one: 'alrededor de 1 semana',\n other: 'alrededor de {{count}} semanas'\n },\n xWeeks: {\n one: '1 semana',\n other: '{{count}} semanas'\n },\n aboutXMonths: {\n one: 'alrededor de 1 mes',\n other: 'alrededor de {{count}} meses'\n },\n xMonths: {\n one: '1 mes',\n other: '{{count}} meses'\n },\n aboutXYears: {\n one: 'alrededor de 1 a\u00F1o',\n other: 'alrededor de {{count}} a\u00F1os'\n },\n xYears: {\n one: '1 a\u00F1o',\n other: '{{count}} a\u00F1os'\n },\n overXYears: {\n one: 'm\u00E1s de 1 a\u00F1o',\n other: 'm\u00E1s de {{count}} a\u00F1os'\n },\n almostXYears: {\n one: 'casi 1 a\u00F1o',\n other: 'casi {{count}} a\u00F1os'\n }\n};\n\nvar formatDistance = function formatDistance(token, count, options) {\n var result;\n var tokenValue = formatDistanceLocale[token];\n\n if (typeof tokenValue === 'string') {\n result = tokenValue;\n } else if (count === 1) {\n result = tokenValue.one;\n } else {\n result = tokenValue.other.replace('{{count}}', count.toString());\n }\n\n if (options !== null && options !== void 0 && options.addSuffix) {\n if (options.comparison && options.comparison > 0) {\n return 'en ' + result;\n } else {\n return 'hace ' + result;\n }\n }\n\n return result;\n};\n\nexport default formatDistance;", "import buildFormatLongFn from \"../../../_lib/buildFormatLongFn/index.js\";\nvar dateFormats = {\n full: \"EEEE, d 'de' MMMM 'de' y\",\n long: \"d 'de' MMMM 'de' y\",\n medium: 'd MMM y',\n short: 'dd/MM/y'\n};\nvar timeFormats = {\n full: 'HH:mm:ss zzzz',\n long: 'HH:mm:ss z',\n medium: 'HH:mm:ss',\n short: 'HH:mm'\n};\nvar dateTimeFormats = {\n full: \"{{date}} 'a las' {{time}}\",\n long: \"{{date}} 'a las' {{time}}\",\n medium: '{{date}}, {{time}}',\n short: '{{date}}, {{time}}'\n};\nvar formatLong = {\n date: buildFormatLongFn({\n formats: dateFormats,\n defaultWidth: 'full'\n }),\n time: buildFormatLongFn({\n formats: timeFormats,\n defaultWidth: 'full'\n }),\n dateTime: buildFormatLongFn({\n formats: dateTimeFormats,\n defaultWidth: 'full'\n })\n};\nexport default formatLong;", "var formatRelativeLocale = {\n lastWeek: \"'el' eeee 'pasado a la' p\",\n yesterday: \"'ayer a la' p\",\n today: \"'hoy a la' p\",\n tomorrow: \"'ma\u00F1ana a la' p\",\n nextWeek: \"eeee 'a la' p\",\n other: 'P'\n};\nvar formatRelativeLocalePlural = {\n lastWeek: \"'el' eeee 'pasado a las' p\",\n yesterday: \"'ayer a las' p\",\n today: \"'hoy a las' p\",\n tomorrow: \"'ma\u00F1ana a las' p\",\n nextWeek: \"eeee 'a las' p\",\n other: 'P'\n};\n\nvar formatRelative = function formatRelative(token, date, _baseDate, _options) {\n if (date.getUTCHours() !== 1) {\n return formatRelativeLocalePlural[token];\n } else {\n return formatRelativeLocale[token];\n }\n};\n\nexport default formatRelative;", "import buildLocalizeFn from \"../../../_lib/buildLocalizeFn/index.js\";\nvar eraValues = {\n narrow: ['AC', 'DC'],\n abbreviated: ['AC', 'DC'],\n wide: ['antes de cristo', 'despu\u00E9s de cristo']\n};\nvar quarterValues = {\n narrow: ['1', '2', '3', '4'],\n abbreviated: ['T1', 'T2', 'T3', 'T4'],\n wide: ['1\u00BA trimestre', '2\u00BA trimestre', '3\u00BA trimestre', '4\u00BA trimestre']\n};\nvar monthValues = {\n narrow: ['e', 'f', 'm', 'a', 'm', 'j', 'j', 'a', 's', 'o', 'n', 'd'],\n abbreviated: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic'],\n wide: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre']\n};\nvar dayValues = {\n narrow: ['d', 'l', 'm', 'm', 'j', 'v', 's'],\n short: ['do', 'lu', 'ma', 'mi', 'ju', 'vi', 's\u00E1'],\n abbreviated: ['dom', 'lun', 'mar', 'mi\u00E9', 'jue', 'vie', 's\u00E1b'],\n wide: ['domingo', 'lunes', 'martes', 'mi\u00E9rcoles', 'jueves', 'viernes', 's\u00E1bado']\n};\nvar dayPeriodValues = {\n narrow: {\n am: 'a',\n pm: 'p',\n midnight: 'mn',\n noon: 'md',\n morning: 'ma\u00F1ana',\n afternoon: 'tarde',\n evening: 'tarde',\n night: 'noche'\n },\n abbreviated: {\n am: 'AM',\n pm: 'PM',\n midnight: 'medianoche',\n noon: 'mediodia',\n morning: 'ma\u00F1ana',\n afternoon: 'tarde',\n evening: 'tarde',\n night: 'noche'\n },\n wide: {\n am: 'a.m.',\n pm: 'p.m.',\n midnight: 'medianoche',\n noon: 'mediodia',\n morning: 'ma\u00F1ana',\n afternoon: 'tarde',\n evening: 'tarde',\n night: 'noche'\n }\n};\nvar formattingDayPeriodValues = {\n narrow: {\n am: 'a',\n pm: 'p',\n midnight: 'mn',\n noon: 'md',\n morning: 'de la ma\u00F1ana',\n afternoon: 'de la tarde',\n evening: 'de la tarde',\n night: 'de la noche'\n },\n abbreviated: {\n am: 'AM',\n pm: 'PM',\n midnight: 'medianoche',\n noon: 'mediodia',\n morning: 'de la ma\u00F1ana',\n afternoon: 'de la tarde',\n evening: 'de la tarde',\n night: 'de la noche'\n },\n wide: {\n am: 'a.m.',\n pm: 'p.m.',\n midnight: 'medianoche',\n noon: 'mediodia',\n morning: 'de la ma\u00F1ana',\n afternoon: 'de la tarde',\n evening: 'de la tarde',\n night: 'de la noche'\n }\n};\n\nvar ordinalNumber = function ordinalNumber(dirtyNumber, _options) {\n var number = Number(dirtyNumber);\n return number + '\u00BA';\n};\n\nvar localize = {\n ordinalNumber: ordinalNumber,\n era: buildLocalizeFn({\n values: eraValues,\n defaultWidth: 'wide'\n }),\n quarter: buildLocalizeFn({\n values: quarterValues,\n defaultWidth: 'wide',\n argumentCallback: function argumentCallback(quarter) {\n return Number(quarter) - 1;\n }\n }),\n month: buildLocalizeFn({\n values: monthValues,\n defaultWidth: 'wide'\n }),\n day: buildLocalizeFn({\n values: dayValues,\n defaultWidth: 'wide'\n }),\n dayPeriod: buildLocalizeFn({\n values: dayPeriodValues,\n defaultWidth: 'wide',\n formattingValues: formattingDayPeriodValues,\n defaultFormattingWidth: 'wide'\n })\n};\nexport default localize;", "import buildMatchPatternFn from \"../../../_lib/buildMatchPatternFn/index.js\";\nimport buildMatchFn from \"../../../_lib/buildMatchFn/index.js\";\nvar matchOrdinalNumberPattern = /^(\\d+)(\u00BA)?/i;\nvar parseOrdinalNumberPattern = /\\d+/i;\nvar matchEraPatterns = {\n narrow: /^(ac|dc|a|d)/i,\n abbreviated: /^(a\\.?\\s?c\\.?|a\\.?\\s?e\\.?\\s?c\\.?|d\\.?\\s?c\\.?|e\\.?\\s?c\\.?)/i,\n wide: /^(antes de cristo|antes de la era com[u\u00FA]n|despu[e\u00E9]s de cristo|era com[u\u00FA]n)/i\n};\nvar parseEraPatterns = {\n any: [/^ac/i, /^dc/i],\n wide: [/^(antes de cristo|antes de la era com[u\u00FA]n)/i, /^(despu[e\u00E9]s de cristo|era com[u\u00FA]n)/i]\n};\nvar matchQuarterPatterns = {\n narrow: /^[1234]/i,\n abbreviated: /^T[1234]/i,\n wide: /^[1234](\u00BA)? trimestre/i\n};\nvar parseQuarterPatterns = {\n any: [/1/i, /2/i, /3/i, /4/i]\n};\nvar matchMonthPatterns = {\n narrow: /^[efmajsond]/i,\n abbreviated: /^(ene|feb|mar|abr|may|jun|jul|ago|sep|oct|nov|dic)/i,\n wide: /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i\n};\nvar parseMonthPatterns = {\n narrow: [/^e/i, /^f/i, /^m/i, /^a/i, /^m/i, /^j/i, /^j/i, /^a/i, /^s/i, /^o/i, /^n/i, /^d/i],\n any: [/^en/i, /^feb/i, /^mar/i, /^abr/i, /^may/i, /^jun/i, /^jul/i, /^ago/i, /^sep/i, /^oct/i, /^nov/i, /^dic/i]\n};\nvar matchDayPatterns = {\n narrow: /^[dlmjvs]/i,\n short: /^(do|lu|ma|mi|ju|vi|s[\u00E1a])/i,\n abbreviated: /^(dom|lun|mar|mi[\u00E9e]|jue|vie|s[\u00E1a]b)/i,\n wide: /^(domingo|lunes|martes|mi[\u00E9e]rcoles|jueves|viernes|s[\u00E1a]bado)/i\n};\nvar parseDayPatterns = {\n narrow: [/^d/i, /^l/i, /^m/i, /^m/i, /^j/i, /^v/i, /^s/i],\n any: [/^do/i, /^lu/i, /^ma/i, /^mi/i, /^ju/i, /^vi/i, /^sa/i]\n};\nvar matchDayPeriodPatterns = {\n narrow: /^(a|p|mn|md|(de la|a las) (ma\u00F1ana|tarde|noche))/i,\n any: /^([ap]\\.?\\s?m\\.?|medianoche|mediodia|(de la|a las) (ma\u00F1ana|tarde|noche))/i\n};\nvar parseDayPeriodPatterns = {\n any: {\n am: /^a/i,\n pm: /^p/i,\n midnight: /^mn/i,\n noon: /^md/i,\n morning: /ma\u00F1ana/i,\n afternoon: /tarde/i,\n evening: /tarde/i,\n night: /noche/i\n }\n};\nvar match = {\n ordinalNumber: buildMatchPatternFn({\n matchPattern: matchOrdinalNumberPattern,\n parsePattern: parseOrdinalNumberPattern,\n valueCallback: function valueCallback(value) {\n return parseInt(value, 10);\n }\n }),\n era: buildMatchFn({\n matchPatterns: matchEraPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseEraPatterns,\n defaultParseWidth: 'any'\n }),\n quarter: buildMatchFn({\n matchPatterns: matchQuarterPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseQuarterPatterns,\n defaultParseWidth: 'any',\n valueCallback: function valueCallback(index) {\n return index + 1;\n }\n }),\n month: buildMatchFn({\n matchPatterns: matchMonthPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseMonthPatterns,\n defaultParseWidth: 'any'\n }),\n day: buildMatchFn({\n matchPatterns: matchDayPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseDayPatterns,\n defaultParseWidth: 'any'\n }),\n dayPeriod: buildMatchFn({\n matchPatterns: matchDayPeriodPatterns,\n defaultMatchWidth: 'any',\n parsePatterns: parseDayPeriodPatterns,\n defaultParseWidth: 'any'\n })\n};\nexport default match;", "import formatDistance from \"./_lib/formatDistance/index.js\";\nimport formatLong from \"./_lib/formatLong/index.js\";\nimport formatRelative from \"./_lib/formatRelative/index.js\";\nimport localize from \"./_lib/localize/index.js\";\nimport match from \"./_lib/match/index.js\";\n\n/**\n * @type {Locale}\n * @category Locales\n * @summary Spanish locale.\n * @language Spanish\n * @iso-639-2 spa\n * @author Juan Angosto [@juanangosto]{@link https://github.com/juanangosto}\n * @author Guillermo Grau [@guigrpa]{@link https://github.com/guigrpa}\n * @author Fernando Ag\u00FCero [@fjaguero]{@link https://github.com/fjaguero}\n * @author Gast\u00F3n Haro [@harogaston]{@link https://github.com/harogaston}\n * @author Yago Carballo [@YagoCarballo]{@link https://github.com/YagoCarballo}\n */\nvar locale = {\n code: 'es',\n formatDistance: formatDistance,\n formatLong: formatLong,\n formatRelative: formatRelative,\n localize: localize,\n match: match,\n options: {\n weekStartsOn: 1\n /* Monday */\n ,\n firstWeekContainsDate: 1\n }\n};\nexport default locale;", "var formatDistanceLocale = {\n lessThanXSeconds: {\n one: 'moins d\u2019une seconde',\n other: 'moins de {{count}} secondes'\n },\n xSeconds: {\n one: '1 seconde',\n other: '{{count}} secondes'\n },\n halfAMinute: '30 secondes',\n lessThanXMinutes: {\n one: 'moins d\u2019une minute',\n other: 'moins de {{count}} minutes'\n },\n xMinutes: {\n one: '1 minute',\n other: '{{count}} minutes'\n },\n aboutXHours: {\n one: 'environ 1 heure',\n other: 'environ {{count}} heures'\n },\n xHours: {\n one: '1 heure',\n other: '{{count}} heures'\n },\n xDays: {\n one: '1 jour',\n other: '{{count}} jours'\n },\n aboutXWeeks: {\n one: 'environ 1 semaine',\n other: 'environ {{count}} semaines'\n },\n xWeeks: {\n one: '1 semaine',\n other: '{{count}} semaines'\n },\n aboutXMonths: {\n one: 'environ 1 mois',\n other: 'environ {{count}} mois'\n },\n xMonths: {\n one: '1 mois',\n other: '{{count}} mois'\n },\n aboutXYears: {\n one: 'environ 1 an',\n other: 'environ {{count}} ans'\n },\n xYears: {\n one: '1 an',\n other: '{{count}} ans'\n },\n overXYears: {\n one: 'plus d\u2019un an',\n other: 'plus de {{count}} ans'\n },\n almostXYears: {\n one: 'presqu\u2019un an',\n other: 'presque {{count}} ans'\n }\n};\n\nvar formatDistance = function formatDistance(token, count, options) {\n var result;\n var form = formatDistanceLocale[token];\n\n if (typeof form === 'string') {\n result = form;\n } else if (count === 1) {\n result = form.one;\n } else {\n result = form.other.replace('{{count}}', String(count));\n }\n\n if (options !== null && options !== void 0 && options.addSuffix) {\n if (options.comparison && options.comparison > 0) {\n return 'dans ' + result;\n } else {\n return 'il y a ' + result;\n }\n }\n\n return result;\n};\n\nexport default formatDistance;", "import buildFormatLongFn from \"../../../_lib/buildFormatLongFn/index.js\";\nvar dateFormats = {\n full: 'EEEE d MMMM y',\n long: 'd MMMM y',\n medium: 'd MMM y',\n short: 'dd/MM/y'\n};\nvar timeFormats = {\n full: 'HH:mm:ss zzzz',\n long: 'HH:mm:ss z',\n medium: 'HH:mm:ss',\n short: 'HH:mm'\n};\nvar dateTimeFormats = {\n full: \"{{date}} '\u00E0' {{time}}\",\n long: \"{{date}} '\u00E0' {{time}}\",\n medium: '{{date}}, {{time}}',\n short: '{{date}}, {{time}}'\n};\nvar formatLong = {\n date: buildFormatLongFn({\n formats: dateFormats,\n defaultWidth: 'full'\n }),\n time: buildFormatLongFn({\n formats: timeFormats,\n defaultWidth: 'full'\n }),\n dateTime: buildFormatLongFn({\n formats: dateTimeFormats,\n defaultWidth: 'full'\n })\n};\nexport default formatLong;", "var formatRelativeLocale = {\n lastWeek: \"eeee 'dernier \u00E0' p\",\n yesterday: \"'hier \u00E0' p\",\n today: \"'aujourd\u2019hui \u00E0' p\",\n tomorrow: \"'demain \u00E0' p'\",\n nextWeek: \"eeee 'prochain \u00E0' p\",\n other: 'P'\n};\n\nvar formatRelative = function formatRelative(token, _date, _baseDate, _options) {\n return formatRelativeLocale[token];\n};\n\nexport default formatRelative;", "import buildLocalizeFn from \"../../../_lib/buildLocalizeFn/index.js\";\nvar eraValues = {\n narrow: ['av. J.-C', 'ap. J.-C'],\n abbreviated: ['av. J.-C', 'ap. J.-C'],\n wide: ['avant J\u00E9sus-Christ', 'apr\u00E8s J\u00E9sus-Christ']\n};\nvar quarterValues = {\n narrow: ['T1', 'T2', 'T3', 'T4'],\n abbreviated: ['1er trim.', '2\u00E8me trim.', '3\u00E8me trim.', '4\u00E8me trim.'],\n wide: ['1er trimestre', '2\u00E8me trimestre', '3\u00E8me trimestre', '4\u00E8me trimestre']\n};\nvar monthValues = {\n narrow: ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'],\n abbreviated: ['janv.', 'f\u00E9vr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'ao\u00FBt', 'sept.', 'oct.', 'nov.', 'd\u00E9c.'],\n wide: ['janvier', 'f\u00E9vrier', 'mars', 'avril', 'mai', 'juin', 'juillet', 'ao\u00FBt', 'septembre', 'octobre', 'novembre', 'd\u00E9cembre']\n};\nvar dayValues = {\n narrow: ['D', 'L', 'M', 'M', 'J', 'V', 'S'],\n short: ['di', 'lu', 'ma', 'me', 'je', 've', 'sa'],\n abbreviated: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],\n wide: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi']\n};\nvar dayPeriodValues = {\n narrow: {\n am: 'AM',\n pm: 'PM',\n midnight: 'minuit',\n noon: 'midi',\n morning: 'mat.',\n afternoon: 'ap.m.',\n evening: 'soir',\n night: 'mat.'\n },\n abbreviated: {\n am: 'AM',\n pm: 'PM',\n midnight: 'minuit',\n noon: 'midi',\n morning: 'matin',\n afternoon: 'apr\u00E8s-midi',\n evening: 'soir',\n night: 'matin'\n },\n wide: {\n am: 'AM',\n pm: 'PM',\n midnight: 'minuit',\n noon: 'midi',\n morning: 'du matin',\n afternoon: 'de l\u2019apr\u00E8s-midi',\n evening: 'du soir',\n night: 'du matin'\n }\n};\n\nvar ordinalNumber = function ordinalNumber(dirtyNumber, options) {\n var number = Number(dirtyNumber);\n var unit = options === null || options === void 0 ? void 0 : options.unit;\n if (number === 0) return '0';\n var feminineUnits = ['year', 'week', 'hour', 'minute', 'second'];\n var suffix;\n\n if (number === 1) {\n suffix = unit && feminineUnits.includes(unit) ? '\u00E8re' : 'er';\n } else {\n suffix = '\u00E8me';\n }\n\n return number + suffix;\n};\n\nvar localize = {\n ordinalNumber: ordinalNumber,\n era: buildLocalizeFn({\n values: eraValues,\n defaultWidth: 'wide'\n }),\n quarter: buildLocalizeFn({\n values: quarterValues,\n defaultWidth: 'wide',\n argumentCallback: function argumentCallback(quarter) {\n return quarter - 1;\n }\n }),\n month: buildLocalizeFn({\n values: monthValues,\n defaultWidth: 'wide'\n }),\n day: buildLocalizeFn({\n values: dayValues,\n defaultWidth: 'wide'\n }),\n dayPeriod: buildLocalizeFn({\n values: dayPeriodValues,\n defaultWidth: 'wide'\n })\n};\nexport default localize;", "import buildMatchFn from \"../../../_lib/buildMatchFn/index.js\";\nimport buildMatchPatternFn from \"../../../_lib/buildMatchPatternFn/index.js\";\nvar matchOrdinalNumberPattern = /^(\\d+)(i\u00E8me|\u00E8re|\u00E8me|er|e)?/i;\nvar parseOrdinalNumberPattern = /\\d+/i;\nvar matchEraPatterns = {\n narrow: /^(av\\.J\\.C|ap\\.J\\.C|ap\\.J\\.-C)/i,\n abbreviated: /^(av\\.J\\.-C|av\\.J-C|apr\\.J\\.-C|apr\\.J-C|ap\\.J-C)/i,\n wide: /^(avant J\u00E9sus-Christ|apr\u00E8s J\u00E9sus-Christ)/i\n};\nvar parseEraPatterns = {\n any: [/^av/i, /^ap/i]\n};\nvar matchQuarterPatterns = {\n narrow: /^T?[1234]/i,\n abbreviated: /^[1234](er|\u00E8me|e)? trim\\.?/i,\n wide: /^[1234](er|\u00E8me|e)? trimestre/i\n};\nvar parseQuarterPatterns = {\n any: [/1/i, /2/i, /3/i, /4/i]\n};\nvar matchMonthPatterns = {\n narrow: /^[jfmasond]/i,\n abbreviated: /^(janv|f\u00E9vr|mars|avr|mai|juin|juill|juil|ao\u00FBt|sept|oct|nov|d\u00E9c)\\.?/i,\n wide: /^(janvier|f\u00E9vrier|mars|avril|mai|juin|juillet|ao\u00FBt|septembre|octobre|novembre|d\u00E9cembre)/i\n};\nvar parseMonthPatterns = {\n narrow: [/^j/i, /^f/i, /^m/i, /^a/i, /^m/i, /^j/i, /^j/i, /^a/i, /^s/i, /^o/i, /^n/i, /^d/i],\n any: [/^ja/i, /^f/i, /^mar/i, /^av/i, /^ma/i, /^juin/i, /^juil/i, /^ao/i, /^s/i, /^o/i, /^n/i, /^d/i]\n};\nvar matchDayPatterns = {\n narrow: /^[lmjvsd]/i,\n short: /^(di|lu|ma|me|je|ve|sa)/i,\n abbreviated: /^(dim|lun|mar|mer|jeu|ven|sam)\\.?/i,\n wide: /^(dimanche|lundi|mardi|mercredi|jeudi|vendredi|samedi)/i\n};\nvar parseDayPatterns = {\n narrow: [/^d/i, /^l/i, /^m/i, /^m/i, /^j/i, /^v/i, /^s/i],\n any: [/^di/i, /^lu/i, /^ma/i, /^me/i, /^je/i, /^ve/i, /^sa/i]\n};\nvar matchDayPeriodPatterns = {\n narrow: /^(a|p|minuit|midi|mat\\.?|ap\\.?m\\.?|soir|nuit)/i,\n any: /^([ap]\\.?\\s?m\\.?|du matin|de l'apr\u00E8s[-\\s]midi|du soir|de la nuit)/i\n};\nvar parseDayPeriodPatterns = {\n any: {\n am: /^a/i,\n pm: /^p/i,\n midnight: /^min/i,\n noon: /^mid/i,\n morning: /mat/i,\n afternoon: /ap/i,\n evening: /soir/i,\n night: /nuit/i\n }\n};\nvar match = {\n ordinalNumber: buildMatchPatternFn({\n matchPattern: matchOrdinalNumberPattern,\n parsePattern: parseOrdinalNumberPattern,\n valueCallback: function valueCallback(value) {\n return parseInt(value);\n }\n }),\n era: buildMatchFn({\n matchPatterns: matchEraPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseEraPatterns,\n defaultParseWidth: 'any'\n }),\n quarter: buildMatchFn({\n matchPatterns: matchQuarterPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseQuarterPatterns,\n defaultParseWidth: 'any',\n valueCallback: function valueCallback(index) {\n return index + 1;\n }\n }),\n month: buildMatchFn({\n matchPatterns: matchMonthPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseMonthPatterns,\n defaultParseWidth: 'any'\n }),\n day: buildMatchFn({\n matchPatterns: matchDayPatterns,\n defaultMatchWidth: 'wide',\n parsePatterns: parseDayPatterns,\n defaultParseWidth: 'any'\n }),\n dayPeriod: buildMatchFn({\n matchPatterns: matchDayPeriodPatterns,\n defaultMatchWidth: 'any',\n parsePatterns: parseDayPeriodPatterns,\n defaultParseWidth: 'any'\n })\n};\nexport default match;", "import formatDistance from \"./_lib/formatDistance/index.js\";\nimport formatLong from \"./_lib/formatLong/index.js\";\nimport formatRelative from \"./_lib/formatRelative/index.js\";\nimport localize from \"./_lib/localize/index.js\";\nimport match from \"./_lib/match/index.js\";\n/**\n * @type {Locale}\n * @category Locales\n * @summary French locale.\n * @language French\n * @iso-639-2 fra\n * @author Jean Dupouy [@izeau]{@link https://github.com/izeau}\n * @author Fran\u00E7ois B [@fbonzon]{@link https://github.com/fbonzon}\n */\n\nvar locale = {\n code: 'fr',\n formatDistance: formatDistance,\n formatLong: formatLong,\n formatRelative: formatRelative,\n localize: localize,\n match: match,\n options: {\n weekStartsOn: 1\n /* Monday */\n ,\n firstWeekContainsDate: 4\n }\n};\nexport default locale;", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n CacheEvictor,\n LibtoolVersion,\n ObservabilityEvent,\n ObservableHttpClientLibrary,\n TalerBankConversionCacheEviction,\n TalerBankConversionHttpClient,\n TalerCoreBankCacheEviction,\n TalerCoreBankHttpClient,\n TalerCorebankApi,\n TalerError,\n} from \"@gnu-taler/taler-util\";\nimport {\n ComponentChildren,\n FunctionComponent,\n VNode,\n createContext,\n h,\n} from \"preact\";\nimport { useContext, useEffect, useState } from \"preact/hooks\";\nimport { BrowserFetchHttpLib, ErrorLoading } from \"../index.browser.js\";\nimport { APIClient, ActiviyTracker, BankLib, Subscriber } from \"./activity.js\";\nimport { useTranslationContext } from \"./translation.js\";\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nexport type BankContextType = {\n url: URL;\n config: TalerCorebankApi.TalerCorebankConfigResponse;\n lib: BankLib;\n hints: VersionHint[];\n onActivity: Subscriber;\n cancelRequest: (eventId: string) => void;\n};\n\n// @ts-expect-error default value to undefined, should it be another thing?\nconst BankContext = createContext(undefined);\n\nexport const useBankCoreApiContext = (): BankContextType =>\n useContext(BankContext);\n\nenum VersionHint {\n NONE,\n}\n\ntype Evictors = {\n conversion?: CacheEvictor;\n bank?: CacheEvictor;\n};\n\ntype ConfigResult =\n | undefined\n | { type: \"ok\"; config: T; hints: VersionHint[] }\n | { type: \"incompatible\"; result: T; supported: string }\n | { type: \"error\"; error: TalerError };\n\nconst CONFIG_FAIL_TRY_AGAIN_MS = 5000;\n\nexport const BankApiProvider = ({\n baseUrl,\n children,\n frameOnError,\n evictors = {},\n}: {\n baseUrl: URL;\n children: ComponentChildren;\n evictors?: Evictors;\n frameOnError: FunctionComponent<{ children: ComponentChildren }>;\n}): VNode => {\n const [checked, setChecked] =\n useState>();\n const { i18n } = useTranslationContext();\n\n const { getRemoteConfig, VERSION, lib, cancelRequest, onActivity } =\n buildBankApiClient(baseUrl, evictors);\n\n useEffect(() => {\n let keepRetrying = true;\n async function testConfig(): Promise {\n try {\n const config = await getRemoteConfig();\n if (LibtoolVersion.compare(VERSION, config.version)) {\n setChecked({ type: \"ok\", config, hints: [] });\n } else {\n setChecked({\n type: \"incompatible\",\n result: config,\n supported: VERSION,\n });\n }\n } catch (error) {\n if (error instanceof TalerError) {\n if (keepRetrying) {\n setTimeout(() => {\n testConfig();\n }, CONFIG_FAIL_TRY_AGAIN_MS);\n }\n setChecked({ type: \"error\", error });\n } else {\n setChecked({ type: \"error\", error: TalerError.fromException(error) });\n }\n }\n }\n testConfig();\n return () => {\n // on unload, stop retry\n keepRetrying = false;\n };\n }, []);\n\n if (checked === undefined) {\n return h(frameOnError, {\n children: h(\"div\", {}, \"checking compatibility with server...\"),\n });\n }\n if (checked.type === \"error\") {\n return h(frameOnError, {\n children: h(ErrorLoading, { error: checked.error }),\n });\n }\n if (checked.type === \"incompatible\") {\n return h(frameOnError, {\n children: h(\n \"div\",\n {},\n i18n.str`The server version is not supported. Supported version \"${checked.supported}\", server version \"${checked.result.version}\"`,\n ),\n });\n }\n\n const value: BankContextType = {\n url: baseUrl,\n config: checked.config,\n onActivity: onActivity,\n lib,\n cancelRequest,\n hints: checked.hints,\n };\n return h(BankContext.Provider, {\n value,\n children,\n });\n};\n\nfunction buildBankApiClient(\n url: URL,\n evictors: Evictors,\n): APIClient {\n const httpFetch = new BrowserFetchHttpLib({\n enableThrottling: true,\n requireTls: false,\n });\n const tracker = new ActiviyTracker();\n const httpLib = new ObservableHttpClientLibrary(httpFetch, {\n observe(ev) {\n tracker.notify(ev);\n },\n });\n\n const bank = new TalerCoreBankHttpClient(url.href, httpLib, evictors.bank);\n const conversion = new TalerBankConversionHttpClient(\n bank.getConversionInfoAPI().href,\n httpLib,\n evictors.conversion,\n );\n\n async function getRemoteConfig(): Promise {\n const resp = await bank.getConfig();\n if (resp.type === \"fail\") {\n if (resp.detail) {\n throw TalerError.fromUncheckedDetail(resp.detail);\n } else {\n throw TalerError.fromException(\n new Error(\"failed to get bank remote config\"),\n );\n }\n }\n return resp.body;\n }\n\n return {\n getRemoteConfig,\n VERSION: TalerCoreBankHttpClient.PROTOCOL_VERSION,\n lib: {\n bank,\n conversion,\n conversionForClass(classId) {\n return new TalerBankConversionHttpClient(\n bank.getConversionInfoAPIForClass(classId).href,\n httpLib,\n evictors.conversion,\n );\n },\n conversionForUser(username) {\n return new TalerBankConversionHttpClient(\n bank.getConversionInfoAPIForUser(username).href,\n httpLib,\n evictors.conversion,\n );\n },\n },\n onActivity: tracker.subscribe,\n cancelRequest: httpLib.cancelRequest,\n };\n}\n\nexport const BankApiProviderTesting = ({\n children,\n value,\n}: {\n value: BankContextType;\n children: ComponentChildren;\n}): VNode => {\n return h(BankContext.Provider, {\n value,\n children,\n });\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n ChallengerHttpClient,\n ObservabilityEvent,\n TalerBankConversionHttpClient,\n TalerCoreBankHttpClient,\n TalerExchangeHttpClient,\n TalerMerchantManagementHttpClient,\n} from \"@gnu-taler/taler-util\";\n\ntype Listener = (e: Event) => void;\ntype Unsuscriber = () => void;\nexport type Subscriber = (fn: Listener) => Unsuscriber;\n\nexport class ActiviyTracker {\n private observers = new Array>();\n constructor() {\n this.notify = this.notify.bind(this);\n this.subscribe = this.subscribe.bind(this);\n }\n notify(data: Event): void {\n this.observers.forEach((observer) => observer(data));\n }\n subscribe(func: Listener): Unsuscriber {\n this.observers.push(func);\n return () => {\n this.observers.forEach((observer, index) => {\n if (observer === func) {\n this.observers.splice(index, 1);\n }\n });\n };\n }\n}\n\n/**\n * build http client with cache breaker due to SWR\n * @param url\n * @returns\n */\nexport interface APIClient {\n getRemoteConfig(): Promise;\n VERSION: string;\n lib: T;\n onActivity: Subscriber;\n cancelRequest(id: string): void;\n}\n\nexport interface MerchantLib {\n instance: TalerMerchantManagementHttpClient;\n subInstanceApi: (instanceId: string) => MerchantLib;\n}\n\nexport interface ExchangeLib {\n exchange: TalerExchangeHttpClient;\n}\n\nexport interface BankLib {\n bank: TalerCoreBankHttpClient;\n conversion: TalerBankConversionHttpClient;\n conversionForUser(username: string): TalerBankConversionHttpClient;\n conversionForClass(classId: number): TalerBankConversionHttpClient;\n}\n\nexport interface ChallengerLib {\n challenger: ChallengerHttpClient;\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n CacheEvictor,\n ChallengerApi,\n ChallengerCacheEviction,\n ChallengerHttpClient,\n LibtoolVersion,\n ObservabilityEvent,\n ObservableHttpClientLibrary,\n TalerError,\n} from \"@gnu-taler/taler-util\";\nimport {\n ComponentChildren,\n FunctionComponent,\n VNode,\n createContext,\n h,\n} from \"preact\";\nimport { useContext, useEffect, useState } from \"preact/hooks\";\nimport { BrowserFetchHttpLib, ErrorLoading } from \"../index.browser.js\";\nimport {\n APIClient,\n ActiviyTracker,\n ChallengerLib,\n Subscriber,\n} from \"./activity.js\";\nimport { useTranslationContext } from \"./translation.js\";\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nexport type ChallengerContextType = {\n url: URL;\n config: ChallengerApi.ChallengerTermsOfServiceResponse;\n lib: ChallengerLib;\n hints: VersionHint[];\n onActivity: Subscriber;\n cancelRequest: (eventId: string) => void;\n};\n\n// @ts-expect-error default value to undefined, should it be another thing?\nconst ChallengerContext = createContext(undefined);\n\nexport const useChallengerApiContext = (): ChallengerContextType =>\n useContext(ChallengerContext);\n\nenum VersionHint {\n NONE,\n}\n\ntype Evictors = {\n challenger?: CacheEvictor;\n};\n\ntype ConfigResult =\n | undefined\n | { type: \"ok\"; config: T; hints: VersionHint[] }\n | { type: \"incompatible\"; result: T; supported: string }\n | { type: \"error\"; error: TalerError };\n\nconst CONFIG_FAIL_TRY_AGAIN_MS = 5000;\n\nexport const ChallengerApiProvider = ({\n baseUrl,\n children,\n frameOnError,\n evictors = {},\n}: {\n baseUrl: URL;\n children: ComponentChildren;\n evictors?: Evictors;\n frameOnError: FunctionComponent<{ children: ComponentChildren }>;\n}): VNode => {\n const [checked, setChecked] =\n useState>();\n const { i18n } = useTranslationContext();\n\n const { getRemoteConfig, VERSION, lib, cancelRequest, onActivity } =\n buildChallengerApiClient(baseUrl, evictors);\n\n useEffect(() => {\n let keepRetrying = true;\n async function testConfig(): Promise {\n try {\n const config = await getRemoteConfig();\n if (LibtoolVersion.compare(VERSION, config.version)) {\n setChecked({ type: \"ok\", config, hints: [] });\n } else {\n setChecked({\n type: \"incompatible\",\n result: config,\n supported: VERSION,\n });\n }\n } catch (error) {\n if (error instanceof TalerError) {\n if (keepRetrying) {\n setTimeout(() => {\n testConfig();\n }, CONFIG_FAIL_TRY_AGAIN_MS);\n }\n setChecked({ type: \"error\", error });\n } else {\n setChecked({ type: \"error\", error: TalerError.fromException(error) });\n }\n }\n }\n testConfig();\n return () => {\n // on unload, stop retry\n keepRetrying = false;\n };\n }, []);\n\n if (checked === undefined) {\n return h(frameOnError, {\n children: h(\"div\", {}, \"checking compatibility with server...\"),\n });\n }\n if (checked.type === \"error\") {\n return h(frameOnError, {\n children: h(ErrorLoading, { error: checked.error }),\n });\n }\n if (checked.type === \"incompatible\") {\n return h(frameOnError, {\n children: h(\n \"div\",\n {},\n i18n.str`The server version is not supported. Supported version \"${checked.supported}\", server version \"${checked.result.version}\"`,\n ),\n });\n }\n\n const value: ChallengerContextType = {\n url: baseUrl,\n config: checked.config,\n onActivity: onActivity,\n lib,\n cancelRequest,\n hints: checked.hints,\n };\n return h(ChallengerContext.Provider, {\n value,\n children,\n });\n};\n\nfunction buildChallengerApiClient(\n url: URL,\n evictors: Evictors,\n): APIClient {\n const httpFetch = new BrowserFetchHttpLib({\n enableThrottling: true,\n requireTls: false,\n });\n const tracker = new ActiviyTracker();\n const httpLib = new ObservableHttpClientLibrary(httpFetch, {\n observe(ev) {\n tracker.notify(ev);\n },\n });\n\n const challenger = new ChallengerHttpClient(\n url.href,\n httpLib,\n evictors.challenger,\n );\n\n async function getRemoteConfig(): Promise {\n const resp = await challenger.getConfig();\n if (resp.type === \"fail\") {\n if (resp.detail) {\n throw TalerError.fromUncheckedDetail(resp.detail);\n } else {\n throw TalerError.fromException(\n new Error(\"failed to get challenger remote config\"),\n );\n }\n }\n return resp.body;\n }\n\n return {\n getRemoteConfig,\n VERSION: ChallengerHttpClient.PROTOCOL_VERSION,\n lib: {\n challenger,\n },\n onActivity: tracker.subscribe,\n cancelRequest: httpLib.cancelRequest,\n };\n}\n\nexport const ChallengerApiProviderTesting = ({\n children,\n value,\n}: {\n value: ChallengerContextType;\n children: ComponentChildren;\n}): VNode => {\n return h(ChallengerContext.Provider, {\n value,\n children,\n });\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n CacheEvictor,\n LibtoolVersion,\n ObservabilityEvent,\n ObservableHttpClientLibrary,\n TalerError,\n TalerMerchantApi,\n TalerMerchantInstanceCacheEviction,\n TalerMerchantManagementCacheEviction,\n TalerMerchantManagementHttpClient,\n} from \"@gnu-taler/taler-util\";\nimport {\n ComponentChildren,\n FunctionComponent,\n VNode,\n createContext,\n h,\n} from \"preact\";\nimport { useContext, useEffect, useState } from \"preact/hooks\";\nimport { BrowserFetchHttpLib } from \"../index.browser.js\";\nimport {\n APIClient,\n ActiviyTracker,\n MerchantLib,\n Subscriber,\n} from \"./activity.js\";\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nexport type MerchantContextType = {\n url: URL;\n config: TalerMerchantApi.MerchantVersionResponse;\n lib: MerchantLib;\n hints: VersionHint[];\n onActivity: Subscriber;\n cancelRequest: (eventId: string) => void;\n changeBackend: (url: URL) => void;\n};\n\n// FIXME: below\n// @ts-expect-error default value to undefined, should it be another thing?\nconst MerchantContext = createContext(undefined);\n\nexport const useMerchantApiContext = (): MerchantContextType =>\n useContext(MerchantContext);\n\nenum VersionHint {\n NONE,\n}\n\ntype Evictors = {\n management?: CacheEvictor<\n TalerMerchantManagementCacheEviction | TalerMerchantInstanceCacheEviction\n >;\n};\n\ntype ConfigResult =\n | undefined\n | { type: \"ok\"; config: T; hints: VersionHint[] }\n | ConfigResultFail;\n\nexport type ConfigResultFail =\n | { type: \"incompatible\"; result: T; supported: string }\n | { type: \"error\"; error: TalerError };\n\nconst CONFIG_FAIL_TRY_AGAIN_MS = 5000;\n\nexport const MerchantApiProvider = ({\n baseUrl,\n children,\n evictors = {},\n frameOnError,\n}: {\n baseUrl: URL;\n evictors?: Evictors;\n children: ComponentChildren;\n frameOnError: FunctionComponent<{\n state:\n | ConfigResultFail\n | undefined;\n }>;\n}): VNode => {\n const [checked, setChecked] =\n useState>();\n\n const [merchantEndpoint, changeMerchantEndpoint] = useState(baseUrl);\n\n const { getRemoteConfig, VERSION, lib, cancelRequest, onActivity } =\n buildMerchantApiClient(merchantEndpoint, evictors);\n\n useEffect(() => {\n let keepRetrying = true;\n async function testConfig(): Promise {\n try {\n const config = await getRemoteConfig();\n if (LibtoolVersion.compare(VERSION, config.version)) {\n setChecked({ type: \"ok\", config, hints: [] });\n } else {\n setChecked({\n type: \"incompatible\",\n result: config,\n supported: VERSION,\n });\n }\n } catch (error) {\n if (error instanceof TalerError) {\n if (keepRetrying) {\n setTimeout(() => {\n testConfig();\n }, CONFIG_FAIL_TRY_AGAIN_MS);\n }\n setChecked({ type: \"error\", error });\n } else {\n setChecked({ type: \"error\", error: TalerError.fromException(error) });\n }\n }\n }\n testConfig();\n return () => {\n // on unload, stop retry\n keepRetrying = false;\n };\n }, []);\n\n if (!checked || checked.type !== \"ok\") {\n return h(frameOnError, { state: checked }, []);\n }\n\n const value: MerchantContextType = {\n url: merchantEndpoint,\n config: checked.config,\n onActivity: onActivity,\n lib,\n cancelRequest,\n changeBackend: changeMerchantEndpoint,\n hints: checked.hints,\n };\n return h(MerchantContext.Provider, {\n value,\n children,\n });\n};\n\nfunction buildMerchantApiClient(\n url: URL,\n evictors: Evictors,\n): APIClient {\n const httpFetch = new BrowserFetchHttpLib({\n enableThrottling: true,\n requireTls: false,\n });\n const tracker = new ActiviyTracker();\n\n const httpLib = new ObservableHttpClientLibrary(httpFetch, {\n observe(ev) {\n tracker.notify(ev);\n },\n });\n\n const instance = new TalerMerchantManagementHttpClient(\n url.href,\n httpLib,\n evictors.management,\n );\n\n function getSubInstanceAPI(instanceId: string): MerchantLib {\n const api = buildMerchantApiClient(\n new URL(instance.getSubInstanceAPI(instanceId)),\n evictors,\n );\n return api.lib;\n }\n\n async function getRemoteConfig(): Promise {\n const resp = await instance.getConfig();\n if (resp.type === \"fail\") {\n if (resp.detail) {\n throw TalerError.fromUncheckedDetail(resp.detail);\n } else {\n throw TalerError.fromException(\n new Error(\"failed to get merchant remote config\"),\n );\n }\n }\n return resp.body;\n }\n\n return {\n getRemoteConfig,\n VERSION: TalerMerchantManagementHttpClient.PROTOCOL_VERSION,\n lib: {\n instance,\n subInstanceApi: getSubInstanceAPI,\n },\n onActivity: tracker.subscribe,\n cancelRequest: httpLib.cancelRequest,\n };\n}\n\nexport const MerchantApiProviderTesting = ({\n children,\n value,\n}: {\n value: MerchantContextType;\n children: ComponentChildren;\n}): VNode => {\n return h(MerchantContext.Provider, {\n value,\n children,\n });\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n CacheEvictor,\n LibtoolVersion,\n ObservabilityEvent,\n ObservableHttpClientLibrary,\n TalerError,\n TalerExchangeApi,\n TalerExchangeCacheEviction,\n TalerExchangeHttpClient,\n} from \"@gnu-taler/taler-util\";\nimport {\n ComponentChildren,\n FunctionComponent,\n VNode,\n createContext,\n h,\n} from \"preact\";\nimport { useContext, useEffect, useState } from \"preact/hooks\";\nimport {\n BrowserFetchHttpLib,\n ErrorLoading,\n useTranslationContext,\n} from \"../index.browser.js\";\nimport {\n APIClient,\n ActiviyTracker,\n ExchangeLib,\n Subscriber,\n} from \"./activity.js\";\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\nexport type ExchangeContextType = {\n url: URL;\n config: KeysAndConfigType;\n lib: ExchangeLib;\n /**\n * Do not use. This is here because the AML dashboard does too many\n * request to the event API\n *\n * FIXME: The server should expose a better API\n * https://bugs.gnunet.org/view.php?id=9776\n * @deprecated\n */\n unthrottledApi: ExchangeLib;\n hints: VersionHint[];\n onActivity: Subscriber;\n cancelRequest: (eventId: string) => void;\n};\n\n// FIXME: below\n// @ts-expect-error default value to undefined, should it be another thing?\nconst ExchangeContext = createContext(undefined);\n\nexport const useExchangeApiContext = (): ExchangeContextType =>\n useContext(ExchangeContext);\n\nenum VersionHint {\n NONE,\n}\n\ntype Evictors = {\n exchange?: CacheEvictor;\n};\n\ntype ConfigResult =\n | undefined\n | { type: \"ok\"; config: T; hints: VersionHint[] }\n | ConfigResultFail;\n\ntype ConfigResultFail =\n | { type: \"incompatible\"; result: T; supported: string }\n | { type: \"error\"; error: TalerError };\n\nconst CONFIG_FAIL_TRY_AGAIN_MS = 5000;\n\nexport type KeysAndConfigType = {\n config: TalerExchangeApi.ExchangeVersionResponse;\n keys: TalerExchangeApi.ExchangeKeysResponse;\n};\n\nexport const ExchangeApiProvider = ({\n baseUrl,\n children,\n evictors = {},\n frameOnError,\n preventCompression,\n}: {\n baseUrl: URL;\n evictors?: Evictors;\n children: ComponentChildren;\n frameOnError: FunctionComponent<{ children: ComponentChildren }>;\n preventCompression?: boolean;\n}): VNode => {\n const [checked, setChecked] = useState>();\n const { i18n } = useTranslationContext();\n\n const { getRemoteConfig, VERSION, lib, cancelRequest, onActivity } =\n buildExchangeApiClient(baseUrl, evictors, !!preventCompression);\n\n useEffect(() => {\n let keepRetrying = true;\n async function testConfig(): Promise {\n try {\n const config = await getRemoteConfig();\n if (LibtoolVersion.compare(VERSION, config.config.version)) {\n setChecked({ type: \"ok\", config, hints: [] });\n } else {\n setChecked({\n type: \"incompatible\",\n result: config,\n supported: VERSION,\n });\n }\n } catch (error) {\n if (error instanceof TalerError) {\n if (keepRetrying) {\n setTimeout(() => {\n testConfig();\n }, CONFIG_FAIL_TRY_AGAIN_MS);\n }\n setChecked({ type: \"error\", error });\n } else {\n setChecked({ type: \"error\", error: TalerError.fromException(error) });\n }\n }\n }\n testConfig();\n return () => {\n // on unload, stop retry\n keepRetrying = false;\n };\n }, []);\n\n if (checked === undefined) {\n return h(frameOnError, {\n children: h(\"div\", {}, \"checking compatibility with server...\"),\n });\n }\n if (checked.type === \"error\") {\n return h(frameOnError, {\n children: h(ErrorLoading, { error: checked.error }),\n });\n }\n if (checked.type === \"incompatible\") {\n return h(frameOnError, {\n children: h(\n \"div\",\n {},\n i18n.str`The server version is not supported. Supported version \"${checked.supported}\", server version \"${checked.result.config.version}\"`,\n ),\n });\n }\n\n const { lib: unthrottledApi } = buildExchangeApiClient(\n baseUrl,\n evictors,\n !!preventCompression,\n true,\n );\n\n const value: ExchangeContextType = {\n url: baseUrl,\n config: checked.config,\n onActivity: onActivity,\n lib,\n unthrottledApi,\n cancelRequest,\n hints: checked.hints,\n };\n return h(ExchangeContext.Provider, {\n value,\n children,\n });\n};\n\nfunction buildExchangeApiClient(\n url: URL,\n evictors: Evictors,\n preventCompression: boolean,\n disableThrottling?: boolean,\n): APIClient {\n const httpFetch = new BrowserFetchHttpLib({\n enableThrottling: !disableThrottling,\n requireTls: false,\n });\n const tracker = new ActiviyTracker();\n\n const httpLib = new ObservableHttpClientLibrary(httpFetch, {\n observe(ev) {\n tracker.notify(ev);\n },\n });\n\n const ex = new TalerExchangeHttpClient(url.href, {\n httpClient: httpLib,\n cacheEvictor: evictors.exchange,\n preventCompression,\n });\n\n async function getRemoteConfig(): Promise {\n const configResp = await ex.getConfig();\n if (configResp.type === \"fail\") {\n if (configResp.detail) {\n throw TalerError.fromUncheckedDetail(configResp.detail);\n } else {\n throw TalerError.fromException(\n new Error(\"failed to get exchange remote config\"),\n );\n }\n }\n const keysResp = await ex.getKeys();\n // if (keysResp.type === \"fail\") {\n // if (keysResp.detail) {\n // throw TalerError.fromUncheckedDetail(keysResp.detail);\n // } else {\n // throw TalerError.fromException(\n // new Error(\"failed to get exchange remote config\"),\n // );\n // }\n // }\n return {\n config: configResp.body,\n keys: keysResp.body,\n };\n }\n\n return {\n getRemoteConfig,\n VERSION: TalerExchangeHttpClient.SUPPORTED_EXCHANGE_PROTOCOL_VERSION,\n lib: {\n exchange: ex,\n },\n onActivity: tracker.subscribe,\n cancelRequest: httpLib.cancelRequest,\n };\n}\n\nexport const ExchangeApiProviderTesting = ({\n children,\n value,\n}: {\n value: ExchangeContextType;\n children: ComponentChildren;\n}): VNode => {\n return h(ExchangeContext.Provider, {\n value,\n children,\n });\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { ComponentChildren, createContext, h, VNode } from \"preact\";\nimport { useContext, useEffect, useState } from \"preact/hooks\";\nimport {\n AppLocation,\n ObjectOf,\n Location,\n findMatch,\n RouteDefinition,\n LocationNotFound,\n} from \"../utils/route.js\";\n\n/**\n *\n * @author Sebastian Javier Marchano (sebasjm)\n */\n\ntype Type = {\n path: string;\n params: Record;\n navigateTo: (path: AppLocation) => void;\n // addNavigationListener: (listener: (path: string, params: Record) => void) => (() => void);\n};\n\n// @ts-expect-error should not be used without provider\nconst Context = createContext(undefined);\n\nexport const useNavigationContext = (): Type => useContext(Context);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useCurrentLocation>>(\n pagesMap: T,\n): Location | LocationNotFound {\n const pageList = Object.keys(pagesMap as object) as Array;\n const { path, params } = useNavigationContext();\n\n return findMatch(pagesMap, pageList, path, params);\n}\n\nfunction getPathAndParamsFromWindow(): {\n path: string;\n params: Record;\n} {\n const path =\n typeof window !== \"undefined\" ? window.location.hash.substring(1) : \"/\";\n const params: Record = {};\n if (typeof window !== \"undefined\") {\n for (const [key, value] of new URLSearchParams(window.location.search)) {\n if (!params[key]) {\n params[key] = [];\n }\n params[key].push(value);\n }\n }\n return { path, params };\n}\n\nconst { path: initialPath, params: initialParams } =\n getPathAndParamsFromWindow();\n\n// there is a possibility that if the browser does a redirection\n// (which doesn't go through navigatTo function) and that executed\n// too early (before addEventListener runs) it won't be taking\n// into account\nconst PopStateEventType = \"popstate\";\n\nexport const BrowserHashNavigationProvider = ({\n children,\n}: {\n children: ComponentChildren;\n}): VNode => {\n const [{ path, params }, setState] = useState({\n path: initialPath,\n params: initialParams,\n });\n if (typeof window === \"undefined\") {\n throw Error(\n \"Can't use BrowserHashNavigationProvider if there is no window object\",\n );\n }\n function navigateTo(path: string): void {\n const { params } = getPathAndParamsFromWindow();\n setState({ path, params });\n window.location.href = path;\n }\n\n useEffect(() => {\n function eventListener(): void {\n setState(getPathAndParamsFromWindow());\n }\n window.addEventListener(PopStateEventType, eventListener);\n return () => {\n window.removeEventListener(PopStateEventType, eventListener);\n };\n }, []);\n return h(Context.Provider, {\n value: { path, params, navigateTo },\n children,\n });\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\ndeclare const __location: unique symbol;\n/**\n * special string that defined a location in the application\n *\n * this help to prevent wrong path\n */\nexport type AppLocation = string & {\n [__location]: true;\n};\n\nexport type EmptyObject = Record;\n/**\n * FIXME: receive parameters\n * maybe return URL for reverse function instead of string\n * @param pattern\n * @param reverse\n * @returns\n */\nexport function urlPattern<\n T extends Record = EmptyObject,\n>(pattern: RegExp, reverse: (p: T) => string): RouteDefinition {\n const url = reverse as (p: T) => AppLocation;\n return {\n pattern: new RegExp(pattern),\n url,\n };\n}\n\n/**\n * defines a location in the app\n *\n * pattern: how a string will trigger this location\n * url(): how a state serialize to a location\n */\n\nexport type ObjectOf = Record | EmptyObject;\n\nexport type RouteDefinition<\n T extends ObjectOf = EmptyObject,\n> = {\n pattern: RegExp;\n url: (p: T) => AppLocation;\n};\n\nconst nullRountDef = {\n pattern: new RegExp(/.*/),\n url: () => \"\" as AppLocation,\n};\nexport function buildNullRoutDefinition<\n T extends ObjectOf,\n>(): RouteDefinition {\n return nullRountDef;\n}\n\n/**\n * Search path in the pageList\n * get the values from the path found\n * add params from searchParams\n *\n * @param path\n * @param params\n */\nexport function findMatch>(\n pagesMap: T,\n pageList: Array,\n path: string,\n params: Record,\n): Location | LocationNotFound {\n for (let idx = 0; idx < pageList.length; idx++) {\n const name = pageList[idx];\n const found = pagesMap[name].pattern.exec(path);\n if (found !== null) {\n const values = {} as Record;\n\n if (found.groups !== undefined) {\n Object.entries(found.groups).forEach(([key, value]) => {\n values[key] = value;\n });\n }\n\n // @ts-expect-error values is a map string which is equivalent to the RouteParamsType\n return { name, parent: pagesMap, values, params };\n }\n }\n // @ts-expect-error values is a map string which is equivalent to the RouteParamsType\n return { name: undefined, parent: pagesMap, values: {}, params };\n}\n\n/**\n * get the type of the params of a location\n *\n */\ntype RouteParamsType =\n RouteType[Key] extends RouteDefinition ? ParamType : never;\n\n/**\n * Helps to create a map of a type with the key\n */\ntype MapKeyValue = {\n [Key in keyof Type]: Key extends string\n ? {\n parent: Type;\n name: Key;\n values: RouteParamsType;\n params: Record;\n }\n : never;\n};\n\n/**\n * create a enumeration of value of a mapped type\n */\ntype EnumerationOf = T[keyof T];\n\nexport type Location = EnumerationOf>;\nexport type LocationNotFound = {\n parent: Type;\n name: undefined;\n values: RouteParamsType;\n params: Record;\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n buildCodecForObject,\n Codec,\n codecForBoolean,\n codecOptionalDefault,\n} from \"@gnu-taler/taler-util\";\nimport { buildStorageKey } from \"../hooks/useLocalStorage.js\";\nimport { useMemoryStorage } from \"../hooks/useMemoryStorage.js\";\n\nconst TALER_SCREEN_ID = 102;\n\ninterface Preferences {\n showDebugInfo: boolean;\n}\ninterface Type extends Preferences {\n toggleShowDebugInfo(): void;\n}\n\nconst codecForPreferences = (): Codec =>\n buildCodecForObject()\n .allowExtra()\n .property(\"showDebugInfo\", codecOptionalDefault(codecForBoolean(), false))\n .build(\"CommonPreferences\");\n\nconst COMMON_PREFERENCES_KEY = buildStorageKey(\n \"common-preferences\",\n codecForPreferences(),\n);\n\nconst initial: Type = {\n showDebugInfo: false,\n toggleShowDebugInfo() {},\n};\n\nexport function useCommonPreferences(): [\n Readonly,\n (key: T, value: Preferences[T]) => void,\n] {\n const { value, update } = useMemoryStorage(\n COMMON_PREFERENCES_KEY.id,\n initial,\n );\n\n function updateField(k: T, v: Preferences[T]) {\n const newValue = { ...value, [k]: v };\n update(newValue);\n }\n return [value, updateField];\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { stringifyTalerUri, TalerUri } from \"@gnu-taler/taler-util\";\nimport { ComponentChildren, createContext, h, VNode } from \"preact\";\nimport { useContext } from \"preact/hooks\";\n\n/**\n * https://docs.taler.net/design-documents/039-taler-browser-integration.html\n *\n * @param uri\n */\nfunction createHeadMetaTag(uri: TalerUri, onNotFound?: () => void) {\n const meta = document.createElement(\"meta\");\n meta.setAttribute(\"name\", \"taler-uri\");\n meta.setAttribute(\"content\", stringifyTalerUri(uri));\n\n document.head.appendChild(meta);\n\n let walletFound = false;\n window.addEventListener(\"beforeunload\", () => {\n walletFound = true;\n });\n setTimeout(() => {\n if (!walletFound && onNotFound) {\n onNotFound();\n }\n }, 10); //very short timeout\n}\ninterface Type {\n /**\n * Tell the active wallet that an action is found\n *\n * @param uri\n * @returns\n */\n publishTalerAction: (uri: TalerUri, onNotFound?: () => void) => void;\n}\n\n// @ts-expect-error default value to undefined, should it be another thing?\nconst Context = createContext(undefined);\n\nexport const useTalerWalletIntegrationAPI = (): Type => useContext(Context);\n\nexport const TalerWalletIntegrationBrowserProvider = ({\n children,\n}: {\n children: ComponentChildren;\n}): VNode => {\n const value: Type = {\n publishTalerAction: createHeadMetaTag,\n };\n return h(Context.Provider, {\n value,\n children,\n });\n};\n\nexport const TalerWalletIntegrationTestingProvider = ({\n children,\n value,\n}: {\n children: ComponentChildren;\n value: Type;\n}): VNode => {\n return h(Context.Provider, {\n value,\n children,\n });\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n TalerFormAttributes,\n TalerProtocolDuration,\n} from \"@gnu-taler/taler-util\";\nimport type {\n InternationalizationAPI,\n SingleColumnFormDesign,\n UIFormElementConfig,\n} from \"@gnu-taler/web-util/browser\";\n\nexport type AcceptTermOfServiceContext = {\n tos_url: string;\n provider_name?: string;\n expiration_time?: TalerProtocolDuration;\n successor_measure?: string;\n tos_version: string;\n\n /**\n * Only open the attached link, do not offer both \"view in browser\"\n * and \"download PDF\" options.\n */\n link_only?: boolean;\n\n /**\n * @deprecated deprecated alias of tos_version.\n */\n tosVersion?: string;\n};\n\nfunction normalize(str: string) {\n return str.replace(/ /g, \"-\");\n}\n/**\n *\n * @param i18n\n * @param context\n * @returns\n */\nexport function acceptTos(\n i18n: InternationalizationAPI,\n context: AcceptTermOfServiceContext,\n): SingleColumnFormDesign {\n const myFields: UIFormElementConfig[] = [];\n const tosFileName = !context.provider_name\n ? \"TermsOfService.pdf\"\n : `${normalize(context.provider_name)}_TermsOfService.PDF`;\n if (context.link_only) {\n myFields.push({\n type: \"external-link\",\n id: TalerFormAttributes.DOWNLOADED_TERMS_OF_SERVICE,\n required: true,\n url: context.tos_url,\n label: i18n.str`Terms of service`,\n help: i18n.str`You must open/download the terms of service to proceed`,\n });\n } else {\n myFields.push(\n {\n type: \"external-link\",\n id: TalerFormAttributes.DOWNLOADED_TERMS_OF_SERVICE,\n required: true,\n url: context.tos_url,\n label: i18n.str`View in Browser`,\n },\n {\n type: \"download-link\",\n id: TalerFormAttributes.DOWNLOADED_TERMS_OF_SERVICE,\n url: context.tos_url,\n label: i18n.str`Download PDF version`,\n // required: true,\n validator(text, form) {\n return !text ? i18n.str`Click to download & read` : undefined;\n },\n media: \"application/pdf\",\n fileName: tosFileName,\n help: i18n.str`You must download to proceed`,\n },\n );\n }\n\n return {\n type: \"single-column\" as const,\n fields: [\n ...myFields,\n {\n type: \"toggle\",\n id: TalerFormAttributes.ACCEPTED_TERMS_OF_SERVICE,\n required: true,\n trueValue: context.tos_version ?? context.tosVersion,\n onlyTrueValue: true,\n label: i18n.str`Do you accept the terms of service?`,\n },\n ],\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.\n\n You should have received a copy of the GNU Affero Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport { format } from \"date-fns\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n SingleColumnFormDesign,\n} from \"../../index.browser.js\";\n\nexport const form_challenger_email = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Challenger EMAIL`,\n description: i18n.str`Challenge email ownership.`,\n id: \"challenger-email\",\n version: 0,\n config: design_challenger_email(i18n),\n});\n\n/**\n * Design of the challenger email.\n */\nexport function design_challenger_email(\n i18n: InternationalizationAPI,\n): SingleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n\n return {\n type: \"single-column\",\n fields: [\n {\n id: TalerFormAttributes.CONTACT_EMAIL,\n label: i18n.str`E-Mail`,\n type: \"text\",\n required: true,\n disabled: true,\n },\n ],\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.\n\n You should have received a copy of the GNU Affero Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport { format } from \"date-fns\";\nimport {\n countryNameList,\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n SingleColumnFormDesign,\n} from \"../../index.browser.js\";\n\nexport const form_challenger_postal = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Challenger POSTAL`,\n description: i18n.str`Challenge address ownership.`,\n id: \"challenger-postal\",\n version: 0,\n config: design_challenger_postal(i18n),\n});\n\n/**\n * Design of the challenger email.\n */\nexport function design_challenger_postal(\n i18n: InternationalizationAPI,\n): SingleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n\n return {\n type: \"single-column\",\n fields: [\n {\n id: TalerFormAttributes.CONTACT_NAME,\n label: i18n.str`Name`,\n type: \"text\",\n required: true,\n disabled: true,\n },\n {\n id: TalerFormAttributes.ADDRESS_LINES,\n label: i18n.str`Address`,\n type: \"textArea\",\n required: true,\n disabled: true,\n },\n {\n id: TalerFormAttributes.ADDRESS_COUNTRY,\n label: i18n.str`Country`,\n type: \"selectOne\",\n choices: countryNameList(i18n),\n required: true,\n disabled: true,\n },\n ],\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.\n\n You should have received a copy of the GNU Affero Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport { format } from \"date-fns\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n SingleColumnFormDesign,\n} from \"../../index.browser.js\";\n\nexport const form_challenger_sms = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Challenger SMS`,\n description: i18n.str`Challenge phone number ownership.`,\n id: \"challenger-sms\",\n version: 0,\n config: design_challenger_phone(i18n),\n});\n\n/**\n * Design of the challenger email.\n */\nexport function design_challenger_phone(\n i18n: InternationalizationAPI,\n): SingleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n\n return {\n type: \"single-column\",\n fields: [\n {\n id: TalerFormAttributes.CONTACT_PHONE,\n label: i18n.str`Phone`,\n type: \"text\",\n required: true,\n disabled: true,\n },\n ],\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.\n\n You should have received a copy of the GNU Affero Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport { format } from \"date-fns\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\n\nexport const form_generic_note = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Generic note`,\n description: i18n.str`Free-form, generic note`,\n id: \"generic_note\",\n version: 1,\n config: design_generic_note(i18n),\n});\n\n/**\n * Design of the generic note form.\n */\nexport function design_generic_note(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n\n return {\n type: \"double-column\",\n sections: [\n {\n title: i18n.str`Note / Memorandum`,\n fields: [\n {\n id: TalerFormAttributes.NOTE_TEXT,\n label: i18n.str`Free-form notes`,\n type: \"textArea\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Supplemental File Upload`,\n description: i18n.str`Optional supplemental information for the establishment of the business relationship with the customer.`,\n fields: [\n {\n id: TalerFormAttributes.SUPPLEMENTAL_FILES_LIST,\n label: i18n.str`Supplemental Files`,\n type: \"array\",\n labelFieldId: \"FILE.FILENAME\",\n required: false,\n fields: [\n {\n id: TalerFormAttributes.DESCRIPTION,\n label: i18n.str`Description`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.FILE,\n label: i18n.str`File (PDF)`,\n type: \"file\",\n accept: \"application/pdf\",\n required: true,\n },\n ],\n },\n ],\n },\n ],\n };\n}\n", "import { TalerFormAttributes, TranslatedString } from \"@gnu-taler/taler-util\";\nimport { intervalToDuration, isFuture, isValid, parse } from \"date-fns\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\nimport {\n countryNameList,\n countryNationalityList,\n drilldownGlsIndustries,\n germanBusinessTypes,\n} from \"../../utils/select-ui-lists.js\";\n\nexport const form_gls_merchant_onboarding = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n config: gls_merchant_onboarding(i18n, {}),\n id: \"gls-merchant-onboarding\",\n label: \"GLS Merchant Onboarding\",\n version: 1,\n});\n\nfunction validateDateOfBirth(\n i18n: InternationalizationAPI,\n text: string,\n _form: any,\n): TranslatedString | undefined {\n // Date is stored as ISO timestamp\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n}\n\nfunction validateFoundingDate(\n i18n: InternationalizationAPI,\n text: string,\n _form: any,\n): TranslatedString | undefined {\n // Date is stored as ISO timestamp\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n}\n\nfunction validateEmail(\n i18n: InternationalizationAPI,\n text: string,\n _form: any,\n): TranslatedString | undefined {\n const re = /^\\S+@\\S+\\.\\S+$/;\n if (re.test(text)) {\n return undefined;\n }\n return i18n.str`Invalid e-mail address`;\n}\n\nfunction validatePhone(\n i18n: InternationalizationAPI,\n text: string,\n _form: any,\n): TranslatedString | undefined {\n const re = /^[+]?([0-9]+[. ]*)+$/;\n if (re.test(text)) {\n return undefined;\n }\n return i18n.str`Invalid phone number`;\n}\n\nexport function gls_merchant_onboarding(\n i18n: InternationalizationAPI,\n context?: any,\n): DoubleColumnFormDesign {\n return {\n type: \"double-column\",\n title: \"Merchant Onboarding Information\",\n sections: [\n {\n title: i18n.str`Personal Details`,\n description: i18n.str`Personal details of the authorised representative.`,\n fields: [\n {\n id: TalerFormAttributes.PERSON_FIRST_NAMES,\n label: i18n.str`First name(s)`,\n help: i18n.str`As on your ID document`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.PERSON_LAST_NAME,\n label: i18n.str`Last name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DATE_OF_BIRTH,\n label: i18n.str`Date of birth`,\n type: \"isoDateText\",\n placeholder: \"dd.MM.yyyy\",\n pattern: \"dd.MM.yyyy\",\n required: true,\n validator: (text, form) => validateDateOfBirth(i18n, text, form),\n },\n {\n id: TalerFormAttributes.NATIONALITY,\n label: i18n.str`Nationality`,\n type: \"selectOne\",\n choices: countryNationalityList(i18n),\n required: true,\n },\n {\n id: TalerFormAttributes.CONTACT_PHONE,\n label: i18n.str`Phone number`,\n type: \"text\",\n required: true,\n validator: (text, form) => validatePhone(i18n, text, form),\n },\n {\n id: TalerFormAttributes.CONTACT_EMAIL,\n label: i18n.str`E-Mail`,\n type: \"text\",\n required: true,\n validator: (text, form) => validateEmail(i18n, text, form),\n },\n ],\n },\n {\n title: i18n.str`Company information`,\n fields: [\n {\n id: TalerFormAttributes.BUSINESS_DISPLAY_NAME,\n label: i18n.str`Name of the company`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.BUSINESS_TYPE,\n label: i18n.str`Legal form`,\n required: true,\n type: \"selectOne\",\n choices: germanBusinessTypes(i18n),\n },\n {\n id: TalerFormAttributes.BUSINESS_TYPE_OTHER,\n label: i18n.str`Legal form (free-form entry for other)`,\n hide(value, root) {\n return root[TalerFormAttributes.BUSINESS_TYPE] !== \"OTHER\";\n },\n required: true,\n type: \"text\",\n },\n {\n id: TalerFormAttributes.COMMERCIAL_REGISTER_NUMBER,\n label: i18n.str`Commercial register number`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.REGISTER_COURT_LOCATION,\n label: i18n.str`Seat of the register court`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.FOUNDING_DATE,\n label: i18n.str`Founding date`,\n type: \"isoDateText\",\n placeholder: \"dd.MM.yyyy\",\n pattern: \"dd.MM.yyyy\",\n required: true,\n validator: (text, form) => validateFoundingDate(i18n, text, form),\n },\n {\n id: TalerFormAttributes.BUSINESS_IS_NON_PROFIT,\n label: i18n.str`Is the company a non-profit organization?`,\n required: true,\n type: \"choiceHorizontal\",\n choices: [\n {\n label: \"Yes\",\n value: true,\n },\n {\n label: \"No\",\n value: false,\n },\n ],\n },\n {\n id: TalerFormAttributes.BUSINESS_INDUSTRY,\n label: i18n.str`Industry`,\n required: true,\n type: \"drilldown\",\n choices: drilldownGlsIndustries,\n },\n ],\n },\n {\n title: i18n.str`Company address`,\n fields: [\n {\n id: TalerFormAttributes.DOMICILE_ADDRESS,\n label: i18n.str`Address`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.ADDRESS_COUNTRY,\n label: i18n.str`Country`,\n type: \"selectOne\",\n choices: countryNameList(i18n),\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Tax information`,\n fields: [\n {\n id: TalerFormAttributes.DE_BUSINESS_OR_TAX_ID,\n label: i18n.str`Business identification number or tax number`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.TAX_IS_USA_LAW,\n label: i18n.str`Was the company incorporated in the USA or under US law?`,\n required: true,\n type: \"choiceHorizontal\",\n choices: [\n {\n label: \"Yes\",\n value: true,\n },\n {\n label: \"No\",\n value: false,\n },\n ],\n },\n {\n id: TalerFormAttributes.TAX_IS_ACTIVE,\n label: i18n.str`Economically active or inactive?`,\n type: \"choiceHorizontal\",\n choices: [\n {\n label: \"Active\",\n value: \"ACTIVE\",\n },\n {\n label: \"Inactive\",\n value: \"INACTIVE\",\n },\n ],\n required: true,\n },\n {\n id: TalerFormAttributes.TAX_IS_DEDUCTED,\n label: i18n.str`Eligible for input tax deduction`,\n type: \"choiceHorizontal\",\n choices: [\n {\n label: \"Yes\",\n value: true,\n },\n {\n label: \"No\",\n value: false,\n },\n ],\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Persons`,\n description: i18n.str`Please list all legal representatives, shareholders/partners, and authorized signatories.`,\n fields: [\n {\n id: TalerFormAttributes.BUSINESS_PERSONS,\n label: i18n.str`Legal representatives / shareholders / partners / authorized signatories`,\n type: \"array\",\n labelFieldId: TalerFormAttributes.PERSON_LAST_NAME,\n fields: [\n {\n id: TalerFormAttributes.PERSON_FIRST_NAMES,\n label: i18n.str`First name(s)`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.PERSON_LAST_NAME,\n label: i18n.str`Last name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DATE_OF_BIRTH,\n label: i18n.str`Date of birth`,\n type: \"isoDateText\",\n placeholder: \"dd.MM.yyyy\",\n pattern: \"dd.MM.yyyy\",\n required: true,\n validator: (text, form) =>\n validateDateOfBirth(i18n, text, form),\n },\n {\n id: TalerFormAttributes.NATIONALITY,\n label: i18n.str`Nationality`,\n type: \"selectOne\",\n choices: countryNationalityList(i18n),\n required: true,\n },\n {\n id: TalerFormAttributes.REPRESENTATIVE_TYPE,\n label: i18n.str`Type of representative`,\n type: \"choiceStacked\",\n choices: [\n {\n label: \"Shareholder (at least 25% of shares)\",\n value: \"SHAREHOLDER_GT_25_PERCENT\",\n },\n {\n label: \"Legal representative\",\n value: \"LEGAL_REPRESENTATIVE\",\n },\n {\n label: \"Authorized employee with account access\",\n value: \"AUTHORIZED_EMPLOYEE\",\n },\n ],\n },\n ],\n required: true,\n },\n ],\n },\n {\n title: i18n.str`New Customer Identification`,\n fields: [\n {\n type: \"caption\",\n label:\n \"Please complete the customer registration and identification for the authorized representative and other persons listed in this form.\",\n },\n {\n type: \"external-link\",\n url: \"https://kontoeroeffnung.gls.de/kundenanlage/gks-v\",\n id: \"none\",\n label: \"GLS Customer Registration\",\n },\n ],\n },\n ],\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n countryNamesByCode,\n countryNationalitiesByCode,\n currencyNamesByCode,\n langNamesByCode,\n} from \"@gnu-taler/taler-util\";\nimport { InternationalizationAPI, SelectUiChoice } from \"../index.browser.js\";\n\nexport function currencyNameList(\n i18n: InternationalizationAPI,\n): SelectUiChoice[] {\n return Object.entries(currencyNamesByCode).map(([value, translator]) => ({\n value,\n label: translator(i18n),\n }));\n}\n\nexport function countryNameList(\n i18n: InternationalizationAPI,\n): SelectUiChoice[] {\n return Object.entries(countryNamesByCode).map(([value, translator]) => ({\n value,\n label: translator(i18n),\n }));\n}\n\nexport function countryNationalityList(\n i18n: InternationalizationAPI,\n): SelectUiChoice[] {\n return Object.entries(countryNationalitiesByCode).map(\n ([value, translator]) => ({\n value,\n label: translator(i18n),\n }),\n );\n}\n\nexport function languageNameList(\n i18n: InternationalizationAPI,\n): SelectUiChoice[] {\n return Object.entries(langNamesByCode).map(([value, translator]) => ({\n value,\n label: translator(i18n),\n }));\n}\n\nexport const germanBusinessTypesList = {\n DE_GMBH: (i18n: InternationalizationAPI) => i18n.str`GmbH`,\n DE_GMBH_IG: (i18n: InternationalizationAPI) => i18n.str`GmbH i.G.`,\n DE_UG: (i18n: InternationalizationAPI) => i18n.str`UG`,\n DE_UG_IG: (i18n: InternationalizationAPI) => i18n.str`UG i.G.`,\n DE_OHG: (i18n: InternationalizationAPI) => i18n.str`UHG`,\n DE_KG: (i18n: InternationalizationAPI) => i18n.str`KG`,\n DE_EV: (i18n: InternationalizationAPI) => i18n.str`e.V.`,\n DE_EV_IG: (i18n: InternationalizationAPI) => i18n.str`e.V. i.G.`,\n DE_EG: (i18n: InternationalizationAPI) => i18n.str`eG`,\n DE_EG_IG: (i18n: InternationalizationAPI) => i18n.str`eG i.G.`,\n DE_PARTG: (i18n: InternationalizationAPI) => i18n.str`PartG`,\n DE_EK: (i18n: InternationalizationAPI) => i18n.str`e.K.`,\n DE_AG_UNLISTED: (i18n: InternationalizationAPI) =>\n i18n.str`AG (nicht b\u00F6rsennotiert)`,\n DE_AG_LISTED: (i18n: InternationalizationAPI) => i18n.str`AG (b\u00F6rsennotiert)`,\n DE_GBR: (i18n: InternationalizationAPI) => i18n.str`GbR`,\n DE_NEV: (i18n: InternationalizationAPI) => i18n.str`n.e.V.`,\n DE_PARTEI: (i18n: InternationalizationAPI) => i18n.str`Partei`,\n DE_WEG: (i18n: InternationalizationAPI) => i18n.str`WEG`,\n OTHER: (i18n: InternationalizationAPI) => i18n.str`Anderes`,\n};\n\nexport function germanBusinessTypes(\n i18n: InternationalizationAPI,\n): SelectUiChoice[] {\n return Object.entries(germanBusinessTypesList).map(([value, translator]) => ({\n value,\n label: translator(i18n),\n }));\n}\n\nexport const drilldownGlsIndustries = {\n \"Land- und Forstwirtschaft, Fischerei\": {\n \"Landwirtschaft, Jagd\": {\n Pflanzenbau: \"aaa\",\n Tierhaltung: \"aab\",\n \"Gemischte Landwirtschaft\": \"aac\",\n \"Erbringung von landwirtschaftlichen und g\u00E4rtnerischen Dienstleistungen\":\n \"aad\",\n Jagd: \"aae\",\n },\n \"Forstwirtschaft, Fischerei, Fischzucht\": {\n \"Erbringung von forstwirtschaftlichen Dienstleistungen\": \"aba\",\n Fischerei: \"abb\",\n },\n },\n \"Bergbau und Gewinnung von Steinen und Erden\": {\n \"Kohlenbergbau, Torfgewinnung, Erd\u00F6l, Erdgas, Erzbergbau\": {\n \"Steinkohlenbergbau und -brikettherstellung\": \"baa\",\n \"Gewinnung von Erd\u00F6l und Erdgas\": \"bab\",\n Eisenerzbergbau: \"bac\",\n },\n \"Gewinnung von Steinen und Erden, sonstiger Bergbau\": {\n \"Gewinnung von Natursteinen\": \"bba\",\n \"Gewinnung von Kies, Sand, Ton und Kaolin\": \"bbb\",\n \"Gewinnung von Mineralien f\u00FCr die Herstellung von chemischen Erzeugnissen\":\n \"bbc\",\n \"Gewinnung von Salz\": \"bbd\",\n \"Gewinnung von Steinen und Erden, anderweitig nicht genannt, sonstiger Bergbau\":\n \"bbe\",\n },\n },\n \"Verarbeitendes Gewerbe\": {\n Ern\u00E4hrungsgewerbe: {\n \"Schlachten und Fleischverarbeitung\": \"caa\",\n Fischverarbeitung: \"cab\",\n \"Obst- und Gem\u00FCseverarbeitung\": \"cac\",\n \"Herstellung von pflanzlichen und tierischen \u00D6len und Fetten\": \"cad\",\n \"Milchverarbeitung, Herstellung von Speiseeis\": \"cae\",\n \"Mahl- und Sch\u00E4lm\u00FChlen, Herstellung von St\u00E4rke und St\u00E4rkeerzeugnissen\":\n \"caf\",\n \"Herstellung von Futtermitteln\": \"cag\",\n \"Sonstiges Ern\u00E4hrungsgewerbe (ohne Getr\u00E4nkeherstellung)\": \"cah\",\n \"Herstellung von Getr\u00E4nken\": \"cai\",\n },\n \"Textil-, Bekleidungs-, Ledergewerbe\": {\n \"Spinnstoffaufbereitung und Spinnerei\": \"cba\",\n Weberei: \"cbb\",\n Textilveredlung: \"cbc\",\n \"Herstellung von konfektionierten Textilwaren (ohne Bekleidung)\": \"cbd\",\n \"Sonstiges Textilgewerbe (ohne Herstellung von Maschenware)\": \"cbe\",\n \"Herstellung von gewirktem und gestricktem Stoff\": \"cbf\",\n \"Herstellung von gewirkten und gestrickten Fertigerzeugnissen\": \"cbg\",\n \"Herstellung von Lederbekleidung\": \"cbh\",\n \"Herstellung von Bekleidung (ohne Lederbekleidung)\": \"cbi\",\n \"Zurichtung und F\u00E4rben von Fellen, Herstellung von Pelzwaren\": \"cbj\",\n \"Herstellung von Leder und Lederfaserstoff\": \"cbk\",\n \"Lederverarbeitung (ohne Herstellung von Lederbekleidung und Schuhen)\":\n \"cbl\",\n \"Herstellung von Schuhen\": \"cbm\",\n },\n \"Holzgewerbe (ohne Herstellung von M\u00F6beln)\": {\n \"S\u00E4ge-, Hobel- und Holzimpr\u00E4gnierwerke\": \"cca\",\n \"Herstellung von Furnier-, Sperrholz-, Holzfaser- und Holzspanplatten\":\n \"ccb\",\n \"Herstellung von Konstruktionsteilen, Fertigbauteilen, Ausbauelementen und Fertigteilbauten aus Holz\":\n \"ccc\",\n \"Herstellung von Verpackungsmitteln, Lagerbeh\u00E4ltern und Ladungstr\u00E4gern aus Holz\":\n \"ccd\",\n \"Herstellung von Holzwaren, anderweitig nicht genannt, sowie von Kork-, Flecht- und Korbwaren (ohne Herstellung von M\u00F6beln)\":\n \"cce\",\n },\n \"Papier-, Verlags-, Druckgewerbe\": {\n \"Herstellung von Holz- und Zellstoff, Papier, Karton und Pappe\": \"cda\",\n \"Herstellung von Waren aus Papier, Karton und Pappe\": \"cdb\",\n Verlagsgewerbe: \"cdc\",\n Druckgewerbe: \"cdd\",\n \"Vervielf\u00E4ltigung von bespielten Ton-, Bild- und Datentr\u00E4gern\": \"cde\",\n },\n \"Kokerei, Mineral\u00F6lverarbeitung\": {\n Kokerei: \"cea\",\n Mineral\u00F6lverarbeitung: \"ceb\",\n },\n \"Herstellung von chemischen und pharmazeutischen Erzeugnissen\": {\n \"Herstellung von chemischen Grundstoffen\": \"cfa\",\n \"Herstellung von Sch\u00E4dlingsbek\u00E4mpfungs-, Pflanzenschutz- und Desinfektionsmitteln\":\n \"cfb\",\n \"Herstellung von Anstrichmitteln, Druckfarben und Kitten\": \"cfc\",\n \"Herstellung von pharmazeutischen Erzeugnissen\": \"cfd\",\n \"Herstellung von Seifen, Wasch-, Reinigungs- und K\u00F6rperpflegemitteln sowie von Duftstoffen\":\n \"cfe\",\n \"Herstellung von sonstigen chemischen Erzeugnissen\": \"cff\",\n \"Herstellung von Chemiefasern\": \"cfg\",\n },\n \"Herstellung von Gummi- und Kunststoffwaren\": {\n \"Herstellung von Gummiwaren\": \"cga\",\n \"Herstellung von Kunststoffwaren\": \"cgb\",\n },\n \"Herstellung von Glas und Glaswaren, Keramik, Verarbeitung von Steinen und Erden\":\n {\n \"Herstellung von Glas und Glaswaren\": \"cha\",\n \"Herstellung von keramischen Erzeugnissen (ohne Herstellung von Ziegeln und Baukeramik)\":\n \"chb\",\n \"Herstellung von keramischen Wand- und Bodenfliesen und -platten\":\n \"chc\",\n \"Herstellung von Ziegeln und sonstiger Baukeramik\": \"chd\",\n \"Herstellung von Zement, Kalk und gebranntem Gips\": \"che\",\n \"Herstellung von Erzeugnissen aus Beton, Zement und Gips\": \"chf\",\n \"Be- und Verarbeitung von Naturwerksteinen und Natursteinen, anderweitig nicht genannt\":\n \"chg\",\n \"Herstellung von sonstigen Erzeugnissen aus nicht metallischen Mineralien\":\n \"chh\",\n },\n \"Metallerzeugung und -bearbeitung\": {\n \"Erzeugung von Roheisen, Stahl und Ferrolegierungen\": \"cia\",\n \"Herstellung von Rohren\": \"cib\",\n \"Sonstige erste Bearbeitung von Eisen und Stahl\": \"cic\",\n \"Erzeugung und erste Bearbeitung von NE-Metallen\": \"cid\",\n Gie\u00DFereien: \"cie\",\n },\n \"Herstellung von Metallerzeugnissen\": {\n \"Stahl- und Leichtmetallbau\": \"cja\",\n \"Herstellung von Metallbeh\u00E4ltern mit einem Fassungsverm\u00F6gen von mehr als 300 l, Herstellung von Heizk\u00F6rpern und -kesseln f\u00FCr Zentralheizungen\":\n \"cjb\",\n \"Herstellung von Dampfkesseln (ohne Zentralheizungskessel)\": \"cjc\",\n \"Herstellung von Schmiede-, Press-, Zieh- und Stanzteilen, gewalzten Ringen und pulvermetallurgischen Erzeugnissen\":\n \"cjd\",\n \"Oberfl\u00E4chenveredlung und W\u00E4rmebehandlung, Mechanik, anderweitig nicht genannt\":\n \"cje\",\n \"Herstellung von Schneidwaren, Werkzeugen, Schl\u00F6ssern und Beschl\u00E4gen aus unedlen Metallen\":\n \"cjf\",\n \"Herstellung von sonstigen Metallwaren\": \"cjg\",\n },\n Maschinenbau: {\n \"Herstellung von Maschinen f\u00FCr die Erzeugung und Nutzung von mechanischer Energie (ohne Motoren f\u00FCr Luft- und Stra\u00DFenfahrzeuge)\":\n \"cka\",\n \"Herstellung von sonstigen nicht wirtschaftszweigspezifischen Maschinen\":\n \"ckb\",\n \"Herstellung von land- und forstwirtschaftlichen Maschinen\": \"ckc\",\n \"Herstellung von Werkzeugmaschinen\": \"ckd\",\n \"Herstellung von Maschinen f\u00FCr sonstige bestimmte Wirtschaftszweige\":\n \"cke\",\n \"Herstellung von Haushaltsger\u00E4ten, anderweitig nicht genannt\": \"ckf\",\n \"Reparatur von sonstigen Ausr\u00FCstungen\": \"ckg\",\n },\n \"Herstellung von B\u00FCromaschinen, Datenverarbeitungsger\u00E4ten und -einrichtungen\":\n {\n \"Herstellung von B\u00FCromaschinen\": \"cla\",\n \"Herstellung von Datenverarbeitungsger\u00E4ten und -einrichtungen\": \"clb\",\n \"Reparatur von Datenverarbeitungs- und Telekommunikationsger\u00E4ten\":\n \"clc\",\n },\n \"Herstellung von Ger\u00E4ten der Elektrizit\u00E4tserzeugung, -verteilung\": {\n \"Herstellung von Elektromotoren, Generatoren und Transformatoren\": \"cma\",\n \"Herstellung von Elektrizit\u00E4tsverteilungs- und -schalteinrichtungen\":\n \"cmb\",\n \"Herstellung von isolierten Elektrokabeln, -leitungen und -dr\u00E4hten\":\n \"cmc\",\n \"Herstellung von Akkumulatoren und Batterien\": \"cmd\",\n \"Herstellung von elektrischen Lampen und Leuchten\": \"cme\",\n \"Herstellung von elektrischen Ausr\u00FCstungen, anderweitig nicht genannt\":\n \"cmf\",\n },\n \"Rundfunk- und Nachrichtentechnik\": {\n \"Herstellung von elektronischen Bauelementen\": \"cna\",\n \"Herstellung von Ger\u00E4ten und Einrichtungen der Telekommunikationstechnik\":\n \"cnb\",\n \"Herstellung von Rundfunkger\u00E4ten sowie phono- und videotechnischen Ger\u00E4ten\":\n \"cnc\",\n },\n \"Medizin-, Mess-, Steuer- und Regelungstechnik, Optik, Herstellung von Uhren\":\n {\n \"Herstellung von medizinischen Ger\u00E4ten und orthop\u00E4dischen Erzeugnissen\":\n \"coa\",\n \"Herstellung von Mess-, Kontroll-, Navigations- u.\u00E4. Instrumenten und Vorrichtungen\":\n \"cob\",\n \"Herstellung von industriellen Prozesssteuerungseinrichtungen\": \"coc\",\n \"Herstellung von optischen und fotografischen Ger\u00E4ten\": \"cod\",\n \"Herstellung von Uhren\": \"coe\",\n \"Reparatur von Haushaltswaren und Ziergegenst\u00E4nden aus Glas, Ton, Steinzeug und Porzellan\":\n \"cof\",\n },\n \"Herstellung von Kraftwagen, Kraftwagenteilen\": {\n \"Herstellung von Kraftwagen und Kraftwagenmotoren\": \"cpa\",\n \"Herstellung von Karosserien, Aufbauten und Anh\u00E4ngern\": \"cpb\",\n \"Herstellung von Teilen und Zubeh\u00F6r f\u00FCr Kraftwagen und Kraftwagenmotoren\":\n \"cpc\",\n },\n \"Sonstiger Fahrzeugbau\": {\n \"Schiff- und Bootsbau\": \"cqa\",\n Bahnindustrie: \"cqb\",\n \"Luft- und Raumfahrzeugbau\": \"cqc\",\n \"Herstellung von Kraftr\u00E4dern, Fahrr\u00E4dern und Behindertenfahrzeugen\":\n \"cqd\",\n \"Fahrzeugbau, anderweitig nicht genannt\": \"cqe\",\n },\n \"Herstellung von M\u00F6beln, Schmuck, Musikinstrumenten, Sportger\u00E4ten, Spielwaren, sonstigen Erzeugnissen\":\n {\n \"Herstellung von M\u00F6beln\": \"cra\",\n \"Herstellung von Schmuck u.\u00E4. Erzeugnissen\": \"crb\",\n \"Herstellung von Musikinstrumenten\": \"crc\",\n \"Herstellung von Sportger\u00E4ten\": \"crd\",\n \"Herstellung von Spielwaren\": \"cre\",\n \"Herstellung von sonstigen Erzeugnissen\": \"crf\",\n },\n Recycling: {\n \"Recycling von metallischen Altmaterialien und Reststoffen\": \"csa\",\n \"Recycling von nicht metallischen Altmaterialien und Reststoffen\": \"csb\",\n },\n },\n \"Energie- und Wasserversorgung, Baugewerbe\": {\n Energieversorgung: {\n Elektrizit\u00E4tsversorgung: \"daa\",\n Gasversorgung: \"dab\",\n W\u00E4rmeversorgung: \"dac\",\n },\n Wasserversorgung: {\n \"Wassergewinnung mit Fremdbezug zur Verteilung\": \"dba\",\n \"Wassergewinnung ohne Fremdbezug zur Verteilung\": \"dbb\",\n },\n Baugewerbe: {\n \"Vorbereitende Baustellenarbeiten\": \"dca\",\n \"Hoch- und Tiefbau\": \"dcb\",\n Bauinstallation: \"dcc\",\n \"Sonstiges Ausbaugewerbe\": \"dcd\",\n \"Vermietung von Baumaschinen und -ger\u00E4ten mit Bedienungspersonal\": \"dce\",\n },\n },\n \"Handel, Instandhaltung und Reparatur von Kraftfahrzeugen, Tankstellen\": {\n \"Kraftfahrzeughandel, Instandhaltung und Reparatur von Kraftfahrzeugen, Tankstellen\":\n {\n \"Handel mit Kraftwagen\": \"eaa\",\n \"Instandhaltung und Reparatur von Kraftwagen\": \"eab\",\n \"Handel mit Kraftwagenteilen und -zubeh\u00F6r\": \"eac\",\n \"Handel mit Kraftr\u00E4dern, Kraftradteilen und -zubeh\u00F6r, Instandhaltung und Reparatur von Kraftr\u00E4dern\":\n \"ead\",\n Tankstellen: \"eae\",\n },\n \"Handelsvermittlung, Gro\u00DFhandel\": {\n Handelsvermittlung: \"eba\",\n \"Gro\u00DFhandel mit landwirtschaftlichen Grundstoffen und lebenden Tieren\":\n \"ebb\",\n \"Gro\u00DFhandel mit Nahrungsmitteln, Getr\u00E4nken und Tabakwaren\": \"ebc\",\n \"Gro\u00DFhandel mit Gebrauchs- und Verbrauchsg\u00FCtern\": \"ebd\",\n \"Gro\u00DFhandel mit nicht landwirtschaftlichen Halbwaren, Altmaterialien und Reststoffen\":\n \"ebe\",\n \"Gro\u00DFhandel mit Maschinen, Ausr\u00FCstungen und Zubeh\u00F6r\": \"ebf\",\n \"Sonstiger Gro\u00DFhandel\": \"ebg\",\n },\n Einzelhandel: {\n \"Einzelhandel mit Waren verschiedener Art (in Verkaufsr\u00E4umen)\": \"eca\",\n \"Facheinzelhandel mit Nahrungsmitteln, Getr\u00E4nken und Tabakwaren (in Verkaufsr\u00E4umen)\":\n \"ecb\",\n \"Apotheken, Facheinzelhandel mit medizinischen, orthop\u00E4dischen und kosmetischen Artikeln (in Verkaufsr\u00E4umen)\":\n \"ecc\",\n \"Sonstiger Facheinzelhandel (in Verkaufsr\u00E4umen)\": \"ecd\",\n \"Einzelhandel mit Antiquit\u00E4ten und Gebrauchtwaren (in Verkaufsr\u00E4umen)\":\n \"ece\",\n \"Einzelhandel (nicht in Verkaufsr\u00E4umen)\": \"ecf\",\n \"Reparatur von Gebrauchsg\u00FCtern\": \"ecg\",\n },\n },\n Gastgewerbe: {\n Beherbergung: {\n Hotellerie: \"faa\",\n \"Sonstiges Beherbergungsgewerbe\": \"fab\",\n },\n Gastronomie: {\n \"Speisengepr\u00E4gte Gastronomie\": \"fba\",\n \"Getr\u00E4nkegepr\u00E4gte Gastronomie\": \"fbb\",\n \"Kantinen und Caterer\": \"fbc\",\n },\n },\n \"Verkehr und Lagerei\": {\n \"Landverkehr, Transport in Rohrfernleitungen\": {\n Eisenbahnverkehr: \"gaa\",\n \"Sonstiger Landverkehr\": \"gab\",\n \"Transport in Rohrfernleitungen\": \"gac\",\n \"Deutsche Bahn AG\": \"gad\",\n },\n \"Schifffahrt, Luftfahrt\": {\n \"See- und K\u00FCstenschifffahrt\": \"gba\",\n Binnenschifffahrt: \"gbb\",\n Linienflugverkehr: \"gbc\",\n },\n \"Lagerei sowie Erbringung von sonstigen Dienstleistungen f\u00FCr den Verkehr\": {\n \"Frachtumschlag und Lagerei\": \"gca\",\n \"Sonstige Hilfs- und Nebent\u00E4tigkeiten f\u00FCr den Verkehr\": \"gcb\",\n \"Reiseb\u00FCros und Reiseveranstalter\": \"gcc\",\n \"Spedition, sonstige Verkehrsvermittlung\": \"gcd\",\n },\n \"Post-, Kurier- und Expressdienste\": {\n \"Postverwaltung und private Post- und Kurierdienste\": \"gda\",\n Fernmeldedienste: \"gdb\",\n \"Telekom AG\": \"gdc\",\n \"Deutsche Post AG\": \"gdd\",\n },\n },\n \"Erbringung von Finanz- und Versicherungsdienstleistungen\": {\n \"Kreditgewerbe, Versicherungsgewerbe\": {\n Wertpapierfirma: \"haa\",\n \"Sonstige Finanzierungsinstitutionen\": \"hab\",\n \"Fonds von Kapitalgesellschaften\": \"hac\",\n \"Ausl\u00E4nd. Finanzges. Als Kreditinst. Gem. \u00A71Abs.1KWG\": \"had\",\n Geldmarktfonds: \"hae\",\n \"Sonstiges Versicherungsgewerbe\": \"hag\",\n },\n \"Mit Finanz- und Versicherungsdienstleistungen verbundene T\u00E4tigkeiten\": {\n \"Mit dem Kreditgewerbe verbundene T\u00E4tigkeiten\": \"hba\",\n \"Mit dem Versicherungsgewerbe verbundene T\u00E4tigkeiten\": \"hbb\",\n \"B\u00F6rseneinrichtungen mit t\u00E4gl. Einsch\u00FCssen\": \"hbc\",\n Postgiro\u00E4mter: \"hae\",\n \"Zust\u00E4ndige genossenschaftliche Zentralbank\": \"hbg\",\n \"Andere Genossenschaftliche Zentralbanken\": \"hbh\",\n \"Angeschlossene Kreditgenoss.(nur f\u00FCr genoss. Zentralbanken)\": \"hbi\",\n \"Sonstige mindestreservepflichtige Kreditinstitute\": \"hbj\",\n \"Ausl\u00E4ndische Kreditinstitute gem. \u00A7 53 KWG\": \"hbk\",\n \"Internationale Organisationen im Bereich KI\": \"hbl\",\n \"Multilaterale Entwicklungsbanken nicht mindestreservefrei und ohne Nullgewichtung\":\n \"hbm\",\n \"LbNRW/InvB Berlin/Hessen/WK/LaBo/BremAB\": \"hbo\",\n \"Multilaterale Entwicklungsbanken nicht mindestreservefrei mit Nullgewichtung\":\n \"hbp\",\n \"Sonstige mindestreservefreie Kreditinstitute\": \"hbq\",\n \"Internat. Organisationen im Bereich KI (AMR-frei)\": \"hbr\",\n \"Europ\u00E4ische Investitionsbank\": \"hbs\",\n \"Multilaterale Entwicklungsbanken (AMR-frei)\": \"hbt\",\n \"Multilaterale Entwicklungsbanken mindestreservefrei und mit Nullgewichtung\":\n \"hbu\",\n },\n },\n \"Grundst\u00FCcks- und Wohnungswesen, Vermietung (inkl. Bewegl. Sachen)\": {\n \"Grundst\u00FCcks- und Wohnungswesen, Vermietung n. bewegl. Sachen\": {\n \"Erschlie\u00DFung, Kauf und Verkauf von Grundst\u00FCcken, Geb\u00E4uden und Wohnungen\":\n \"iaa\",\n \"Vermietung und Verpachtung von eigenen Grundst\u00FCcken, Geb\u00E4uden und Wohnungen\":\n \"iab\",\n \"Vermittlung und Verwaltung von fremden Grundst\u00FCcken, Geb\u00E4uden und Wohnungen\":\n \"iac\",\n \"Vermietung und Verpachtung von eigenen Grundst\u00FCcken und Nichtwohngeb\u00E4uden und Bautr\u00E4ger f\u00FCr Nichtwohngeb\u00E4ude\":\n \"iad\",\n },\n \"Vermietung beweglicher Sachen\": {\n \"Vermietung von Kraftwagen bis 3,5 t Gesamtgewicht\": \"iba\",\n \"Vermietung von Maschinen und Ger\u00E4ten\": \"ibb\",\n \"Vermietung von Gebrauchsg\u00FCtern, anderweitig nicht genannt\": \"ibc\",\n \"Leasing von nichtfinanziellen immatriellen Verm\u00F6gensgegenst\u00E4nden (ohne Copyrights)\":\n \"ibd\",\n },\n },\n \"Informations- und Datenverarbeitung, Forschung und Entwicklung\": {\n Informationsdienstleistungen: {\n Hardwareberatung: \"jaa\",\n Softwareh\u00E4user: \"jab\",\n },\n Datenverarbeitung: {\n Datenverarbeitungsdienste: \"jba\",\n Datenbanken: \"jbb\",\n \"Instandhaltung und Reparatur von B\u00FCromaschinen, Datenverarbeitungsger\u00E4ten und -einrichtungen\":\n \"jbc\",\n \"Sonstige mit der Datenverarbeitung verbundene T\u00E4tigkeiten und Rundfunkveranstalter\":\n \"jbd\",\n },\n \"Forschung und Entwicklung\": {\n \"Forschung und Entwicklung im Bereich Natur-, Ingenieur-, Agrarwissenschaften und Medizin\":\n \"jca\",\n \"Forschung und Entwicklung im Bereich Rechts-, Wirtschafts- und Sozialwissenschaften sowie im Bereich Sprach-, Kultur- und Kunstwissenschaften\":\n \"jcb\",\n },\n },\n \"Erbringung von freiberuflichen, wirtschaftlichen und technischen Dienstleistungen\":\n {\n \"Freiberufliche Dienstleistungen\": {\n \"Rechts-, Steuer- und Unternehmensberatung, Wirtschaftspr\u00FCfung, Buchf\u00FChrung, Markt- und Meinungsforschung, Managementt\u00E4tigkeiten von Holdinggesellschaften\":\n \"kaa\",\n \"Architektur- und Ingenieurb\u00FCros\": \"kab\",\n Werbung: \"kac\",\n \"Personal- und Stellenvermittlung, \u00DCberlassung von Arbeitskr\u00E4ften\":\n \"kad\",\n \"Wach- und Sicherheitsdienste sowie Detekteien\": \"kae\",\n },\n \"Technische Dienstleistungen\": {\n \"Technische, physikalische und chemische Untersuchung\": \"kba\",\n \"Reinigung von Geb\u00E4uden, Inventar und Verkehrsmitteln\": \"kbb\",\n },\n \"Wirtschaftliche Dienstleistungen\": {\n \"Erbringung von sonstigen wirtschaftlichen Dienstleistungen, anderweitig nicht genannt\":\n \"kca\",\n },\n },\n \"\u00D6ffentliche Verwaltung, Verteidigung, Sozialversicherung\": {\n \"Verwaltung, Verteidigung, Sozialversicherung\": {\n \"\u00D6ffentliche Verwaltung\": \"laa\",\n \"Ausw\u00E4rtige Angelegenheiten, Verteidigung, Rechtspflege, \u00F6ffentliche Sicherheit und Ordnung\":\n \"lab\",\n \"Sozialversicherung und Arbeitsf\u00F6rderung\": \"lac\",\n },\n Bund: {\n \"Fonds Deutsche Einheit / Erblastentilgungsfonds\": \"lba\",\n \"ERP-Sonderverm\u00F6gen\": \"lbb\",\n Bundeseisenbahnverm\u00F6gen: \"lbc\",\n },\n L\u00E4nder: {\n Gemeinden: \"lcb\",\n \"Kommunale Zweckverb\u00E4nde\": \"lcc\",\n \"Sonstige ausl\u00E4ndische Gebietsk\u00F6rperschaften\": \"lcd\",\n },\n },\n \"Gesundheits-, Veterin\u00E4r- und Sozialwesen, Erziehung und Unterricht\": {\n \"Erziehung und Unterricht\": {\n \"Kinderg\u00E4rten, Vor- und Grundschulen\": \"maa\",\n \"Weiterf\u00FChrende Schulen\": \"mab\",\n \"Hochschulen und andere Bildungseinrichtungen des Terti\u00E4rsbereichs\":\n \"mac\",\n \"Erwachsenenbildung und sonstiger Unterricht\": \"mad\",\n },\n \"Gesundheits-, Veterin\u00E4r- und Sozialwesen\": {\n Gesundheitswesen: \"mba\",\n Veterin\u00E4rwesen: \"mbb\",\n Sozialwesen: \"mbc\",\n },\n },\n \"Abwasser- und Abfallentsorgung, Private Haushalte\": {\n Abwasserentsorgung: {\n Abwasserbeseitigung: \"naa\",\n },\n Abfallbeseitigung: {\n Abfallbeseitigung: \"nba\",\n },\n \"Private Haushalte\": {\n \"Private Haushalte mit sonstigem Hauspersonal\": \"nca\",\n },\n },\n \"Interessenvertretungen sowie kirchliche und sonstige Vereinigungen, Organisationen\":\n {\n Interessenvertretungen: {\n \"Wirtschafts- und Arbeitgeberverb\u00E4nde\": \"oaa\",\n Gewerkschaften: \"oab\",\n Berufsorganisationen: \"oac\",\n },\n \"Kirchliche und sonstige Vereinigungen\": {\n \"Kirchliche und sonstige religi\u00F6se Vereinigungen\": \"oba\",\n \"Politische Parteien und Vereinigungen\": \"obb\",\n \"Interessenvertretungen und Vereinigungen, anderweitig nicht genannt\":\n \"obc\",\n },\n Organisationen: {\n \"Organisationen der freien Wohlfahrts-/Jugendpflege\": \"oca\",\n \"Organisationen der Bildung/Wissenschaft/Forsch./Kultur\": \"ocb\",\n \"Organisationen des Sports und Gesundheitswesens\": \"occ\",\n \"Kommunale Spitzen- und Regionalverb\u00E4nde\": \"ocd\",\n \"Sonstige Organisationen ohne Erwerbszweck\": \"oce\",\n },\n },\n \"Kunst, Unterhaltung und Erholung, Erbringung von sonstigen Dienstleistungen\":\n {\n \"Kunst, Unterhaltung und Erholung\": {\n \"Film- und Videofilmherstellung, -verleih und -vertrieb, Kinos\": \"paa\",\n \"Rundfunkveranstalter, Herstellung von H\u00F6rfunk- und Fernsehprogrammen\":\n \"pab\",\n \"Erbringung von sonstigen kulturellen und unterhaltenden Leistungen\":\n \"pac\",\n \"Korrespondenz- und Nachrichtenb\u00FCros, selbstst\u00E4ndige Journalistinnen und Journalisten\":\n \"pad\",\n \"Bibliotheken, Archive, Museen, botanische und zoologische G\u00E4rten\":\n \"pae\",\n Sport: \"paf\",\n \"Erbringung von sonstigen Dienstleistungen f\u00FCr Unterhaltung, Erholung und Freizeit\":\n \"pag\",\n },\n \"Erbringung von sonstigen Dienstleistungen\": {\n \"W\u00E4scherei und chemische Reinigung\": \"pba\",\n \"Fris\u00F6r- und Kosmetiksalons\": \"pbb\",\n Bestattungswesen: \"pbc\",\n \"Saunas, Solarien, Fitnesszentren u.\u00E4.\": \"pbd\",\n \"Erbringung von Dienstleistungen, anderweitig nicht genannt\": \"pbe\",\n },\n },\n};\n", "import { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\n\nexport const form_gls_wallet_confirmation = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n config: gls_wallet_confirmation(i18n, {}),\n id: \"gls-wallet-confirmation\",\n label: \"GLS Wallet Confirmation\",\n version: 1,\n});\n\nexport function gls_wallet_confirmation(\n i18n: InternationalizationAPI,\n context?: any,\n): DoubleColumnFormDesign {\n return {\n type: \"double-column\",\n title: \"GLS Wallet Confirmation\",\n sections: [\n {\n title: i18n.str`Confirmation`,\n description: i18n.str`Confirmation of private customer / wallet.`,\n fields: [\n {\n id: TalerFormAttributes.WALLET_USER_IS_PRIVATE_CUSTOMER,\n label: i18n.str`Please confirm that you are a private customer that wants to redeem their wallet balance.`,\n type: \"choiceHorizontal\",\n required: true,\n choices: [\n {\n label: \"Yes\",\n value: true,\n },\n {\n label: \"No\",\n value: false,\n },\n ],\n },\n ],\n },\n ],\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.\n\n You should have received a copy of the GNU Affero Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\n\nexport interface MultiUploadContext {\n REQUESTED_FILES: {\n REQUESTED_FILE_ID: string;\n REQUESTED_FILE_TITLE: string;\n REQUESTED_FILE_DESCRIPTION: string;\n REQUESTED_FILE_REQUIRED?: boolean;\n }[];\n}\n\nexport const form_multi_upload = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Upload multiple documents`,\n description: i18n.str`Upload multiple documents.`,\n id: \"multi_upload\",\n version: 1,\n config: (context: any) => design_multi_upload(i18n, context),\n});\n\n/**\n * Form for uploading multiple documents.\n */\nexport function design_multi_upload(\n i18n: InternationalizationAPI,\n context: MultiUploadContext,\n): DoubleColumnFormDesign {\n return {\n type: \"double-column\",\n sections: context.REQUESTED_FILES.map((x, i) => {\n let fileId: string;\n if (x.REQUESTED_FILE_ID != null) {\n fileId = x.REQUESTED_FILE_ID;\n } else {\n fileId = `file_${String(i).padStart(4, \"0\")}`;\n }\n return {\n title: i18n.str`Document upload (${x.REQUESTED_FILE_TITLE})`,\n description: x.REQUESTED_FILE_DESCRIPTION ?? undefined,\n fields: [\n {\n id: `FILE_MAP.${fileId}`,\n label: i18n.str`File (PDF)`,\n type: \"file\",\n accept: \"application/pdf\",\n required: x.REQUESTED_FILE_REQUIRED ?? true,\n },\n ],\n };\n }),\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport type {\n DoubleColumnFormDesign,\n InternationalizationAPI,\n UIHandlerId,\n} from \"@gnu-taler/web-util/browser\";\n\nconst TALER_SCREEN_ID = 111;\n\nexport const nameAndDob = (\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign => ({\n type: \"double-column\" as const,\n sections: [\n {\n title: i18n.str`Simple form`,\n fields: [\n {\n type: \"textArea\",\n id: \"full_name\" as UIHandlerId,\n label: i18n.str`Full Name`,\n },\n {\n type: \"textArea\",\n id: \"birthdate\" as UIHandlerId,\n label: i18n.str`Birthdate`,\n },\n ],\n },\n ],\n});\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport type {\n DoubleColumnFormDesign,\n DoubleColumnFormSection,\n InternationalizationAPI,\n UIHandlerId,\n} from \"@gnu-taler/web-util/browser\";\n\nexport const simplest = (\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign => ({\n type: \"double-column\" as const,\n sections: [\n {\n title: i18n.str`Simple form`,\n fields: [\n {\n type: \"textArea\",\n id: \"comment\" as UIHandlerId,\n label: i18n.str`Comment`,\n },\n ],\n },\n resolutionSection(i18n),\n ],\n});\n\nexport function resolutionSection(\n i18n: InternationalizationAPI,\n): DoubleColumnFormSection {\n return {\n title: i18n.str`Resolution`,\n fields: [\n {\n type: \"choiceHorizontal\",\n id: \"state\" as UIHandlerId,\n label: i18n.str`New state`,\n converterId: \"TalerExchangeApi.AmlState\",\n choices: [\n {\n value: \"frozen\",\n label: i18n.str`Frozen`,\n },\n {\n value: \"pending\",\n label: i18n.str`Pending`,\n },\n {\n value: \"normal\",\n label: i18n.str`Normal`,\n },\n ],\n },\n {\n type: \"amount\",\n id: \"threshold\" as UIHandlerId,\n currency: \"NETZBON\",\n converterId: \"Taler.Amount\",\n label: i18n.str`New threshold`,\n },\n ],\n };\n}\n", "import { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport { format } from \"date-fns\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\n\nexport const form_vqf_902_11_customer = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Establishing of the controlling person of operating legal entities and partnerships both not quoted on the stock exchange (K)`,\n description: i18n.str`for operating legal entities and partnerships that are contracting partner as well as analogously for operating legal entities and partnership that are beneficial owners`,\n id: \"vqf_902_11_customer\",\n version: 1,\n config: VQF_902_11_customer(i18n),\n});\n\nexport function VQF_902_11_customer(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n return {\n type: \"double-column\",\n title: i18n.str`Establishment of the controlling person (submitted by customer)`,\n sections: [\n {\n title: \"Identity of the contracting partner\",\n description: \"Name and address\",\n fields: [\n {\n id: TalerFormAttributes.IDENTITY_CONTRACTING_PARTNER,\n label: i18n.str`Contracting partner`,\n type: \"textArea\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Controlling person(s)`,\n fields: [\n {\n id: TalerFormAttributes.CONTROL_REASON,\n label: i18n.str`Reason for control`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"HAS_25_MORE_RIGHTS\",\n label: i18n.str`Holding 25% or more`,\n description: i18n.str`The person(s) listed below is/are holding 25% or more of the contracting partner's shares (capital shares or voting rights)`,\n },\n {\n value: \"OTHER_WAY\",\n label: i18n.str`Other way`,\n description: i18n.str`If the capital shares or voting rights cannot be determined or in case there are no capital shares or voting rights 25% or more, the contracting partner hereby declares that the person(s) listed below is/are controlling the contracting partner in other ways`,\n },\n {\n value: \"DIRECTOR\",\n label: i18n.str`Managing director`,\n description: i18n.str`In case this/these person(s) cannot be determined or this/these person(s) does/do not exist, the contracting partner hereby declares that the person(s) listed below is/are the managing director(s)`,\n },\n ],\n required: true,\n },\n {\n id: TalerFormAttributes.IDENTITY_LIST,\n label: i18n.str`Controlling person(s)`,\n type: \"array\",\n validator(persons) {\n if (!persons || persons.length < 1) {\n return i18n.str`Can't be empty`;\n }\n return undefined;\n },\n labelFieldId: TalerFormAttributes.FULL_NAME,\n fields: [\n {\n id: TalerFormAttributes.FULL_NAME,\n label: i18n.str`Full name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DOMICILE_ADDRESS,\n label: i18n.str`Actual address of domicile`,\n type: \"textArea\",\n required: true,\n },\n ],\n },\n ],\n },\n {\n title: i18n.str`Fiduciary holding assets`,\n fields: [\n {\n id: TalerFormAttributes.THIRD_PARTY_OWNERSHIP,\n label: i18n.str`Is a third person the beneficial owner of the assets held in the account/securities account?`,\n required: true,\n type: \"choiceHorizontal\",\n choices: [\n {\n label: i18n.str`Yes`,\n value: true,\n },\n {\n label: i18n.str`No`,\n value: false,\n },\n ],\n },\n ],\n },\n {\n title: i18n.str`Signature(s)`,\n description: i18n.str`It is a criminal offence to deliberately provide false information on this form (article 251 of the Swiss Criminal Code, documents forgery)`,\n fields: [\n {\n type: \"caption\",\n label: i18n.str`The contracting partner hereby undertakes to inform automatically of any changes to the information contained herein.`,\n },\n {\n id: TalerFormAttributes.SIGNATURE,\n label: i18n.str`Signature(s)`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.SIGN_DATE,\n label: i18n.str`Date`,\n type: \"isoDateText\",\n defaultValue: today,\n placeholder: \"dd/MM/yyyy\",\n disabled: true,\n pattern: \"dd/MM/yyyy\",\n required: true,\n },\n ],\n },\n ],\n };\n}\n", "import { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\nimport { format } from \"date-fns\";\n\nexport const form_vqf_902_11_officer = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Establishing of the controlling person of operating legal entities and partnerships both not quoted on the stock exchange (K)`,\n description: i18n.str`for operating legal entities and partnerships that are contracting partner as well as analogously for operating legal entities and partnership that are beneficial owners`,\n id: \"vqf_902_11_officer\",\n version: 1,\n config: VQF_902_11_officer(i18n),\n});\n\nexport function VQF_902_11_officer(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n\n return {\n type: \"double-column\",\n title: i18n.str`Establishment of the controlling person (submitted by AML officer)`,\n sections: [\n {\n title: \"Identity of the contracting partner\",\n description: \"Name and address\",\n fields: [\n {\n id: TalerFormAttributes.IDENTITY_CONTRACTING_PARTNER,\n label: i18n.str`Contracting partner`,\n type: \"textArea\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Controlling person(s)`,\n fields: [\n {\n id: TalerFormAttributes.CONTROL_REASON,\n label: i18n.str`Reason for control`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"HAS_25_MORE_RIGHTS\",\n label: i18n.str`Holding 25% or more`,\n description: i18n.str`The person(s) listed below is/are holding 25% or more of the contracting partner's shares (capital shares or voting rights)`,\n },\n {\n value: \"OTHER_WAY\",\n label: i18n.str`Other way`,\n description: i18n.str`If the capital shares or voting rights cannot be determined or in case there are no capital shares or voting rights 25% or more, the contracting partner hereby declares that the person(s) listed below is/are controlling the contracting partner in other ways`,\n },\n {\n value: \"DIRECTOR\",\n label: i18n.str`Managing director`,\n description: i18n.str`In case this/these person(s) cannot be determined or this/these person(s) does/do not exist, the contracting partner hereby declares that the person(s) listed below is/are the managing director(s)`,\n },\n ],\n required: true,\n },\n {\n id: TalerFormAttributes.IDENTITY_LIST,\n label: i18n.str`Controlling person(s)`,\n type: \"array\",\n validator(persons) {\n if (!persons || persons.length < 1) {\n return i18n.str`Can't be empty`;\n }\n return undefined;\n },\n labelFieldId: TalerFormAttributes.FULL_NAME,\n fields: [\n {\n id: TalerFormAttributes.FULL_NAME,\n label: i18n.str`Full name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DOMICILE_ADDRESS,\n label: i18n.str`Actual address of domicile`,\n type: \"textArea\",\n required: true,\n },\n ],\n },\n ],\n },\n {\n title: i18n.str`Fiduciary holding assets`,\n fields: [\n {\n id: TalerFormAttributes.THIRD_PARTY_OWNERSHIP,\n label: i18n.str`Is a third person the beneficial owner of the assets held in the account/securities account?`,\n required: true,\n type: \"choiceHorizontal\",\n choices: [\n {\n label: i18n.str`Yes`,\n value: true,\n },\n {\n label: i18n.str`No`,\n value: false,\n },\n ],\n },\n ],\n },\n {\n title: i18n.str`Signature(s)`,\n description: i18n.str`It is a criminal offence to deliberately provide false information on this form (article 251 of the Swiss Criminal Code, documents forgery)`,\n hide(root) {\n return root[TalerFormAttributes.SUBMITTED_BY] != \"CUSTOMER\";\n },\n fields: [\n {\n type: \"caption\",\n label: i18n.str`The contracting partner hereby undertakes to inform automatically of any changes to the information contained herein.`,\n },\n {\n id: TalerFormAttributes.SIGNATURE,\n label: i18n.str`Signature(s)`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.SIGN_DATE,\n label: i18n.str`Date`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n required: true,\n defaultValue: today,\n disabled: true,\n },\n ],\n },\n {\n title: i18n.str`Signed Declaration`,\n description: i18n.str`Signed declaration by the customer`,\n hide(root) {\n return root[TalerFormAttributes.SUBMITTED_BY] != \"AML_OFFICER\";\n },\n fields: [\n {\n type: \"caption\",\n label: i18n.str`The uploaded document must contain the customer's signature on the beneficial owner declaration.`,\n },\n {\n id: TalerFormAttributes.ATTACHMENT_SIGNED_DOCUMENT,\n label: i18n.str`Signed Document`,\n type: \"file\",\n accept: \"application/pdf\",\n required: true,\n },\n ],\n },\n ],\n };\n}\n", "import { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport {\n Descr,\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\n\nexport const form_vqf_902_14 = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Special Clarifications`,\n description: i18n.str`When a business relationship or transaction is associated with increased risk, appears unusual or evidence exists that the assets are the proceeds of a felony or a qualified tax offence, the member has to perform additional clarifications.`,\n id: \"vqf_902_14\",\n version: 1,\n config: VQF_902_14(i18n),\n});\n\nexport function VQF_902_14(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n return {\n type: \"double-column\",\n title: \"Special Clarifications\",\n sections: [\n {\n title: i18n.str`Information on customer`,\n description: Descr.CUSTOMER_INFO_TYPE(i18n),\n fields: [\n {\n id: TalerFormAttributes.CUSTOMER_NAME,\n label: i18n.str`Customer`,\n // help: i18n.str``,\n type: \"text\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Reason for special clarifications`,\n fields: [\n {\n id: TalerFormAttributes.INCRISK_REASON,\n label: i18n.str`Reason`,\n help: i18n.str`Description of the circumstances/transactions, which triggered the special clarifications`,\n type: \"textArea\",\n required: true,\n validator(text, form) {\n return !text ? i18n.str`can't be empty` : undefined;\n },\n },\n ],\n },\n {\n title: i18n.str`Used means of clarification`,\n fields: [\n {\n id: TalerFormAttributes.INCRISK_MEANS,\n label: i18n.str`Means`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"GATHERING\",\n label: i18n.str`Gathering of information from the customer, beneficial owner of the assets, controlling person`,\n },\n {\n value: \"CONSULTATION\",\n label: i18n.str`Consultation of generally accessible sources and databases`,\n },\n {\n value: \"ENQUIRIES\",\n label: i18n.str`Enquiries with trustworthy persons`,\n },\n {\n value: \"OTHER\",\n label: i18n.str`Other, which?`,\n },\n ],\n required: true,\n },\n {\n id: TalerFormAttributes.INCRISK_MEANS_OTHER,\n type: \"text\",\n label: i18n.str`Other means of clarification:`,\n required: true,\n hide(value, root) {\n return root[TalerFormAttributes.INCRISK_MEANS] !== \"OTHER\";\n },\n },\n ],\n },\n {\n title: i18n.str`Supplemental File Upload`,\n description: i18n.str`Optional supplemental information for the special clarifications.`,\n fields: [\n {\n id: TalerFormAttributes.SUPPLEMENTAL_FILES_LIST,\n label: i18n.str`Supplemental Files`,\n type: \"array\",\n labelFieldId: \"FILE.FILENAME\",\n required: false,\n fields: [\n {\n id: TalerFormAttributes.DESCRIPTION,\n label: i18n.str`Description`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.FILE,\n label: i18n.str`File (PDF)`,\n type: \"file\",\n accept: \"application/pdf\",\n required: true,\n },\n ],\n },\n ],\n },\n {\n title: i18n.str`Summary and plausbility check of the gathered information`,\n description: i18n.str`The results of the clarifications have to be documented and their plausibility has to be checked.`,\n fields: [\n {\n id: TalerFormAttributes.INCRISK_SUMMARY,\n label: i18n.str`Summary`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.INCRISK_DOCUMENTS,\n label: i18n.str`Gathered/Consulted documents`,\n type: \"textArea\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Result of the special clarification`,\n fields: [\n {\n id: TalerFormAttributes.INCRISK_RESULT,\n label: i18n.str`Result`,\n type: \"choiceStacked\",\n choices: [\n {\n label: i18n.str`No suspicion`,\n value: \"NO_SUSPICION\",\n description: i18n.str`The plausibility of the circumstances could be checked, no reasonable suspicion pursuant to Art. 9 AMLA (possibly update of customer profile and/or risk profile)`,\n },\n {\n label: i18n.str`Reasonable suspicion`,\n value: \"REASONABLE_SUSPICION\",\n description: i18n.str`Reasonable suspicion pursuant to Art. 9 AMLA, duty to file a report with MROS`,\n },\n {\n label: i18n.str`Simple suspicion`,\n value: \"SIMPLE_SUSPICION\",\n description: i18n.str`Simple suspicion pursuant to Art. 305 Para. 2 StGB, right to notify MROS`,\n },\n {\n label: i18n.str`Other, what?`,\n value: \"OTHER\",\n },\n ],\n required: true,\n },\n {\n id: TalerFormAttributes.INCRISK_RESULT_OTHER,\n type: \"text\",\n label: i18n.str`Result clarification`,\n required: true,\n hide(value, root) {\n return root[TalerFormAttributes.INCRISK_RESULT] !== \"OTHER\";\n },\n },\n ],\n },\n ],\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.\n\n You should have received a copy of the GNU Affero Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport { format, intervalToDuration, isFuture, isValid, parse } from \"date-fns\";\nimport {\n DoubleColumnFormDesign,\n InternationalizationAPI,\n UIFormElementConfig,\n} from \"../../index.browser.js\";\nimport { countryNationalityList } from \"../../utils/select-ui-lists.js\";\n\nexport const Descr = {\n CUSTOMER_INFO_TYPE: (\n i18n: InternationalizationAPI,\n ) => i18n.str`The customer is the person with whom the member concludes the contract with regard to the financial service provided (civil law). Does the\n member act as director of a domiciliary company, this domiciliary company is the customer.`,\n} as const;\n\nexport const form_vqf_902_1_customer = (i18n: InternationalizationAPI) => ({\n label: i18n.str`Identification Form (customer)`,\n description: i18n.str`The customer has to be identified on entering into a permanent business relationship or on concluding a cash transaction, which meets the according threshold.`,\n id: \"vqf_902_1_customer\",\n version: 1,\n config: design_VQF_902_1_customer(i18n),\n});\n\nconst fieldCorrespondenceLanguage = (\n i18n: InternationalizationAPI,\n): UIFormElementConfig => ({\n id: TalerFormAttributes.CORRESPONDENCE_LANGUAGE,\n required: true,\n label: i18n.str`Correspondence language:`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"en\",\n label: i18n.str`English`,\n },\n {\n value: \"de\",\n label: i18n.str`German`,\n },\n {\n value: \"fr\",\n label: i18n.str`French`,\n },\n {\n value: \"it\",\n label: i18n.str`Italian`,\n },\n ],\n});\n\n/**\n * Form vqf_902_1_customer.\n */\nexport function design_VQF_902_1_customer(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n\n return {\n type: \"double-column\",\n title: i18n.str`Identification form (basic customer information)`,\n sections: [\n {\n title: i18n.str`Information on customer`,\n description: Descr.CUSTOMER_INFO_TYPE(i18n),\n fields: [\n {\n id: TalerFormAttributes.CUSTOMER_TYPE,\n label: i18n.str`Customer type`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"NATURAL_PERSON\",\n label: i18n.str`Natural person (incl. sole proprietors)`,\n },\n {\n value: \"LEGAL_ENTITY\",\n label: i18n.str`Legal entity`,\n },\n ],\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Information on customer`,\n description: i18n.str`Applicable if customer is a natural person`,\n hide(root) {\n return root[TalerFormAttributes.CUSTOMER_TYPE] !== \"NATURAL_PERSON\";\n },\n fields: [\n {\n id: TalerFormAttributes.FULL_NAME,\n label: i18n.str`Full name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DOMICILE_ADDRESS,\n label: i18n.str`Residential address in Switzerland`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.CONTACT_PHONE,\n label: i18n.str`Telephone`,\n type: \"text\",\n required: false,\n },\n {\n id: TalerFormAttributes.CONTACT_EMAIL,\n label: i18n.str`E-mail`,\n type: \"text\",\n required: false,\n },\n {\n id: TalerFormAttributes.DATE_OF_BIRTH,\n label: i18n.str`Date of birth`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n defaultCalendarValue: \"1980-01-01\",\n required: true,\n validator(text, form) {\n //FIXME: why returning in this format even if pattern is in another?\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n },\n },\n {\n id: TalerFormAttributes.NATIONALITY,\n label: i18n.str`Nationality`,\n type: \"selectOne\",\n choices: countryNationalityList(i18n),\n preferredChoiceVals: [\"CH\"],\n required: true,\n },\n {\n id: TalerFormAttributes.PERSONAL_IDENTIFICATION_DOCUMENT_COPY,\n label: i18n.str`Copy of identification document`,\n type: \"file\",\n accept: \"application/pdf\",\n tooltip: i18n.str`Only official government IDs (incl. passports) are accepted. Please scan both sides if applicable.`,\n required: true,\n },\n {\n id: TalerFormAttributes.CUSTOMER_IS_SOLE_PROPRIETOR,\n label: i18n.str`Sole proprietor`,\n type: \"toggle\",\n threeState: false,\n },\n ],\n },\n {\n title: i18n.str`Information on customer (sole proprietor)`,\n description: i18n.str`Applicable only if customer is a sole proprietor`,\n hide(root) {\n return (\n root[TalerFormAttributes.CUSTOMER_TYPE] !== \"NATURAL_PERSON\" ||\n !root[TalerFormAttributes.CUSTOMER_IS_SOLE_PROPRIETOR]\n );\n },\n fields: [\n {\n id: TalerFormAttributes.COMPANY_NAME,\n label: i18n.str`Company name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.REGISTERED_OFFICE_ADDRESS,\n label: i18n.str`Registered office`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY,\n label: i18n.str`Company identification document`,\n type: \"file\",\n required: true,\n accept: \"application/pdf\",\n },\n ],\n },\n {\n title: i18n.str`Information on customer (legal entity)`,\n description: i18n.str`Applicable if customer is a legal entity`,\n hide(root) {\n return root[TalerFormAttributes.CUSTOMER_TYPE] !== \"LEGAL_ENTITY\";\n },\n fields: [\n {\n id: TalerFormAttributes.COMPANY_NAME,\n label: i18n.str`Company name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DOMICILE_ADDRESS,\n label: i18n.str`Domicile`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.CONTACT_PERSON_NAME,\n label: i18n.str`Contact person`,\n type: \"text\",\n required: false,\n },\n {\n id: TalerFormAttributes.CONTACT_PHONE,\n label: i18n.str`Telephone`,\n type: \"text\",\n required: false,\n },\n {\n id: TalerFormAttributes.CONTACT_EMAIL,\n label: i18n.str`E-mail`,\n type: \"text\",\n required: false,\n },\n {\n id: TalerFormAttributes.LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY,\n label: i18n.str`Copy of identification document (not older than 12 months)`,\n type: \"file\",\n accept: \"application/pdf\",\n required: true,\n },\n {\n id: TalerFormAttributes.COMPANY_SHARE_REGISTRY,\n label: i18n.str`Company share registry file`,\n type: \"file\",\n accept: \"application/pdf\",\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Correspondence Preferences`,\n hide(root) {\n return !root[TalerFormAttributes.CUSTOMER_TYPE];\n },\n fields: [fieldCorrespondenceLanguage(i18n)],\n },\n {\n title: i18n.str`Information on the natural persons who establish the business relationship for legal entities and partnerships`,\n description: i18n.str`For legal entities and partnerships the identity of the natural persons who establish the business relationship must be verified.`,\n hide(root) {\n return root[TalerFormAttributes.CUSTOMER_TYPE] !== \"LEGAL_ENTITY\";\n },\n fields: [\n {\n id: TalerFormAttributes.ESTABLISHER_LIST,\n label: i18n.str`Establishers of the legal relationship`,\n type: \"array\",\n labelFieldId: TalerFormAttributes.FULL_NAME,\n required: true,\n fields: [\n {\n id: TalerFormAttributes.FULL_NAME,\n label: i18n.str`Full name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DOMICILE_ADDRESS,\n label: i18n.str`Residential address`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.DATE_OF_BIRTH,\n label: i18n.str`Date of birth`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n defaultCalendarValue: \"1980-01-01\",\n required: true,\n validator(text, form) {\n //FIXME: why returning in this format even if pattern is in another?\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n },\n },\n {\n id: TalerFormAttributes.NATIONALITY,\n label: i18n.str`Nationality`,\n type: \"selectOne\",\n choices: countryNationalityList(i18n),\n preferredChoiceVals: [\"CH\"],\n required: true,\n },\n {\n id: TalerFormAttributes.PERSONAL_IDENTIFICATION_DOCUMENT_COPY,\n label: i18n.str`Copy of identification document`,\n type: \"file\",\n accept: \"application/pdf\",\n tooltip: i18n.str`Only official government IDs (incl. passports) are accepted. Please scan both sides if applicable.`,\n required: true,\n },\n {\n id: TalerFormAttributes.SIGNING_AUTHORITY_TYPE,\n tooltip: i18n.str`Signing authority of the person`,\n label: i18n.str`Power of attorney arrangements`,\n type: \"choiceStacked\",\n required: true,\n choices: [\n {\n label: \"Sole signature authority\",\n value: \"SINGLE\",\n },\n {\n label: \"Collective authority with two signatures\",\n value: \"COLLECTIVE_TWO\",\n },\n {\n label: \"Other (please specify)\",\n value: \"OTHER\",\n },\n ],\n },\n {\n id: TalerFormAttributes.SIGNING_AUTHORITY_TYPE_OTHER,\n required: true,\n label: i18n.str`Other type of signing authority`,\n type: \"text\",\n hide(value, root) {\n return (\n root[TalerFormAttributes.SIGNING_AUTHORITY_TYPE] !== \"OTHER\"\n );\n },\n },\n {\n id: TalerFormAttributes.SIGNING_AUTHORITY_EVIDENCE,\n required: true,\n label: i18n.str`Evidence of signing authority:`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"CR\",\n label: i18n.str`Company register extract`,\n },\n {\n value: \"MANDATE\",\n label: i18n.str`Mandate`,\n },\n {\n value: \"OTHER\",\n label: i18n.str`Other`,\n },\n ],\n },\n {\n id: TalerFormAttributes.SIGNING_AUTHORITY_EVIDENCE_OTHER,\n required: true,\n label: i18n.str`Specify other way of establishing signing authority:`,\n type: \"text\",\n hide(value, root) {\n return (\n root[TalerFormAttributes.SIGNING_AUTHORITY_EVIDENCE] !==\n \"OTHER\"\n );\n },\n },\n {\n id: TalerFormAttributes.SIGNING_AUTHORITY_EVIDENCE_DOCUMENT_COPY,\n label: i18n.str`Copy of document that serves as evidence of signing authority:`,\n type: \"file\",\n accept: \"application/pdf\",\n required: true,\n },\n ],\n },\n ],\n },\n // Version of the question for natural persons\n {\n title: i18n.str`Customer classification`,\n description: i18n.str`Classification for the establishment of the beneficial owner of the assets and/or controlling person`,\n hide(root) {\n return root[TalerFormAttributes.CUSTOMER_TYPE] !== \"NATURAL_PERSON\";\n },\n fields: [\n {\n id: TalerFormAttributes.CUSTOMER_TYPE_VQF,\n required: true,\n label: i18n.str`The customer is:`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"NATURAL_PERSON\",\n label: i18n.str`A natural person and there are no doubts that this person is the sole beneficial owner of the assets`,\n },\n {\n value: \"OTHER\",\n label: i18n.str`Other`,\n },\n ],\n },\n ],\n },\n // Version for Businesses\n {\n title: i18n.str`Customer classification`,\n description: i18n.str`Classification for the establishment of the beneficial owner of the assets and/or controlling person`,\n hide(root) {\n return root[TalerFormAttributes.CUSTOMER_TYPE] !== \"LEGAL_ENTITY\";\n },\n fields: [\n {\n id: TalerFormAttributes.CUSTOMER_TYPE_VQF,\n required: true,\n label: i18n.str`The customer is:`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"OPERATIONAL\",\n label: i18n.str`An operational legal entity or partnership`,\n },\n {\n value: \"FOUNDATION\",\n label: i18n.str`A foundation (or a similar construct; incl. underlying companies)`,\n },\n {\n value: \"TRUST\",\n label: i18n.str`A trust (incl. underlying companies)`,\n },\n {\n value: \"LIFE_INSURANCE\",\n label: i18n.str`A life insurance policy with separately managed accounts / securities accounts (so-called insurance wrappers)`,\n },\n {\n value: \"OTHER\",\n label: i18n.str`Other`,\n },\n ],\n },\n ],\n },\n {\n title: i18n.str`Signature(s)`,\n description: i18n.str`It is a criminal offence to deliberately provide false information on this form (article 251 of the Swiss Criminal Code, documents forgery)`,\n fields: [\n {\n type: \"caption\",\n label: i18n.str`The contracting partner hereby undertakes to inform automatically of any changes to the information contained herein.`,\n },\n {\n id: TalerFormAttributes.SIGNATURE,\n label: i18n.str`Signature(s)`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.SIGN_DATE,\n label: i18n.str`Date`,\n type: \"isoDateText\",\n defaultValue: today,\n placeholder: \"dd/MM/yyyy\",\n disabled: true,\n pattern: \"dd/MM/yyyy\",\n required: true,\n },\n ],\n },\n ],\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.\n\n You should have received a copy of the GNU Affero Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport {\n format,\n intervalToDuration,\n isFuture,\n isToday,\n isValid,\n parse,\n} from \"date-fns\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\n\nexport const form_vqf_902_1_officer = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Identification Form (acceptance)`,\n description: i18n.str`The customer has to be identified on entering into a permanent business relationship or on concluding a cash transaction, which meets the according threshold.`,\n id: \"vqf_902_1_officer\",\n version: 1,\n config: VQF_902_1_officer(i18n),\n});\n\n/**\n * Design of the vqf_902_1_officer form.\n */\nexport function VQF_902_1_officer(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n\n return {\n type: \"double-column\",\n sections: [\n {\n title: i18n.str`Acceptance of business relationship`,\n fields: [\n {\n id: TalerFormAttributes.ACCEPTANCE_DATE,\n label: i18n.str`Date (conclusion of contract):`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n defaultValue: today,\n disabled: true,\n required: true,\n },\n {\n id: TalerFormAttributes.ACCEPTANCE_METHOD,\n label: i18n.str`Accepted via:`,\n type: \"choiceStacked\",\n choices: [\n {\n value: \"FACE_TO_FACE\",\n label: i18n.str`Face to face`,\n },\n {\n value: \"AUTHENTICATED_COPY\",\n label: i18n.str`Authenticated copy of identification document`,\n },\n {\n value: \"RESIDENTIAL_ADDRESS_VALIDATED\",\n label: i18n.str`Residentail address validated`,\n },\n ],\n required: true,\n },\n {\n id: TalerFormAttributes.ACCEPTANCE_FURTHER_INFO,\n label: i18n.str`Further information:`,\n type: \"textArea\",\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Evaluation with regard to embargo procedures/terrorism lists on establishing the business relationship`,\n description: i18n.str`Verification whether the customer, beneficial owners of the assets, controlling persons, authorized representatives or other involved persons are listed on an embargo/terrorism list.`,\n fields: [\n {\n id: TalerFormAttributes.EMBARGO_TERRORISM_CHECK_RESULT,\n label: i18n.str`Embargo/terrorism status:`,\n type: \"choiceStacked\",\n required: true,\n choices: [\n {\n label: i18n.str`Not listed on embargo/terrorism list.`,\n value: \"NOT_LISTED\",\n },\n {\n label: i18n.str`Listed on embargo/terrorism list.`,\n value: \"LISTED\",\n },\n ],\n },\n {\n id: TalerFormAttributes.EMBARGO_TERRORISM_INFO,\n label: i18n.str`Embargo/terrorism information:`,\n type: \"textArea\",\n hide(value, root): boolean {\n return (\n root[TalerFormAttributes.EMBARGO_TERRORISM_CHECK_RESULT] !==\n \"LISTED\"\n );\n },\n required: true,\n },\n {\n id: TalerFormAttributes.EMBARGO_TERRORISM_CHECK_DATE,\n label: i18n.str`Verification date`,\n type: \"isoDateText\",\n required: true,\n defaultValue: today,\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n validator(text, form) {\n //FIXME: why returning in this format even if pattern is in another?\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n },\n },\n ],\n },\n {\n title: i18n.str`Supplemental File Upload`,\n description: i18n.str`Optional supplemental information for the establishment of the business relationship with the customer.`,\n fields: [\n {\n id: TalerFormAttributes.SUPPLEMENTAL_FILES_LIST,\n label: i18n.str`Supplemental files`,\n type: \"array\",\n labelFieldId: \"FILE.FILENAME\",\n required: false,\n fields: [\n {\n id: TalerFormAttributes.DESCRIPTION,\n label: i18n.str`Description`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.FILE,\n label: i18n.str`File (PDF)`,\n type: \"file\",\n accept: \"application/pdf\",\n required: true,\n },\n ],\n },\n ],\n },\n ],\n };\n}\n", "import { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport {\n Descr,\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\nimport { intervalToDuration, parse, isFuture, isValid } from \"date-fns\";\n\nexport const form_vqf_902_4 = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Risk Profile AMLA`,\n id: \"vqf_902_4\",\n version: 1,\n config: VQF_902_4(i18n),\n});\n\nexport function VQF_902_4(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n return {\n type: \"double-column\",\n sections: [\n {\n title: i18n.str`Information on customer`,\n description: Descr.CUSTOMER_INFO_TYPE(i18n),\n fields: [\n {\n id: TalerFormAttributes.CUSTOMER_NAME,\n label: i18n.str`Customer`,\n // help: i18n.str``,\n type: \"text\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Evaluation of politically exposed persons (PEP-Check)`,\n description: i18n.str`This evaluation has to be completed by all members for every business relationship.`,\n fields: [\n {\n id: TalerFormAttributes.PEP_FOREIGN,\n label: i18n.str`Foreign PEP`,\n help: i18n.str`Is the customer, the beneficial owner or the controlling person or authorised representative a foreign PEP or closely related to such a person?`,\n type: \"choiceHorizontal\",\n required: true,\n choices: [\n {\n value: true,\n label: `Yes`,\n },\n {\n value: false,\n label: `No`,\n },\n ],\n },\n {\n id: TalerFormAttributes.PEP_DOMESTIC,\n label: i18n.str`Domestic PEP`,\n help: i18n.str`Is the customer, the beneficial owner or the controlling person or authorised representative a domestic PEP or closely related to such a person?`,\n type: \"choiceHorizontal\",\n required: true,\n choices: [\n {\n value: true,\n label: `Yes`,\n },\n {\n value: false,\n label: `No`,\n },\n ],\n },\n {\n id: TalerFormAttributes.PEP_INTERNATIONAL_ORGANIZATION,\n label: i18n.str`PEP of International Organisatons`,\n help: i18n.str`Is the customer, the beneficial owner or the controlling person or authorised representative a PEP in International Organizations or closely related to such a person?`,\n type: \"choiceHorizontal\",\n required: true,\n choices: [\n {\n value: true,\n label: `Yes`,\n },\n {\n value: false,\n label: `No`,\n },\n ],\n },\n {\n id: TalerFormAttributes.PEP_ACCEPTANCE_DATE,\n label: i18n.str`Acceptance date`,\n help: i18n.str`When the decision of the Senior executive body on the acceptance of a business relationship with a PEP was obtain on.`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n required: true,\n validator(text, form) {\n //FIXME: why returning in this format even if pattern is in another?\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n },\n hide(value, root) {\n return !(\n root[TalerFormAttributes.PEP_FOREIGN] ||\n root[TalerFormAttributes.PEP_DOMESTIC] ||\n root[TalerFormAttributes.PEP_INTERNATIONAL_ORGANIZATION]\n );\n },\n },\n ],\n },\n {\n title: i18n.str`Evaluation \"high risk\" or non-cooperative country`,\n description: i18n.str`This evaluation has to be completed by all members for every business relationship.`,\n fields: [\n {\n id: TalerFormAttributes.HIGH_RISK_COUNTRY,\n label: i18n.str`High-risk or non-cooperative country`,\n help: i18n.str`Is the customer, the beneficial owner or the controlling person or authorised representative in a country considered by the FATF as high-risk or non-cooperative and for which FATF requires increased diligence?`,\n type: \"choiceHorizontal\",\n required: true,\n choices: [\n {\n value: true,\n label: `Yes`,\n },\n {\n value: false,\n label: `No`,\n },\n ],\n },\n {\n id: TalerFormAttributes.HIGH_RISK_ACCEPTANCE_DATE,\n label: i18n.str`Acceptance date`,\n help: i18n.str`When the decision of the Senior executive body on the acceptance of such a business relationship was obtained on.`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n required: true,\n validator(text, form) {\n //FIXME: why returning in this format even if pattern is in another?\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n },\n\n hide(value, root) {\n return !root[TalerFormAttributes.HIGH_RISK_COUNTRY];\n },\n },\n ],\n },\n {\n title: i18n.str`Evaluation of business relationship risk`,\n fields: [\n {\n type: \"caption\",\n label:\n \"This evaluation has to be completed by all members who have in total more than 20 customers for every business relationship. At least two risk categories have to be chosen and assessed.\",\n },\n ],\n },\n {\n title: i18n.str`Country risk`,\n fields: [\n {\n id: TalerFormAttributes.COUNTRY_RISK_NATIONALITY_TYPE,\n label: i18n.str`Applicable country risk types`,\n choices: [\n {\n label: i18n.str`Nationality of the customer`,\n value: \"NATIONALITY_CUSTOMER\",\n },\n {\n label: i18n.str`Nationality of the beneficial owner of the assets`,\n value: \"NATIONALITY_OWNER\",\n },\n {\n label: i18n.str`Domicile/residential address of the customer`,\n value: \"DOMICILE_CUSTOMER\",\n },\n {\n label: i18n.str`Domicile/residential address of the beneficial owner of the assets`,\n value: \"DOMICILE_OWNER\",\n },\n {\n label: i18n.str`Domicile/residential address of the controlling person`,\n value: \"DOMICILE_CONTROLLING\",\n },\n ],\n type: \"selectMultiple\",\n required: false,\n },\n {\n id: TalerFormAttributes.COUNTRY_RISK_NATIONALITY_LEVEL,\n label: i18n.str`Country risk level (nationality)`,\n help: i18n.str`Risk category according to VQF country list (VQF doc. no. 902.4.1)`,\n choices: [\n {\n label: i18n.str`Low (Risk 0)`,\n value: \"LOW\",\n description: i18n.str`Risk 0 acc. to VQF country list (VQF doc. no. 902.4.1)`,\n },\n {\n label: i18n.str`Medium (Risk 1)`,\n value: \"MEDIUM\",\n description: i18n.str`Risk 1 acc. to VQF country list (VQF doc. no. 902.4.1)`,\n },\n {\n label: i18n.str`High (Risk 2)`,\n value: \"HIGH\",\n description: i18n.str`Risk 2 acc. to VQF country list (VQF doc. no. 902.4.1)`,\n },\n ],\n type: \"choiceHorizontal\",\n required: false,\n },\n {\n id: TalerFormAttributes.COUNTRY_RISK_BUSINESS_TYPE,\n label: i18n.str`Country risk type (place of business activity)`,\n choices: [\n {\n label: i18n.str`Customer`,\n value: \"CUSTOMER\",\n },\n {\n label: i18n.str`Beneficial owner`,\n value: \"OWNER\",\n },\n ],\n type: \"selectMultiple\",\n required: false,\n },\n {\n id: TalerFormAttributes.COUNTRY_RISK_BUSINESS_LEVEL,\n label: i18n.str`Country risk level (business activity)`,\n help: i18n.str`Risk category according to VQF country list (VQF doc. no. 902.4.1)`,\n choices: [\n {\n label: i18n.str`Low (Risk 0)`,\n value: \"LOW\",\n description: i18n.str`Risk 0 acc. to VQF country list (VQF doc. no. 902.4.1)`,\n },\n {\n label: i18n.str`Medium (Risk 1)`,\n value: \"MEDIUM\",\n description: i18n.str`Risk 1 acc. to VQF country list (VQF doc. no. 902.4.1)`,\n },\n {\n label: i18n.str`High (Risk 2)`,\n value: \"HIGH\",\n description: i18n.str`Risk 2 acc. to VQF country list (VQF doc. no. 902.4.1)`,\n },\n ],\n type: \"choiceHorizontal\",\n },\n ],\n },\n {\n title: i18n.str`Industry risk`,\n fields: [\n {\n id: TalerFormAttributes.INDUSTRY_RISK_TYPE,\n label: i18n.str`Industry risk source`,\n type: \"selectMultiple\",\n choices: [\n { label: i18n.str`Customer`, value: \"CUSTOMER\" },\n {\n label: i18n.str`Beneficial owner of the assets`,\n value: \"OWNER\",\n },\n ],\n required: false,\n },\n {\n id: TalerFormAttributes.INDUSTRY_RISK_LEVEL,\n label: i18n.str`Industry risk level`,\n type: \"choiceStacked\",\n choices: [\n {\n label: `Transparent (Risk Level 0)`,\n description: i18n.str`Clearly defined, transparent, easily comprehensible business activity well known to the member.`,\n value: \"TRANSPARENT\",\n },\n {\n label: `High cash transactions (Risk Level 1)`,\n description: i18n.str`Business activity with a high level of cash transactions.`,\n value: \"HIGH_CASH_TRANSACTION\",\n },\n {\n label: `Not well known (Risk Level 1)`,\n description: i18n.str`Business activity not well known to the member.`,\n value: \"NOT_WELL_KNOWN\",\n },\n {\n label: `High-risk trade (Risk Level 2)`,\n description: i18n.str`Trade in munitions/arms, raw gem stones/diamonds, jewellery, international trade in exotic animals, casino and lottery business, trade in erotic wares.`,\n value: \"HIGH_RISK_TRADE\",\n },\n {\n label: `Unknown industry (Risk Level 2)`,\n description: i18n.str`Member has no personal knowledge of the customer\u2019s industry.`,\n value: \"UNKNOWN_INDUSTRY\",\n },\n ],\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Contact risk`,\n description: i18n.str`Type of contact to the customer/benefcial owner of the assets.`,\n fields: [\n {\n id: TalerFormAttributes.CONTACT_RISK_LEVEL,\n label: i18n.str`Contact risk level`,\n choices: [\n {\n label: \"Low contact risk\",\n description: i18n.str`Personal acquaintance between member and customer/beneficial owner of the assets over several years (at least 2) prior to entering into the business relationship`,\n value: \"LOW\",\n },\n {\n label: \"Medium contact risk\",\n description: i18n.str`The customer/beneficial owner was not personally known to the member for several years (at least 2) prior to entering into the business relationship; however (a) no business was entered into in the absence of the customer/beneficial owner, or (b) the customer was at least introduced/brokered by a trusted third party.`,\n value: \"MEDIUM\",\n },\n {\n label: \"High contact risk\",\n description: i18n.str`The customer/beneficial owner was not personally known to the member and business was entered into in the absence of the former (relationship by correspondence) and the customer was not introduced/brokered by a trusted third party.`,\n value: \"HIGH\",\n },\n ],\n type: \"choiceStacked\",\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Summary evaluation`,\n fields: [\n {\n id: TalerFormAttributes.RISK_RATIONALE,\n label: i18n.str`Justification for risk assessment`,\n type: \"textArea\",\n required: false,\n },\n {\n id: TalerFormAttributes.RISK_CLASSIFICATION_LEVEL,\n label: i18n.str`Risk classification`,\n help: i18n.str`Conclusion whether the business relationship is with or without increased risk.`,\n choices: [\n { label: i18n.str`No high risk`, value: \"NO_HIGH_RISK\" },\n { label: i18n.str`High risk`, value: \"HIGH_RISK\" },\n ],\n type: \"choiceHorizontal\",\n required: false,\n },\n {\n id: TalerFormAttributes.RISK_ACCEPTANCE_DATE,\n label: i18n.str`Acceptance date`,\n help: i18n.str`When the decision of the Senior executive body on the acceptance of a business relationship with increased risk was obtained on.`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n required: true,\n validator(text, form) {\n //FIXME: why returning in this format even if pattern is in another?\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n },\n hide(value, root) {\n return (\n root[TalerFormAttributes.RISK_CLASSIFICATION_LEVEL] !=\n \"HIGH_RISK\"\n );\n },\n },\n ],\n },\n ],\n };\n}\n", "import {\n Descr,\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\nimport { TalerFormAttributes } from \"@gnu-taler/taler-util\";\n\nexport const form_vqf_902_5 = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Customer Profile`,\n description: i18n.str`The information below has to refer to the persons from whom the assets originate ultimately (e.g. beneficial owner of the assets, founder/creator of a trust or foundation). Is the customer an operational legal entity or partnership the information may refer to the entity itself (not to the controlling person), unless the entity holds the assets in trust for a third party.`,\n id: \"vqf_902_5\",\n version: 1,\n config: VQF_902_5(i18n),\n});\n\nexport function VQF_902_5(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n return {\n type: \"double-column\",\n sections: [\n {\n title: i18n.str`Information on customer`,\n description: Descr.CUSTOMER_INFO_TYPE(i18n),\n fields: [\n {\n id: TalerFormAttributes.CUSTOMER_NAME,\n label: i18n.str`Customer`,\n // help: i18n.str``,\n type: \"text\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Business activity`,\n fields: [\n {\n id: TalerFormAttributes.BIZREL_PROFESSION,\n label: i18n.str`Profession, business activities, etc. (former, current, potentially planned)`,\n type: \"textArea\",\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Financial circumstances`,\n fields: [\n {\n id: TalerFormAttributes.BIZREL_INCOME,\n label: i18n.str`Income and assets, liabilities (estimated)`,\n type: \"textArea\",\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Origin of the deposited assets involved`,\n fields: [\n {\n id: TalerFormAttributes.BIZREL_HAVE_ASSETS,\n label: i18n.str`Will the the customer deposit assets with Taler Operations AG?`,\n type: \"choiceHorizontal\",\n required: true,\n choices: [\n {\n label: \"Yes\",\n value: true,\n },\n {\n label: \"No\",\n value: false,\n },\n ],\n },\n {\n id: TalerFormAttributes.BIZREL_ORIGIN_NATURE,\n label: i18n.str`Nature, amount and currency of deposited assets.`,\n type: \"textArea\",\n required: true,\n hide(value, root) {\n return !root[TalerFormAttributes.BIZREL_HAVE_ASSETS];\n },\n },\n {\n id: TalerFormAttributes.BIZREL_ORIGIN_CATEGORY,\n label: i18n.str`Category`,\n type: \"choiceStacked\",\n choices: [\n { label: i18n.str`Savings`, value: \"SAVINGS\" },\n {\n label: i18n.str`Own business operations`,\n value: \"OWN_BUSINESS\",\n },\n { label: i18n.str`Inheritance`, value: \"INHERITANCE\" },\n { label: i18n.str`Other`, value: \"OTHER\" },\n ],\n required: true,\n hide(value, root) {\n return !root[TalerFormAttributes.BIZREL_HAVE_ASSETS];\n },\n },\n {\n id: TalerFormAttributes.BIZREL_ORIGIN_CATEGORY_OTHER,\n type: \"text\",\n label: i18n.str`Category clarification`,\n required: true,\n hide(value, root) {\n return (\n root[TalerFormAttributes.BIZREL_ORIGIN_CATEGORY] !== \"OTHER\"\n );\n },\n },\n {\n id: TalerFormAttributes.BIZREL_ORIGIN_DETAIL,\n label: i18n.str`Detail description of the origings/economical background of the assets involved in the business relationship`,\n type: \"textArea\",\n required: false,\n hide(value, root) {\n return (\n root[TalerFormAttributes.BIZREL_ORIGIN_CATEGORY] !== \"OTHER\"\n );\n },\n },\n ],\n },\n {\n title: i18n.str`Nature and purpose of the business relationship`,\n fields: [\n {\n id: TalerFormAttributes.BIZREL_PURPOSE,\n label: i18n.str`Purpose of the business relationship`,\n type: \"textArea\",\n required: false,\n },\n {\n id: TalerFormAttributes.BIZREL_DEVELOPMENT,\n label: i18n.str`Information on the planned development of the business relationship and the assets`,\n type: \"textArea\",\n required: false,\n },\n {\n id: TalerFormAttributes.BIZREL_FINANCIAL_VOLUME,\n label: i18n.str`Detail on usual business volume`,\n type: \"textArea\",\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Relationship with third parties`,\n fields: [\n {\n id: TalerFormAttributes.BIZREL_THIRDPARTY_RELATIONSHIP,\n label: i18n.str`Relation of the customer to the beneficial owner, controlling persons, authorised signatories and other persons involved in the business relationship`,\n type: \"textArea\",\n required: false,\n },\n {\n id: TalerFormAttributes.BIZREL_THIRDPARTY_AMLA_FILES,\n label: i18n.str`Relation to other AMLA-Files`,\n type: \"textArea\",\n required: false,\n },\n {\n id: TalerFormAttributes.BIZREL_THIRDPARTY_REFERENCES,\n label: i18n.str`Introducer / agents / references`,\n type: \"textArea\",\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Further information`,\n fields: [\n {\n id: TalerFormAttributes.BIZREL_FURTHER_INFO,\n label: i18n.str`Other relevant information`,\n type: \"textArea\",\n required: false,\n },\n ],\n },\n ],\n };\n}\n", "import { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\nimport { countryNationalityList } from \"../../utils/select-ui-lists.js\";\nimport { format, intervalToDuration, isFuture, isValid, parse } from \"date-fns\";\n\nexport const form_vqf_902_9_customer = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Declaration of identity of the beneficial owner (A)`,\n id: \"vqf_902_9_customer\",\n version: 1,\n config: VQF_902_9_customer(i18n),\n});\n\nexport function VQF_902_9_customer(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n const today = format(new Date(), \"yyyy-MM-dd\");\n\n return {\n type: \"double-column\",\n title: i18n.str`Declaration of identity of the beneficial owner`,\n sections: [\n {\n title: \"Identity of the contracting partner\",\n fields: [\n {\n id: TalerFormAttributes.IDENTITY_CONTRACTING_PARTNER,\n label: i18n.str`Contracting partner`,\n type: \"textArea\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Beneficial owner details`,\n fields: [\n {\n id: TalerFormAttributes.IDENTITY_LIST,\n label: i18n.str`Beneficial owner(s)`,\n help: i18n.str`The person(s) listed below is/are the beneficial owner(s) of the assets involved in the business relationship. If the contracting partner is also the sole beneficial owner of the assets, the contracting partner's detail must be set out below`,\n type: \"array\",\n validator(persons) {\n if (!persons || persons.length < 1) {\n return i18n.str`Can't be empty`;\n }\n return undefined;\n },\n labelFieldId: TalerFormAttributes.FULL_NAME,\n fields: [\n {\n id: TalerFormAttributes.FULL_NAME,\n label: i18n.str`Full name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DOMICILE_ADDRESS,\n label: i18n.str`Domicile address`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.DATE_OF_BIRTH,\n label: i18n.str`Date of birth`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n required: true,\n validator(text, form) {\n //FIXME: why returning in this format even if pattern is in another?\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n },\n },\n {\n id: TalerFormAttributes.NATIONALITY,\n label: i18n.str`Nationality`,\n type: \"selectOne\",\n choices: countryNationalityList(i18n),\n preferredChoiceVals: [\"CH\"],\n required: true,\n },\n ],\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Signature(s)`,\n description: i18n.str`It is a criminal offence to deliberately provide false information on this form (article 251 of the Swiss Criminal Code, documents forgery)`,\n fields: [\n {\n type: \"caption\",\n label: i18n.str`The contracting partner hereby undertakes to inform automatically of any changes to the information contained herein.`,\n },\n {\n id: TalerFormAttributes.SIGNATURE,\n label: i18n.str`Signature(s)`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.SIGN_DATE,\n label: i18n.str`Date`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n defaultValue: today,\n required: true,\n disabled: true,\n },\n ],\n },\n ],\n };\n}\n", "import { TalerFormAttributes } from \"@gnu-taler/taler-util\";\nimport {\n DoubleColumnFormDesign,\n FormMetadata,\n InternationalizationAPI,\n} from \"../../index.browser.js\";\nimport { countryNationalityList } from \"../../utils/select-ui-lists.js\";\nimport { intervalToDuration, isFuture, isValid, parse } from \"date-fns\";\n\nexport const form_vqf_902_9_officer = (\n i18n: InternationalizationAPI,\n): FormMetadata => ({\n label: i18n.str`Declaration of identity of the beneficial owner (A)`,\n id: \"vqf_902_9_officer\",\n version: 1,\n config: VQF_902_9_officer(i18n),\n});\n\nexport function VQF_902_9_officer(\n i18n: InternationalizationAPI,\n): DoubleColumnFormDesign {\n return {\n type: \"double-column\",\n title: i18n.str`Declaration of identity of the beneficial owner`,\n sections: [\n {\n title: \"Identity of the contracting partner\",\n fields: [\n {\n id: TalerFormAttributes.IDENTITY_CONTRACTING_PARTNER,\n label: i18n.str`Contracting partner`,\n type: \"textArea\",\n required: true,\n },\n ],\n },\n {\n title: i18n.str`Beneficial owner details`,\n fields: [\n {\n id: TalerFormAttributes.IDENTITY_LIST,\n label: i18n.str`Beneficial owner(s)`,\n help: i18n.str`The person(s) listed below is/are the beneficial owner(s) of the assets involved in the business relationship. If the contracting partner is also the sole beneficial owner of the assets, the contracting partner's detail must be set out below`,\n type: \"array\",\n validator(persons) {\n if (!persons || persons.length < 1) {\n return i18n.str`Can't be empty`;\n }\n return undefined;\n },\n labelFieldId: TalerFormAttributes.FULL_NAME,\n fields: [\n {\n id: TalerFormAttributes.FULL_NAME,\n label: i18n.str`Full name`,\n type: \"text\",\n required: true,\n },\n {\n id: TalerFormAttributes.DOMICILE_ADDRESS,\n label: i18n.str`Domicile address`,\n type: \"textArea\",\n required: true,\n },\n {\n id: TalerFormAttributes.DATE_OF_BIRTH,\n label: i18n.str`Date of birth`,\n type: \"isoDateText\",\n placeholder: \"dd/MM/yyyy\",\n pattern: \"dd/MM/yyyy\",\n required: true,\n validator(text, form) {\n //FIXME: why returning in this format even if pattern is in another?\n const time = parse(text, \"yyyy-MM-dd\", new Date());\n if (!isValid(time)) {\n return i18n.str`invalid format`;\n }\n if (isFuture(time)) {\n return i18n.str`it can't be in the future`;\n }\n const { years } = intervalToDuration({\n start: time,\n end: new Date(),\n });\n if (years && years > 120) {\n return i18n.str`it can't be greater than 120 years`;\n }\n return undefined;\n },\n },\n {\n id: TalerFormAttributes.NATIONALITY,\n label: i18n.str`Nationality`,\n type: \"selectOne\",\n choices: countryNationalityList(i18n),\n preferredChoiceVals: [\"CH\"],\n required: true,\n },\n ],\n required: false,\n },\n ],\n },\n {\n title: i18n.str`Signed Declaration`,\n description: i18n.str`Signed declaration by the customer`,\n fields: [\n {\n type: \"caption\",\n label: i18n.str`The uploaded document must contain the customer's signature on the beneficial owner declaration.`,\n },\n {\n id: TalerFormAttributes.ATTACHMENT_SIGNED_DOCUMENT,\n label: i18n.str`Signed Document`,\n type: \"file\",\n accept: \"application/pdf\",\n required: true,\n },\n ],\n },\n ],\n };\n}\n", "import { AbsoluteTime } from \"@gnu-taler/taler-util\";\nimport {\n add as dateAdd,\n sub as dateSub,\n eachDayOfInterval,\n endOfMonth,\n endOfWeek,\n format,\n getMonth,\n getYear,\n isSameDay,\n isSameMonth,\n isValid,\n setYear,\n startOfDay,\n startOfMonth,\n startOfWeek,\n subYears,\n} from \"date-fns\";\nimport { VNode, h } from \"preact\";\nimport { useEffect, useRef, useState } from \"preact/hooks\";\nimport { useTranslationContext } from \"../index.browser.js\";\nimport { composeRef, saveRef } from \"../components/utils.js\";\n\nconst THIS_MONTH = getMonth(new Date());\nconst THIS_YEAR = getYear(new Date());\nconst TODAY = startOfDay(new Date());\n\nexport function Calendar({\n value,\n onChange,\n}: {\n value: AbsoluteTime | undefined;\n onChange: (v: AbsoluteTime) => void;\n}): VNode {\n const selectedMaybeInvalid = !value\n ? TODAY\n : new Date(AbsoluteTime.toStampMs(value));\n const selected = isValid(selectedMaybeInvalid) ? selectedMaybeInvalid : TODAY;\n const [showingDate, setShowingDate] = useState(selected);\n const m = getMonth(showingDate);\n const y = getYear(showingDate);\n const month = Number.isNaN(m) ? THIS_MONTH : m;\n const year = Number.isNaN(y) ? THIS_YEAR : y;\n const input = useRef();\n useEffect(() => {\n if (!input.current) return;\n if (input.current === document.activeElement) return;\n input.current.value = !year ? \"\" : String(year);\n }, [year]);\n\n const start = startOfWeek(startOfMonth(showingDate));\n const end = endOfWeek(endOfMonth(showingDate));\n const daysInMonth = eachDayOfInterval({ start, end });\n const { i18n } = useTranslationContext();\n const monthNames = [\n i18n.str`January`,\n i18n.str`February`,\n i18n.str`March`,\n i18n.str`April`,\n i18n.str`May`,\n i18n.str`June`,\n i18n.str`July`,\n i18n.str`August`,\n i18n.str`September`,\n i18n.str`October`,\n i18n.str`November`,\n i18n.str`December`,\n ];\n return (\n
\n
\n {\n setShowingDate(dateSub(showingDate, { years: 1 }));\n }}\n >\n {i18n.str`Previous year`}\n \n \n \n \n
\n {\n const text = e.currentTarget.value;\n const num = Number.parseInt(text, 10);\n\n if (Number.isSafeInteger(num) && num > 0) {\n const nextYear = setYear(showingDate, num);\n\n if (isValid(nextYear)) {\n setShowingDate(nextYear);\n }\n }\n }}\n />\n
\n {\n setShowingDate(dateAdd(showingDate, { years: 1 }));\n }}\n >\n {i18n.str`Next year`}\n \n \n \n \n
\n
\n {\n setShowingDate(dateSub(showingDate, { months: 1 }));\n }}\n >\n {i18n.str`Previous month`}\n \n \n \n \n
{monthNames[month]}
\n {\n setShowingDate(dateAdd(showingDate, { months: 1 }));\n }}\n >\n {i18n.str`Next month`}\n \n \n \n \n
\n
\n
M
\n
T
\n
W
\n
T
\n
F
\n
S
\n
S
\n
\n
\n
\n {daysInMonth.map((current, idx) => (\n {\n onChange(AbsoluteTime.fromStampMs(current.getTime()));\n }}\n class=\"text-gray-400 hover:bg-gray-700 focus:z-10 py-1.5 \n data-[month=false]:bg-gray-100 data-[month=true]:bg-white \n data-[today=true]:font-semibold \n data-[month=true]:text-gray-900\n data-[today=true]:bg-red-300 data-[today=true]:hover:bg-red-200\n data-[month=true]:hover:bg-gray-200\n data-[selected=true]:!bg-blue-400 data-[selected=true]:hover:!bg-blue-300 \"\n >\n \n {format(current, \"dd\")}\n \n \n ))}\n
\n {daysInMonth.length < 40 ?
: undefined}\n
\n
\n );\n}\n", "import { TranslatedString } from \"@gnu-taler/taler-util\";\nimport { Fragment, VNode, h } from \"preact\";\nimport {\n LabelWithTooltipMaybeRequired,\n RenderAddon,\n} from \"./fields/InputLine.js\";\nimport { Addon } from \"./FormProvider.js\";\n\ninterface Props {\n label: TranslatedString;\n tooltip?: TranslatedString;\n help?: TranslatedString;\n before?: Addon;\n after?: Addon;\n hidden?: boolean;\n}\n\nexport function Caption({\n hidden,\n before,\n after,\n label,\n tooltip,\n help,\n}: Props): VNode {\n if (hidden) {\n return ;\n }\n return (\n
\n {before !== undefined && }\n \n {after !== undefined && }\n {help && (\n

\n {help}\n

\n )}\n
\n );\n}\n", "import { TranslatedString } from \"@gnu-taler/taler-util\";\nimport { ComponentChildren, Fragment, VNode, h } from \"preact\";\nimport { useEffect, useRef } from \"preact/hooks\";\nimport { composeRef, saveRef } from \"../../components/utils.js\";\nimport { Addon, UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\n\n//@ts-ignore\nconst TooltipIcon = (\n \n \n \n);\n\nexport function LabelWithTooltipMaybeRequired({\n label,\n required,\n tooltip,\n name,\n}: {\n label: TranslatedString;\n required?: boolean;\n tooltip?: TranslatedString;\n name?: string;\n}): VNode {\n const Label = (\n
\n \n {label}\n \n
\n );\n const WithTooltip = tooltip ? (\n
\n {Label}\n \n {TooltipIcon}\n \n \n
\n ) : (\n Label\n );\n if (required) {\n return (\n
\n {WithTooltip}\n *\n
\n );\n }\n return WithTooltip;\n}\n\nexport function RenderAddon({\n disabled,\n addon,\n reverse,\n}: {\n disabled?: boolean;\n reverse?: boolean;\n addon: Addon;\n}): VNode {\n switch (addon.type) {\n case \"text\": {\n return (\n \n {addon.text}\n \n );\n }\n case \"icon\": {\n return (\n
\n {addon.icon}\n
\n );\n }\n case \"button\": {\n return (\n \n {addon.children}\n \n );\n }\n }\n}\n\n/**\n * FIXME: Document what this is!\n */\nexport function InputWrapper({\n children,\n label,\n tooltip,\n before,\n after,\n help,\n error,\n disabled,\n required,\n name,\n}: {\n error?: string;\n disabled: boolean;\n children: ComponentChildren;\n} & UIFormProps): VNode {\n return (\n
\n \n
\n {before && }\n\n {children}\n\n {after && }\n
\n {error && (\n

\n {error}\n

\n )}\n {help && (\n

\n {help}\n

\n )}\n
\n );\n}\n\nfunction defaultToString(v: unknown) {\n return v === undefined ? \"\" : typeof v !== \"object\" ? String(v) : \"\";\n}\nfunction defaultFromString(v: string) {\n return v;\n}\n\ntype InputType = \"text\" | \"text-area\" | \"password\" | \"email\" | \"number\" | \"tel\";\n\nexport function InputLine(\n props: { type: InputType; defaultValue?: string } & UIFormProps,\n): VNode {\n const {\n name,\n placeholder,\n before,\n after,\n converter,\n type,\n disabled,\n hidden,\n } = props;\n const input = useRef();\n\n const { value, onChange, error } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n\n const fromString: (s: string) => any =\n converter?.fromStringUI ?? defaultFromString;\n const toString: (s: any) => string = converter?.toStringUI ?? defaultToString;\n\n useEffect(() => {\n if (!input.current) return;\n if (input.current === document.activeElement) return;\n input.current.value = !value ? \"\" : toString(value);\n }, [value]);\n\n // useHiddenHandler(name as string, hidden ?? false, value, onChange);\n if (hidden) {\n return ;\n }\n\n let clazz =\n \"block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200\";\n if (before) {\n switch (before.type) {\n case \"icon\": {\n clazz += \" pl-10\";\n break;\n }\n case \"button\": {\n clazz += \" rounded-none rounded-r-md \";\n break;\n }\n case \"text\": {\n clazz += \" min-w-0 flex-1 rounded-r-md rounded-none \";\n break;\n }\n }\n }\n if (after) {\n switch (after.type) {\n case \"icon\": {\n clazz += \" pr-10\";\n break;\n }\n case \"button\": {\n clazz += \" rounded-none rounded-l-md\";\n break;\n }\n case \"text\": {\n clazz += \" min-w-0 flex-1 rounded-l-md rounded-none \";\n break;\n }\n }\n }\n const showError = value !== undefined && error;\n if (showError) {\n clazz +=\n \" text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-red-500\";\n } else {\n clazz +=\n \" text-gray-900 ring-gray-300 placeholder:text-gray-400 focus:ring-indigo-600\";\n }\n\n if (type === \"text-area\") {\n return (\n \n {\n onChange(fromString(e.currentTarget.value));\n }}\n defaultValue={props.defaultValue}\n placeholder={placeholder ? placeholder : undefined}\n // value={toString(value) ?? \"\"}\n // defaultValue={toString(value)}\n disabled={disabled ?? false}\n aria-invalid={showError}\n // aria-describedby=\"email-error\"\n class={clazz}\n />\n \n );\n }\n\n return (\n \n {\n onChange(fromString(e.currentTarget.value));\n }}\n placeholder={placeholder ? placeholder : undefined}\n // value={toString(value) ?? \"\"}\n // onBlur={() => {\n // onChange(fromString(value as any));\n // }}\n defaultValue={toString(value)}\n disabled={disabled ?? false}\n aria-invalid={showError}\n // aria-describedby=\"email-error\"\n class={clazz}\n />\n \n );\n}\n", "import { TranslatedString } from \"@gnu-taler/taler-util\";\nimport { Fragment, h, VNode } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport {\n getValueFromPath,\n RecursivePartial,\n useForm,\n} from \"../../hooks/useForm.js\";\nimport {\n SingleColumnFormSectionUI,\n useTranslationContext,\n} from \"../../index.browser.js\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { UIFormElementConfig } from \"../forms-types.js\";\nimport { LabelWithTooltipMaybeRequired } from \"./InputLine.js\";\n\nexport function noHandlerPropsAndNoContextForField(\n field: string | number | symbol,\n): never {\n throw Error(\n `Field ${field.toString()} doesn't have handler and is not in a form provider context.`,\n );\n}\n\ntype FormType = {};\n\nfunction ArrayForm({\n fields,\n selected,\n onClose,\n onRemove,\n onConfirm,\n name,\n}: {\n fields: UIFormElementConfig[];\n selected: Record | undefined;\n onClose: () => void;\n onRemove: () => void;\n onConfirm: (r: RecursivePartial) => void;\n name: string;\n}): VNode {\n const { i18n } = useTranslationContext();\n const form = useForm(\n {\n type: \"single-column\",\n fields,\n },\n selected ?? {},\n );\n\n return (\n
\n
\n \n
\n {/*
{JSON.stringify(form.status, undefined, 2)}
*/}\n\n
\n \n Cancel\n \n\n {\n onRemove();\n }}\n // onClick={() => {\n // const newValue = [...list];\n // newValue.splice(selectedIndex, 1);\n // onChange(newValue as any);\n // // setSelectedIndex(undefined);\n // }}\n class=\"block rounded-md bg-red-600 px-3 py-2 text-center text-sm text-white shadow-sm hover:bg-red-500 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200\"\n >\n Remove\n \n\n {\n onConfirm(form.status.result);\n }}\n class=\"block rounded-md bg-indigo-600 px-3 py-2 text-center text-sm text-white shadow-sm hover:bg-indigo-500 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200\"\n >\n Confirm\n \n
\n
\n );\n}\n\nexport function InputArray(\n props: {\n fields: UIFormElementConfig[];\n labelField: string;\n } & UIFormProps,\n): VNode {\n const { fields, labelField, label, required, tooltip, hidden, help } = props;\n const { i18n } = useTranslationContext();\n\n const { value, onChange, error } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n const [dirty, setDirty] = useState(); // FIXME: dirty state should come from handler\n\n //@ts-ignore\n const list = (value ?? []) as Array>;\n const [selectedIndex, setSelectedIndex] = useState(\n undefined,\n );\n\n if (hidden) {\n return ;\n }\n const selected =\n selectedIndex === undefined ? undefined : list[selectedIndex];\n\n return (\n
\n \n {help && (\n

\n {help}\n

\n )}\n {dirty !== undefined && error && (\n

\n {error}\n

\n )}\n\n
\n
\n {list.map((v, idx) => {\n const labelValue =\n getValueFromPath(v, labelField.split(\".\")) ??\n `<>`;\n const label = Array.isArray(labelValue)\n ? labelValue.join(\", \")\n : labelValue;\n return (\n {\n setSelectedIndex(selectedIndex === idx ? undefined : idx);\n }}\n />\n );\n })}\n {!props.disabled && (\n
\n {\n setSelectedIndex(\n selectedIndex === list.length ? undefined : list.length,\n );\n }}\n />\n
\n )}\n
\n {selectedIndex !== undefined && (\n {\n const newValue = [...list];\n newValue.splice(selectedIndex, 1);\n onChange(newValue as any);\n setDirty(true);\n setSelectedIndex(undefined);\n }}\n onClose={() => {\n setDirty(true);\n setSelectedIndex(undefined);\n }}\n onConfirm={(value) => {\n const newValue = [...list];\n newValue.splice(selectedIndex, 1, value);\n onChange(newValue as any);\n setDirty(true);\n setSelectedIndex(undefined);\n }}\n selected={selected}\n />\n )}\n
\n
\n );\n}\n\nfunction Option({\n label,\n disabled,\n isFirst,\n isLast,\n isSelected,\n onClick,\n}: {\n label: TranslatedString;\n isFirst?: boolean;\n isLast?: boolean;\n isSelected?: boolean;\n disabled?: boolean;\n onClick: () => void;\n}): VNode {\n let clazz = \"relative flex border p-4 focus:outline-none disabled:text-grey\";\n if (isFirst) {\n clazz += \" rounded-tl-md rounded-tr-md \";\n }\n if (isLast) {\n clazz += \" rounded-bl-md rounded-br-md \";\n }\n if (isSelected) {\n clazz += \" z-10 border-indigo-200 bg-indigo-50 \";\n } else {\n clazz += \" border-gray-200\";\n }\n if (disabled) {\n clazz +=\n \" cursor-not-allowed bg-gray-50 text-gray-500 ring-gray-200 text-gray\";\n } else {\n clazz += \" cursor-pointer\";\n }\n return (\n \n );\n}\n", "import { ComponentChildren, VNode, h } from \"preact\";\n\nexport function Dialog({\n children,\n onClose,\n}: {\n onClose?: () => void;\n children: ComponentChildren;\n}): VNode {\n return (\n \n
\n\n
\n
\n e.stopPropagation()}\n >\n {children}\n
\n
\n
\n \n );\n}\n", "import { TranslatedString } from \"@gnu-taler/taler-util\";\nimport { VNode, h } from \"preact\";\nimport { RenderAddon } from \"./InputLine.js\";\nimport { Addon, UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\n\ninterface Props {\n label: TranslatedString;\n url: string;\n media?: string;\n tooltip?: TranslatedString;\n help?: TranslatedString;\n before?: Addon;\n after?: Addon;\n}\n\nexport function ExternalLink({\n before,\n after,\n label,\n url,\n media,\n tooltip,\n handler,\n name,\n help,\n}: Props & UIFormProps): VNode {\n const { value, onChange, error } =\n handler ?? noHandlerPropsAndNoContextForField(name);\n return (\n
\n {before !== undefined && }\n {\n onChange(true);\n }}\n >\n {label}\n \n {after !== undefined && }\n {help && (\n

\n {help}\n

\n )}\n
\n );\n}\n", "import { AbsoluteTime } from \"@gnu-taler/taler-util\";\nimport { format, parse } from \"date-fns\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { Calendar } from \"../Calendar.js\";\nimport { Dialog } from \"../Dialog.js\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { InputLine } from \"./InputLine.js\";\n\nexport function InputAbsoluteTime(\n properties: { pattern?: string } & UIFormProps,\n): VNode {\n const pattern = properties.pattern ?? \"dd/MM/yyyy\";\n const [open, setOpen] = useState(false);\n\n const { value, onChange } =\n properties.handler ?? noHandlerPropsAndNoContextForField(properties.name);\n return (\n \n {\n setOpen(true);\n },\n // icon: ,\n children: (\n \n \n \n ),\n }}\n converter={{\n //@ts-ignore\n fromStringUI: (v): AbsoluteTime | undefined => {\n if (!v) return undefined;\n try {\n const t_ms = parse(v, pattern, Date.now()).getTime();\n return AbsoluteTime.fromMilliseconds(t_ms);\n } catch (e) {\n return undefined;\n }\n },\n //@ts-ignore\n toStringUI: (v: AbsoluteTime | undefined) => {\n return !v || !v.t_ms\n ? undefined\n : v.t_ms === \"never\"\n ? \"never\"\n : format(v.t_ms, pattern);\n },\n }}\n {...properties}\n />\n {open && (\n setOpen(false)}>\n {\n onChange(v as any);\n setOpen(false);\n }}\n />\n \n )}\n {/* {open &&\n setOpen(false)} >\n {\n onChange(v as any)\n }}\n onConfirm={() => {\n setOpen(false)\n }} />\n } */}\n \n );\n}\n", "import { AmountJson, Amounts, TranslatedString } from \"@gnu-taler/taler-util\";\nimport { VNode, h } from \"preact\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { InputLine } from \"./InputLine.js\";\n\nexport function InputAmount(\n props: { currency: string } & UIFormProps,\n): VNode {\n return (\n {\n return (\n Amounts.parse(`${props.currency}:${v}`) ??\n Amounts.zeroOfCurrency(props.currency)\n );\n },\n toStringUI: (v: AmountJson) => {\n return v === undefined ? \"\" : Amounts.stringifyValue(v);\n },\n }\n }\n />\n );\n}\n", "import { TranslatedString } from \"@gnu-taler/taler-util\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { LabelWithTooltipMaybeRequired } from \"./InputLine.js\";\n\nexport interface ChoiceH {\n label: TranslatedString;\n value: V;\n}\n\nexport function InputChoiceHorizontal(\n props: {\n choices: ChoiceH[];\n } & UIFormProps,\n): VNode {\n const { hidden, choices, label, tooltip, help, required, converter } = props;\n const { value, onChange } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n if (hidden) {\n return ;\n }\n\n return (\n
\n \n
\n
\n {choices.map((choice, idx) => {\n const convertedValue = converter?.fromStringUI(choice.value as any);\n const isFirst = idx === 0;\n const isLast = idx === choices.length - 1;\n let clazz =\n \"relative inline-flex items-center px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 focus:z-10\";\n if (convertedValue !== undefined && convertedValue === value) {\n clazz +=\n \" text-white bg-indigo-600 hover:bg-indigo-500 ring-2 ring-indigo-600 hover:ring-indigo-500\";\n } else {\n clazz += \" hover:bg-gray-100 border-gray-300\";\n }\n if (isFirst) {\n clazz += \" rounded-l-md\";\n } else {\n clazz += \" -ml-px\";\n }\n if (isLast) {\n clazz += \" rounded-r-md\";\n }\n return (\n {\n onChange(\n (value === choice.value\n ? undefined\n : convertedValue) as any,\n );\n }}\n >\n {choice.label}\n \n );\n })}\n
\n
\n {help && (\n

\n {help}\n

\n )}\n
\n );\n}\n", "import { TranslatedString } from \"@gnu-taler/taler-util\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useEffect } from \"preact/hooks\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { LabelWithTooltipMaybeRequired } from \"./InputLine.js\";\n\n/**\n * Choice of a translated string, with attached description\n * of the choice.\n *\n * The value is usually a string or numeric constant.\n */\nexport interface ChoiceS {\n label: TranslatedString;\n description?: TranslatedString;\n value: V;\n}\n\nexport function InputChoiceStacked(\n props: {\n choices: ChoiceS[];\n } & UIFormProps,\n): VNode {\n const { choices, name, label, tooltip, help, hidden, required, converter } =\n props;\n\n const { value, onChange } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n\n if (hidden) {\n return ;\n }\n\n useEffect(() => {\n // Reset choice if value is set to a choices that's\n // not available to this input.\n for (const choice of choices) {\n if (choice.value === value) {\n return;\n }\n }\n onChange(undefined);\n }, []);\n\n return (\n
\n \n
\n
\n {choices.map((choice, idx) => {\n let clazz =\n \"border relative block cursor-pointer rounded-lg bg-white px-6 py-4 shadow-sm focus:outline-none sm:flex sm:justify-between data-[disabled=true]:cursor-not-allowed data-[disabled=true]:bg-gray-50 data-[disabled=true]:text-gray-500 \";\n if (choice.value === value) {\n clazz +=\n \" border-transparent border-indigo-600 ring-2 ring-indigo-600\";\n } else {\n clazz += \" border-gray-300\";\n }\n\n return (\n \n );\n })}\n
\n
\n {help && (\n

\n {help}\n

\n )}\n
\n );\n}\n", "import { TranslatedString } from \"@gnu-taler/taler-util\";\nimport { VNode, h } from \"preact\";\nimport { noHandlerPropsAndNoContextForField } from \"../../index.browser.js\";\nimport { Addon, UIFormProps } from \"../FormProvider.js\";\nimport { RenderAddon } from \"./InputLine.js\";\n\ninterface Props {\n label: TranslatedString;\n url: string;\n media?: string;\n tooltip?: TranslatedString;\n help?: TranslatedString;\n before?: Addon;\n after?: Addon;\n fileName?: string;\n}\n\nexport function InputDownloadLink(props: Props & UIFormProps): VNode {\n const {\n media,\n url,\n label,\n tooltip,\n help,\n required,\n disabled,\n before,\n after,\n fileName,\n } = props;\n const { value, onChange, error } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n\n return (\n
\n {before !== undefined && }\n \n {required ? (\n *\n ) : undefined}\n\n {after !== undefined && }\n {help && (\n

\n {help}\n

\n )}\n
\n );\n}\n", "import { i18n, TranslatedString } from \"@gnu-taler/taler-util\";\nimport { Fragment, h, VNode } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { InputSelectOne } from \"./InputSelectOne.js\";\n\nexport interface ChoiceH {\n label: TranslatedString;\n value: V;\n}\n\nexport function InputDrilldown(\n props: {\n choices: any;\n } & UIFormProps,\n): VNode {\n const { hidden, choices, label, tooltip, help, required, converter } = props;\n const { value, onChange } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n if (hidden) {\n return ;\n }\n\n const [choiceStack, setChoiceStack] = useState([]);\n\n let ch = props.choices;\n\n let inputs = [];\n\n for (let lvl = 0; lvl < choiceStack.length + 1; lvl++) {\n if (typeof ch === \"string\") {\n break;\n }\n inputs.push(\n ({\n label: x as TranslatedString,\n value: x,\n }))}\n />,\n );\n\n ch = ch[choiceStack[lvl]];\n }\n\n return <>{inputs};\n}\n", "import { i18n } from \"@gnu-taler/taler-util\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useRef, useState } from \"preact/hooks\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { ChoiceS } from \"./InputChoiceStacked.js\";\nimport { LabelWithTooltipMaybeRequired } from \"./InputLine.js\";\n\nexport interface InputSelectOneProps {\n preferredChoiceVals?: Choices[];\n choices: ChoiceS[];\n}\n\nexport function InputSelectOne(\n props: InputSelectOneProps & UIFormProps,\n): VNode {\n const { label, choices, placeholder, tooltip, required, help, hidden } =\n props;\n const { value, onChange, error } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n\n const [filter, setFilter] = useState(undefined);\n const [dirty, setDirty] = useState(); // FIXME: dirty state should come from handler\n const regex = new RegExp(`.*${filter}.*`, \"i\");\n const choiceMap = choices.reduce(\n (prev, curr) => {\n return { ...prev, [curr.value as string]: curr.label };\n },\n {} as Record,\n );\n if (hidden) {\n return ;\n }\n\n const prefChoices = choices.filter(\n (x) =>\n props.preferredChoiceVals && props.preferredChoiceVals.includes(x.value),\n );\n const normalChoices = choices.filter(\n (x) =>\n !(\n props.preferredChoiceVals && props.preferredChoiceVals.includes(x.value)\n ),\n );\n\n const inputRef = useRef(null);\n\n const sortedChoices = [...prefChoices, ...normalChoices];\n\n let filteredChoices =\n filter === undefined\n ? undefined\n : sortedChoices.filter((v) => {\n return regex.test(v.label);\n });\n\n const noItems =\n filter === undefined\n ? undefined\n : filteredChoices === undefined || !filteredChoices.length;\n return (\n
\n \n {value ? (\n \n {choiceMap[value as string]}\n {\n onChange(undefined!);\n setDirty(true);\n }}\n class=\"group relative h-5 w-5 rounded-sm hover:bg-gray-500/20 disabled:cursor-not-allowed\"\n >\n \n \n \n \n \n \n ) : (\n
\n {\n setFilter(e.currentTarget.value);\n setDirty(true);\n }}\n onBlur={(e) => {\n setFilter(undefined);\n }}\n onFocus={(e) => {\n setFilter(\"\");\n }}\n placeholder={placeholder}\n class=\"w-full rounded-md border-0 bg-white py-1.5 pl-3 pr-12 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6\"\n role=\"combobox\"\n aria-controls=\"options\"\n aria-expanded=\"false\"\n />\n {\n // Input element should not lose focus\n e.preventDefault();\n }}\n onClick={() => {\n setFilter(filter === undefined ? \"\" : undefined);\n setDirty(true);\n inputRef.current?.focus();\n }}\n class=\"absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none\"\n >\n \n \n \n \n {noItems && (\n \n
  • \n \n No element found\n \n
  • \n \n )}\n {!noItems && filteredChoices && (\n \n {filteredChoices.map((v, idx) => {\n return (\n {\n // Input element should not lose focus\n e.preventDefault();\n }}\n onClick={() => {\n setFilter(undefined);\n onChange(v.value as any);\n setDirty(true);\n }}\n >\n {v.label}\n \n );\n })}\n \n )}\n
    \n )}\n {help && (\n

    \n {help}\n

    \n )}\n {dirty !== undefined && error && (\n

    \n {error}\n

    \n )}\n
    \n );\n}\n", "import { Duration } from \"@gnu-taler/taler-util\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useEffect, useRef } from \"preact/hooks\";\nimport { useTranslationContext } from \"../../index.browser.js\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { InputWrapper } from \"./InputLine.js\";\n\nexport function InputDuration(props: UIFormProps): VNode {\n const { name, placeholder, before, after, converter, disabled } = props;\n const { i18n } = useTranslationContext();\n const { value, onChange, error } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n\n const specDuration = !value ? undefined : Duration.toSpec(value as Duration);\n // const [seconds, setSeconds] = useState(sd?.seconds ?? 0);\n // const [hours, setHours] = useState(sd?.hours ?? 0);\n // const [minutes, setMinutes] = useState(sd?.minutes ?? 0);\n // const [days, setDays] = useState(sd?.days ?? 0);\n // const [months, setMonths] = useState(sd?.month ?? 0);\n // const [years, setYears] = useState(sd?.years ?? 0);\n\n const secondsRef = useRef(null);\n const hoursRef = useRef(null);\n const minutesRef = useRef(null);\n const daysRef = useRef(null);\n const monthsRef = useRef(null);\n const yearsRef = useRef(null);\n\n // useEffect(() => {\n // onChange(\n // Duration.fromSpec({\n // days,\n // hours,\n // minutes,\n // seconds,\n // months,\n // years,\n // }),\n // );\n // }, [days, hours, minutes, seconds, months, years]);\n const fromString: (s: string) => any =\n converter?.fromStringUI ?? defaultFromString;\n const toString: (s: any) => string = converter?.toStringUI ?? defaultToString;\n\n const strSeconds = toString(specDuration?.seconds ?? 0) ?? \"\";\n const strHours = toString(specDuration?.hours ?? 0) ?? \"\";\n const strMinutes = toString(specDuration?.minutes ?? 0) ?? \"\";\n const strDays = toString(specDuration?.days ?? 0) ?? \"\";\n const strMonths = toString(specDuration?.month ?? 0) ?? \"\";\n const strYears = toString(specDuration?.years ?? 0) ?? \"\";\n\n useEffect(() => {\n if (!secondsRef.current) return;\n if (secondsRef.current === document.activeElement) return;\n secondsRef.current.value = strSeconds;\n }, [strSeconds]);\n useEffect(() => {\n if (!minutesRef.current) return;\n if (minutesRef.current === document.activeElement) return;\n minutesRef.current.value = strMinutes;\n }, [strMinutes]);\n useEffect(() => {\n if (!hoursRef.current) return;\n if (hoursRef.current === document.activeElement) return;\n hoursRef.current.value = strHours;\n }, [strHours]);\n useEffect(() => {\n if (!daysRef.current) return;\n if (daysRef.current === document.activeElement) return;\n daysRef.current.value = strDays;\n }, [strDays]);\n useEffect(() => {\n if (!monthsRef.current) return;\n if (monthsRef.current === document.activeElement) return;\n monthsRef.current.value = strMonths;\n }, [strMonths]);\n useEffect(() => {\n if (!yearsRef.current) return;\n if (yearsRef.current === document.activeElement) return;\n yearsRef.current.value = strYears;\n }, [strYears]);\n\n if (props.hidden) {\n return ;\n }\n\n let clazz =\n \"block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200\";\n // if (before) {\n // switch (before.type) {\n // case \"icon\": {\n // clazz += \" pl-10\";\n // break;\n // }\n // case \"button\": {\n // clazz += \" rounded-none rounded-r-md \";\n // break;\n // }\n // case \"text\": {\n clazz += \" min-w-0 flex-1 rounded-r-md rounded-none \";\n // break;\n // }\n // }\n // }\n if (after) {\n switch (after.type) {\n case \"icon\": {\n clazz += \" pr-10\";\n break;\n }\n case \"button\": {\n clazz += \" rounded-none rounded-l-md\";\n break;\n }\n case \"text\": {\n clazz += \" min-w-0 flex-1 rounded-l-md rounded-none \";\n break;\n }\n }\n }\n const showError = value !== undefined && error;\n if (showError) {\n clazz +=\n \" text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-red-500\";\n } else {\n clazz +=\n \" text-gray-900 ring-gray-300 placeholder:text-gray-400 focus:ring-indigo-600\";\n }\n // FIXME: Fix the types!\n return (\n \n
    \n
    \n \n years\n \n {\n onChange(\n Duration.fromSpec({\n ...specDuration,\n years: fromString(e.currentTarget.value),\n }),\n );\n }}\n placeholder={placeholder ? placeholder : undefined}\n ref={yearsRef}\n // value={toString(sd?.years) ?? \"\"}\n // onBlur={() => {\n // onChange(fromString(value as any));\n // }}\n // defaultValue={toString(value)}\n disabled={disabled ?? false}\n aria-invalid={showError}\n // aria-describedby=\"email-error\"\n class={clazz}\n />\n \n months\n \n {\n onChange(\n Duration.fromSpec({\n ...specDuration,\n months: fromString(e.currentTarget.value),\n }),\n );\n }}\n placeholder={placeholder ? placeholder : undefined}\n // value={toString(specDuration?.month) ?? \"\"}\n // onBlur={() => {\n // onChange(fromString(value as any));\n // }}\n // defaultValue={toString(value)}\n disabled={disabled ?? false}\n aria-invalid={showError}\n // aria-describedby=\"email-error\"\n class={clazz}\n />\n
    \n
    \n \n days\n \n {\n onChange(\n Duration.fromSpec({\n ...specDuration,\n days: fromString(e.currentTarget.value),\n }),\n );\n }}\n placeholder={placeholder ? placeholder : undefined}\n // value={toString(specDuration?.days) ?? \"\"}\n // onBlur={() => {\n // onChange(fromString(value as any));\n // }}\n // defaultValue={toString(value)}\n disabled={disabled ?? false}\n aria-invalid={showError}\n // aria-describedby=\"email-error\"\n class={clazz}\n />\n \n hours\n \n {\n onChange(\n Duration.fromSpec({\n ...specDuration,\n hours: fromString(e.currentTarget.value),\n }),\n );\n }}\n placeholder={placeholder ? placeholder : undefined}\n // value={toString(specDuration?.hours) ?? \"\"}\n // onBlur={() => {\n // onChange(fromString(value as any));\n // }}\n // defaultValue={toString(value)}\n disabled={disabled ?? false}\n aria-invalid={showError}\n // aria-describedby=\"email-error\"\n class={clazz}\n />\n
    \n
    \n \n minutes\n \n {\n onChange(\n Duration.fromSpec({\n ...specDuration,\n minutes: fromString(e.currentTarget.value),\n }),\n );\n }}\n placeholder={placeholder ? placeholder : undefined}\n // value={toString(specDuration?.minutes) ?? \"\"}\n // onBlur={() => {\n // onChange(fromString(value as any));\n // }}\n // defaultValue={toString(value)}\n disabled={disabled ?? false}\n aria-invalid={showError}\n // aria-describedby=\"email-error\"\n class={clazz}\n />\n \n seconds\n \n {\n // setSeconds(fromString(e.currentTarget.value));\n onChange(\n Duration.fromSpec({\n ...specDuration,\n seconds: fromString(e.currentTarget.value),\n }),\n );\n }}\n placeholder={placeholder ? placeholder : undefined}\n // value={toString(specDuration?.seconds) ?? \"\"}\n // onBlur={() => {\n // onChange(fromString(value as any));\n // }}\n // defaultValue={toString(value)}\n disabled={disabled ?? false}\n aria-invalid={showError}\n // aria-describedby=\"email-error\"\n class={clazz}\n />\n
    \n
    \n \n );\n}\n\nfunction defaultToString(v: unknown) {\n return v === undefined ? \"\" : typeof v !== \"object\" ? String(v) : \"\";\n}\n\nfunction defaultFromString(v: string) {\n return v;\n}\n", "import { Duration } from \"@gnu-taler/taler-util\";\nimport { VNode, h } from \"preact\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { InputLine } from \"./InputLine.js\";\n\nconst PATTERN = /^(?[0-9]+)(?[smhDMY])$/;\nconst UNIT_GROUP = \"unit\";\nconst VALUE_GROUP = \"value\";\n\ntype DurationUnit = \"s\" | \"m\" | \"h\" | \"D\" | \"M\" | \"Y\";\ntype DurationSpec = Parameters[0];\n\ntype DurationValue = {\n unit: DurationUnit;\n value: number;\n};\n\nfunction updateSpec(spec: DurationSpec, value: DurationValue): void {\n switch (value.unit) {\n case \"s\": {\n spec.seconds = value.value;\n break;\n }\n case \"m\": {\n spec.minutes = value.value;\n break;\n }\n case \"h\": {\n spec.hours = value.value;\n break;\n }\n case \"D\": {\n spec.days = value.value;\n break;\n }\n case \"M\": {\n spec.months = value.value;\n break;\n }\n case \"Y\": {\n spec.years = value.value;\n break;\n }\n }\n}\n\nfunction parseDurationValue(str: string): DurationValue | undefined {\n const r = PATTERN.exec(str);\n if (!r) return undefined;\n const value = Number.parseInt(r.groups![VALUE_GROUP], 10);\n const unit = r.groups![UNIT_GROUP] as DurationUnit;\n return { value, unit };\n}\n\nexport function InputDurationText(props: UIFormProps): VNode {\n return (\n {\n if (!v) return Duration.getForever();\n const spec = v.split(\" \").reduce((prev, cur) => {\n const v = parseDurationValue(cur);\n if (v) {\n updateSpec(prev, v);\n }\n return prev;\n }, {} as DurationSpec);\n return Duration.fromSpecOrUndefined(spec);\n },\n //@ts-ignore\n toStringUI: (v?: Duration): string => {\n if (v === undefined) return \"\";\n // return v! as any;\n const spec = Duration.toSpec(v);\n let result = \"\";\n if (spec?.years) {\n result += `${spec.years}Y `;\n }\n if (spec?.month) {\n result += `${spec.month}M `;\n }\n if (spec?.days) {\n result += `${spec.days}D `;\n }\n if (spec?.hours) {\n result += `${spec.hours}h `;\n }\n if (spec?.minutes) {\n result += `${spec.minutes}m `;\n }\n if (spec?.seconds) {\n result += `${spec.seconds}s `;\n }\n return result.trimEnd();\n },\n }}\n />\n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { Fragment, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { useTranslationContext } from \"../../index.browser.js\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { FileFieldData } from \"../forms-types.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { LabelWithTooltipMaybeRequired } from \"./InputLine.js\";\n\nexport function InputFile(\n props: { maxBites: number; accept?: string } & UIFormProps,\n): VNode {\n const { i18n } = useTranslationContext();\n const { label, tooltip, required, help: propsHelp, maxBites, accept } = props;\n const { value, onChange } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n\n const help = propsHelp;\n if (props.hidden) {\n return ;\n }\n\n const [dataUri, setDataUri] = useState(() => {\n if (!value) {\n return undefined;\n }\n if (value.ENCODING != \"base64\") {\n throw Error(\"unsupported file storage type\");\n }\n return `data:${value.MIME_TYPE ?? \"application/octet-stream\"};base64,${\n value.CONTENTS\n }`;\n });\n\n const handleFile = (\n contentsBase64?: string,\n mimeType?: string,\n filename?: string,\n ) => {\n // console.log(`handleFile`, contentsBase64, mimeType, filename);\n if (contentsBase64 == null) {\n setDataUri(undefined);\n onChange(undefined);\n return;\n }\n setDataUri(`data:${mimeType}};base64,${contentsBase64}`);\n onChange({\n CONTENTS: contentsBase64,\n ENCODING: \"base64\",\n FILENAME: filename,\n MIME_TYPE: mimeType,\n });\n };\n\n return (\n
    \n \n {!value ? (\n
    \n
    \n \n \n \n {!props.disabled && (\n
    \n \n \n Upload a file\n \n {\n const f: FileList | null = e.currentTarget.files;\n if (!f || f.length != 1) {\n handleFile(undefined);\n return;\n }\n if (f[0].size > maxBites) {\n handleFile(undefined);\n return;\n }\n const fileName = f[0].name;\n return f[0].arrayBuffer().then((b) => {\n const b64 = window.btoa(\n new Uint8Array(b).reduce(\n (data, byte) => data + String.fromCharCode(byte),\n \"\",\n ),\n );\n handleFile(b64, f[0].type, fileName);\n });\n }}\n />\n \n {/*

    or drag and drop

    */}\n
    \n )}\n
    \n
    \n ) : (\n \n
    \n {value.MIME_TYPE?.startsWith(\"image/\") ? (\n \n \n {value.FILENAME ? (\n
    \n {value.FILENAME}\n
    \n ) : (\n \n )}\n \n ) : (\n
    \n
    \n \n \n \n\n {value.FILENAME ? (\n
    \n {value.FILENAME}\n
    \n ) : (\n
    \n )}\n
    \n
    \n )}\n\n {!props.disabled && (\n {\n handleFile(undefined);\n }}\n >\n Clear\n
    \n )}\n
    \n {\n return false;\n }}\n >\n Download a copy.\n \n
    \n )}\n {help &&

    {help}

    }\n
    \n );\n}\n", "import { VNode, h } from \"preact\";\nimport { InputLine } from \"./InputLine.js\";\nimport { UIFormProps } from \"../FormProvider.js\";\n\nexport function InputInteger(props: UIFormProps): VNode {\n return (\n {\n return !v ? 0 : Number.parseInt(v, 10);\n },\n //@ts-ignore\n toStringUI: (v?: number): string => {\n return v === undefined ? \"\" : String(v);\n },\n }}\n {...props}\n />\n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2025 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU Affero Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.\n\n You should have received a copy of the GNU Affero Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { AbsoluteTime } from \"@gnu-taler/taler-util\";\nimport { format, parse, parseISO } from \"date-fns\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\nimport { Calendar } from \"../Calendar.js\";\nimport { Dialog } from \"../Dialog.js\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { InputLine } from \"./InputLine.js\";\n\nexport interface InputIsoDateProps {\n /**\n * Pattern for displaying / parsing the date in the UI.\n *\n * Defaults to \"dd/MM/yyyy\".\n */\n pattern?: string;\n\n defaultValue?: string;\n\n /**\n * Default value when the calener widget is opened.\n */\n calendarDefaultValue?: string;\n}\n\n/**\n * Input field for an ISO date (yyyy-MM-dd).\n *\n * The user can enter the date in a format specified by a\n * pattern.\n */\nexport function InputIsoDate(\n properties: InputIsoDateProps & UIFormProps,\n): VNode {\n const pattern = properties.pattern ?? \"dd/MM/yyyy\";\n const [open, setOpen] = useState(false);\n\n const { value, onChange } =\n properties.handler ?? noHandlerPropsAndNoContextForField(properties.name);\n\n useEffect(() => {\n if (!value && !!properties.defaultValue) {\n onChange(properties.defaultValue);\n }\n }, [value, properties.handler, properties.defaultValue]);\n\n let calendarOpenTime: number;\n\n if (!value) {\n if (properties.calendarDefaultValue) {\n calendarOpenTime = parseISO(properties.calendarDefaultValue).getTime();\n } else {\n calendarOpenTime = Date.now();\n }\n } else {\n calendarOpenTime = parseISO(value).getTime();\n }\n return (\n \n {\n setOpen(true);\n },\n children: (\n \n \n \n ),\n }}\n converter={{\n toStringUI(v: string | undefined) {\n if (!v || typeof v !== \"string\") {\n return \"\";\n }\n try {\n const d = parse(v, \"yyyy-MM-dd\", Date.now());\n return format(d, pattern);\n } catch (e) {\n console.error(`toStringUI: failed to convert ${v}: ${e}`);\n return \"\";\n }\n },\n fromStringUI: (v: string | undefined): string => {\n if (!v) {\n return \"\";\n }\n try {\n const t_ms = parse(v, pattern, Date.now()).getTime();\n return format(t_ms, \"yyyy-MM-dd\");\n } catch (e) {\n console.error(`fromStringUI: failed to convert ${v}`);\n return \"\";\n }\n },\n }}\n />\n {open && (\n setOpen(false)}>\n {\n // The date is always *stored* as an ISO date.\n // !!!!! why?\n /**\n * form and fields should only care about how the information is asked\n * to the user and should not care about how is store or sent to the server\n *\n * this format here should always be the 'pattern' of the field\n */\n onChange(\n v.t_ms === \"never\" ? undefined : format(v.t_ms, \"yyyy-MM-dd\"),\n );\n setOpen(false);\n }}\n />\n \n )}\n \n );\n}\n", "import { VNode, h } from \"preact\";\nimport { InputLine } from \"./InputLine.js\";\nimport { UIFormProps } from \"../FormProvider.js\";\n\nexport function InputSecret(props: UIFormProps): VNode {\n return ;\n}\n", "import { Fragment, VNode, h } from \"preact\";\nimport { useRef, useState } from \"preact/hooks\";\nimport { useTranslationContext } from \"../../index.browser.js\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { ChoiceS } from \"./InputChoiceStacked.js\";\nimport { LabelWithTooltipMaybeRequired } from \"./InputLine.js\";\n\n/**\n * @type ChoiceVal result type of the choice (for example: \"choiceA\" | \"choiceB\")\n */\nexport function InputSelectMultiple(\n props: {\n choices: ChoiceS[];\n unique?: boolean;\n max?: number;\n } & UIFormProps,\n): VNode {\n const {\n converter,\n label,\n choices,\n placeholder,\n tooltip,\n help,\n required,\n hidden,\n unique,\n max,\n } = props;\n const { i18n } = useTranslationContext();\n const { value, onChange } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n\n const [filter, setFilter] = useState(undefined);\n const [dirty, setDirty] = useState();\n\n if (hidden) {\n return ;\n }\n const regex = new RegExp(`.*${filter}.*`, \"i\");\n const choiceMap = choices.reduce(\n (prev, curr) => {\n return { ...prev, [curr.value as string]: curr.label };\n },\n {} as Record,\n );\n\n const inputRef = useRef(null);\n\n const list = (value ?? []) as string[];\n const filteredChoices =\n filter === undefined\n ? undefined\n : choices.filter((v) => {\n const match = regex.test(v.label);\n if (!unique) return match;\n return match && list.indexOf(v.value as string) === -1;\n });\n return (\n
    \n \n\n {!props.disabled && (\n
    \n {\n setFilter(e.currentTarget.value);\n setDirty(true);\n }}\n onBlur={(e) => {\n setFilter(undefined);\n }}\n onFocus={(e) => {\n setFilter(\"\");\n }}\n onClick={(e) => {\n setFilter(\"\");\n }}\n placeholder={placeholder}\n class=\"w-full rounded-md border-0 bg-white py-1.5 pl-3 pr-12 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6\"\n role=\"combobox\"\n aria-controls=\"options\"\n aria-expanded=\"false\"\n />\n {\n // Input element should not lose focus\n e.preventDefault();\n }}\n onClick={(e) => {\n setFilter(filter === undefined ? \"\" : undefined);\n setDirty(true);\n inputRef.current?.focus();\n }}\n class=\"absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none\"\n >\n \n \n \n \n\n {filter === undefined ? undefined : filteredChoices === undefined ||\n !filteredChoices.length ? (\n \n
  • \n \n No element found\n \n
  • \n \n ) : (\n \n {filteredChoices.map((v, idx) => {\n return (\n {\n // Input element should not lose focus\n e.preventDefault();\n }}\n onClick={() => {\n setFilter(undefined);\n if (unique && list.indexOf(v.value as string) !== -1) {\n return;\n }\n if (max !== undefined && list.length >= max) {\n return;\n }\n const newValue = [...list];\n newValue.push(v.value as string);\n onChange(newValue as any);\n }}\n >\n {v.label}\n \n );\n })}\n \n )}\n
    \n )}\n {list.map((v, idx) => {\n return (\n \n {choiceMap[v]}\n {\n const newValue = [...list];\n newValue.splice(idx, 1);\n onChange(newValue as any);\n setFilter(undefined);\n }}\n class=\"group relative h-5 w-5 rounded-sm hover:bg-gray-500/20\"\n >\n \n Remove\n \n \n \n \n \n \n \n );\n })}\n {help && (\n

    \n {help}\n

    \n )}\n
    \n );\n}\n", "import { VNode, h } from \"preact\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { InputLine } from \"./InputLine.js\";\n\nexport function InputText(props: UIFormProps): VNode {\n return ;\n}\n", "import { VNode, h } from \"preact\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { InputLine } from \"./InputLine.js\";\n\nexport function InputTextArea(props: UIFormProps): VNode {\n return ;\n}\n", "import { Fragment, VNode, h } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\nimport { UIFormProps } from \"../FormProvider.js\";\nimport { noHandlerPropsAndNoContextForField } from \"./InputArray.js\";\nimport { LabelWithTooltipMaybeRequired } from \"./InputLine.js\";\n\n/**\n * Two-state (on/off) or tri-state (on/off/unselected) toggle.\n *\n * FIXME: Types would be clearer if two/tri state were different types.\n */\nexport function InputToggle(\n props: {\n threeState?: boolean;\n defaultValue?: boolean;\n trueValue?: any;\n falseValue?: any;\n onlyTrueValue?: boolean;\n } & UIFormProps,\n): VNode {\n const {\n label,\n tooltip,\n help,\n required,\n threeState,\n disabled,\n trueValue = true,\n falseValue = false,\n onlyTrueValue = false,\n } = props;\n const { value, onChange, error } =\n props.handler ?? noHandlerPropsAndNoContextForField(props.name);\n const [dirty, setDirty] = useState();\n\n const isOn = trueValue === value;\n\n if (props.hidden) {\n return ;\n }\n\n return (\n
    \n
    \n \n {\n setDirty(true);\n if (value === falseValue && threeState) {\n return onChange(undefined as any);\n }\n if (onlyTrueValue && value === trueValue) {\n return onChange(undefined as any);\n }\n if (value === trueValue) {\n return onChange(falseValue);\n }\n return onChange(trueValue);\n }}\n >\n \n \n
    \n {help && (\n

    \n {help}\n

    \n )}\n {dirty !== undefined && error && (\n

    \n {error}\n

    \n )}\n
    \n );\n}\n", "import { TranslatedString } from \"@gnu-taler/taler-util\";\nimport { VNode, h } from \"preact\";\nimport { Addon } from \"./FormProvider.js\";\nimport {\n LabelWithTooltipMaybeRequired,\n RenderAddon,\n} from \"./fields/InputLine.js\";\nimport { RenderAllFieldsByUiConfig } from \"./forms-ui.js\";\nimport { UIFormField } from \"./field-types.js\";\n\ninterface Props {\n label: TranslatedString;\n tooltip?: TranslatedString;\n help?: TranslatedString;\n before?: Addon;\n after?: Addon;\n fields: UIFormField[];\n}\n\nexport function Group({\n before,\n after,\n label,\n tooltip,\n help,\n fields,\n}: Props): VNode {\n return (\n
    \n {before !== undefined && }\n \n {after !== undefined && }\n {help && (\n

    \n {help}\n

    \n )}\n
    \n \n
    \n
    \n );\n}\n", "import { h as create, Fragment, h, VNode } from \"preact\";\nimport {\n ErrorAndLabel,\n FormErrors,\n FormModel,\n useForm,\n} from \"../hooks/useForm.js\";\n// import { getConverterById, useTranslationContext } from \"../index.browser.js\";\nimport { useState } from \"preact/hooks\";\nimport { useTranslationContext } from \"../index.browser.js\";\nimport {\n FieldComponentFunction,\n UIFormConfiguration,\n UIFormField,\n} from \"./field-types.js\";\nimport {\n DoubleColumnFormSection,\n FormDesign,\n UIFormElementConfig,\n} from \"./forms-types.js\";\nimport { convertFormConfigToUiField } from \"./forms-utils.js\";\n\nexport function DefaultForm({\n design,\n initial,\n disabled,\n}: {\n disabled?: boolean;\n design: FormDesign;\n initial: object;\n}): VNode {\n const { model: handler, status } = useForm(design, initial);\n\n const [shorten, setShorten] = useState(true);\n\n return (\n
    \n
    \n \n
    \n \n\n

    Result JSON:

    \n
    \n        {JSON.stringify(\n          shorten\n            ? redactFileContents(status.result ?? {})\n            : (status.result ?? {}),\n          undefined,\n          2,\n        )}\n      
    \n
    \n {status.status !== \"ok\" ? (\n \n ) : undefined}\n
    \n );\n}\n\nexport function redactFileContents(result: any): any {\n if (Array.isArray(result)) {\n return result.map((x) => redactFileContents(x));\n }\n if (\n typeof result === \"object\" &&\n \"ENCODING\" in result &&\n result.ENCODING === \"base64\" &&\n \"CONTENTS\" in result\n ) {\n return {\n ...result,\n CONTENTS: \"[... skipped ...]\",\n };\n }\n if (typeof result === \"object\") {\n return Object.fromEntries(\n Object.entries(result).map(([k, v]) => {\n return [k, redactFileContents(v)];\n }),\n );\n }\n return result;\n}\n\nexport const DEFAULT_FORM_UI_NAME = \"form-ui\";\n\n/**\n * FIXME: formDesign should be embedded in formHandler\n */\nexport function FormUI({\n name = DEFAULT_FORM_UI_NAME,\n design,\n model,\n disabled,\n focus,\n onSubmit,\n}: {\n name?: string;\n design: FormDesign;\n model: FormModel;\n focus?: boolean;\n disabled?: boolean;\n onSubmit?: () => void;\n}): VNode {\n switch (design.type) {\n case \"double-column\": {\n const ui = design.sections.map((section, i) => {\n if (!section) return ;\n return (\n \n );\n });\n return (\n \n {design.title ? (\n

    {design.title}

    \n ) : (\n \n )}\n {ui}\n \n );\n }\n case \"single-column\": {\n return (\n \n );\n }\n }\n}\n\nexport function DoubleColumnFormSectionUI({\n sectionKey,\n section,\n name,\n focus,\n model,\n disabled,\n onSubmit,\n}: {\n sectionKey: string;\n name: string;\n model: FormModel;\n section: DoubleColumnFormSection;\n focus?: boolean;\n disabled?: boolean;\n onSubmit?: () => void;\n}): VNode {\n const { i18n } = useTranslationContext();\n const fs = convertFormConfigToUiField(\n i18n,\n sectionKey,\n section.fields,\n model,\n );\n const allHidden = fs.every((v) => {\n // FIXME: Handler should probably be present for all Form UI fields, not just some.\n if (\"handler\" in v.properties) {\n return v.properties.hidden ?? false;\n }\n return false;\n });\n const sectionHidden = model.isSectionHidden(sectionKey);\n if (allHidden || sectionHidden) {\n return (\n
    \n \n \n {i18n.str`Date`}\n {i18n.str`Amount`}\n {i18n.str`Counterpart`}\n {i18n.str`Subject`}\n \n \n \n {Object.entries(txByDate).map(([date, txs], idx) => {\n return (\n \n \n \n {date}\n \n \n {txs.map((item) => {\n return (\n \n \n \n {item.amount ? (\n \n ) : (\n \n <\n {i18n.str`Invalid value`}>\n \n )}\n \n \n \n \n );\n })}\n \n );\n })}\n \n
    \n
    \n \n
    \n
    \n
    \n Amount\n
    \n
    \n {item.negative\n ? i18n.str`sent`\n : i18n.str`received`}{\" \"}\n {item.amount ? (\n \n \n \n ) : (\n \n <{i18n.str`Invalid value`}>\n \n )}\n
    \n\n
    \n Counterpart\n
    \n
    \n {item.negative ? i18n.str`to` : i18n.str`from`}{\" \"}\n {!routeCreateWireTransfer ? (\n item.counterpart\n ) : (\n \n {item.counterpart}\n \n )}\n
    \n
    \n
    \n                                {item.subject}\n                              
    \n
    \n
    \n
    \n {!routeCreateWireTransfer ? (\n item.counterpart\n ) : (\n \n {item.counterpart}\n \n )}\n \n {item.subject}\n
    \n\n \n
    \n \n First page\n \n \n Next\n \n
    \n \n
    \n \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { AbsoluteTime, AmountJson, TalerError } from \"@gnu-taler/taler-util\";\nimport {\n ErrorLoading,\n Loading,\n RouteDefinition,\n utils,\n} from \"@gnu-taler/web-util/browser\";\nimport { VNode } from \"preact\";\n\nimport { useComponentState } from \"./state.js\";\nimport { ReadyView } from \"./views.js\";\n\nexport interface Props {\n account: string;\n routeCreateWireTransfer:\n | RouteDefinition<{\n account?: string;\n subject?: string;\n amount?: string;\n }>\n | undefined;\n}\n\nexport type State = State.Loading | State.LoadingUriError | State.Ready;\n\nexport namespace State {\n export interface Loading {\n status: \"loading\";\n error: undefined;\n }\n\n export interface LoadingUriError {\n status: \"loading-error\";\n error: TalerError;\n }\n\n export interface BaseInfo {\n error: undefined;\n }\n export interface Ready extends BaseInfo {\n status: \"ready\";\n error: undefined;\n routeCreateWireTransfer:\n | RouteDefinition<{\n account?: string;\n subject?: string;\n amount?: string;\n }>\n | undefined;\n transactions: Transaction[];\n onGoStart?: () => void;\n onGoNext?: () => void;\n }\n}\n\nexport interface Transaction {\n negative: boolean;\n counterpart: string;\n when: AbsoluteTime;\n amount: AmountJson | undefined;\n subject: string;\n}\n\nconst viewMapping: utils.StateViewMap = {\n loading: Loading,\n \"loading-error\": ErrorLoading,\n ready: ReadyView,\n};\n\nexport const Transactions: (p: Props) => VNode = utils.compose(\n (p: Props) => useComponentState(p),\n viewMapping,\n);\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { AmountJson } from \"@gnu-taler/taler-util\";\nimport {\n RouteDefinition,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useBankState } from \"../hooks/bank-state.js\";\nimport { PaytoWireTransferForm } from \"./PaytoWireTransferForm.js\";\nimport { WalletWithdrawForm } from \"./WalletWithdrawForm.js\";\nimport { IntAmountJson, IntAmounts } from \"./regional/CreateCashout.js\";\n\nconst TALER_SCREEN_ID = 105;\n\n// function ShowOperationPendingTag({\n// woid,\n// onOperationAlreadyCompleted,\n// }: {\n// woid: string;\n// onOperationAlreadyCompleted?: () => void;\n// }): VNode {\n// const { i18n } = useTranslationContext();\n// const { state: credentials } = useSessionState();\n// const result = useWithdrawalDetails(woid);\n// const loading = !result;\n// const error =\n// !loading && (result instanceof TalerError || result.type === \"fail\");\n// const pending =\n// !loading &&\n// !error &&\n// result.body.status === \"selected\" &&\n// // (result.body.status === \"pending\" || result.body.status === \"selected\") &&\n// credentials.status === \"loggedIn\" &&\n// credentials.username === result.body.username;\n\n// if (error || !pending) {\n// return ;\n// }\n\n// return (\n// \n// \n// \n// \n// Pending operation\n// \n// );\n// }\n\nexport interface PaymentOptionProps {\n limit: IntAmountJson;\n balance: AmountJson;\n tab: \"charge-wallet\" | \"wire-transfer\" | undefined;\n\n onOperationCreated: (wopid: string) => void;\n onClose: () => void;\n\n routeOperationDetails: RouteDefinition<{ wopid: string }>;\n routeClose: RouteDefinition;\n routeCashout: RouteDefinition;\n routeChargeWallet: RouteDefinition;\n routeWireTransfer: RouteDefinition<{\n account?: string;\n subject?: string;\n amount?: string;\n }>;\n}\n\n/**\n * Let the user choose a payment option,\n * then specify the details trigger the action.\n */\nexport function PaymentOptions({\n routeClose,\n routeCashout,\n routeChargeWallet,\n routeWireTransfer,\n tab,\n limit,\n balance,\n onOperationCreated,\n onClose,\n routeOperationDetails,\n}: PaymentOptionProps): VNode {\n const { i18n } = useTranslationContext();\n\n return (\n \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AmountJson,\n AmountString,\n Amounts,\n HttpStatusCode,\n TalerUriAction,\n TalerUris,\n UserAndToken,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ButtonBetter,\n LocalNotificationBanner,\n RenderAmount,\n RouteDefinition,\n ShowInputErrorLabel,\n notifyError,\n useBankCoreApiContext,\n useLocalNotificationBetter,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { VNode, h } from \"preact\";\nimport { forwardRef } from \"preact/compat\";\nimport { useState } from \"preact/hooks\";\nimport { useSettingsContext } from \"../context/settings.js\";\nimport { useBankState } from \"../hooks/bank-state.js\";\nimport { usePreferences } from \"../hooks/preferences.js\";\nimport { useSessionState } from \"../hooks/session.js\";\nimport { undefinedIfEmpty } from \"../utils.js\";\nimport { OperationState } from \"./OperationState/index.js\";\nimport { InputAmount, doAutoFocus } from \"./PaytoWireTransferForm.js\";\nimport { IntAmountJson } from \"./regional/CreateCashout.js\";\n\nconst TALER_SCREEN_ID = 112;\n\nconst RefAmount = forwardRef(InputAmount);\n\nfunction OldWithdrawalForm({\n onOperationCreated,\n limit,\n balance,\n routeCancel,\n focus,\n}: {\n limit: IntAmountJson;\n balance: AmountJson;\n focus?: boolean;\n onOperationCreated: (wopid: string) => void;\n routeCancel: RouteDefinition;\n}): VNode {\n const { i18n } = useTranslationContext();\n const settings = useSettingsContext();\n const [preference] = usePreferences();\n\n const [, updateBankState] = useBankState();\n const {\n lib: { bank: api },\n config,\n } = useBankCoreApiContext();\n\n const { state: credentials } = useSessionState();\n const creds = credentials.status !== \"loggedIn\" ? undefined : credentials;\n\n const [amountStr, setAmountStr] = useState(\n `${settings.defaultSuggestedAmount ?? 1}`,\n );\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const trimmedAmountStr = amountStr?.trim();\n\n const parsedAmount = trimmedAmountStr\n ? Amounts.parse(`${limit.currency}:${trimmedAmountStr}`)\n : undefined;\n\n const errors = undefinedIfEmpty({\n amount:\n trimmedAmountStr == null\n ? i18n.str`Required`\n : !parsedAmount\n ? i18n.str`Invalid`\n : Amounts.cmp(limit, parsedAmount) === -1\n ? i18n.str`Balance is not enough`\n : undefined,\n });\n\n const start = safeFunctionHandler(\n i18n.str`create withdrawal`,\n (creds: UserAndToken, amount: AmountString) =>\n api.createWithdrawal(\n creds,\n preference.fastWithdrawalForm\n ? { suggested_amount: amount }\n : { amount: amount },\n ),\n !parsedAmount || !creds\n ? undefined\n : [creds, Amounts.stringify(parsedAmount)],\n );\n\n start.onSuccess = (success) => {\n const uri = TalerUris.fromString(success.taler_withdraw_uri);\n if (uri.tag === \"error\" || uri.value.type !== TalerUriAction.Withdraw) {\n return notifyError(\n i18n.str`The server replied with an invalid taler://withdraw URI`,\n i18n.str`Withdraw URI: ${success.taler_withdraw_uri}`,\n );\n } else {\n updateBankState(\n \"currentWithdrawalOperationId\",\n uri.value.withdrawalOperationId,\n );\n onOperationCreated(uri.value.withdrawalOperationId);\n }\n };\n\n start.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Conflict:\n return i18n.str`The operation was rejected due to insufficient funds`;\n case HttpStatusCode.Unauthorized:\n return i18n.str`The operation was rejected due to insufficient funds`;\n case HttpStatusCode.NotFound:\n return i18n.str`Account not found`;\n default:\n assertUnreachable(fail);\n }\n };\n\n return (\n {\n e.preventDefault();\n }}\n >\n \n\n
    \n
    \n
    \n \n {\n setAmountStr(v);\n }}\n ref={focus ? doAutoFocus : undefined}\n />\n
    \n \n
    \n

    \n \n Current balance is{\" \"}\n \n \n

    \n {Amounts.cmp(limit, balance) > 0 ? (\n

    \n \n You can withdraw up to{\" \"}\n \n \n

    \n ) : undefined}\n
    \n
    \n {\n e.preventDefault();\n setAmountStr(\"50.00\");\n }}\n >\n 50.00\n \n {\n e.preventDefault();\n setAmountStr(\"25.00\");\n }}\n >\n 25.00\n \n
    \n
    \n {\n e.preventDefault();\n setAmountStr(\"10.00\");\n }}\n >\n 10.00\n \n {\n e.preventDefault();\n setAmountStr(\"5.00\");\n }}\n >\n 5.00\n \n
    \n
    \n
    \n
    \n \n Cancel\n \n \n Continue\n \n
    \n \n );\n}\n\nexport function WalletWithdrawForm({\n focus,\n limit,\n balance,\n routeCancel,\n onOperationCreated,\n onOperationAborted,\n}: {\n limit: IntAmountJson;\n balance: AmountJson;\n focus?: boolean;\n\n onOperationCreated: (wopid: string) => void;\n onOperationAborted: () => void;\n routeCancel: RouteDefinition;\n}): VNode {\n const { i18n } = useTranslationContext();\n const [pref, updatePref] = usePreferences();\n\n return (\n
    \n
    \n

    \n Use your Taler wallet\n

    \n

    \n \n After using your wallet you will need to authorize or cancel the\n operation on this site.\n \n

    \n
    \n\n
    \n {pref.showInstallWallet && (\n {\n updatePref(\"showInstallWallet\", false);\n }}\n >\n \n If you don't have one yet you can follow the instruction in\n {\" \"}\n \n this page\n \n \n )}\n\n {!pref.fastWithdrawalForm ? (\n \n ) : (\n \n )}\n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TokenRequest } from \"@gnu-taler/taler-util\";\nimport {\n AbsoluteTime,\n Codec,\n TalerCorebankApi,\n buildCodecForObject,\n buildCodecForUnion,\n codecForAbsoluteTime,\n codecForAny,\n codecForConstString,\n codecForString,\n codecOptional,\n} from \"@gnu-taler/taler-util\";\nimport {\n AppLocation,\n buildStorageKey,\n useLocalStorage,\n} from \"@gnu-taler/web-util/browser\";\n\nexport type ChallengeInProgess =\n | LoginChallenge\n | DeleteAccountChallenge\n | UpdateAccountChallenge\n | UpdatePasswordChallenge\n | CreateTransactionChallenge\n | ConfirmWithdrawalChallenge\n | CashoutChallenge;\n\ntype BaseChallenge = {\n id: string;\n operation: OpType;\n sent: AbsoluteTime;\n location: AppLocation | undefined;\n // info?: TalerCorebankApi.TanTransmission;\n request: ReqType;\n};\n\ntype DeleteAccountChallenge = BaseChallenge<\"delete-account\", string>;\ntype LoginChallenge = BaseChallenge<\n \"login\",\n {\n tokenRequest: TokenRequest;\n username: string;\n password: string;\n }\n>;\ntype UpdateAccountChallenge = BaseChallenge<\n \"update-account\",\n TalerCorebankApi.AccountReconfiguration\n>;\ntype UpdatePasswordChallenge = BaseChallenge<\n \"update-password\",\n TalerCorebankApi.AccountPasswordChange\n>;\ntype CreateTransactionChallenge = BaseChallenge<\n \"create-transaction\",\n TalerCorebankApi.CreateTransactionRequest\n>;\ntype ConfirmWithdrawalChallenge = BaseChallenge<\n \"confirm-withdrawal\",\n TalerCorebankApi.BankAccountConfirmWithdrawalRequest & {\n id: string;\n }\n>;\ntype CashoutChallenge = BaseChallenge<\n \"create-cashout\",\n TalerCorebankApi.CashoutRequest\n>;\n\nconst codecForChallengeUpdatePassword = (): Codec =>\n buildCodecForObject()\n .property(\"operation\", codecForConstString(\"update-password\"))\n .property(\"id\", codecForString())\n .property(\"location\", codecForAppLocation())\n .property(\"sent\", codecForAbsoluteTime)\n // .property(\"info\", codecOptional(codecForTanTransmission()))\n .property(\"request\", codecForAny())\n .build(\"UpdatePasswordChallenge\");\n\nconst codecForChallengeDeleteAccount = (): Codec =>\n buildCodecForObject()\n .property(\"operation\", codecForConstString(\"delete-account\"))\n .property(\"id\", codecForString())\n .property(\"location\", codecForAppLocation())\n .property(\"sent\", codecForAbsoluteTime)\n .property(\"request\", codecForString())\n // .property(\"info\", codecOptional(codecForTanTransmission()))\n .build(\"DeleteAccountChallenge\");\n\nconst codecForChallengeUpdateAccount = (): Codec =>\n buildCodecForObject()\n .property(\"operation\", codecForConstString(\"update-account\"))\n .property(\"id\", codecForString())\n .property(\"location\", codecForAppLocation())\n .property(\"sent\", codecForAbsoluteTime)\n // .property(\"info\", codecOptional(codecForTanTransmission()))\n .property(\"request\", codecForAny()) //FIXME: complete definition\n .build(\"UpdateAccountChallenge\");\n\nconst codecForChallengeCreateTransaction =\n (): Codec =>\n buildCodecForObject()\n .property(\"operation\", codecForConstString(\"create-transaction\"))\n .property(\"id\", codecForString())\n .property(\"location\", codecForAppLocation())\n .property(\"sent\", codecForAbsoluteTime)\n // .property(\"info\", codecOptional(codecForTanTransmission()))\n .property(\"request\", codecForAny()) //FIXME: complete definition\n .build(\"CreateTransactionChallenge\");\n\nconst codecForChallengeConfirmWithdrawal =\n (): Codec =>\n buildCodecForObject()\n .property(\"operation\", codecForConstString(\"confirm-withdrawal\"))\n .property(\"id\", codecForString())\n .property(\"location\", codecForAppLocation())\n .property(\"sent\", codecForAbsoluteTime)\n // .property(\"info\", codecOptional(codecForTanTransmission()))\n .property(\"request\", codecForAny()) //FIXME: complete definition\n .build(\"ConfirmWithdrawalChallenge\");\n\nconst codecForAppLocation = codecForString as () => Codec;\n\nconst codecForChallengeCashout = (): Codec =>\n buildCodecForObject()\n .property(\"operation\", codecForConstString(\"create-cashout\"))\n .property(\"id\", codecForString())\n .property(\"location\", codecForAppLocation())\n .property(\"sent\", codecForAbsoluteTime)\n // .property(\"info\", codecOptional(codecForTanTransmission()))\n .property(\"request\", codecForAny()) //FIXME: complete definition\n .build(\"CashoutChallenge\");\n\nconst codecForLoginChallenge = (): Codec =>\n buildCodecForObject()\n .property(\"operation\", codecForConstString(\"login\"))\n .property(\"id\", codecForString())\n .property(\"location\", codecOptional(codecForAppLocation()))\n .property(\"sent\", codecForAbsoluteTime)\n // .property(\"info\", codecOptional(codecForTanTransmission()))\n .property(\"request\", codecForAny()) //FIXME: complete definition\n .build(\"LoginChallenge\");\n\nconst codecForChallenge = (): Codec =>\n buildCodecForUnion()\n .discriminateOn(\"operation\")\n .alternative(\"confirm-withdrawal\", codecForChallengeConfirmWithdrawal())\n .alternative(\"create-cashout\", codecForChallengeCashout())\n .alternative(\"create-transaction\", codecForChallengeCreateTransaction())\n .alternative(\"delete-account\", codecForChallengeDeleteAccount())\n .alternative(\"update-account\", codecForChallengeUpdateAccount())\n .alternative(\"update-password\", codecForChallengeUpdatePassword())\n .alternative(\"login\", codecForLoginChallenge())\n .build(\"ChallengeInProgess\");\n\ninterface BankState {\n currentWithdrawalOperationId: string | undefined;\n currentChallenge: ChallengeInProgess | undefined;\n}\n\nexport const codecForBankState = (): Codec =>\n buildCodecForObject()\n .property(\"currentWithdrawalOperationId\", codecOptional(codecForString()))\n .property(\"currentChallenge\", codecOptional(codecForChallenge()))\n .build(\"BankState\");\n\nconst defaultBankState: BankState = {\n currentWithdrawalOperationId: undefined,\n currentChallenge: undefined,\n};\n\nconst BANK_STATE_KEY = buildStorageKey(\"bank-app-state\", codecForBankState());\n\n/**\n * Client state saved in local storage.\n *\n * This information is saved in the client because\n * the backend server session API is not enough.\n *\n * @returns tuple of [state, update(), reset()]\n */\nexport function useBankState(): [\n Readonly,\n (key: T, value: BankState[T]) => void,\n () => void,\n] {\n const { value, update } = useLocalStorage(BANK_STATE_KEY, defaultBankState);\n\n function updateField(k: T, v: BankState[T]) {\n const newValue = { ...value, [k]: v };\n update(newValue);\n }\n function reset() {\n update(defaultBankState);\n }\n return [value, updateField, reset];\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n Amounts,\n HostPortPath,\n HttpStatusCode,\n Paytos,\n TalerCoreBankErrorsByMethod,\n TalerCorebankApi,\n TalerError,\n TalerUris,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport { useBankCoreApiContext, utils } from \"@gnu-taler/web-util/browser\";\nimport { useEffect, useState } from \"preact/hooks\";\nimport { useSettingsContext } from \"../../context/settings.js\";\nimport { useWithdrawalDetails } from \"../../hooks/account.js\";\nimport { useBankState } from \"../../hooks/bank-state.js\";\nimport { usePreferences } from \"../../hooks/preferences.js\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport { Props, State } from \"./index.js\";\n\nexport function useComponentState({\n routeClose,\n onAbort,\n focus,\n}: Props): utils.RecursiveState {\n const [preference] = usePreferences();\n const settings = useSettingsContext();\n const [bankState, updateBankState] = useBankState();\n const { state: credentials } = useSessionState();\n const creds = credentials.status !== \"loggedIn\" ? undefined : credentials;\n const {\n config,\n lib: { bank },\n } = useBankCoreApiContext();\n\n const [failure, setFailure] = useState<\n TalerCoreBankErrorsByMethod<\"createWithdrawal\"> | undefined\n >();\n const amount = settings.defaultSuggestedAmount;\n\n async function doSilentStart() {\n // FIXME: if amount is not enough use balance\n const parsedAmount = Amounts.parseOrThrow(`${config.currency}:${amount}`);\n if (!creds) return;\n const params: TalerCorebankApi.BankAccountCreateWithdrawalRequest =\n preference.fastWithdrawalForm\n ? {\n suggested_amount: Amounts.stringify(parsedAmount),\n }\n : {\n amount: Amounts.stringify(parsedAmount),\n };\n\n const resp = await bank.createWithdrawal(creds, params);\n if (resp.type === \"fail\") {\n setFailure(resp);\n return;\n }\n updateBankState(\"currentWithdrawalOperationId\", resp.body.withdrawal_id);\n }\n\n const withdrawalOperationId = bankState.currentWithdrawalOperationId;\n useEffect(() => {\n if (withdrawalOperationId === undefined) {\n doSilentStart();\n }\n }, [preference.fastWithdrawalForm, amount]);\n\n if (failure) {\n return {\n status: \"failed\",\n error: failure,\n };\n }\n\n if (!withdrawalOperationId) {\n return {\n status: \"loading\",\n error: undefined,\n };\n }\n\n const parsedUri = TalerUris.createTalerWithdraw(\n bank.getIntegrationAPI().href as HostPortPath,\n withdrawalOperationId,\n );\n const uri = TalerUris.toString(parsedUri);\n if (!parsedUri) {\n return {\n status: \"invalid-withdrawal\",\n error: undefined,\n uri,\n };\n }\n\n return (): utils.RecursiveState => {\n const result = useWithdrawalDetails(withdrawalOperationId);\n\n const shouldCreateNewOperation =\n result &&\n (result instanceof TalerError ||\n result.type === \"fail\" ||\n result.body.status === \"aborted\" ||\n result.body.status === \"confirmed\");\n\n useEffect(() => {\n if (shouldCreateNewOperation) {\n doSilentStart();\n }\n }, [shouldCreateNewOperation]);\n if (!result) {\n return {\n status: \"loading\",\n error: undefined,\n };\n }\n if (result instanceof TalerError) {\n return {\n status: \"loading-error\",\n error: result,\n };\n }\n\n if (result.type === \"fail\") {\n switch (result.case) {\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.NotFound: {\n return {\n status: \"aborted\",\n error: undefined,\n routeClose,\n };\n }\n default:\n assertUnreachable(result);\n }\n }\n\n const { body: data } = result;\n if (data.status === \"aborted\") {\n return {\n status: \"aborted\",\n error: undefined,\n routeClose,\n };\n }\n\n if (data.status === \"confirmed\") {\n if (!preference.showWithdrawalSuccess) {\n updateBankState(\"currentWithdrawalOperationId\", undefined);\n // onClose()\n }\n return {\n status: \"confirmed\",\n error: undefined,\n routeClose,\n };\n }\n\n if (data.status === \"pending\") {\n return {\n status: \"ready\",\n error: undefined,\n uri: parsedUri,\n routeClose,\n focus,\n operationId: withdrawalOperationId,\n onAbort,\n };\n }\n\n if (!data.selected_reserve_pub) {\n return {\n status: \"invalid-reserve\",\n error: undefined,\n reserve: data.selected_reserve_pub,\n };\n }\n\n const account = !data.selected_exchange_account\n ? undefined\n : Paytos.fromString(data.selected_exchange_account);\n\n if (!account || account.tag === \"error\" || !account.value.targetType) {\n return {\n status: \"invalid-payto\",\n error: undefined,\n payto: data.selected_exchange_account,\n };\n }\n\n return {\n status: \"need-confirmation\",\n error: undefined,\n details: {\n account: account.value,\n reserve: data.selected_reserve_pub,\n username: data.username,\n amount: !data.amount ? undefined : Amounts.parse(data.amount),\n },\n\n account: data.username,\n operationId: withdrawalOperationId,\n onAbort,\n };\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n Amounts,\n HttpStatusCode,\n PaytoType,\n TalerErrorCode,\n TalerUris,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ButtonBetter,\n LocalNotificationBanner,\n notifyInfo,\n RenderAmount,\n useBankCoreApiContext,\n useChallengeHandler,\n useLocalNotificationBetter,\n useTalerWalletIntegrationAPI,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useEffect } from \"preact/hooks\";\nimport { QR } from \"../../components/QR.js\";\nimport { usePreferences } from \"../../hooks/preferences.js\";\nimport { LoggedIn, useSessionState } from \"../../hooks/session.js\";\n\nimport { SolveMFAChallenges } from \"../SolveMFA.js\";\nimport { ShouldBeSameUser } from \"../WithdrawalConfirmationQuestion.js\";\nimport { State } from \"./index.js\";\n\nconst TALER_SCREEN_ID = 6;\n\nexport function InvalidPaytoView({ payto }: State.InvalidPayto) {\n return
    Payto from server is not valid "{payto}"
    ;\n}\nexport function InvalidWithdrawalView({ uri }: State.InvalidWithdrawal) {\n return
    Withdrawal uri from server is not valid "{uri}"
    ;\n}\nexport function InvalidReserveView({ reserve }: State.InvalidReserve) {\n return (\n
    \n Reserve from server is not valid "\n {reserve}"\n
    \n );\n}\n\nexport function NeedConfirmationView({\n onAbort,\n account,\n details,\n operationId,\n}: State.NeedConfirmation) {\n const { i18n } = useTranslationContext();\n const [settings] = usePreferences();\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const { state: credentials } = useSessionState();\n const creds = credentials.status !== \"loggedIn\" ? undefined : credentials;\n const mfa = useChallengeHandler();\n const {\n config,\n lib: { bank },\n } = useBankCoreApiContext();\n const wireFee =\n config.wire_transfer_fees === undefined\n ? Amounts.zeroOfCurrency(config.currency)\n : Amounts.parseOrThrow(config.wire_transfer_fees);\n\n const abort = safeFunctionHandler(\n i18n.str`abort withdrawal`,\n (creds: LoggedIn) => bank.abortWithdrawalById(creds, operationId),\n !creds ? undefined : [creds],\n );\n abort.onSuccess = onAbort;\n abort.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Conflict:\n return i18n.str`The reserve operation has been confirmed previously and can't be aborted`;\n case HttpStatusCode.BadRequest:\n return i18n.str`The operation ID is invalid.`;\n case HttpStatusCode.NotFound:\n return i18n.str`The operation was not found.`;\n default:\n assertUnreachable(fail);\n }\n };\n\n const confirm = safeFunctionHandler(\n i18n.str`confirm withdrawal`,\n (creds: LoggedIn, challengeIds: string[]) =>\n bank.confirmWithdrawalById(creds, {}, operationId, { challengeIds }),\n !creds ? undefined : [creds, []],\n );\n confirm.onSuccess = () => {\n if (!settings.showWithdrawalSuccess) {\n notifyInfo(i18n.str`Wire transfer completed!`);\n }\n onAbort();\n };\n confirm.onFail = (fail) => {\n switch (fail.case) {\n case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT:\n return i18n.str`The withdrawal has been aborted previously and can't be confirmed`;\n case TalerErrorCode.BANK_CONFIRM_INCOMPLETE:\n return i18n.str`The withdrawal operation can't be confirmed before a wallet accepted the transaction.`;\n case HttpStatusCode.BadRequest:\n return i18n.str`The operation ID is invalid.`;\n case HttpStatusCode.NotFound:\n return i18n.str`The operation was not found.`;\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n return i18n.str`Your balance is not sufficient for the operation.`;\n case HttpStatusCode.Accepted: {\n mfa.onChallengeRequired(fail.body);\n return i18n.str`A second factor authentication is required.`;\n }\n case TalerErrorCode.BANK_AMOUNT_DIFFERS:\n return i18n.str`The starting withdrawal amount and the confirmation amount differs.`;\n case TalerErrorCode.BANK_AMOUNT_REQUIRED:\n return i18n.str`The bank requires a bank account which has not been specified yet.`;\n default:\n assertUnreachable(fail);\n }\n };\n\n const repeatConfirm = confirm.lambda((ids: string[]) => {\n return [confirm.args![0], ids];\n });\n if (mfa.pendingChallenge) {\n return (\n \n );\n }\n\n return (\n
    \n \n
    \n

    \n Confirm the withdrawal operation\n

    \n
    \n \n {\n e.preventDefault();\n }}\n >\n
    \n
    \n
    \n {((): VNode => {\n switch (details.account.targetType) {\n case undefined:\n case PaytoType.TalerReserveHttp:\n case PaytoType.TalerReserve: {\n // FIXME: support wire transfer to wallet\n return
    not yet supported
    ;\n }\n case PaytoType.IBAN: {\n const name = details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account number\n \n
    \n
    \n {details.account.iban}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n case PaytoType.TalerBank: {\n const name = details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account bank\n hostname\n \n
    \n
    \n {details.account.host}\n
    \n
    \n
    \n
    \n \n Payment Service Provider's account id\n \n
    \n
    \n {details.account.account}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n case PaytoType.Bitcoin: {\n const name = details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account address\n \n
    \n
    \n {details.account.address}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n case PaytoType.Ethereum: {\n const name = details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account address\n \n
    \n
    \n {details.account.address}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n case PaytoType.Cyclos: {\n const name = details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account cyclos\n hostname\n \n
    \n
    \n {details.account.url}\n
    \n
    \n
    \n
    \n \n Payment Service Provider's account id\n \n
    \n
    \n {details.account.account}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n default: {\n assertUnreachable(details.account);\n }\n }\n })()}\n
    \n
    \n Amount\n
    \n
    \n {details.amount !== undefined ? (\n \n ) : (\n \n No amount has yet been determined.\n \n )}\n
    \n
    \n {Amounts.isZero(wireFee) ? undefined : (\n \n
    \n
    \n Cost\n
    \n
    \n \n
    \n
    \n
    \n )}\n
    \n
    \n
    \n
    \n \n Cancel\n \n \n Transfer\n \n
    \n \n
    \n
    \n
    \n
    \n );\n}\nexport function FailedView({ error }: State.Failed) {\n const { i18n } = useTranslationContext();\n switch (error.case) {\n case HttpStatusCode.Unauthorized:\n return (\n \n {!error.detail ? undefined : (\n
    {error.detail.hint}
    \n )}\n \n );\n case HttpStatusCode.Conflict:\n return (\n \n {!error.detail ? undefined : (\n
    {error.detail.hint}
    \n )}\n \n );\n case HttpStatusCode.NotFound:\n return (\n \n {!error.detail ? undefined : (\n
    {error.detail.hint}
    \n )}\n \n );\n default:\n assertUnreachable(error);\n }\n}\n\nexport function AbortedView() {\n return
    aborted
    ;\n}\n\nexport function ConfirmedView({ routeClose }: State.Confirmed) {\n const { i18n } = useTranslationContext();\n const [settings, updateSettings] = usePreferences();\n return (\n \n
    \n
    \n \n \n \n
    \n
    \n \n Withdrawal confirmed\n \n
    \n

    \n \n The wire transfer to the Payment Service Provider has been\n initiated. You will shortly receive the requested amount in your\n Taler wallet.{\" \"}\n \n

    \n
    \n
    \n
    \n
    \n
    \n \n \n Do not show this again\n \n \n {\n updateSettings(\n \"showWithdrawalSuccess\",\n !settings.showWithdrawalSuccess,\n );\n }}\n >\n \n \n
    \n
    \n
    \n \n Close\n \n
    \n
    \n );\n}\n\nexport function ReadyView({\n uri,\n focus,\n onAbort,\n operationId,\n}: State.Ready): VNode {\n const { i18n } = useTranslationContext();\n const walletInegrationApi = useTalerWalletIntegrationAPI();\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const { state: credentials } = useSessionState();\n const creds = credentials.status !== \"loggedIn\" ? undefined : credentials;\n const {\n config,\n lib: { bank },\n } = useBankCoreApiContext();\n\n const parsedUri = TalerUris.createTalerWithdraw(\n uri.bankIntegrationApiBaseUrl,\n uri.withdrawalOperationId,\n );\n const talerWithdrawUri = TalerUris.toString(parsedUri);\n useEffect(() => {\n walletInegrationApi.publishTalerAction(uri);\n }, []);\n\n const abort = safeFunctionHandler(\n i18n.str`abort withdrawal`,\n (creds: LoggedIn) => bank.abortWithdrawalById(creds, operationId),\n !creds ? undefined : [creds],\n );\n abort.onSuccess = onAbort;\n abort.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Conflict:\n return i18n.str`The reserve operation has been confirmed previously and can't be aborted`;\n case HttpStatusCode.BadRequest:\n return i18n.str`The operation ID is invalid.`;\n case HttpStatusCode.NotFound:\n return i18n.str`The operation was not found.`;\n }\n };\n\n return (\n \n \n\n
    \n
    \n

    \n \n If you have a Taler wallet installed on this device\n \n

    \n
    \n

    \n \n Your wallet will display the details of the transaction\n including the fees (if applicable). If you do not yet have a\n wallet, please follow the instructions\n {\" \"}\n \n on this page\n \n .\n

    \n
    \n
    \n \n Cancel\n \n\n \n Withdraw\n \n
    \n
    \n
    \n\n
    \n
    \n

    \n \n In case you have a Taler wallet on another device\n \n

    \n
    \n \n Scan the QR below to start the withdrawal.\n \n
    \n
    \n \n
    \n
    \n
    \n \n Cancel\n \n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { h, VNode } from \"preact\";\nimport { useEffect, useRef } from \"preact/hooks\";\nimport qrcode from \"qrcode-generator\";\n\nexport function QR({ text }: { text: string }): VNode {\n const divRef = useRef(null);\n useEffect(() => {\n const qr = qrcode(0, \"L\");\n qr.addData(text);\n qr.make();\n if (divRef.current)\n divRef.current.innerHTML = qr.createSvgTag({\n scalable: true,\n });\n });\n\n return (\n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AmountJson,\n Amounts,\n HttpStatusCode,\n PaytoType,\n Paytos,\n TalerErrorCode,\n WithdrawUriResult,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ButtonBetter,\n LocalNotificationBanner,\n RenderAmount,\n useBankCoreApiContext,\n useChallengeHandler,\n useLocalNotificationBetter,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { ComponentChildren, Fragment, VNode, h } from \"preact\";\nimport { mutate } from \"swr\";\nimport { LoggedIn, useSessionState } from \"../hooks/session.js\";\nimport { LoginForm } from \"./LoginForm.js\";\nimport { SolveMFAChallenges } from \"./SolveMFA.js\";\n\nconst TALER_SCREEN_ID = 114;\n\ninterface Props {\n withdrawUri: WithdrawUriResult;\n details: {\n account: Paytos.URI;\n reserve: string;\n username: string;\n amount?: AmountJson;\n };\n}\n\nfunction useComponentState(opid: string) {\n const { state: credentials } = useSessionState();\n const creds = credentials.status !== \"loggedIn\" ? undefined : credentials;\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n const { i18n } = useTranslationContext();\n const mfa = useChallengeHandler();\n\n const {\n config,\n lib: { bank: api },\n } = useBankCoreApiContext();\n\n const wireFee =\n config.wire_transfer_fees === undefined\n ? Amounts.zeroOfCurrency(config.currency)\n : Amounts.parseOrThrow(config.wire_transfer_fees);\n\n const confirm = safeFunctionHandler(\n i18n.str`confirm withdrawal`,\n (creds: LoggedIn, challengeIds: string[]) =>\n api.confirmWithdrawalById(creds, {}, opid, {\n challengeIds,\n }),\n !creds ? undefined : [creds, []],\n );\n\n confirm.onSuccess = () => {\n mutate(() => true); // clean any info that we have\n };\n confirm.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Accepted:\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.NotFound:\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT:\n case TalerErrorCode.BANK_CONFIRM_INCOMPLETE:\n case TalerErrorCode.BANK_AMOUNT_DIFFERS:\n case TalerErrorCode.BANK_AMOUNT_REQUIRED:\n return i18n.str`cambiar`;\n default:\n assertUnreachable(fail);\n }\n };\n\n const repeat = confirm.lambda((ids: string[]) => {\n return [confirm.args![0], ids];\n });\n\n const abort = safeFunctionHandler(\n i18n.str`abort withdrawal`,\n api.abortWithdrawalById.bind(api),\n !creds ? undefined : [creds, opid],\n );\n\n abort.onSuccess = () => {\n mutate(() => true); // clean any info that we have\n };\n\n abort.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.Conflict:\n return i18n.str`cambiar`;\n default:\n assertUnreachable(fail);\n }\n };\n\n const spec = config.currency_specification;\n\n return {\n notification,\n mfa,\n wireFee,\n spec,\n abort,\n confirm,\n repeat,\n };\n}\n\n/**\n * Additional authentication required to complete the operation.\n * Not providing a back button, only abort.\n */\nexport function WithdrawalConfirmationQuestion({\n details,\n withdrawUri,\n}: Props): VNode {\n const { i18n } = useTranslationContext();\n const { notification, mfa, wireFee, spec, abort, confirm, repeat } =\n useComponentState(withdrawUri.withdrawalOperationId);\n\n confirm.onFail = (fail) => {\n switch (fail.case) {\n case TalerErrorCode.BANK_CONFIRM_ABORT_CONFLICT:\n return i18n.str`The withdrawal has been aborted previously and can't be confirmed`;\n case TalerErrorCode.BANK_CONFIRM_INCOMPLETE:\n return i18n.str`The withdrawal operation can't be confirmed before a wallet accepted the transaction.`;\n case HttpStatusCode.BadRequest:\n return i18n.str`The operation ID is invalid.`;\n case HttpStatusCode.NotFound:\n return i18n.str`The operation was not found.`;\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n return i18n.str`Your balance is not sufficient for the operation.`;\n case TalerErrorCode.BANK_AMOUNT_DIFFERS:\n return i18n.str`The starting withdrawal amount and the confirmation amount differs.`;\n case TalerErrorCode.BANK_AMOUNT_REQUIRED:\n return i18n.str`The bank requires a bank account which has not been specified yet.`;\n case HttpStatusCode.Accepted: {\n mfa.onChallengeRequired(fail.body);\n return i18n.str`A second factor authentication is required.`;\n }\n }\n };\n\n abort.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.BadRequest:\n return i18n.str`Bad request`;\n case HttpStatusCode.NotFound:\n return i18n.str`The withdrawal operation has been aborted.`;\n case HttpStatusCode.Conflict:\n return i18n.str`The withdrawal operation has been confirmed previously and can\u2019t be aborted.`;\n }\n };\n\n if (mfa.pendingChallenge) {\n return (\n \n );\n }\n\n return (\n \n \n\n
    \n
    \n

    \n Confirm the withdrawal operation\n

    \n
    \n \n
    \n {\n e.preventDefault();\n }}\n >\n
    \n
    \n
    \n

    \n Wire transfer details\n

    \n
    \n
    \n
    \n {((): VNode => {\n switch (details.account.targetType) {\n case undefined:\n case PaytoType.TalerReserveHttp:\n case PaytoType.TalerReserve: {\n // FIXME: support wire transfer to wallet\n return
    not yet supported
    ;\n }\n case PaytoType.IBAN: {\n const name =\n details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account\n number\n \n
    \n
    \n {details.account.iban}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n case PaytoType.TalerBank: {\n const name =\n details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account\n bank hostname\n \n
    \n
    \n {details.account.host}\n
    \n
    \n
    \n
    \n \n Payment Service Provider's account id\n \n
    \n
    \n {details.account.account}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n case PaytoType.Bitcoin: {\n const name =\n details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account\n address\n \n
    \n
    \n {details.account.address}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n case PaytoType.Ethereum: {\n const name =\n details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account\n address\n \n
    \n
    \n {details.account.address}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n case PaytoType.Cyclos: {\n const name =\n details.account.params[\"receiver-name\"];\n return (\n \n
    \n
    \n \n Payment Service Provider's account\n cyclos hostname\n \n
    \n
    \n {details.account.url}\n
    \n
    \n
    \n
    \n \n Payment Service Provider's account id\n \n
    \n
    \n {details.account.account}\n
    \n
    \n {name && (\n
    \n
    \n \n Payment Service Provider's name\n \n
    \n
    \n {name}\n
    \n
    \n )}\n
    \n );\n }\n default: {\n assertUnreachable(details.account);\n }\n }\n })()}\n
    \n
    \n Amount\n
    \n
    \n {details.amount !== undefined ? (\n \n ) : (\n \n No amount has yet been determined.\n \n )}\n
    \n
    \n {Amounts.isZero(wireFee) ? undefined : (\n \n
    \n
    \n Cost\n
    \n
    \n \n
    \n
    \n
    \n )}\n
    \n
    \n
    \n
    \n\n
    \n \n Cancel\n \n \n Transfer\n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n );\n}\n\nexport function ShouldBeSameUser({\n username,\n children,\n}: {\n username: string;\n children: ComponentChildren;\n}): VNode {\n const { state: credentials } = useSessionState();\n const { i18n } = useTranslationContext();\n if (credentials.status === \"loggedOut\") {\n return (\n \n \n \n \n );\n }\n if (credentials.status === \"expired\") {\n return ;\n }\n if (credentials.username !== username) {\n return (\n \n \n

    \n \n You are currently logged in with user \"{credentials.username}\" and\n the operation was made with user \"{username}\"\n \n

    \n \n \n
    \n );\n }\n return {children};\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AbsoluteTime,\n AmountJson,\n PaytoUri,\n TalerCoreBankErrorsByMethod,\n TalerCoreBankHttpClient,\n TalerError,\n WithdrawUriResult,\n} from \"@gnu-taler/taler-util\";\nimport {\n ErrorLoading,\n Loading,\n RouteDefinition,\n utils,\n} from \"@gnu-taler/web-util/browser\";\nimport { VNode } from \"preact\";\n\nimport { useComponentState } from \"./state.js\";\nimport {\n AbortedView,\n ConfirmedView,\n FailedView,\n InvalidPaytoView,\n InvalidReserveView,\n InvalidWithdrawalView,\n NeedConfirmationView,\n ReadyView,\n} from \"./views.js\";\nimport { Paytos } from \"@gnu-taler/taler-util\";\n\nexport interface Props {\n routeClose: RouteDefinition;\n onAbort: () => void;\n focus?: boolean;\n}\n\nexport type State =\n | State.Loading\n | State.LoadingError\n | State.Ready\n | State.Failed\n | State.Aborted\n | State.Confirmed\n | State.InvalidPayto\n | State.InvalidWithdrawal\n | State.InvalidReserve\n | State.NeedConfirmation;\n\nexport namespace State {\n export interface Loading {\n status: \"loading\";\n error: undefined;\n }\n\n export interface Failed {\n status: \"failed\";\n error: TalerCoreBankErrorsByMethod<\"createWithdrawal\">;\n }\n\n export interface LoadingError {\n status: \"loading-error\";\n error: TalerError;\n }\n\n /**\n * Need to open the wallet\n */\n export interface Ready {\n status: \"ready\";\n error: undefined;\n uri: WithdrawUriResult;\n focus?: boolean;\n onAbort: () => void;\n operationId: string;\n routeClose: RouteDefinition;\n }\n\n export interface InvalidPayto {\n status: \"invalid-payto\";\n error: undefined;\n payto: string | undefined;\n }\n export interface InvalidWithdrawal {\n status: \"invalid-withdrawal\";\n error: undefined;\n uri: string;\n }\n export interface InvalidReserve {\n status: \"invalid-reserve\";\n error: undefined;\n reserve: string | undefined;\n }\n export interface NeedConfirmation {\n status: \"need-confirmation\";\n\n account: string;\n onAbort: () => void;\n\n error: undefined;\n details: {\n account: Paytos.URI;\n reserve: string;\n username: string;\n amount?: AmountJson;\n };\n operationId: string;\n }\n export interface Aborted {\n status: \"aborted\";\n error: undefined;\n routeClose: RouteDefinition;\n }\n export interface Confirmed {\n status: \"confirmed\";\n error: undefined;\n routeClose: RouteDefinition;\n }\n}\n\nexport interface Transaction {\n negative: boolean;\n counterpart: string;\n when: AbsoluteTime;\n amount: AmountJson | undefined;\n subject: string;\n}\n\nconst viewMapping: utils.StateViewMap = {\n loading: Loading,\n failed: FailedView,\n \"invalid-payto\": InvalidPaytoView,\n \"invalid-withdrawal\": InvalidWithdrawalView,\n \"invalid-reserve\": InvalidReserveView,\n \"need-confirmation\": NeedConfirmationView,\n aborted: AbortedView,\n confirmed: ConfirmedView,\n \"loading-error\": ErrorLoading,\n ready: ReadyView,\n};\n\nexport const OperationState: (p: Props) => VNode = utils.compose(\n (p: Props) => useComponentState(p),\n viewMapping,\n);\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AbsoluteTime,\n AmountJson,\n TalerCorebankApi,\n TalerError,\n} from \"@gnu-taler/taler-util\";\nimport {\n ErrorLoading,\n Loading,\n RouteDefinition,\n utils,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode } from \"preact\";\n\nimport { LoginForm } from \"../LoginForm.js\";\nimport { useComponentState } from \"./state.js\";\nimport { InvalidIbanView, ReadyView } from \"./views.js\";\nimport { IntAmountJson, IntAmounts } from \"../regional/CreateCashout.js\";\n\nexport interface Props {\n account: string;\n\n onOperationCreated: (wopid: string) => void;\n onClose: () => void;\n tab: \"charge-wallet\" | \"wire-transfer\" | undefined;\n routeClose: RouteDefinition;\n routeCashout: RouteDefinition;\n routeChargeWallet: RouteDefinition;\n routeWireTransfer: RouteDefinition<{\n account?: string;\n subject?: string;\n amount?: string;\n }>;\n routePublicAccounts: RouteDefinition;\n routeCreateWireTransfer: RouteDefinition<{\n account?: string;\n subject?: string;\n amount?: string;\n }>;\n routeOperationDetails: RouteDefinition<{ wopid: string }>;\n}\n\nexport type State =\n | State.Loading\n | State.LoadingError\n | State.Ready\n | State.InvalidIban\n | State.UserNotFound;\n\nexport namespace State {\n export interface Loading {\n status: \"loading\";\n error: undefined;\n }\n\n export interface LoadingError {\n status: \"loading-error\";\n error: TalerError;\n }\n\n export interface BaseInfo {\n error: undefined;\n }\n\n export interface Ready extends BaseInfo {\n status: \"ready\";\n error: undefined;\n account: string;\n tab: \"charge-wallet\" | \"wire-transfer\" | undefined;\n limit: IntAmountJson;\n balance: AmountJson;\n\n onOperationCreated: (wopid: string) => void;\n onClose: () => void;\n routeClose: RouteDefinition;\n routeCashout: RouteDefinition;\n routeChargeWallet: RouteDefinition;\n routePublicAccounts: RouteDefinition;\n routeWireTransfer: RouteDefinition<{\n account?: string;\n subject?: string;\n amount?: string;\n }>;\n routeCreateWireTransfer: RouteDefinition<{\n account?: string;\n subject?: string;\n amount?: string;\n }>;\n routeOperationDetails: RouteDefinition<{ wopid: string }>;\n }\n\n export interface InvalidIban {\n status: \"invalid-iban\";\n error: TalerCorebankApi.AccountData;\n }\n\n export interface UserNotFound {\n status: \"login\";\n reason: \"not-found\" | \"forbidden\";\n routeRegister?: RouteDefinition;\n }\n}\n\nexport interface Transaction {\n negative: boolean;\n counterpart: string;\n when: AbsoluteTime;\n amount: AmountJson | undefined;\n subject: string;\n}\n\nconst viewMapping: utils.StateViewMap = {\n loading: Loading,\n login: LoginForm,\n \"invalid-iban\": InvalidIbanView,\n \"loading-error\": ErrorLoading,\n ready: ReadyView,\n};\n\nexport const AccountPage: (p: Props) => VNode = utils.compose(\n (p: Props) => useComponentState(p),\n viewMapping,\n);\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AbsoluteTime,\n Amounts,\n ObservabilityEventType,\n TalerError,\n TranslatedString,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Footer,\n Header,\n Loading,\n RenderAmount,\n RouteDefinition,\n ToastBanner,\n logBugForDevelopers,\n notifyError,\n notifyException,\n useBankCoreApiContext,\n useCommonPreferences,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { ComponentChildren, Fragment, VNode, h } from \"preact\";\nimport { useEffect, useErrorBoundary, useState } from \"preact/hooks\";\nimport { useSettingsContext } from \"../context/settings.js\";\nimport { useAccountDetails } from \"../hooks/account.js\";\nimport { useBankState } from \"../hooks/bank-state.js\";\nimport {\n getAllBooleanPreferences,\n getLabelForPreferences,\n usePreferences,\n} from \"../hooks/preferences.js\";\nimport { useSessionState } from \"../hooks/session.js\";\n\nconst TALER_SCREEN_ID = 103;\n\nconst GIT_HASH = typeof __GIT_HASH__ !== \"undefined\" ? __GIT_HASH__ : undefined;\nconst VERSION = typeof __VERSION__ !== \"undefined\" ? __VERSION__ : undefined;\n\nBankFrame.SCREEN_ID = TALER_SCREEN_ID;\nexport function BankFrame({\n children,\n account,\n routeAccountDetails,\n routeNotifications,\n}: {\n account?: string;\n routeAccountDetails?: RouteDefinition;\n routeNotifications?: RouteDefinition;\n children: ComponentChildren;\n}): VNode {\n const { i18n } = useTranslationContext();\n const session = useSessionState();\n const settings = useSettingsContext();\n const [{ showDebugInfo }, update] = useCommonPreferences();\n const [preferences, updatePreferences] = usePreferences();\n const [, , resetBankState] = useBankState();\n const d = useBankCoreApiContext();\n const config = d === undefined ? undefined : d.config;\n const authenticator = d === undefined ? undefined : d.lib.bank;\n const [error, resetError] = useErrorBoundary();\n\n useEffect(() => {\n if (error) {\n logBugForDevelopers(error);\n if (error instanceof Error) {\n notifyException(\n i18n.str`Internal error, please report. There should be more information in the console.`,\n error,\n );\n } else {\n notifyError(\n i18n.str`Internal error, please report.`,\n String(error) as TranslatedString,\n );\n }\n resetError();\n }\n }, [error]);\n\n return (\n \n
    \n {\n if (session.state.status === \"loggedIn\" && authenticator) {\n // FIXME: This returns a promise, should await on it!\n authenticator.deleteAccessToken(\n session.state.username,\n session.state.token,\n );\n }\n session.logOut();\n resetBankState();\n }\n }\n sites={\n !settings.topNavSites ? [] : Object.entries(settings.topNavSites)\n }\n >\n
  • \n
    \n Preferences\n
    \n
      \n {getAllBooleanPreferences(settings).map((set) => {\n const isOn: boolean = !!preferences[set];\n return (\n
    • \n
      \n \n \n {getLabelForPreferences(set, i18n)}\n \n \n {\n updatePreferences(set, !isOn);\n }}\n >\n \n \n
      \n
    • \n );\n })}\n
    • \n
      \n \n \n Show debug information\n \n \n {\n update(\"showDebugInfo\", !showDebugInfo);\n }}\n >\n \n \n
      \n
    • \n
    \n
  • \n \n
    \n\n
    \n
    \n \n
    \n
    \n\n
    \n {account && routeAccountDetails && (\n
    \n
    \n

    \n \n \n \n \n \n \n

    \n
    \n
    \n )}\n\n
    \n
    \n {children}\n
    \n
    \n
    \n\n \n\n \n
    \n );\n}\n\nWait.SCREEN_ID = TALER_SCREEN_ID;\nfunction Wait({ class: clazz }: { class?: string }): VNode {\n return (\n \n \n
    \n \n );\n}\n\nAppActivity.SCREEN_ID = TALER_SCREEN_ID;\nfunction AppActivity(): VNode {\n const [lastEvent, setLastEvent] = useState<{\n url: string;\n id: string;\n when: AbsoluteTime;\n }>();\n const [status, setStatus] = useState<\"ok\" | \"fail\">();\n const d = useBankCoreApiContext();\n const onBackendActivity = !d ? undefined : d.onActivity;\n const cancelRequest = !d ? undefined : d.cancelRequest;\n const [{ showDebugInfo }] = useCommonPreferences();\n useEffect(() => {\n // console.log(\"ASDASDS\", onBackendActivity)\n if (!showDebugInfo) return;\n if (!onBackendActivity) return;\n return onBackendActivity((ev) => {\n switch (ev.type) {\n case ObservabilityEventType.HttpFetchStart: {\n setLastEvent(ev);\n setStatus(undefined);\n return;\n }\n case ObservabilityEventType.HttpFetchFinishError: {\n setStatus(\"fail\");\n return;\n }\n case ObservabilityEventType.HttpFetchFinishSuccess: {\n setStatus(\"ok\");\n return;\n }\n /**\n * all of these are ignored\n */\n case ObservabilityEventType.DbQueryStart:\n case ObservabilityEventType.DbQueryFinishSuccess:\n case ObservabilityEventType.DbQueryFinishError:\n case ObservabilityEventType.RequestStart:\n case ObservabilityEventType.RequestFinishSuccess:\n case ObservabilityEventType.RequestFinishError:\n case ObservabilityEventType.TaskStart:\n case ObservabilityEventType.TaskStop:\n case ObservabilityEventType.TaskReset:\n case ObservabilityEventType.ShepherdTaskResult:\n case ObservabilityEventType.DeclareTaskDependency:\n case ObservabilityEventType.CryptoStart:\n case ObservabilityEventType.CryptoFinishSuccess:\n case ObservabilityEventType.CryptoFinishError:\n case ObservabilityEventType.Message:\n case ObservabilityEventType.DeclareConcernsTransaction:\n return;\n default: {\n assertUnreachable(ev);\n }\n }\n });\n });\n if (!showDebugInfo || !lastEvent) return ;\n return (\n \n \n {!status ? :
    }\n\n

    {lastEvent.url}

    \n {!status ? (\n {\n if (cancelRequest) cancelRequest(lastEvent.id);\n }}\n >\n cancel\n \n ) : undefined}\n
    \n
    \n );\n}\n\nWelcomeAccount.SCREEN_ID = TALER_SCREEN_ID;\nfunction WelcomeAccount({\n account,\n routeAccountDetails,\n}: {\n account: string;\n routeAccountDetails: RouteDefinition;\n}): VNode {\n const { i18n } = useTranslationContext();\n const result = useAccountDetails(account);\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return
    ;\n }\n if (result.type === \"fail\") {\n return (\n \n Welcome\n \n );\n }\n return (\n \n \n Welcome, {result.body.name}\n \n \n );\n}\n\nfunction AccountBalance({ account }: { account: string }): VNode {\n const result = useAccountDetails(account);\n const { config } = useBankCoreApiContext();\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return
    ;\n }\n if (result.type === \"fail\") return
    ;\n\n return (\n \n );\n}\n", "import {\n Amounts,\n assertUnreachable,\n HttpStatusCode,\n InternationalizationAPI,\n RoundingMode,\n TalerBankConversionApi,\n TalerCorebankApi,\n TalerError,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ButtonBetter,\n ErrorLoading,\n InputText,\n InputToggle,\n Loading,\n LocalNotificationBanner,\n RenderAmount,\n RouteDefinition,\n ShowInputErrorLabel,\n useBankCoreApiContext,\n useLocalNotificationBetter,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, h, VNode } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\n\nimport {\n FormErrors,\n FormStatus,\n FormValues,\n useFormState,\n} from \"../hooks/form.js\";\nimport {\n revalidateConversionRateClassDetails,\n revalidateConversionRateClassUsers,\n TransferCalculation,\n useCashinEstimatorForClass,\n useCashoutEstimatorForClass,\n useConversionInfo,\n useConversionRateClassDetails,\n useConversionRateClassUsers,\n} from \"../hooks/regional.js\";\nimport { useSessionState } from \"../hooks/session.js\";\nimport { RecursivePartial, undefinedIfEmpty } from \"../utils.js\";\nimport { DescribeConversion } from \"./admin/ConversionClassList.js\";\nimport { doAutoFocus, InputAmount } from \"./PaytoWireTransferForm.js\";\nimport { ConversionForm } from \"./regional/ConversionConfig.js\";\nimport { AccessToken } from \"@gnu-taler/taler-util\";\nimport { TalerErrorCode } from \"@gnu-taler/taler-util\";\nimport { opFixedSuccess } from \"@gnu-taler/taler-util\";\nimport { AmountJson } from \"@gnu-taler/taler-util\";\n\nconst TALER_SCREEN_ID = 11;\ninterface Props {\n classId: number;\n routeCancel: RouteDefinition;\n onClassDeleted: () => void;\n}\n\ntype FormType = {\n name: string;\n description: string;\n conv: Omit<\n Omit,\n \"cashin_tiny_amount\"\n >;\n};\n\nexport function ConversionRateClassDetails({\n routeCancel,\n classId,\n onClassDeleted,\n}: Props): VNode {\n const { i18n } = useTranslationContext();\n\n const detailsResult = useConversionRateClassDetails(classId);\n const conversionInfoResult = useConversionInfo();\n const conversionInfo =\n conversionInfoResult &&\n !(conversionInfoResult instanceof TalerError) &&\n conversionInfoResult.type === \"ok\"\n ? conversionInfoResult.body\n : undefined;\n\n if (!detailsResult || !conversionInfo) {\n return ;\n }\n if (detailsResult instanceof TalerError) {\n return ;\n }\n if (detailsResult.type === \"fail\") {\n switch (detailsResult.case) {\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.Forbidden:\n case HttpStatusCode.NotFound:\n case HttpStatusCode.NotImplemented:\n return (\n \n \n Conversion should be enabled in the configuration, the conversion\n rate should be initialized with fee(s), rates and a rounding mode.\n \n \n );\n default:\n assertUnreachable(detailsResult);\n }\n }\n return (\n \n );\n}\n\nfunction Form({\n conversionInfo,\n detailsResult,\n routeCancel,\n classId,\n onClassDeleted,\n}: {\n conversionInfo: TalerBankConversionApi.TalerConversionInfoConfig;\n detailsResult: TalerCorebankApi.ConversionRateClass;\n routeCancel: RouteDefinition;\n classId: number;\n onClassDeleted: () => void;\n}) {\n const { i18n } = useTranslationContext();\n const { state: credentials } = useSessionState();\n const creds = credentials.status !== \"loggedIn\" ? undefined : credentials;\n const { lib, config } = useBankCoreApiContext();\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n const [section, setSection] = useState<\n \"detail\" | \"cashout\" | \"cashin\" | \"users\" | \"test\" | \"delete\"\n >(\"detail\");\n\n const initalState: FormValues = {\n name: detailsResult.name,\n description: detailsResult.description,\n conv: {\n cashin_min_amount: detailsResult.cashin_min_amount?.split(\":\")[1],\n cashin_fee: detailsResult.cashin_fee?.split(\":\")[1],\n cashin_ratio: detailsResult?.cashin_ratio,\n cashin_rounding_mode: detailsResult?.cashin_rounding_mode,\n cashout_min_amount: detailsResult.cashout_min_amount?.split(\":\")[1],\n cashout_fee: detailsResult.cashout_fee?.split(\":\")[1],\n cashout_ratio: detailsResult.cashout_ratio,\n cashout_rounding_mode: detailsResult.cashout_rounding_mode,\n },\n };\n\n const [form, status] = useFormState(\n initalState,\n createFormValidator(\n i18n,\n conversionInfo.regional_currency,\n conversionInfo.fiat_currency,\n ),\n );\n\n const deleteClass = safeFunctionHandler(\n i18n.str`delete conversion rate class`,\n (token: AccessToken) => lib.bank.deleteConversionRateClass(token, classId),\n !creds || section !== \"delete\" || detailsResult.num_users > 0\n ? undefined\n : [creds.token],\n );\n deleteClass.onSuccess = onClassDeleted;\n deleteClass.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Unauthorized:\n return i18n.str`Unauthorized`;\n case HttpStatusCode.Forbidden:\n return i18n.str`Forbidden`;\n case HttpStatusCode.NotFound:\n return i18n.str`NotFound`;\n case HttpStatusCode.NotImplemented:\n return i18n.str`NotImplemented`;\n default:\n assertUnreachable(fail);\n }\n };\n\n const input: TalerCorebankApi.ConversionRateClassInput | undefined =\n status.status === \"fail\"\n ? undefined\n : {\n name: status.result.name,\n description: status.result.description,\n\n cashin_fee: status.result.conv.cashin_fee,\n cashin_min_amount: status.result.conv.cashin_min_amount,\n cashin_ratio: status.result.conv.cashin_ratio,\n cashin_rounding_mode: status.result.conv.cashin_rounding_mode,\n\n cashout_fee: status.result.conv.cashout_fee,\n cashout_min_amount: status.result.conv.cashout_min_amount,\n cashout_ratio: status.result.conv.cashout_ratio,\n cashout_rounding_mode: status.result.conv.cashout_rounding_mode,\n };\n\n const updateClass = safeFunctionHandler(\n i18n.str`update conversion rate class`,\n lib.bank.updateConversionRateClass.bind(lib.bank),\n !creds || !input ? undefined : [creds.token, classId, input],\n );\n updateClass.onSuccess = () => {\n setSection(\"detail\");\n };\n updateClass.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Unauthorized:\n return i18n.str`Unauthorized`;\n case HttpStatusCode.Forbidden:\n return i18n.str`Forbidden`;\n case HttpStatusCode.NotFound:\n return i18n.str`Not Found`;\n case HttpStatusCode.NotImplemented:\n return i18n.str`Not implemented`;\n case TalerErrorCode.BANK_NAME_REUSE:\n return i18n.str`The name of the conversion is already used.`;\n default:\n assertUnreachable(fail);\n }\n };\n\n const updateRequest: TalerCorebankApi.ConversionRateClassInput | undefined =\n status.status === \"fail\"\n ? undefined\n : {\n name: status.result.name,\n description: status.result.description,\n\n cashin_fee: status.result.conv.cashin_fee,\n cashin_min_amount: status.result.conv.cashin_min_amount,\n cashin_ratio: status.result.conv.cashin_ratio,\n cashin_rounding_mode: status.result.conv.cashin_rounding_mode,\n\n cashout_fee: status.result.conv.cashout_fee,\n cashout_min_amount: status.result.conv.cashout_min_amount,\n cashout_ratio: status.result.conv.cashout_ratio,\n cashout_rounding_mode: status.result.conv.cashout_rounding_mode,\n };\n\n const updateDetails = updateClass.lambda(\n (\n t: AccessToken,\n id: number,\n r: TalerCorebankApi.ConversionRateClassInput,\n ) => [t, id, r],\n !creds ||\n !updateRequest ||\n section !== \"detail\" ||\n status.errors?.name ||\n status.errors?.description ||\n (status.result.name === initalState.name &&\n status.result.description === initalState.description)\n ? undefined\n : [creds.token, classId, updateRequest],\n );\n\n // const doUpdateDetails1 =\n // !creds ||\n // section !== \"detail\" ||\n // status.errors?.name ||\n // status.errors?.description ||\n // (status.result.name === initalState.name &&\n // status.result.description === initalState.description)\n // ? undefined\n // : doUpdateClass2;\n\n const updateCashin = updateClass.lambda(\n (\n t: AccessToken,\n id: number,\n r: TalerCorebankApi.ConversionRateClassInput,\n ) => [t, id, r],\n !creds ||\n !updateRequest ||\n section !== \"cashin\" ||\n status.errors?.conv?.cashin_fee ||\n status.errors?.conv?.cashin_min_amount ||\n status.errors?.conv?.cashin_ratio ||\n status.errors?.conv?.cashin_rounding_mode\n ? undefined\n : [creds.token, classId, updateRequest],\n );\n // const doUpdateCashin1 =\n // !creds ||\n // section !== \"cashin\" ||\n // status.errors?.conv?.cashin_fee ||\n // status.errors?.conv?.cashin_min_amount ||\n // status.errors?.conv?.cashin_ratio ||\n // status.errors?.conv?.cashin_rounding_mode\n // ? undefined\n // : doUpdateClass2;\n\n const updateCashout = updateClass.lambda(\n (\n t: AccessToken,\n id: number,\n r: TalerCorebankApi.ConversionRateClassInput,\n ) => [t, id, r],\n !creds ||\n !updateRequest ||\n section !== \"cashout\" ||\n // no errors on fields\n status.errors?.conv?.cashout_fee ||\n status.errors?.conv?.cashout_min_amount ||\n status.errors?.conv?.cashout_ratio ||\n status.errors?.conv?.cashout_rounding_mode ||\n // at least on field changed\n (status.result?.conv?.cashout_fee === initalState.conv.cashout_fee &&\n status.result?.conv?.cashout_min_amount ===\n initalState.conv.cashout_min_amount &&\n status.result?.conv?.cashout_ratio === initalState.conv.cashout_ratio &&\n status.result?.conv?.cashout_rounding_mode ===\n initalState.conv.cashout_rounding_mode)\n ? undefined\n : [creds.token, classId, updateRequest],\n );\n\n // const doUpdateCashout1 =\n // !creds ||\n // section !== \"cashout\" ||\n // // no errors on fields\n // status.errors?.conv?.cashout_fee ||\n // status.errors?.conv?.cashout_min_amount ||\n // status.errors?.conv?.cashout_ratio ||\n // status.errors?.conv?.cashout_rounding_mode ||\n // // at least on field changed\n // (status.result?.conv?.cashout_fee === initalState.conv.cashout_fee &&\n // status.result?.conv?.cashout_min_amount ===\n // initalState.conv.cashout_min_amount &&\n // status.result?.conv?.cashout_ratio === initalState.conv.cashout_ratio &&\n // status.result?.conv?.cashout_rounding_mode ===\n // initalState.conv.cashout_rounding_mode)\n // ? undefined\n // : doUpdateClass2;\n\n const default_rate = conversionInfo.conversion_rate;\n\n const final_cashin_ratio =\n detailsResult.cashin_ratio ?? default_rate.cashin_ratio;\n const final_cashin_fee = detailsResult.cashin_fee ?? default_rate.cashin_fee;\n const final_cashin_min =\n detailsResult.cashin_min_amount ?? default_rate.cashin_min_amount;\n const final_cashin_rounding =\n detailsResult.cashin_rounding_mode ?? default_rate.cashin_rounding_mode;\n\n const final_cashout_ratio =\n detailsResult.cashout_ratio ?? default_rate.cashout_ratio;\n const final_cashout_fee =\n detailsResult.cashout_fee ?? default_rate.cashout_fee;\n const final_cashout_min =\n detailsResult.cashout_min_amount ?? default_rate.cashout_min_amount;\n const final_cashout_rounding =\n detailsResult.cashout_rounding_mode ?? default_rate.cashout_rounding_mode;\n\n const in_ratio = Number.parseFloat(final_cashin_ratio);\n const out_ratio = Number.parseFloat(final_cashout_ratio);\n\n const both_high = in_ratio > 1 && out_ratio > 1;\n const both_low = in_ratio < 1 && out_ratio < 1;\n\n return (\n
    \n \n
    \n
    \n

    \n Conversion rate class\n

    \n
    \n \n {\n setSection(\"detail\");\n }}\n />\n \n \n \n Details\n \n \n \n \n \n {\n setSection(\"cashout\");\n }}\n />\n \n \n \n Config cashout\n \n \n \n \n \n {\n setSection(\"cashin\");\n }}\n />\n \n \n \n Config cashin\n \n \n \n \n \n {\n setSection(\"users\");\n }}\n />\n \n \n \n Accounts\n \n \n \n \n \n {\n setSection(\"test\");\n }}\n />\n \n \n \n Test\n \n \n \n {\" \"}\n \n {\n setSection(\"delete\");\n }}\n />\n \n \n \n Delete\n \n \n \n \n
    \n
    \n\n {\n e.preventDefault();\n }}\n >\n {section == \"cashin\" && (\n \n )}\n\n {section == \"cashout\" && (\n \n \n \n )}\n\n {section == \"detail\" && (\n \n
    \n
    \n
    \n Name\n
    \n
    \n {\n form?.name?.onUpdate(e.currentTarget.value);\n }}\n />\n \n
    \n
    \n
    \n\n
    \n
    \n
    \n Description\n
    \n
    \n {\n form?.description?.onUpdate(e.currentTarget.value);\n }}\n />\n \n
    \n
    \n
    \n
    \n
    \n
    \n Cashin\n
    \n
    \n \n
    \n
    \n
    \n\n
    \n
    \n
    \n Cashout\n
    \n
    \n \n
    \n
    \n
    \n\n
    \n
    \n
    \n Users\n
    \n
    \n {detailsResult.num_users}\n
    \n
    \n
    \n\n {both_low || both_high ? (\n
    \n \n \n One of the ratios should be higher or equal than 1 an the\n other should be lower or equal than 1.\n \n \n
    \n ) : undefined}\n
    \n )}\n\n {section == \"users\" && (\n \n )}\n {section == \"delete\" && (\n \n )}\n\n {section == \"test\" && (\n \n )}\n\n
    \n \n Cancel\n \n {section == \"cashin\" ? (\n \n \n Update\n \n \n ) : undefined}\n {section == \"cashout\" ? (\n \n \n Update\n \n \n ) : undefined}\n {section == \"detail\" ? (\n \n \n Update\n \n \n ) : undefined}\n {section == \"delete\" ? (\n \n \n Delete\n \n \n ) : undefined}\n
    \n \n
    \n
    \n );\n}\n\nexport function createFormValidator(\n i18n: InternationalizationAPI,\n regional: string,\n fiat: string,\n) {\n return function check(state: FormValues): FormStatus {\n const cashin_min_amount = Amounts.parse(\n `${fiat}:${state.conv.cashin_min_amount}`,\n );\n\n const cashin_fee = Amounts.parse(`${regional}:${state.conv.cashin_fee}`);\n\n const cashout_min_amount = Amounts.parse(\n `${regional}:${state.conv.cashout_min_amount}`,\n );\n const cashout_fee = Amounts.parse(`${fiat}:${state.conv.cashout_fee}`);\n\n const cashin_ratio_f = Number.parseFloat(state.conv.cashin_ratio ?? \"\");\n const cashout_ratio_f = Number.parseFloat(state.conv.cashout_ratio ?? \"\");\n\n const cashin_ratio = Number.isNaN(cashin_ratio_f)\n ? undefined\n : cashin_ratio_f;\n const cashout_ratio = Number.isNaN(cashout_ratio_f)\n ? undefined\n : cashout_ratio_f;\n\n const errors = undefinedIfEmpty>({\n conv: undefinedIfEmpty>({\n cashin_min_amount: !state.conv.cashin_min_amount\n ? undefined\n : !cashin_min_amount\n ? i18n.str`Invalid`\n : undefined,\n cashin_fee: !state.conv.cashin_fee\n ? undefined\n : !cashin_fee\n ? i18n.str`Invalid`\n : undefined,\n\n cashout_min_amount: !state.conv.cashout_min_amount\n ? undefined\n : !cashout_min_amount\n ? i18n.str`Invalid`\n : undefined,\n cashout_fee: !state.conv.cashin_fee\n ? undefined\n : !cashout_fee\n ? i18n.str`Invalid`\n : undefined,\n\n cashin_rounding_mode: !state.conv.cashin_rounding_mode\n ? undefined\n : undefined,\n cashout_rounding_mode: !state.conv.cashout_rounding_mode\n ? undefined\n : undefined,\n\n cashin_ratio: !state.conv.cashin_ratio\n ? undefined\n : Number.isNaN(cashin_ratio)\n ? i18n.str`Invalid`\n : undefined,\n cashout_ratio: !state.conv.cashout_ratio\n ? undefined\n : Number.isNaN(cashout_ratio)\n ? i18n.str`Invalid`\n : undefined,\n }),\n\n description: undefined,\n name: !state.name ? i18n.str`Required` : undefined,\n });\n\n const result: RecursivePartial = {\n name: !errors?.name ? state.name : undefined,\n description: state.description,\n conv: {\n cashin_fee:\n !errors?.conv?.cashin_fee && cashin_fee\n ? Amounts.stringify(cashin_fee)\n : undefined,\n cashin_min_amount:\n !errors?.conv?.cashin_min_amount && cashin_min_amount\n ? Amounts.stringify(cashin_min_amount)\n : undefined,\n cashin_ratio:\n !errors?.conv?.cashin_ratio && cashin_ratio\n ? String(cashin_ratio)\n : undefined,\n cashin_rounding_mode: !errors?.conv?.cashin_rounding_mode\n ? (state.conv.cashin_rounding_mode! as RoundingMode)\n : undefined,\n cashout_fee:\n !errors?.conv?.cashout_fee && cashout_fee\n ? Amounts.stringify(cashout_fee)\n : undefined,\n cashout_min_amount:\n !errors?.conv?.cashout_min_amount && cashout_min_amount\n ? Amounts.stringify(cashout_min_amount)\n : undefined,\n cashout_ratio:\n !errors?.conv?.cashout_ratio && cashout_ratio\n ? String(cashout_ratio)\n : undefined,\n cashout_rounding_mode: !errors?.conv?.cashout_rounding_mode\n ? (state.conv.cashout_rounding_mode! as RoundingMode)\n : undefined,\n },\n };\n return errors === undefined\n ? { status: \"ok\", result: result as FormType, errors }\n : { status: \"fail\", result: result as FormType, errors };\n };\n}\n\nfunction TestConversionClass({\n classId,\n info,\n}: {\n classId: number;\n info: TalerBankConversionApi.TalerConversionInfoConfig;\n}): VNode {\n const { i18n } = useTranslationContext();\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const { estimateByDebit: calculateCashoutFromDebit } =\n useCashoutEstimatorForClass(classId);\n const { estimateByDebit: calculateCashinFromDebit } =\n useCashinEstimatorForClass(classId);\n\n const [amount, setAmount] = useState(\"100\");\n const [error, setError] = useState();\n\n const [calculationResult, setCalc] = useState<{\n cashin: TransferCalculation;\n cashout: TransferCalculation;\n }>();\n\n const in_amount = !amount\n ? undefined\n : Amounts.parseOrThrow(`${info.fiat_currency}:${amount}`);\n\n const in_fee = Amounts.parseOrThrow(info.conversion_rate.cashin_fee);\n const out_fee = Amounts.parseOrThrow(info.conversion_rate.cashout_fee);\n\n const calculate = safeFunctionHandler(\n i18n.str`calculate cashout fee`,\n async (amount: AmountJson) => {\n const respCashin = await calculateCashinFromDebit(amount, in_fee);\n if (respCashin.type === \"fail\") {\n return respCashin;\n }\n const cashin = respCashin.body;\n const respCashout = await calculateCashoutFromDebit(\n cashin.credit,\n out_fee,\n );\n if (respCashout.type === \"fail\") {\n return respCashout;\n }\n const cashout = respCashout.body;\n return opFixedSuccess({ cashin, cashout });\n },\n !in_amount || !!error ? undefined : [in_amount],\n );\n\n calculate.onSuccess = (resp) => setCalc(resp);\n calculate.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.BadRequest:\n return i18n.str`The server didn't understand the request.`;\n case HttpStatusCode.Conflict:\n return i18n.str`The amount is too small`;\n case HttpStatusCode.NotImplemented:\n return i18n.str`Conversion is not implemented.`;\n case TalerErrorCode.GENERIC_PARAMETER_MISSING:\n return i18n.str`At least debit or credit needs to be provided`;\n case TalerErrorCode.GENERIC_PARAMETER_MALFORMED:\n return i18n.str`The amount is malfored`;\n case TalerErrorCode.GENERIC_CURRENCY_MISMATCH:\n return i18n.str`The currency is not supported`;\n default:\n assertUnreachable(fail);\n }\n };\n\n useEffect(() => {\n calculate.call();\n }, [amount]);\n\n const cashinCalc = calculationResult?.cashin;\n const cashoutCalc = calculationResult?.cashout;\n\n return (\n \n
    \n
    \n
    \n {i18n.str`Initial amount`}\n {\n setAmount(d);\n }}\n />\n \n

    \n \n Use it to test how the conversion will affect the amount.\n \n

    \n
    \n
    \n
    \n\n {!cashoutCalc || !cashinCalc ? undefined : (\n
    \n
    \n
    \n
    \n
    \n Sending to this bank\n
    \n
    \n \n
    \n
    \n\n {Amounts.isZero(cashinCalc.beforeFee) ? undefined : (\n
    \n
    \n \n Converted\n \n
    \n
    \n \n
    \n
    \n )}\n
    \n
    \n Cashin after fee\n
    \n
    \n \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n Sending from this bank\n
    \n
    \n \n
    \n
    \n\n {Amounts.isZero(cashoutCalc.beforeFee) ? undefined : (\n
    \n
    \n \n Converted\n \n
    \n
    \n \n
    \n
    \n )}\n
    \n
    \n Cashout after fee\n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n )}\n
    \n );\n}\nfunction DeleteConversionClass({\n classId,\n userCount,\n}: {\n classId: number;\n userCount: number;\n}): VNode {\n const { i18n } = useTranslationContext();\n\n return (\n \n
    \n {userCount > 0 ? (\n \n \n There are some user associated to this class. You need to remove\n them first.\n \n \n ) : (\n \n This step can't be undone.\n \n )}\n
    \n
    \n );\n}\n\nfunction AccountsOnConversionClass({ classId }: { classId: number }): VNode {\n const { i18n } = useTranslationContext();\n\n const {\n lib: { bank },\n config,\n } = useBankCoreApiContext();\n const { state } = useSessionState();\n const resultInfo = useConversionInfo();\n const convInfo =\n !resultInfo || resultInfo instanceof Error || resultInfo.type === \"fail\"\n ? undefined\n : resultInfo.body;\n const token = state.status === \"loggedIn\" ? state.token : undefined;\n\n const [filter, setFilter] = useState<{\n showAll?: boolean;\n classId?: number;\n account?: string;\n }>({\n showAll: classId === undefined,\n classId,\n });\n const userListResult = useConversionRateClassUsers(\n filter.classId,\n filter.account,\n );\n if (!userListResult) {\n return ;\n }\n if (userListResult instanceof TalerError) {\n return ;\n }\n if (userListResult.type === \"fail\") {\n switch (userListResult.case) {\n case HttpStatusCode.Unauthorized:\n return (\n \n \n Conversion should be enabled in the configuration, the conversion\n rate should be initialized with fee(s), rates and a rounding mode.\n \n \n );\n default:\n assertUnreachable(userListResult);\n }\n }\n return (\n \n
    \n
    \n
    \n

    \n Filters\n

    \n
    \n
    \n
    \n
    \n \n \n {filter.showAll ? (\n \n ) : undefined}\n
    \n
    \n
    \n
    \n {!userListResult.body.length ? (\n
    \n \n No users in this conversion rate class\n \n
    \n ) : (\n \n \n \n {i18n.str`Name`}\n {i18n.str`Class`}\n {i18n.str`Cashin`}\n {i18n.str`Cashout`}\n {i18n.str`Action`}\n \n \n \n {userListResult.body.map((item, idx) => {\n return (\n \n \n \n \n \n \n \n );\n })}\n \n
    \n {item.name}\n \n {item.conversion_rate_class_id}\n \n \n \n \n \n {classId === item.conversion_rate_class_id ? (\n {\n if (token) {\n await bank.updateAccount(\n { username: item.username, token },\n { conversion_rate_class_id: null },\n );\n await revalidateConversionRateClassUsers();\n await revalidateConversionRateClassDetails();\n }\n }}\n >\n Remove\n \n ) : (\n {\n if (token) {\n await bank.updateAccount(\n { username: item.username, token },\n { conversion_rate_class_id: classId },\n );\n await revalidateConversionRateClassUsers();\n await revalidateConversionRateClassDetails();\n }\n }}\n >\n Add\n \n )}\n
    \n )}\n
    \n {!userListResult.loadFirst && !userListResult.loadNext ? undefined : (\n \n
    \n \n First page\n \n \n Next\n \n
    \n \n )}\n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { AmountJson, TranslatedString } from \"@gnu-taler/taler-util\";\nimport { useState } from \"preact/hooks\";\n\nexport type UIField = {\n value: string | undefined;\n onUpdate: (s: string) => void;\n error: TranslatedString | undefined;\n};\n\ntype FormHandler = {\n [k in keyof T]?: T[k] extends string\n ? UIField\n : T[k] extends AmountJson\n ? UIField\n : FormHandler;\n};\n\nexport type FormValues = {\n [k in keyof T]: T[k] extends string\n ? string | undefined\n : T[k] extends AmountJson\n ? string | undefined\n : FormValues;\n};\n\nexport type RecursivePartial = {\n [k in keyof T]?: T[k] extends string\n ? string\n : T[k] extends AmountJson\n ? AmountJson\n : RecursivePartial;\n};\n\nexport type FormErrors = {\n [k in keyof T]?: T[k] extends string\n ? TranslatedString\n : T[k] extends AmountJson\n ? TranslatedString\n : FormErrors;\n};\n\nexport type FormStatus =\n | {\n status: \"ok\";\n result: T;\n errors: undefined;\n }\n | {\n status: \"fail\";\n result: RecursivePartial;\n errors: FormErrors;\n };\n\nfunction constructFormHandler(\n form: FormValues,\n updateForm: (d: FormValues) => void,\n errors: FormErrors | undefined,\n): FormHandler {\n const keys = Object.keys(form) as Array;\n\n const handler = keys.reduce((prev, fieldName) => {\n const currentValue: unknown = form[fieldName];\n const currentError: unknown = errors ? errors[fieldName] : undefined;\n function updater(newValue: unknown) {\n updateForm({ ...form, [fieldName]: newValue });\n }\n if (typeof currentValue === \"object\") {\n // @ts-expect-error FIXME better typing\n const group = constructFormHandler(currentValue, updater, currentError);\n // @ts-expect-error FIXME better typing\n prev[fieldName] = group;\n return prev;\n }\n const field: UIField = {\n // @ts-expect-error FIXME better typing\n error: currentError,\n // @ts-expect-error FIXME better typing\n value: currentValue,\n onUpdate: updater,\n };\n // @ts-expect-error FIXME better typing\n prev[fieldName] = field;\n return prev;\n }, {} as FormHandler);\n\n return handler;\n}\n\n/**\n * FIXME: Consider sending this to web-utils\n *\n *\n * @param defaultValue\n * @param check\n * @returns\n */\nexport function useFormState(\n defaultValue: FormValues,\n check: (f: FormValues) => FormStatus,\n): [FormHandler, FormStatus] {\n const [form, updateForm] = useState>(defaultValue);\n\n const status = check(form);\n const handler = constructFormHandler(form, updateForm, status.errors);\n\n return [handler, status];\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n AmountString,\n Amounts,\n DecimalNumber,\n HttpStatusCode,\n RoundingMode,\n TalerError,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ErrorLoading,\n Loading,\n RenderAmount,\n RouteDefinition,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\n\nimport { CurrencySpecification } from \"@gnu-taler/taler-util\";\nimport {\n useConversionInfo,\n useConversionRateClasses,\n} from \"../../hooks/regional.js\";\n\nconst TALER_SCREEN_ID = 130;\n\ninterface Props {\n routeCreate: RouteDefinition;\n routeShowDetails: RouteDefinition<{ classId: string }>;\n}\n\nexport function ConversionClassList({\n routeCreate,\n routeShowDetails,\n}: Props): VNode {\n const result = useConversionRateClasses();\n const { i18n } = useTranslationContext();\n const resultInfo = useConversionInfo();\n\n const convInfo =\n !resultInfo || resultInfo instanceof Error || resultInfo.type === \"fail\"\n ? undefined\n : resultInfo.body;\n\n if (!convInfo) {\n return -;\n }\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return ;\n }\n\n if (result.type !== \"ok\") {\n switch (result.case) {\n case HttpStatusCode.Forbidden:\n return (\n \n );\n case HttpStatusCode.NotFound:\n return (\n \n );\n case HttpStatusCode.NotImplemented:\n return (\n \n );\n case HttpStatusCode.Unauthorized:\n return (\n \n );\n default:\n assertUnreachable(result);\n }\n }\n\n const classes = result.body;\n\n return (\n \n
    \n
    \n
    \n

    \n Conversion rate classes\n

    \n
    \n
    \n \n Create conversion rate class\n \n
    \n
    \n
    \n
    \n
    \n {!classes.length ? (\n
    \n No conversion rate class\n
    \n ) : (\n \n \n \n {i18n.str`Name`}\n {i18n.str`Description`}\n {i18n.str`Cashin`}\n {i18n.str`Cashout`}\n \n \n \n {classes.map((row, idx) => {\n return (\n \n \n \n \n \n \n );\n })}\n \n
    \n \n {row.name}\n \n \n \n {row.description}\n \n \n \n \n \n \n \n \n \n
    \n )}\n
    \n \n
    \n \n First page\n \n \n Next\n \n
    \n \n
    \n
    \n
    \n
    \n );\n}\n\nexport function DescribeConversion({\n fee,\n min,\n ratio,\n rounding,\n feeSpec,\n minSpec,\n}: {\n min: AmountString;\n ratio: DecimalNumber;\n fee: AmountString;\n rounding: RoundingMode;\n minSpec: CurrencySpecification;\n feeSpec: CurrencySpecification;\n}): VNode {\n const { i18n } = useTranslationContext();\n\n return (\n \n 1:{ratio}\n {Amounts.isZero(min) ? undefined : (\n \n
    \n min: \n \n
    \n )}\n {Amounts.isZero(fee) ? undefined : (\n \n
    \n fee: \n \n
    \n )}\n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AmountJson,\n Amounts,\n HttpStatusCode,\n TalerBankConversionApi,\n TalerError,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ButtonBetter,\n ErrorLoading,\n InternationalizationAPI,\n Loading,\n LocalNotificationBanner,\n RenderAmount,\n RouteDefinition,\n ShowInputErrorLabel,\n useBankCoreApiContext,\n useLocalNotificationBetter,\n useTranslationContext,\n utils,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useEffect, useState } from \"preact/hooks\";\nimport {\n FormErrors,\n FormStatus,\n FormValues,\n RecursivePartial,\n UIField,\n useFormState,\n} from \"../../hooks/form.js\";\nimport {\n TransferCalculation,\n useCashinEstimator,\n useCashoutEstimator,\n useConversionInfo,\n} from \"../../hooks/regional.js\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport { undefinedIfEmpty } from \"../../utils.js\";\nimport { InputAmount } from \"../PaytoWireTransferForm.js\";\nimport { ProfileNavigation } from \"../ProfileNavigation.js\";\n\nimport { TalerErrorCode, opFixedSuccess } from \"@gnu-taler/taler-util\";\nimport { DescribeConversion } from \"../admin/ConversionClassList.js\";\n\nconst TALER_SCREEN_ID = 126;\n\ninterface Props {\n routeMyAccountDetails: RouteDefinition;\n routeMyAccountDelete: RouteDefinition;\n routeMyAccountPassword: RouteDefinition;\n routeMyAccountCashout: RouteDefinition;\n routeConversionConfig: RouteDefinition;\n routeCancel: RouteDefinition;\n onUpdateSuccess: () => void;\n}\n\ntype FormType = {\n amount: AmountJson;\n conv: TalerBankConversionApi.ConversionRate;\n};\n\nfunction useComponentState({\n routeCancel,\n routeConversionConfig,\n routeMyAccountCashout,\n routeMyAccountDelete,\n routeMyAccountDetails,\n routeMyAccountPassword,\n}: Props): utils.RecursiveState {\n const { i18n } = useTranslationContext();\n\n const { state: credentials } = useSessionState();\n const creds =\n credentials.status !== \"loggedIn\" || !credentials.isUserAdministrator\n ? undefined\n : credentials;\n\n if (!creds) {\n return only admin can setup conversion;\n }\n\n const resp = useConversionInfo();\n if (!resp) {\n return ;\n }\n if (resp instanceof TalerError) {\n return ;\n }\n\n if (resp.type !== \"ok\") {\n switch (resp.case) {\n case HttpStatusCode.NotImplemented: {\n return (\n \n \n Cashout should be enabled in the configuration, the conversion\n rate should be initialized with fee(s), rates and a rounding mode.\n \n \n );\n }\n default:\n assertUnreachable(resp);\n }\n }\n const info = resp.body;\n\n return function afterComponentLoads() {\n const {\n lib: { conversion },\n } = useBankCoreApiContext();\n\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const initalState: FormValues = {\n amount: \"100\",\n conv: {\n cashin_min_amount: info.conversion_rate.cashin_min_amount.split(\":\")[1],\n cashin_fee: info.conversion_rate.cashin_fee.split(\":\")[1],\n cashin_ratio: info.conversion_rate.cashin_ratio,\n cashin_rounding_mode: info.conversion_rate.cashin_rounding_mode,\n cashin_tiny_amount:\n info.conversion_rate.cashin_tiny_amount.split(\":\")[1],\n cashout_min_amount:\n info.conversion_rate.cashout_min_amount.split(\":\")[1],\n cashout_fee: info.conversion_rate.cashout_fee.split(\":\")[1],\n cashout_ratio: info.conversion_rate.cashout_ratio,\n cashout_rounding_mode: info.conversion_rate.cashout_rounding_mode,\n cashout_tiny_amount:\n info.conversion_rate.cashout_tiny_amount.split(\":\")[1],\n },\n };\n\n const [form, status] = useFormState(\n initalState,\n createFormValidator(i18n, info.regional_currency, info.fiat_currency),\n );\n\n const { estimateByDebit: calculateCashoutFromDebit } =\n useCashoutEstimator();\n\n const { estimateByDebit: calculateCashinFromDebit } = useCashinEstimator();\n\n const [calculationResult, setCalc] = useState<{\n cashin: TransferCalculation;\n cashout: TransferCalculation;\n }>();\n\n const in_amount = !form.amount\n ? undefined\n : Amounts.parseOrThrow(`${info.fiat_currency}:${form.amount.value}`);\n\n const in_fee = Amounts.parseOrThrow(info.conversion_rate.cashin_fee);\n const out_fee = Amounts.parseOrThrow(info.conversion_rate.cashout_fee);\n\n const calculate = safeFunctionHandler(\n i18n.str`calculate cashout fee`,\n async (amount: AmountJson) => {\n const respCashin = await calculateCashinFromDebit(amount, in_fee);\n if (respCashin.type === \"fail\") {\n return respCashin;\n }\n const cashin = respCashin.body;\n const respCashout = await calculateCashoutFromDebit(\n cashin.credit,\n out_fee,\n );\n if (respCashout.type === \"fail\") {\n return respCashout;\n }\n const cashout = respCashout.body;\n return opFixedSuccess({ cashin, cashout });\n },\n !in_amount || status.status === \"fail\" ? undefined : [in_amount],\n );\n calculate.onSuccess = (resp) => setCalc(resp);\n calculate.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.BadRequest:\n return i18n.str`The server didn't understand the request.`;\n case HttpStatusCode.Conflict:\n return i18n.str`The amount is too small`;\n case HttpStatusCode.NotImplemented:\n return i18n.str`Conversion is not implemented.`;\n case TalerErrorCode.GENERIC_PARAMETER_MISSING:\n return i18n.str`At least debit or credit needs to be provided`;\n case TalerErrorCode.GENERIC_PARAMETER_MALFORMED:\n return i18n.str`The amount is malfored`;\n case TalerErrorCode.GENERIC_CURRENCY_MISMATCH:\n return i18n.str`The currency is not supported`;\n default:\n assertUnreachable(fail);\n }\n };\n\n useEffect(() => {\n calculate.call();\n }, [\n form.amount?.value,\n form.conv?.cashin_fee?.value,\n form.conv?.cashout_fee?.value,\n ]);\n\n const [section, setSection] = useState<\"detail\" | \"cashout\" | \"cashin\">(\n \"detail\",\n );\n const cashinCalc = calculationResult?.cashin;\n const cashoutCalc = calculationResult?.cashout;\n\n const update = safeFunctionHandler(\n i18n.str`update conversion rate`,\n conversion.updateConversionRate.bind(conversion),\n !creds || status.status === \"fail\"\n ? undefined\n : [{ type: \"bearer\", token: creds.token }, status.result.conv],\n );\n\n update.onSuccess = () => {\n setSection(\"detail\");\n };\n update.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Unauthorized:\n return i18n.str`Wrong credentials`;\n case HttpStatusCode.NotImplemented:\n return i18n.str`Conversion is disabled`;\n default:\n assertUnreachable(fail);\n }\n };\n\n const in_ratio = Number.parseFloat(info.conversion_rate.cashin_ratio);\n const out_ratio = Number.parseFloat(info.conversion_rate.cashout_ratio);\n\n const both_high = in_ratio > 1 && out_ratio > 1;\n const both_low = in_ratio < 1 && out_ratio < 1;\n\n return (\n
    \n \n\n \n
    \n
    \n

    \n Conversion\n

    \n
    \n \n {\n setSection(\"detail\");\n }}\n />\n \n \n \n Details\n \n \n \n \n\n \n {\n setSection(\"cashout\");\n }}\n />\n \n \n \n Config cashout\n \n \n \n \n \n {\n setSection(\"cashin\");\n }}\n />\n \n \n \n Config cashin\n \n \n \n \n
    \n
    \n\n {\n e.preventDefault();\n }}\n >\n {section == \"cashin\" && (\n \n )}\n\n {section == \"cashout\" && (\n \n \n \n )}\n\n {section == \"detail\" && (\n \n
    \n
    \n
    \n Cashin\n
    \n
    \n \n
    \n
    \n
    \n\n
    \n
    \n
    \n Cashout\n
    \n
    \n \n
    \n
    \n
    \n\n {both_low || both_high ? (\n
    \n \n \n One of the ratios should be higher or equal than 1 an\n the other should be lower or equal than 1.\n \n \n
    \n ) : undefined}\n\n
    \n
    \n
    \n {i18n.str`Initial amount`}\n \n \n

    \n \n Use it to test how the conversion will affect the\n amount.\n \n

    \n
    \n
    \n
    \n\n {!cashoutCalc || !cashinCalc ? undefined : (\n
    \n
    \n
    \n
    \n
    \n \n Sending to this bank\n \n
    \n
    \n \n
    \n
    \n\n {Amounts.isZero(cashinCalc.beforeFee) ? undefined : (\n
    \n
    \n \n Converted\n \n
    \n
    \n \n
    \n
    \n )}\n
    \n
    \n Cashin after fee\n
    \n
    \n \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n \n Sending from this bank\n \n
    \n
    \n \n
    \n
    \n\n {Amounts.isZero(cashoutCalc.beforeFee) ? undefined : (\n
    \n
    \n \n Converted\n \n
    \n
    \n \n
    \n
    \n )}\n
    \n
    \n Cashout after fee\n
    \n
    \n \n
    \n
    \n
    \n
    \n\n {cashoutCalc &&\n status.status === \"ok\" &&\n Amounts.cmp(status.result.amount, cashoutCalc.credit) <\n 0 ? (\n
    \n \n \n This configuration allows users to cash out more of\n what has been cashed in.\n \n \n
    \n ) : undefined}\n
    \n )}\n
    \n )}\n\n
    \n \n Cancel\n \n {section == \"cashin\" || section == \"cashout\" ? (\n \n Update\n \n ) : (\n
    \n )}\n
    \n \n
    \n
    \n );\n };\n}\n\nexport const ConversionConfig = utils.recursive(useComponentState);\n\n/**\n *\n * @param i18n\n * @param regional\n * @param fiat\n * @returns form validator\n */\nfunction createFormValidator(\n i18n: InternationalizationAPI,\n regional: string,\n fiat: string,\n) {\n return function check(state: FormValues): FormStatus {\n const cashin_min_amount = Amounts.parse(\n `${fiat}:${state.conv.cashin_min_amount}`,\n );\n const cashin_tiny_amount = Amounts.parse(\n `${regional}:${state.conv.cashin_tiny_amount}`,\n );\n const cashin_fee = Amounts.parse(`${regional}:${state.conv.cashin_fee}`);\n\n const cashout_min_amount = Amounts.parse(\n `${regional}:${state.conv.cashout_min_amount}`,\n );\n const cashout_tiny_amount = Amounts.parse(\n `${fiat}:${state.conv.cashout_tiny_amount}`,\n );\n const cashout_fee = Amounts.parse(`${fiat}:${state.conv.cashout_fee}`);\n\n const am = Amounts.parse(`${fiat}:${state.amount}`);\n\n const cashin_ratio = Number.parseFloat(state.conv.cashin_ratio ?? \"\");\n const cashout_ratio = Number.parseFloat(state.conv.cashout_ratio ?? \"\");\n\n const errors = undefinedIfEmpty>({\n conv: undefinedIfEmpty>({\n cashin_min_amount: !state.conv.cashin_min_amount\n ? i18n.str`Required`\n : !cashin_min_amount\n ? i18n.str`Invalid`\n : undefined,\n cashin_fee: !state.conv.cashin_fee\n ? i18n.str`Required`\n : !cashin_fee\n ? i18n.str`Invalid`\n : undefined,\n\n cashout_min_amount: !state.conv.cashout_min_amount\n ? i18n.str`Required`\n : !cashout_min_amount\n ? i18n.str`Invalid`\n : undefined,\n cashout_fee: !state.conv.cashin_fee\n ? i18n.str`Required`\n : !cashout_fee\n ? i18n.str`Invalid`\n : undefined,\n\n cashin_rounding_mode: !state.conv.cashin_rounding_mode\n ? i18n.str`Required`\n : undefined,\n cashout_rounding_mode: !state.conv.cashout_rounding_mode\n ? i18n.str`Required`\n : undefined,\n\n cashin_ratio: !state.conv.cashin_ratio\n ? i18n.str`Required`\n : Number.isNaN(cashin_ratio)\n ? i18n.str`Invalid`\n : undefined,\n cashout_ratio: !state.conv.cashout_ratio\n ? i18n.str`Required`\n : Number.isNaN(cashout_ratio)\n ? i18n.str`Rnvalid`\n : undefined,\n\n cashin_tiny_amount: !state.conv.cashin_tiny_amount\n ? i18n.str`Required`\n : !cashin_tiny_amount\n ? i18n.str`Invalid`\n : +state.conv.cashin_tiny_amount == 0\n ? i18n.str`Must be > 0`\n : undefined,\n cashout_tiny_amount: !state.conv.cashout_tiny_amount\n ? i18n.str`Required`\n : !cashout_tiny_amount\n ? i18n.str`Invalid`\n : +state.conv.cashout_tiny_amount == 0\n ? i18n.str`Must be > 0`\n : undefined,\n }),\n\n amount: !state.amount\n ? i18n.str`Required`\n : !am\n ? i18n.str`Invalid`\n : undefined,\n });\n\n const result: RecursivePartial = {\n amount: am,\n conv: {\n cashin_fee: !errors?.conv?.cashin_fee\n ? Amounts.stringify(cashin_fee!)\n : undefined,\n cashin_min_amount: !errors?.conv?.cashin_min_amount\n ? Amounts.stringify(cashin_min_amount!)\n : undefined,\n cashin_tiny_amount: !errors?.conv?.cashin_tiny_amount\n ? Amounts.stringify(cashin_tiny_amount!)\n : undefined,\n cashin_ratio: !errors?.conv?.cashin_ratio\n ? String(cashin_ratio!)\n : undefined,\n cashin_rounding_mode: !errors?.conv?.cashin_rounding_mode\n ? state.conv.cashin_rounding_mode!\n : undefined,\n cashout_fee: !errors?.conv?.cashout_fee\n ? Amounts.stringify(cashout_fee!)\n : undefined,\n cashout_min_amount: !errors?.conv?.cashout_min_amount\n ? Amounts.stringify(cashout_min_amount!)\n : undefined,\n cashout_tiny_amount: !errors?.conv?.cashout_tiny_amount\n ? Amounts.stringify(cashout_tiny_amount!)\n : undefined,\n cashout_ratio: !errors?.conv?.cashout_ratio\n ? String(cashout_ratio!)\n : undefined,\n cashout_rounding_mode: !errors?.conv?.cashout_rounding_mode\n ? state.conv.cashout_rounding_mode!\n : undefined,\n },\n };\n return errors === undefined\n ? { status: \"ok\", result: result as FormType, errors }\n : { status: \"fail\", result, errors };\n };\n}\n\nexport function ConversionForm({\n id,\n inputCurrency,\n outputCurrency,\n fee,\n minimum,\n ratio,\n rounding,\n tiny,\n fallback_fee,\n fallback_minimum,\n fallback_ratio,\n fallback_rounding,\n fallback_tiny,\n}: {\n inputCurrency: string;\n outputCurrency: string;\n minimum: UIField | undefined;\n fallback_minimum?: string;\n fee: UIField | undefined;\n fallback_fee?: string;\n rounding: UIField | undefined;\n fallback_rounding?: string;\n tiny: UIField | undefined;\n fallback_tiny?: string;\n ratio: UIField | undefined;\n fallback_ratio?: string;\n id: string;\n}): VNode {\n const { i18n } = useTranslationContext();\n return (\n \n
    \n
    \n
    \n {i18n.str`Minimum amount`}\n \n \n

    \n \n Only cashout operation above this threshold will be allowed.\n \n  \n

    \n
    \n
    \n
    \n\n
    \n \n {i18n.str`Ratio`}\n \n
    \n {\n ratio?.onUpdate(e.currentTarget.value);\n }}\n autocomplete=\"off\"\n placeholder={fallback_ratio ?? \"1.0\"}\n />\n \n
    \n

    \n Conversion ratio between currencies\n

    \n
    \n\n
    \n \n \n 1 {inputCurrency} will be converted into{\" \"}\n {ratio?.value ?? fallback_ratio} {outputCurrency}\n \n \n
    \n\n
    \n
    \n
    \n \n {i18n.str`Tiny amount`}\n \n \n \n
    \n
    \n
    \n\n
    \n
    \n
    \n \n {i18n.str`Rounding mode`}\n \n
    \n
    \n {\n e.preventDefault();\n rounding?.onUpdate(\"zero\");\n }}\n data-selected={rounding?.value === \"zero\"}\n class=\"relative flex data-[disabled=false]:cursor-pointer rounded-lg border bg-white data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600\"\n >\n \n \n \n \n Zero\n \n \n Amount will be round below to the largest possible value\n smaller than the input.\n \n \n \n \n \n \n \n\n {\n e.preventDefault();\n rounding?.onUpdate(\"up\");\n }}\n data-selected={rounding?.value === \"up\"}\n class=\"relative flex data-[disabled=false]:cursor-pointer rounded-lg border data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600\"\n >\n \n \n \n \n Up\n \n \n Amount will be round up to the smallest possible value\n larger than the input.\n \n \n \n \n \n \n \n {\n e.preventDefault();\n rounding?.onUpdate(\"nearest\");\n }}\n data-selected={rounding?.value === \"nearest\"}\n class=\"relative flex data-[disabled=false]:cursor-pointer rounded-lg border data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600\"\n >\n \n \n \n \n Nearest\n \n \n Amount will be round to the closest possible value.\n \n \n \n \n \n \n \n
    \n {!fallback_rounding ? undefined : (\n

    \n \n If none specified the fallback value is \"{fallback_rounding}\n \".\n \n

    \n )}\n
    \n
    \n
    \n
    \n\n
    \n \n
    \n
    \n \n \n Rounding an amount of 1.24 with rounding value 0.1\n \n \n \n \n \n

    \n \n Given the rounding value of 0.1 the possible values closest to\n 1.24 are: 1.1, 1.2, 1.3, 1.4.\n \n

    \n

    \n \n With the \"zero\" mode the value will be rounded to 1.2\n \n

    \n

    \n \n With the \"nearest\" mode the value will be rounded to 1.2\n \n

    \n

    \n \n With the \"up\" mode the value will be rounded to 1.3\n \n

    \n
    \n
    \n \n \n Rounding an amount of 1.26 with rounding value 0.1\n \n \n \n \n \n

    \n \n Given the rounding value of 0.1 the possible values closest to\n 1.24 are: 1.1, 1.2, 1.3, 1.4.\n \n

    \n

    \n \n With the \"zero\" mode the value will be rounded to 1.2\n \n

    \n

    \n \n With the \"nearest\" mode the value will be rounded to 1.3\n \n

    \n

    \n \n With the \"up\" mode the value will be rounded to 1.3\n \n

    \n
    \n
    \n \n \n Rounding an amount of 1.24 with rounding value 0.3\n \n \n \n \n \n

    \n \n Given the rounding value of 0.3 the possible values closest to\n 1.24 are: 0.9, 1.2, 1.5, 1.8.\n \n

    \n

    \n \n With the \"zero\" mode the value will be rounded to 1.2\n \n

    \n

    \n \n With the \"nearest\" mode the value will be rounded to 1.2\n \n

    \n

    \n \n With the \"up\" mode the value will be rounded to 1.5\n \n

    \n
    \n
    \n \n \n Rounding an amount of 1.26 with rounding value 0.3\n \n \n \n \n \n

    \n \n Given the rounding value of 0.3 the possible values closest to\n 1.24 are: 0.9, 1.2, 1.5, 1.8.\n \n

    \n

    \n \n With the \"zero\" mode the value will be rounded to 1.2\n \n

    \n

    \n \n With the \"nearest\" mode the value will be rounded to 1.3\n \n

    \n

    \n \n With the \"up\" mode the value will be rounded to 1.3\n \n .0\n

    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n {i18n.str`Fee`}\n \n \n

    \n \n Amount to be deducted before amount is credited.\n \n

    \n
    \n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport { assertUnreachable } from \"@gnu-taler/taler-util\";\nimport {\n useNavigationContext,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useBankCoreApiContext } from \"@gnu-taler/web-util/browser\";\nimport { useSessionState } from \"../hooks/session.js\";\nimport { RouteDefinition } from \"@gnu-taler/web-util/browser\";\n\nconst TALER_SCREEN_ID = 107;\n\nexport function ProfileNavigation({\n current,\n routeMyAccountCashout,\n routeMyAccountDelete,\n routeMyAccountDetails,\n routeMyAccountPassword,\n routeConversionConfig,\n}: {\n current: \"details\" | \"delete\" | \"credentials\" | \"cashouts\" | \"conversion\";\n routeMyAccountDetails: RouteDefinition;\n routeMyAccountDelete: RouteDefinition;\n routeMyAccountPassword: RouteDefinition;\n routeMyAccountCashout: RouteDefinition;\n routeConversionConfig: RouteDefinition;\n}): VNode {\n const { i18n } = useTranslationContext();\n const { config } = useBankCoreApiContext();\n const { state: credentials } = useSessionState();\n const isAdminUser =\n credentials.status !== \"loggedIn\" ? false : credentials.isUserAdministrator;\n const nonAdminUser = !isAdminUser;\n\n const { navigateTo } = useNavigationContext();\n return (\n
    \n
    \n \n {\n const op = e.currentTarget.value as typeof current;\n switch (op) {\n case \"details\": {\n navigateTo(routeMyAccountDetails.url({}));\n return;\n }\n case \"delete\": {\n navigateTo(routeMyAccountDelete.url({}));\n return;\n }\n case \"credentials\": {\n navigateTo(routeMyAccountPassword.url({}));\n return;\n }\n case \"cashouts\": {\n navigateTo(routeMyAccountCashout.url({}));\n return;\n }\n case \"conversion\": {\n navigateTo(routeConversionConfig.url({}));\n return;\n }\n default:\n assertUnreachable(op);\n }\n }}\n >\n \n {!config.allow_deletions ? undefined : (\n \n )}\n \n {config.allow_conversion ? (\n \n \n \n \n ) : undefined}\n \n
    \n
    \n \n \n \n Details\n \n \n \n {!config.allow_deletions ? undefined : (\n \n \n Delete\n \n \n \n )}\n \n \n Credentials\n \n \n \n {config.allow_conversion && nonAdminUser ? (\n \n \n Cashouts\n \n \n \n ) : undefined}\n {config.allow_conversion && isAdminUser ? (\n \n \n Conversion\n \n \n \n ) : undefined}\n \n
    \n
    \n );\n}\n", "import {\n AccessToken,\n assertUnreachable,\n HttpStatusCode,\n TalerCorebankApi,\n TalerErrorCode,\n} from \"@gnu-taler/taler-util\";\nimport {\n ButtonBetter,\n LocalNotificationBanner,\n notifyInfo,\n RouteDefinition,\n useBankCoreApiContext,\n useLocalNotificationBetter,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { h, VNode } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { useSessionState } from \"../hooks/session.js\";\nimport { ConversionRateClassForm } from \"./admin/ConversionRateClassForm.js\";\n\nconst TALER_SCREEN_ID = 13;\ninterface Props {\n routeCancel: RouteDefinition;\n onCreated: (id: number) => void;\n}\nexport function NewConversionRateClass({\n routeCancel,\n onCreated,\n}: Props): VNode {\n const { i18n } = useTranslationContext();\n const { state: credentials } = useSessionState();\n const token =\n credentials.status !== \"loggedIn\" ? undefined : credentials.token;\n const {\n lib: { bank: api },\n } = useBankCoreApiContext();\n\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const [submitData, setSubmitData] = useState<\n TalerCorebankApi.ConversionRateClassInput | undefined\n >();\n\n const create = safeFunctionHandler(\n i18n.str`create conversion rate class`,\n (token: AccessToken, data: TalerCorebankApi.ConversionRateClassInput) =>\n api.createConversionRateClass(token, data),\n !submitData || !token ? undefined : [token, submitData],\n );\n create.onSuccess = (success) => {\n notifyInfo(i18n.str`Conversion rate class created.`);\n onCreated(success.conversion_rate_class_id);\n };\n create.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Unauthorized:\n return i18n.str`The rights to change the account are not sufficient`;\n case HttpStatusCode.Forbidden:\n return i18n.str`Wrong credentials`;\n case HttpStatusCode.NotFound:\n return i18n.str`Account not found`;\n case HttpStatusCode.NotImplemented:\n return i18n.str`Not implemented`;\n case TalerErrorCode.BANK_NAME_REUSE:\n return i18n.str`The name of the conversion is already used.`;\n default:\n assertUnreachable(fail);\n }\n };\n\n return (\n
    \n \n\n
    \n

    \n New conversion rate class\n

    \n
    \n\n \n
    \n \n Cancel\n \n \n Create\n \n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n DecimalNumber,\n RoundingMode,\n TalerCorebankApi,\n} from \"@gnu-taler/taler-util\";\nimport {\n ShowInputErrorLabel,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { ComponentChildren, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport { ErrorMessageMappingFor, undefinedIfEmpty } from \"../../utils.js\";\nimport { doAutoFocus } from \"../PaytoWireTransferForm.js\";\n\nconst TALER_SCREEN_ID = 129;\n\nexport type ConversionRateClassFormData = {\n name?: string;\n description?: string;\n\n cashin_enabled?: boolean;\n cashin_min_amount?: string;\n cashin_ratio?: string;\n cashin_fee?: string;\n cashin_rounding_mode?: RoundingMode;\n\n cashout_enabled?: boolean;\n cashout_min_amount?: string;\n cashout_ratio?: DecimalNumber;\n cashout_fee?: string;\n cashout_rounding_mode?: RoundingMode;\n};\n\n// type ChangeByPurposeType = {\n// create: (a: TalerCorebankApi.ConversionRateClassInput | undefined) => void;\n// update: (a: TalerCorebankApi.ConversionRateClassInput | undefined) => void;\n// show: undefined;\n// };\n/**\n *\n * @param param0\n * @returns\n */\nexport function ConversionRateClassForm(\n // <\n // PurposeType extends keyof ChangeByPurposeType,\n // >\n {\n onChange,\n focus,\n children,\n }: {\n focus?: boolean;\n children: ComponentChildren;\n // onChange: ChangeByPurposeType[PurposeType];\n onChange: (\n a: TalerCorebankApi.ConversionRateClassInput | undefined,\n ) => void;\n },\n): VNode {\n // const { config, url } = useBankCoreApiContext();\n const { i18n } = useTranslationContext();\n const { state: credentials } = useSessionState();\n const [form, setForm] = useState({});\n\n const [errors, setErrors] = useState<\n ErrorMessageMappingFor | undefined\n >(undefined);\n\n // const defaultValue: ConversionRateClassFormData = {\n // // cashin_fee: Amounts.stringifyValue(\n // // template?.cashin_fee ?? `${config.currency}:0`,\n // // ),\n // // cashin_min_amount: Amounts.stringifyValue(\n // // template?.cashin_min_amount ?? `${config.currency}:0`,\n // // ),\n // // cashout_fee: Amounts.stringifyValue(\n // // template?.cashout_fee ?? `${config.currency}:0`,\n // // ),\n // // cashin_ratio: template?.cashin_ratio ?? \"0\",\n // // cashin_rounding_mode: template?.cashin_rounding_mode,\n\n // // cashout_min_amount: Amounts.stringifyValue(\n // // template?.cashout_min_amount ?? `${config.currency}:0`,\n // // ),\n // // cashout_ratio: template?.cashout_ratio ?? \"0\",\n // // cashout_rounding_mode: template?.cashout_rounding_mode,\n\n // // cashin_enabled:\n // // template?.cashin_ratio !== undefined &&\n // // Number.parseInt(template.cashin_ratio, 10) > 0,\n\n // // cashout_enabled:\n // // template?.cashout_ratio !== undefined &&\n // // Number.parseInt(template.cashout_ratio, 10) > 0,\n\n // name: template?.name,\n // description: template?.description,\n // };\n\n const userIsAdmin =\n credentials.status !== \"loggedIn\" ? false : credentials.isUserAdministrator;\n\n const editableForm = userIsAdmin;\n\n function updateForm(newForm: ConversionRateClassFormData): void {\n const errors = undefinedIfEmpty<\n ErrorMessageMappingFor\n >({\n name: !editableForm\n ? undefined // disabled\n : !newForm.name\n ? i18n.str`Required`\n : undefined,\n // cashin_fee:\n // !editableForm || !newForm.cashin_enabled\n // ? undefined\n // : !newForm.cashin_fee\n // ? i18n.str`Required`\n // : undefined,\n // cashout_fee:\n // !editableForm || !newForm.cashout_fee\n // ? undefined\n // : !newForm.cashout_fee\n // ? i18n.str`Required`\n // : undefined,\n // cashin_min_amount:\n // !editableForm || !newForm.cashin_min_amount\n // ? undefined\n // : !newForm.cashin_min_amount\n // ? i18n.str`Required`\n // : undefined,\n // cashout_min_amount:\n // !editableForm || !newForm.cashout_min_amount\n // ? undefined\n // : !newForm.cashout_min_amount\n // ? i18n.str`Required`\n // : undefined,\n });\n setErrors(errors);\n\n setForm(newForm);\n if (!onChange) return;\n\n if (errors) {\n onChange(undefined);\n } else {\n const result: TalerCorebankApi.ConversionRateClassInput = {\n name: newForm.name!,\n description: newForm.description,\n };\n onChange(result);\n // switch (purpose) {\n // case \"create\": {\n // // typescript doesn't correctly narrow a generic type\n // const callback = onChange as ChangeByPurposeType[\"create\"];\n // const result: TalerCorebankApi.ConversionRateClassInput = {\n // name: newForm.name!,\n // description: newForm.description,\n // };\n // callback(result);\n // return;\n // }\n // case \"update\": {\n // // typescript doesn't correctly narrow a generic type\n // const callback = onChange as ChangeByPurposeType[\"update\"];\n\n // const result: TalerCorebankApi.ConversionRateClassInput = {\n // name: newForm.name!,\n // };\n // callback(result);\n // return;\n // }\n // case \"show\": {\n // return;\n // }\n // default: {\n // assertUnreachable(purpose);\n // }\n // }\n }\n }\n return (\n {\n e.preventDefault();\n }}\n >\n
    \n
    \n
    \n \n {i18n.str`Name`}\n {editableForm && *}\n \n
    \n {\n form.name = e.currentTarget.value;\n updateForm(structuredClone(form));\n }}\n // placeholder=\"\"\n autocomplete=\"off\"\n />\n \n
    \n

    \n Conversion rate name\n

    \n
    \n\n
    \n \n {i18n.str`Description`}\n \n
    \n {\n form.description = e.currentTarget.value;\n updateForm(structuredClone(form));\n }}\n // placeholder=\"\"\n autocomplete=\"off\"\n />\n \n
    \n

    \n Short description of the class\n

    \n
    \n\n {/* \n */}\n\n {/* {!form.cashin_enabled ? undefined : (\n \n
    \n \n {i18n.str`Cashin rounding mode`}\n \n
    \n
    \n {([\"nearest\", \"zero\", \"up\"] as Array).map(\n (ROUNDING_MODE) => {\n let LABEL: TranslatedString;\n switch (ROUNDING_MODE) {\n case \"zero\": {\n LABEL = i18n.str`To zero`;\n break;\n }\n case \"up\": {\n LABEL = i18n.str`Round up`;\n break;\n }\n case \"nearest\": {\n LABEL = i18n.str`To nearest int`;\n break;\n }\n default: {\n assertUnreachable(ROUNDING_MODE);\n }\n }\n return (\n {\n form.cashin_rounding_mode = ROUNDING_MODE;\n updateForm(structuredClone(form));\n e.preventDefault();\n }}\n data-disabled={purpose === \"show\"}\n data-selected={\n (form.cashin_rounding_mode ??\n defaultValue.cashin_rounding_mode) ===\n ROUNDING_MODE\n }\n class=\"relative flex data-[disabled=false]:cursor-pointer rounded-lg border bg-white data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600\"\n >\n \n \n \n \n {LABEL}\n \n \n \n \n \n \n \n );\n },\n )}\n
    \n
    \n
    \n\n
    \n {i18n.str`Cashin fee`}\n {\n form.cashin_fee = e as AmountString;\n updateForm(structuredClone(form));\n }\n }\n />\n \n

    \n FIXME.\n

    \n
    \n\n
    \n {i18n.str`Cashin min amount`}\n {\n form.cashin_min_amount = e as AmountString;\n updateForm(structuredClone(form));\n }\n }\n />\n \n

    \n FIXME.\n

    \n
    \n
    \n )}\n\n {!form.cashout_enabled ? undefined : (\n \n
    \n \n {i18n.str`Cashout rounding mode`}\n \n
    \n
    \n {([\"nearest\", \"zero\", \"up\"] as Array).map(\n (ROUNDING_MODE) => {\n let LABEL: TranslatedString;\n switch (ROUNDING_MODE) {\n case \"zero\": {\n LABEL = i18n.str`To zero`;\n break;\n }\n case \"up\": {\n LABEL = i18n.str`Round up`;\n break;\n }\n case \"nearest\": {\n LABEL = i18n.str`To nearest int`;\n break;\n }\n default: {\n assertUnreachable(ROUNDING_MODE);\n }\n }\n return (\n {\n form.cashout_rounding_mode = ROUNDING_MODE;\n updateForm(structuredClone(form));\n e.preventDefault();\n }}\n data-disabled={purpose === \"show\"}\n data-selected={\n (form.cashout_rounding_mode ??\n defaultValue.cashout_rounding_mode) ===\n ROUNDING_MODE\n }\n class=\"relative flex data-[disabled=false]:cursor-pointer rounded-lg border bg-white data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600\"\n >\n \n \n \n \n {LABEL}\n \n \n \n \n \n \n \n );\n },\n )}\n
    \n
    \n
    \n\n
    \n {i18n.str`Cashout min amount`}\n {\n form.cashout_min_amount = e as AmountString;\n updateForm(structuredClone(form));\n }\n }\n />\n \n

    \n FIXME.\n

    \n
    \n
    \n {i18n.str`Cashout fee`}\n {\n form.cashout_fee = e as AmountString;\n updateForm(structuredClone(form));\n }\n }\n />\n \n

    \n FIXME.\n

    \n
    \n
    \n )} */}\n
    \n
    \n {children}\n \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TalerError } from \"@gnu-taler/taler-util\";\nimport { Loading, useTranslationContext } from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { Transactions } from \"../components/Transactions/index.js\";\nimport { usePublicAccounts } from \"../hooks/account.js\";\n\nconst TALER_SCREEN_ID = 108;\n\n/**\n * Show histories of public accounts.\n */\nexport function PublicHistoriesPage(): VNode {\n const { i18n } = useTranslationContext();\n\n // TODO: implemented filter by account name\n const result = usePublicAccounts(undefined);\n const firstAccount =\n result && !(result instanceof TalerError) && result.body.length > 0\n ? result.body[0].username\n : undefined;\n\n const [showAccount, setShowAccount] = useState(firstAccount);\n\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return ;\n }\n\n const { body: accountList } = result;\n\n const txs: Record = {};\n const accountsBar = [];\n\n // Ask story of all the public accounts.\n for (const account of accountList) {\n const isSelected = account.username == showAccount;\n accountsBar.push(\n \n setShowAccount(account.username)}\n >\n {account.username}\n \n ,\n );\n txs[account.username] = (\n \n );\n }\n\n return (\n \n

    {i18n.str`History of public accounts`}

    \n
    \n
    \n
    \n
      {accountsBar}
    \n {typeof showAccount !== \"undefined\" ? (\n txs[showAccount]\n ) : (\n

    No public transactions found.

    \n )}\n
    \n
    \n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { Time, useNotifications } from \"@gnu-taler/web-util/browser\";\nimport { VNode, h } from \"preact\";\n\nexport function ShowNotifications(): VNode {\n const ns = useNotifications();\n if (!ns.length) {\n return
    no notifications
    ;\n }\n return (\n
    \n

    Notifications

    \n \n \n \n {ns.map((n, idx) => {\n return (\n \n \n \n \n \n );\n })}\n \n
    \n \n {n.message.title}\n {n.message.type === \"error\"\n ? n.message.description\n : undefined}\n
    \n {/* */}\n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n Amounts,\n HttpStatusCode,\n TalerError,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n ErrorLoading,\n Loading,\n notifyInfo,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\n\nimport { useAccountDetails } from \"../hooks/account.js\";\nimport { useSessionState } from \"../hooks/session.js\";\nimport { LoginForm } from \"./LoginForm.js\";\nimport { PaytoWireTransferForm } from \"./PaytoWireTransferForm.js\";\nimport { RouteDefinition } from \"@gnu-taler/web-util/browser\";\nimport { IntAmounts } from \"./regional/CreateCashout.js\";\n\nconst TALER_SCREEN_ID = 113;\n\nexport function WireTransfer({\n toAccount,\n withSubject,\n withAmount,\n\n routeCancel,\n onSuccess,\n}: {\n onSuccess?: () => void;\n toAccount?: string;\n withSubject?: string;\n withAmount?: string;\n routeCancel?: RouteDefinition;\n}): VNode {\n const { i18n } = useTranslationContext();\n const r = useSessionState();\n const account = r.state.status !== \"loggedOut\" ? r.state.username : \"admin\";\n const result = useAccountDetails(account);\n\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return (\n \n \n \n \n );\n }\n if (result.type === \"fail\") {\n switch (result.case) {\n case HttpStatusCode.Unauthorized:\n return ;\n case HttpStatusCode.NotFound:\n return ;\n default:\n assertUnreachable(result);\n }\n }\n const { body: data } = result;\n\n const balanceAbs = Amounts.parseOrThrow(data.balance.amount);\n const isBalanceNegative = data.balance.credit_debit_indicator == \"debit\";\n const debitThreshold = Amounts.parseOrThrow(data.debit_threshold);\n\n const balance = IntAmounts.toIntAmount(balanceAbs, isBalanceNegative);\n const limit = balance.increment(debitThreshold).result;\n\n const positiveBalance = balance.getResultZeroIfNegative();\n\n return (\n
    \n
    \n
    \n

    \n Make a wire transfer\n

    \n
    \n
    \n\n {\n notifyInfo(i18n.str`The wire transfer was successfully completed!`);\n if (onSuccess) onSuccess();\n }}\n routeCancel={routeCancel}\n />\n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { Attention, useTranslationContext } from \"@gnu-taler/web-util/browser\";\nimport { VNode, h } from \"preact\";\nimport { useBankCoreApiContext } from \"@gnu-taler/web-util/browser\";\nimport { useBankState } from \"../hooks/bank-state.js\";\nimport { RouteDefinition } from \"@gnu-taler/web-util/browser\";\nimport { WithdrawalQRCode } from \"./WithdrawalQRCode.js\";\nimport { HostPortPath } from \"@gnu-taler/taler-util\";\nimport { TalerUris } from \"@gnu-taler/taler-util\";\n\nconst TALER_SCREEN_ID = 115;\n\nexport function WithdrawalOperationPage({\n operationId,\n onOperationAborted,\n routeClose,\n origin,\n}: {\n operationId: string;\n origin: \"from-bank-ui\" | \"from-wallet-ui\";\n onOperationAborted: () => void;\n routeClose: RouteDefinition;\n}): VNode {\n const {\n lib: { bank: api },\n } = useBankCoreApiContext();\n const parsedUri = TalerUris.createTalerWithdraw(\n api.getIntegrationAPI().href as HostPortPath,\n operationId,\n );\n const uri = TalerUris.toString(parsedUri);\n const { i18n } = useTranslationContext();\n const [, updateBankState] = useBankState();\n\n if (!parsedUri) {\n return (\n \n {uri}\n \n );\n }\n\n return (\n {\n updateBankState(\"currentWithdrawalOperationId\", undefined);\n onOperationAborted();\n }}\n routeClose={routeClose}\n />\n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n Amounts,\n HttpStatusCode,\n TalerError,\n WithdrawUriResult,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ErrorLoading,\n Loading,\n RouteDefinition,\n notifyInfo,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { VNode, h } from \"preact\";\n\nimport { Paytos, TalerUris } from \"@gnu-taler/taler-util\";\nimport { useWithdrawalDetails } from \"../hooks/account.js\";\nimport { QrCodeSection } from \"./QrCodeSection.js\";\nimport { WithdrawalConfirmationQuestion } from \"./WithdrawalConfirmationQuestion.js\";\n\nconst TALER_SCREEN_ID = 116;\n\ninterface Props {\n withdrawUri: WithdrawUriResult;\n origin: \"from-bank-ui\" | \"from-wallet-ui\";\n onOperationAborted: () => void;\n routeClose: RouteDefinition;\n}\n/**\n * Offer the QR code (and a clickable taler://-link) to\n * permit the passing of exchange and reserve details to\n * the bank. Poll the backend until such operation is done.\n */\nexport function WithdrawalQRCode({\n withdrawUri,\n onOperationAborted,\n routeClose,\n origin,\n}: Props): VNode {\n const { i18n } = useTranslationContext();\n const result = useWithdrawalDetails(withdrawUri.withdrawalOperationId);\n\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return ;\n }\n if (result.type === \"fail\") {\n switch (result.case) {\n case HttpStatusCode.BadRequest:\n case HttpStatusCode.NotFound:\n return ;\n default:\n assertUnreachable(result);\n }\n }\n\n const { body: data } = result;\n\n if (data.status === \"aborted\") {\n return (\n
    \n
    \n
    \n \n \n \n
    \n
    \n \n Operation aborted\n \n
    \n

    \n \n The wire transfer to the Payment Service Provider's account\n was aborted from somewhere else, your balance was not\n affected.\n \n

    \n
    \n
    \n
    \n
    \n \n Continue\n \n
    \n
    \n );\n }\n const talerWithdrawUri = TalerUris.toString(withdrawUri);\n\n if (data.status === \"confirmed\") {\n return (\n
    \n
    \n
    \n \n \n \n
    \n
    \n \n Withdrawal confirmed\n \n
    \n

    \n \n The wire transfer to the Payment Service Provider has been\n initiated. You will shortly receive the requested amount in\n your Taler wallet.{\" \"}\n \n

    \n
    \n
    \n
    \n
    \n \n Close\n \n {origin === \"from-wallet-ui\" && false ? (\n \n Go to your wallet now\n \n ) : undefined}\n
    \n
    \n );\n }\n\n if (data.status === \"pending\") {\n return (\n {\n notifyInfo(i18n.str`Operation aborted`);\n onOperationAborted();\n }}\n />\n );\n }\n\n const account = !data.selected_exchange_account\n ? undefined\n : Paytos.fromString(data.selected_exchange_account);\n\n if (!account || account.tag === \"error\") {\n if (!data.selected_reserve_pub) {\n return (\n \n \n A withdrawal reserve ID was not found and no account has been\n selected.\n \n \n );\n }\n return (\n \n \n There is a withdrawal reserve ID but no account has been selected or\n the selected account is invalid.\n \n \n );\n }\n\n if (!data.selected_reserve_pub) {\n return (\n \n \n The account was selected, but no withdrawal reserve ID was found.\n \n \n );\n }\n\n return (\n \n );\n}\n\nexport function OperationNotFound({\n routeClose,\n}: {\n routeClose: RouteDefinition | undefined;\n}): VNode {\n const { i18n } = useTranslationContext();\n return (\n
    \n
    \n
    \n \n \n \n
    \n\n
    \n \n Operation not found\n \n
    \n

    \n \n This process is not known to the server. The process ID is\n incorrect or the server has deleted the process information\n before it arrived here.\n \n

    \n
    \n
    \n
    \n {routeClose && (\n
    \n \n Continue to dashboard\n \n
    \n )}\n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n assertUnreachable,\n HttpStatusCode,\n TalerUris,\n WithdrawUriResult,\n} from \"@gnu-taler/taler-util\";\nimport {\n Button,\n ButtonBetter,\n LocalNotificationBanner,\n useBankCoreApiContext,\n useLocalNotificationBetter,\n useTalerWalletIntegrationAPI,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, h, VNode } from \"preact\";\nimport { useEffect } from \"preact/hooks\";\nimport { QR } from \"../components/QR.js\";\nimport { useSessionState } from \"../hooks/session.js\";\nimport { UserAndToken } from \"@gnu-taler/taler-util\";\n\nconst TALER_SCREEN_ID = 109;\n\nexport function QrCodeSection({\n withdrawUri,\n onAborted,\n}: {\n withdrawUri: WithdrawUriResult;\n onAborted: () => void;\n}): VNode {\n const { i18n } = useTranslationContext();\n const walletInegrationApi = useTalerWalletIntegrationAPI();\n const talerWithdrawUri = TalerUris.toString(withdrawUri);\n const { state: credentials } = useSessionState();\n const creds = credentials.status !== \"loggedIn\" ? undefined : credentials;\n\n useEffect(() => {\n walletInegrationApi.publishTalerAction(withdrawUri);\n }, []);\n\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const {\n lib: { bank: api },\n } = useBankCoreApiContext();\n\n const abort = safeFunctionHandler(\n i18n.str`abort withdrawal`,\n (creds: UserAndToken) =>\n api.abortWithdrawalById(creds, withdrawUri.withdrawalOperationId),\n !creds ? undefined : [creds],\n );\n\n abort.onSuccess = onAborted;\n abort.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.BadRequest:\n return i18n.str`The operation ID is invalid.`;\n case HttpStatusCode.NotFound:\n return i18n.str`The operation was not found.`;\n case HttpStatusCode.Conflict:\n return i18n.str`The reserve operation has been confirmed previously and can't be aborted`;\n default:\n assertUnreachable(fail);\n }\n };\n\n return (\n \n \n\n
    \n
    \n

    \n \n If you have a Taler wallet installed on this device\n \n

    \n
    \n

    \n \n Your wallet will display the details of the transaction\n including the fees (if applicable). If you do not yet have a\n wallet, please follow the instructions\n {\" \"}\n \n on this page\n \n .\n

    \n
    \n
    \n \n Cancel\n \n \n Withdraw\n \n
    \n
    \n
    \n\n
    \n
    \n

    \n \n In case you have a Taler wallet on another device\n \n

    \n
    \n \n Scan the QR code below to start the withdrawal.\n \n
    \n
    \n \n
    \n
    \n
    \n \n Cancel\n \n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport { useTranslationContext } from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { Cashouts } from \"../../components/Cashouts/index.js\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport { ProfileNavigation } from \"../ProfileNavigation.js\";\nimport { CreateCashout } from \"../regional/CreateCashout.js\";\nimport { RouteDefinition } from \"@gnu-taler/web-util/browser\";\n\nconst TALER_SCREEN_ID = 117;\n\ninterface Props {\n account: string;\n routeClose: RouteDefinition;\n\n onCashout: () => void;\n routeCashoutDetails: RouteDefinition<{ cid: string }>;\n routeMyAccountDetails: RouteDefinition;\n routeMyAccountDelete: RouteDefinition;\n routeMyAccountPassword: RouteDefinition;\n routeMyAccountCashout: RouteDefinition;\n routeConversionConfig: RouteDefinition;\n}\n\nexport function CashoutListForAccount({\n account,\n\n onCashout,\n routeCashoutDetails,\n routeMyAccountCashout,\n routeMyAccountDelete,\n routeMyAccountDetails,\n routeConversionConfig,\n routeMyAccountPassword,\n routeClose,\n}: Props): VNode {\n const { i18n } = useTranslationContext();\n\n const { state: credentials } = useSessionState();\n\n const accountIsTheCurrentUser =\n credentials.status === \"loggedIn\"\n ? credentials.username === account\n : false;\n\n return (\n \n {accountIsTheCurrentUser ? (\n \n ) : (\n

    \n Cashout for account {account}\n

    \n )}\n\n \n\n \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { TalerError } from \"@gnu-taler/taler-util\";\nimport { useCashouts } from \"../../hooks/regional.js\";\nimport { Props, State } from \"./index.js\";\n\nexport function useComponentState({\n account,\n routeCashoutDetails,\n}: Props): State {\n const result = useCashouts(account);\n if (!result) {\n return {\n status: \"loading\",\n error: undefined,\n };\n }\n if (result instanceof TalerError) {\n return {\n status: \"loading-error\",\n error: result,\n };\n }\n if (result.type === \"fail\") {\n return {\n status: \"failed\",\n error: result,\n };\n }\n\n return {\n status: \"ready\",\n error: undefined,\n cashouts: result.body.cashouts,\n routeCashoutDetails,\n };\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AbsoluteTime,\n Amounts,\n HttpStatusCode,\n TalerError,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ErrorLoading,\n Loading,\n RenderAmount,\n Time,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { format } from \"date-fns\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { State } from \"./index.js\";\nimport { useConversionInfo } from \"../../hooks/regional.js\";\n\nconst TALER_SCREEN_ID = 3;\n\nexport function FailedView({ error }: State.Failed) {\n const { i18n } = useTranslationContext();\n switch (error.case) {\n case HttpStatusCode.NotImplemented: {\n return (\n \n \n Cashout should be enable by configuration and the conversion rate\n should be initialized with fee, ratio and rounding mode.\n \n \n );\n }\n default:\n assertUnreachable(error.case);\n }\n}\n\nexport function ReadyView({\n cashouts,\n routeCashoutDetails,\n}: State.Ready): VNode {\n const { i18n, dateLocale } = useTranslationContext();\n\n if (!cashouts.length) return
    ;\n const txByDate = cashouts.reduce(\n (prev, cur) => {\n const d =\n cur.creation_time.t_s === \"never\"\n ? \"\"\n : format(cur.creation_time.t_s * 1000, \"dd/MM/yyyy\", {\n locale: dateLocale,\n });\n if (!prev[d]) {\n prev[d] = [];\n }\n prev[d].push(cur);\n return prev;\n },\n {} as Record,\n );\n const conversionResp = useConversionInfo();\n if (!conversionResp) {\n return ;\n } else if (conversionResp instanceof TalerError) {\n return ;\n } else if (conversionResp.type === \"fail\") {\n switch (conversionResp.case) {\n case HttpStatusCode.NotImplemented: {\n return (\n \n \n Cashout should be enabled in the configuration, the conversion\n rate should be initialized with fee(s), rates and a rounding mode.\n \n \n );\n }\n default:\n assertUnreachable(conversionResp);\n }\n }\n const { fiat_currency_specification, regional_currency_specification } =\n conversionResp.body;\n\n return (\n
    \n
    \n
    \n

    \n Latest cashouts\n

    \n
    \n
    \n
    \n \n \n \n {i18n.str`Created`}\n {i18n.str`Total debit`}\n {i18n.str`Total credit`}\n {i18n.str`Subject`}\n \n \n \n {Object.entries(txByDate).map(([date, txs], idx) => {\n return (\n \n \n \n {date}\n \n \n {txs.map((item) => {\n return (\n \n \n \n \n\n \n \n );\n })}\n \n );\n })}\n \n
    \n
    \n \n
    \n
    \n \n \n \n \n {item.subject}\n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AbsoluteTime,\n AmountJson,\n TalerCoreBankErrorsByMethod,\n TalerCorebankApi,\n TalerError,\n} from \"@gnu-taler/taler-util\";\nimport {\n ErrorLoading,\n Loading,\n RouteDefinition,\n utils,\n} from \"@gnu-taler/web-util/browser\";\nimport { VNode } from \"preact\";\n\nimport { useComponentState } from \"./state.js\";\nimport { FailedView, ReadyView } from \"./views.js\";\n\nexport interface Props {\n account: string;\n routeCashoutDetails: RouteDefinition<{ cid: string }>;\n}\n\nexport type State =\n | State.Loading\n | State.Failed\n | State.LoadingUriError\n | State.Ready;\n\nexport namespace State {\n export interface Loading {\n status: \"loading\";\n error: undefined;\n }\n\n export interface LoadingUriError {\n status: \"loading-error\";\n error: TalerError;\n }\n\n export interface Failed {\n status: \"failed\";\n error: TalerCoreBankErrorsByMethod<\"getAccountCashouts\">;\n }\n\n export interface BaseInfo {\n error: undefined;\n }\n export interface Ready extends BaseInfo {\n status: \"ready\";\n error: undefined;\n cashouts: (TalerCorebankApi.CashoutStatusResponse & { id: number })[];\n routeCashoutDetails: RouteDefinition<{ cid: string }>;\n }\n}\n\nexport interface Transaction {\n negative: boolean;\n counterpart: string;\n when: AbsoluteTime;\n amount: AmountJson | undefined;\n subject: string;\n}\n\nconst viewMapping: utils.StateViewMap = {\n loading: Loading,\n \"loading-error\": ErrorLoading,\n failed: FailedView,\n ready: ReadyView,\n};\n\nexport const Cashouts: (p: Props) => VNode = utils.compose(\n (p: Props) => useComponentState(p),\n viewMapping,\n);\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n AccessToken,\n HttpStatusCode,\n TalerCorebankApi,\n TalerError,\n TalerErrorCode,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ButtonBetter,\n CopyButton,\n ErrorLoading,\n Loading,\n LocalNotificationBanner,\n RouteDefinition,\n notifyInfo,\n useBankCoreApiContext,\n useChallengeHandler,\n useLocalNotificationBetter,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\n\nimport { Paytos } from \"@gnu-taler/taler-util\";\nimport { useAccountDetails } from \"../../hooks/account.js\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport { AccountForm } from \"../admin/AccountForm.js\";\nimport { LoginForm } from \"../LoginForm.js\";\nimport { ProfileNavigation } from \"../ProfileNavigation.js\";\nimport { SolveMFAChallenges } from \"../SolveMFA.js\";\n\nconst TALER_SCREEN_ID = 118;\n\nexport function ShowAccountDetails({\n account,\n routeClose,\n onUpdateSuccess,\n\n routeMyAccountCashout,\n routeMyAccountDelete,\n routeMyAccountDetails,\n routeMyAccountPassword,\n routeConversionConfig,\n}: {\n routeClose: RouteDefinition;\n routeMyAccountDetails: RouteDefinition;\n routeMyAccountDelete: RouteDefinition;\n routeMyAccountPassword: RouteDefinition;\n routeMyAccountCashout: RouteDefinition;\n routeConversionConfig: RouteDefinition;\n onUpdateSuccess: () => void;\n\n account: string;\n}): VNode {\n const { i18n } = useTranslationContext();\n const { state: credentials } = useSessionState();\n const sessionToken =\n credentials.status !== \"loggedIn\" ? undefined : credentials.token;\n const {\n lib: { bank },\n } = useBankCoreApiContext();\n const accountIsTheCurrentUser =\n credentials.status === \"loggedIn\"\n ? credentials.username === account\n : false;\n\n const [submitAccount, setSubmitAccount] = useState<\n TalerCorebankApi.AccountReconfiguration | undefined\n >();\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const mfa = useChallengeHandler();\n\n const result = useAccountDetails(account);\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return (\n \n \n \n \n );\n }\n if (result.type === \"fail\") {\n switch (result.case) {\n case HttpStatusCode.Unauthorized:\n case HttpStatusCode.NotFound:\n return ;\n default:\n assertUnreachable(result);\n }\n }\n\n const update = safeFunctionHandler(\n i18n.str`update account`,\n (\n username: string,\n token: AccessToken,\n account: TalerCorebankApi.AccountReconfiguration,\n challengeIds: string[],\n ) => bank.updateAccount({ username, token }, account, { challengeIds }),\n !sessionToken || !submitAccount\n ? undefined\n : [account, sessionToken, submitAccount, []],\n );\n\n update.onSuccess = (success) => {\n notifyInfo(i18n.str`Account updated`);\n onUpdateSuccess();\n };\n\n update.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Unauthorized:\n return i18n.str`The rights to change the account are not sufficient`;\n case HttpStatusCode.NotFound:\n return i18n.str`The username was not found`;\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME:\n return i18n.str`You can't change the legal name, please contact the your account administrator.`;\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:\n return i18n.str`You can't change the debt limit, please contact the your account administrator.`;\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT:\n return i18n.str`You can't change the cashout address, please contact the your account administrator.`;\n case TalerErrorCode.BANK_MISSING_TAN_INFO:\n return i18n.str`No information for the selected authentication channel.`;\n case HttpStatusCode.Accepted: {\n mfa.onChallengeRequired(fail.body);\n return i18n.str`A second factor authentication is required.`;\n }\n case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED:\n return i18n.str`Authentication channel is not supported.`;\n case TalerErrorCode.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:\n return i18n.str`Only the administrator can change the conversion rate.`;\n case TalerErrorCode.BANK_CONVERSION_RATE_CLASS_UNKNOWN:\n return i18n.str`The conversion rate class doesn't exist.`;\n case TalerErrorCode.BANK_PASSWORD_TOO_SHORT:\n return i18n.str`The password is too short. Can't have less than 8 characters.`;\n case TalerErrorCode.BANK_PASSWORD_TOO_LONG:\n return i18n.str`The password is too long. Can't have more than 64 characters.`;\n default:\n assertUnreachable(fail);\n }\n };\n\n const repeatUpdate = update.lambda((ids: string[]) => {\n return [update.args![0], update.args![1], update.args![2], ids];\n });\n\n const url = bank.getRevenueAPI(account);\n const baseURL = url.href;\n const revenueURL = new URL(baseURL);\n revenueURL.username = account;\n revenueURL.password;\n const ac = Paytos.fromString(result.body.payto_uri);\n const payto =\n ac.tag === \"error\" || !ac.value.targetType ? undefined : ac.value;\n\n if (mfa.pendingChallenge) {\n return (\n \n );\n }\n\n return (\n \n \n {accountIsTheCurrentUser ? (\n \n ) : (\n

    \n Account \"{account}\"\n

    \n )}\n\n {result.body.status !== \"deleted\" ? undefined : (\n \n This account can't be used.\n \n )}\n\n
    \n
    \n

    \n
    \n \n \n Change details\n \n \n
    \n

    \n
    \n\n setSubmitAccount(a)}\n >\n
    \n \n Cancel\n \n \n Update\n \n
    \n \n
    \n {result.body.is_taler_exchange || account === \"admin\" ? undefined : (\n
    \n
    \n

    \n
    \n \n \n Merchant integration\n \n \n
    \n

    \n

    \n \n Use this information to link your Taler Merchant Backoffice\n account with the current bank account. You can start by copying\n the values, then go to your merchant backoffice service\n provider, login into your account and look for the \"import\"\n button in the \"bank account\" section.\n \n

    \n
    \n\n {payto !== undefined && (\n
    \n
    \n
    \n
    \n \n {i18n.str`Account type`}\n \n
    \n \n
    \n

    \n \n Method to use for wire transfer.\n \n

    \n
    \n {((payto) => {\n switch (payto.targetType) {\n case \"iban\": {\n return (\n
    \n \n {i18n.str`IBAN`}\n \n
    \n
    \n \n payto.iban}\n />\n
    \n
    \n

    \n \n International Bank Account Number.\n \n

    \n
    \n );\n }\n case \"x-taler-bank\": {\n return (\n \n
    \n \n {i18n.str`Account name`}\n \n
    \n
    \n \n
    \n payto.host}\n />\n
    \n\n

    \n \n Bank host where the service is located.\n \n

    \n
    \n
    \n \n {i18n.str`Account name`}\n \n
    \n
    \n \n
    \n payto.account}\n />\n
    \n\n

    \n \n Bank account identifier for wire transfers.\n \n

    \n
    \n
    \n );\n }\n case \"bitcoin\": {\n return (\n
    \n \n {i18n.str`Address`}\n \n
    \n \n \"Asd\"}\n />\n
    \n

    \n \n International Bank Account Number.\n \n

    \n
    \n );\n }\n default:\n return `unsupported account type ${payto.targetType}`;\n }\n })(payto)}\n\n
    \n \n {i18n.str`Owner's name`}\n \n
    \n
    \n \n result.body.name}\n />\n
    \n
    \n

    \n \n Legal name of the person holding the account.\n \n

    \n
    \n
    \n \n {i18n.str`Account info URL`}\n \n
    \n
    \n \n baseURL}\n />\n
    \n
    \n

    \n \n From where the merchant can download information about\n incoming wire transfers to this account.\n \n

    \n
    \n
    \n
    \n
    \n \n Cancel\n \n \n
    \n
    \n )}\n
    \n )}\n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n AmountString,\n Amounts,\n HostPortPath,\n IbanString,\n PaytoString,\n PaytoType,\n Paytos,\n TalerCorebankApi,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n CopyButton,\n ShowInputErrorLabel,\n useBankCoreApiContext,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { ComponentChildren, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport {\n ErrorMessageMappingFor,\n TanChannel,\n undefinedIfEmpty,\n validateIBAN,\n validateTalerBank,\n} from \"../../utils.js\";\nimport {\n InputAmount,\n TextField,\n doAutoFocus,\n} from \"../PaytoWireTransferForm.js\";\nimport { getRandomPassword } from \"../rnd.js\";\n\nconst TALER_SCREEN_ID = 120;\n\nconst EMAIL_REGEX =\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\nconst REGEX_JUST_NUMBERS_REGEX = /^\\+[0-9 ]*$/;\n\nexport type AccountFormData = {\n debit_threshold?: string;\n isExchange?: boolean;\n isPublic?: boolean;\n name?: string;\n username?: string;\n payto_uri?: string;\n cashout_payto_uri?: string;\n email?: string;\n phone?: string;\n tan_channel?: TanChannel | \"remove\";\n};\n\ntype ChangeByPurposeType = {\n create: (a: TalerCorebankApi.RegisterAccountRequest | undefined) => void;\n update: (a: TalerCorebankApi.AccountReconfiguration | undefined) => void;\n show: undefined;\n};\n/**\n * FIXME:\n * is_public is missing on PATCH\n * account email/password should require 2FA\n *\n *\n * @param param0\n * @returns\n */\nexport function AccountForm({\n template,\n username,\n purpose,\n onChange,\n focus,\n children,\n}: {\n focus?: boolean;\n children: ComponentChildren;\n username?: string;\n template: TalerCorebankApi.AccountData | undefined;\n onChange: ChangeByPurposeType[PurposeType];\n purpose: PurposeType;\n}): VNode {\n const { config, url } = useBankCoreApiContext();\n const { i18n } = useTranslationContext();\n const { state: credentials } = useSessionState();\n const [form, setForm] = useState({});\n\n const [errors, setErrors] = useState<\n ErrorMessageMappingFor | undefined\n >(undefined);\n\n const paytoType =\n config.wire_type === \"X_TALER_BANK\"\n ? (\"x-taler-bank\" as const)\n : (\"iban\" as const);\n const cashoutPaytoType: typeof paytoType = \"iban\" as const;\n\n const defaultValue: AccountFormData = {\n debit_threshold: Amounts.stringifyValue(\n template?.debit_threshold ??\n config.default_debit_threshold ??\n `${config.currency}:0`,\n ),\n isExchange: template?.is_taler_exchange,\n isPublic: template?.is_public,\n name: template?.name ?? \"\",\n cashout_payto_uri:\n getAccountId(\n cashoutPaytoType,\n template?.cashout_payto_uri as Paytos.FullPaytoString,\n ) ?? \"\",\n payto_uri:\n getAccountId(paytoType, template?.payto_uri as Paytos.FullPaytoString) ??\n \"\",\n email: template?.contact_data?.email ?? \"\",\n phone: template?.contact_data?.phone ?? \"\",\n username: username ?? \"\",\n tan_channel: template?.tan_channel,\n };\n\n const userIsAdmin =\n credentials.status !== \"loggedIn\" ? false : credentials.isUserAdministrator;\n\n const editableUsername = purpose === \"create\";\n const editableName =\n purpose === \"create\" ||\n (purpose === \"update\" && (config.allow_edit_name || userIsAdmin));\n\n const isCashoutEnabled = config.allow_conversion;\n const editableCashout =\n purpose === \"create\" ||\n (purpose === \"update\" &&\n (config.allow_edit_cashout_payto_uri || userIsAdmin));\n const editableThreshold =\n userIsAdmin && (purpose === \"create\" || purpose === \"update\");\n const editableAccount = purpose === \"create\" && userIsAdmin;\n\n const hasPhone = !!defaultValue.phone || !!form.phone;\n const hasEmail = !!defaultValue.email || !!form.email;\n\n function updateForm(newForm: typeof defaultValue): void {\n const trimmedDebitThresholdStr = newForm.debit_threshold?.trim();\n const parsedDebitThreshold = Amounts.parse(\n `${config.currency}:${trimmedDebitThresholdStr}`,\n );\n\n const errors = undefinedIfEmpty<\n ErrorMessageMappingFor\n >({\n cashout_payto_uri: !newForm.cashout_payto_uri\n ? undefined\n : !editableCashout\n ? undefined\n : !newForm.cashout_payto_uri\n ? undefined\n : cashoutPaytoType === \"iban\"\n ? validateIBAN(newForm.cashout_payto_uri, i18n)\n : cashoutPaytoType === \"x-taler-bank\"\n ? validateTalerBank(newForm.cashout_payto_uri, i18n)\n : undefined,\n\n payto_uri: !newForm.payto_uri\n ? undefined\n : !editableAccount\n ? undefined\n : !newForm.payto_uri\n ? undefined\n : paytoType === \"iban\"\n ? validateIBAN(newForm.payto_uri, i18n)\n : paytoType === \"x-taler-bank\"\n ? validateTalerBank(newForm.payto_uri, i18n)\n : undefined,\n\n email: !newForm.email\n ? undefined\n : !EMAIL_REGEX.test(newForm.email)\n ? i18n.str`Invalid email format`\n : undefined,\n phone: !newForm.phone\n ? undefined\n : !newForm.phone.startsWith(\"+\") // FIXME: better phone number check\n ? i18n.str`Should start with +`\n : !REGEX_JUST_NUMBERS_REGEX.test(newForm.phone)\n ? i18n.str`A phone number consists of numbers only`\n : undefined,\n debit_threshold: !editableThreshold\n ? undefined\n : !trimmedDebitThresholdStr\n ? undefined\n : !parsedDebitThreshold\n ? i18n.str`Not valid`\n : undefined,\n name: !editableName\n ? undefined // disabled\n : purpose === \"update\" && newForm.name === undefined\n ? undefined // the field hasn't been changed\n : !newForm.name\n ? i18n.str`Required`\n : undefined,\n username: !editableUsername\n ? undefined\n : !newForm.username\n ? i18n.str`Required`\n : undefined,\n });\n setErrors(errors);\n\n setForm(newForm);\n if (!onChange) return;\n\n if (errors) {\n onChange(undefined);\n } else {\n let cashout: Paytos.URI | undefined;\n if (newForm.cashout_payto_uri)\n switch (cashoutPaytoType) {\n case \"x-taler-bank\": {\n cashout = Paytos.createTalerBank(\n url.href as HostPortPath,\n newForm.cashout_payto_uri,\n );\n break;\n }\n case \"iban\": {\n cashout = Paytos.createIban(\n newForm.cashout_payto_uri as IbanString,\n undefined,\n );\n break;\n }\n default:\n assertUnreachable(cashoutPaytoType);\n }\n const cashoutURI = !cashout ? null : Paytos.toFullString(cashout);\n let internal: Paytos.URI | undefined;\n if (newForm.payto_uri)\n switch (paytoType) {\n case \"x-taler-bank\": {\n internal = Paytos.createTalerBank(\n url.href as HostPortPath,\n newForm.payto_uri,\n );\n break;\n }\n case \"iban\": {\n internal = Paytos.createIban(\n newForm.payto_uri as IbanString,\n undefined,\n );\n break;\n }\n default:\n assertUnreachable(paytoType);\n }\n const internalURI = !internal ? undefined : Paytos.toFullString(internal);\n\n const threshold = !parsedDebitThreshold\n ? undefined\n : Amounts.stringify(parsedDebitThreshold);\n\n switch (purpose) {\n case \"create\": {\n // typescript doesn't correctly narrow a generic type\n const callback = onChange as ChangeByPurposeType[\"create\"];\n const result: TalerCorebankApi.RegisterAccountRequest = {\n name: newForm.name!,\n password: getRandomPassword(),\n username: newForm.username!,\n contact_data: undefinedIfEmpty({\n email: !newForm.email ? undefined : newForm.email,\n phone: !newForm.phone ? undefined : newForm.phone,\n }),\n debit_threshold: threshold ?? config.default_debit_threshold,\n cashout_payto_uri: cashoutURI === null ? undefined : cashoutURI,\n payto_uri: internalURI,\n is_public: newForm.isPublic,\n is_taler_exchange: newForm.isExchange,\n tan_channel:\n newForm.tan_channel === \"remove\"\n ? undefined\n : newForm.tan_channel,\n };\n callback(result);\n return;\n }\n case \"update\": {\n // typescript doesn't correctly narrow a generic type\n const callback = onChange as ChangeByPurposeType[\"update\"];\n\n const result: TalerCorebankApi.AccountReconfiguration = {\n cashout_payto_uri: cashoutURI,\n contact_data: undefinedIfEmpty({\n email: !newForm.email ? undefined : newForm.email,\n phone: !newForm.phone ? undefined : newForm.phone,\n }),\n debit_threshold: threshold,\n is_public: newForm.isPublic,\n name: newForm.name,\n tan_channel:\n newForm.tan_channel === \"remove\" ? null : newForm.tan_channel,\n };\n callback(result);\n return;\n }\n case \"show\": {\n return;\n }\n default: {\n assertUnreachable(purpose);\n }\n }\n }\n }\n return (\n {\n e.preventDefault();\n }}\n >\n
    \n
    \n
    \n \n {i18n.str`Login username`}\n {editableUsername && *}\n \n
    \n {\n form.username = e.currentTarget.value;\n updateForm(structuredClone(form));\n }}\n // placeholder=\"\"\n autocomplete=\"off\"\n />\n \n
    \n

    \n Account ID for authentication\n

    \n
    \n\n
    \n \n {i18n.str`Full name`}\n {editableName && *}\n \n
    \n {\n form.name = e.currentTarget.value;\n updateForm(structuredClone(form));\n }}\n // placeholder=\"\"\n autocomplete=\"off\"\n />\n \n
    \n

    \n Name of the account holder\n

    \n
    \n\n {purpose === \"create\" ? undefined : (\n {\n form.payto_uri = e as PaytoString;\n updateForm(structuredClone(form));\n }}\n rightIcons={\n \n form.payto_uri ?? defaultValue.payto_uri ?? \"\"\n }\n />\n }\n value={(form.payto_uri ?? defaultValue.payto_uri) as PaytoString}\n disabled={!editableAccount}\n />\n )}\n\n
    \n \n {i18n.str`Email`}\n \n
    \n {\n form.email = e.currentTarget.value;\n updateForm(structuredClone(form));\n }}\n autocomplete=\"off\"\n />\n \n
    \n

    \n \n To be used when second factor authentication is enabled\n \n

    \n
    \n\n
    \n \n {i18n.str`Phone`}\n \n
    \n {\n form.phone = e.currentTarget.value;\n updateForm(structuredClone(form));\n }}\n autocomplete=\"off\"\n />\n \n
    \n

    \n \n To be used when second factor authentication is enabled\n \n

    \n
    \n\n {!config.supported_tan_channels ||\n config.supported_tan_channels.length === 0 ? undefined : (\n
    \n \n {i18n.str`Enable second factor authentication`}\n \n
    \n
    \n {config.supported_tan_channels.indexOf(TanChannel.EMAIL) ===\n -1 ? undefined : (\n {\n if (!hasEmail) return;\n if (form.tan_channel === TanChannel.EMAIL) {\n form.tan_channel = \"remove\";\n } else {\n form.tan_channel = TanChannel.EMAIL;\n }\n updateForm(structuredClone(form));\n e.preventDefault();\n }}\n data-disabled={purpose === \"show\" || !hasEmail}\n data-selected={\n (form.tan_channel ?? defaultValue.tan_channel) ===\n TanChannel.EMAIL\n }\n class=\"relative flex data-[disabled=false]:cursor-pointer rounded-lg border bg-white data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600\"\n >\n \n \n \n \n Using email\n \n {purpose !== \"show\" &&\n !hasEmail &&\n i18n.str`Add an email in your profile to enable this option`}\n \n \n \n \n \n \n )}\n\n {config.supported_tan_channels.indexOf(TanChannel.SMS) ===\n -1 ? undefined : (\n {\n if (!hasPhone) return;\n if (form.tan_channel === TanChannel.SMS) {\n form.tan_channel = \"remove\";\n } else {\n form.tan_channel = TanChannel.SMS;\n }\n updateForm(structuredClone(form));\n e.preventDefault();\n }}\n data-disabled={purpose === \"show\" || !hasPhone}\n data-selected={\n (form.tan_channel ?? defaultValue.tan_channel) ===\n TanChannel.SMS\n }\n class=\"relative flex data-[disabled=false]:cursor-pointer rounded-lg border data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600\"\n >\n \n \n \n \n Using SMS\n \n {purpose !== \"show\" &&\n !hasPhone &&\n i18n.str`Add a phone number in your profile to enable this option`}\n \n \n \n \n \n \n )}\n
    \n
    \n
    \n )}\n\n {isCashoutEnabled && (\n {\n form.cashout_payto_uri = e as PaytoString;\n updateForm(structuredClone(form));\n }}\n value={\n (form.cashout_payto_uri ??\n defaultValue.cashout_payto_uri) as PaytoString\n }\n disabled={!editableCashout}\n />\n )}\n\n
    \n {i18n.str`Max debt`}\n {\n form.debit_threshold = e as AmountString;\n updateForm(structuredClone(form));\n }\n }\n />\n \n

    \n \n How much the balance can go below zero.\n \n

    \n
    \n\n
    \n
    \n \n \n Is this account public?\n \n \n {\n form.isPublic = !(form.isPublic ?? defaultValue.isPublic);\n updateForm(structuredClone(form));\n }}\n >\n \n \n
    \n

    \n \n Public accounts have their balance publicly accessible\n \n

    \n
    \n\n {purpose !== \"create\" || !userIsAdmin ? undefined : (\n
    \n
    \n \n \n \n Does this account belong to a Payment Service Provider?\n \n \n \n {\n form.isExchange = !form.isExchange;\n updateForm(structuredClone(form));\n }}\n >\n \n \n
    \n
    \n )}\n
    \n
    \n {children}\n \n );\n}\n\nfunction getAccountId(\n type: \"iban\" | \"x-taler-bank\",\n s: Paytos.FullPaytoString | undefined,\n): string | undefined {\n if (s === undefined) {\n return undefined;\n }\n const p = Paytos.fromString(s);\n if (p.tag === \"error\") {\n return undefined;\n }\n if (type === \"iban\" && p.value.targetType === PaytoType.IBAN) {\n return p.value.iban;\n }\n if (type === \"x-taler-bank\" && p.value.targetType === PaytoType.TalerBank) {\n return p.value.account;\n }\n return \"\";\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n AccessToken,\n assertUnreachable,\n TalerCorebankApi,\n} from \"@gnu-taler/taler-util\";\nimport {\n ButtonBetter,\n LocalNotificationBanner,\n RouteDefinition,\n ShowInputErrorLabel,\n notifyInfo,\n useBankCoreApiContext,\n useChallengeHandler,\n useLocalNotificationBetter,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport { undefinedIfEmpty } from \"../../utils.js\";\nimport { doAutoFocus } from \"../PaytoWireTransferForm.js\";\nimport { ProfileNavigation } from \"../ProfileNavigation.js\";\nimport { SolveMFAChallenges } from \"../SolveMFA.js\";\nimport { TalerErrorCode } from \"@gnu-taler/taler-util\";\nimport { HttpStatusCode } from \"@gnu-taler/taler-util\";\n\nconst TALER_SCREEN_ID = 119;\n\nexport function UpdateAccountPassword({\n account: accountName,\n routeClose,\n onUpdateSuccess,\n\n routeMyAccountCashout,\n routeMyAccountDelete,\n routeMyAccountDetails,\n routeMyAccountPassword,\n routeConversionConfig,\n focus,\n}: {\n routeClose: RouteDefinition;\n routeMyAccountDetails: RouteDefinition;\n routeMyAccountDelete: RouteDefinition;\n routeMyAccountPassword: RouteDefinition;\n routeMyAccountCashout: RouteDefinition;\n routeConversionConfig: RouteDefinition;\n focus?: boolean;\n\n onUpdateSuccess: () => void;\n account: string;\n}): VNode {\n const { i18n } = useTranslationContext();\n const { state: credentials } = useSessionState();\n const token =\n credentials.status !== \"loggedIn\" ? undefined : credentials.token;\n const {\n lib: { bank: api },\n } = useBankCoreApiContext();\n\n const [current, setCurrent] = useState();\n const [password, setPassword] = useState();\n const [repeat, setRepeat] = useState();\n\n const accountIsTheCurrentUser =\n credentials.status === \"loggedIn\"\n ? credentials.username === accountName\n : false;\n\n const errors = undefinedIfEmpty({\n current: !accountIsTheCurrentUser\n ? undefined\n : !current\n ? i18n.str`Required`\n : undefined,\n password: !password ? i18n.str`Required` : undefined,\n repeat: !repeat\n ? i18n.str`Required`\n : password !== repeat\n ? i18n.str`Repeated password doesn't match`\n : undefined,\n });\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n const mfa = useChallengeHandler();\n\n const update = safeFunctionHandler(\n i18n.str`update password`,\n (\n token: AccessToken,\n request: TalerCorebankApi.AccountPasswordChange,\n challengeIds: string[],\n ) =>\n api.updatePassword({ username: accountName, token }, request, {\n challengeIds,\n }),\n !password || !token\n ? undefined\n : [\n token,\n {\n old_password: current,\n new_password: password,\n },\n [],\n ],\n );\n\n update.onSuccess = (success) => {\n notifyInfo(i18n.str`Password changed`);\n onUpdateSuccess();\n };\n update.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Unauthorized:\n return i18n.str`Not authorized to change the password, maybe the session is invalid.`;\n case HttpStatusCode.NotFound:\n return i18n.str`Account not found`;\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD:\n return i18n.str`You need to provide the old password. If you don't have it contact your account administrator.`;\n case TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD:\n return i18n.str`Your current password doesn't match, can't change to a new password.`;\n case HttpStatusCode.Accepted: {\n mfa.onChallengeRequired(fail.body);\n return i18n.str`A second factor authentication is required.`;\n }\n case HttpStatusCode.Forbidden:\n return i18n.str`You don't have the rights to change the password.`;\n case TalerErrorCode.BANK_PASSWORD_TOO_SHORT:\n return i18n.str`The password is too short. Can't have less than 8 characters.`;\n case TalerErrorCode.BANK_PASSWORD_TOO_LONG:\n return i18n.str`The password is too long. Can't have more than 64 characters.`;\n default:\n assertUnreachable(fail);\n }\n };\n const repeatUpdate = update.lambda((ids: string[]) => {\n return [update.args![0], update.args![1], ids];\n });\n\n if (mfa.pendingChallenge) {\n return (\n \n );\n }\n return (\n \n \n {accountIsTheCurrentUser ? (\n \n ) : (\n

    \n Account \"{accountName}\"\n

    \n )}\n\n
    \n
    \n

    \n Update password\n

    \n
    \n {\n e.preventDefault();\n }}\n >\n
    \n
    \n {accountIsTheCurrentUser ? (\n
    \n \n {i18n.str`Current password`}\n *\n \n
    \n {\n setCurrent(e.currentTarget.value);\n }}\n autocomplete=\"off\"\n />\n \n
    \n

    \n \n Your current password, for security\n \n

    \n
    \n ) : undefined}\n\n
    \n \n {i18n.str`New password`}\n *\n \n
    \n {\n setPassword(e.currentTarget.value);\n }}\n autocomplete=\"off\"\n />\n \n
    \n
    \n\n
    \n \n {i18n.str`Type it again`}\n *\n \n
    \n {\n setRepeat(e.currentTarget.value);\n }}\n // placeholder=\"\"\n autocomplete=\"off\"\n />\n \n
    \n

    \n Repeat the same password\n

    \n
    \n
    \n
    \n
    \n \n Cancel\n \n \n Change\n \n
    \n \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n AbsoluteTime,\n AmountString,\n Amounts,\n CurrencySpecification,\n Duration,\n HttpStatusCode,\n TalerCorebankApi,\n TalerError,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ErrorLoading,\n RenderAmount,\n RouteDefinition,\n useBankCoreApiContext,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { format, sub } from \"date-fns\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\n\nimport { Transactions } from \"../../components/Transactions/index.js\";\nimport { useConversionInfo, useLastMonitorInfo } from \"../../hooks/regional.js\";\n\nimport { WireTransfer } from \"../WireTransfer.js\";\nimport { AccountList } from \"./AccountList.js\";\nimport { ConversionClassList } from \"./ConversionClassList.js\";\n\nconst TALER_SCREEN_ID = 122;\n\n/**\n * Query account information and show QR code if there is pending withdrawal\n */\ninterface Props {\n routeDownloadStats: RouteDefinition;\n routeCreateWireTransfer: RouteDefinition<{\n account?: string;\n subject?: string;\n amount?: string;\n }>;\n\n routeCreateAccount: RouteDefinition;\n routeRemoveAccount: RouteDefinition<{ account: string }>;\n routeShowAccount: RouteDefinition<{ account: string }>;\n routeUpdatePasswordAccount: RouteDefinition<{ account: string }>;\n routeShowCashoutsAccount: RouteDefinition<{ account: string }>;\n\n routeCreateConversionRateClass: RouteDefinition;\n routeShowConversionRateClass: RouteDefinition<{ classId: string }>;\n}\nexport function AdminHome({\n routeCreateAccount,\n routeRemoveAccount,\n routeShowAccount,\n routeUpdatePasswordAccount,\n routeDownloadStats,\n routeCreateWireTransfer,\n routeCreateConversionRateClass,\n routeShowConversionRateClass,\n}: Props): VNode {\n const { config } = useBankCoreApiContext();\n return (\n \n \n \n \n \n {!config.allow_conversion ? undefined : (\n \n )}\n \n );\n}\n\nfunction getDateForTimeframeStart(\n date: AbsoluteTime,\n timeframe: TalerCorebankApi.MonitorTimeframeParam,\n locale: Locale,\n): string {\n if (date.t_ms === \"never\") return \"--\";\n switch (timeframe) {\n case TalerCorebankApi.MonitorTimeframeParam.hour:\n return `${format(date.t_ms, \"HH:00\", { locale })}hs`;\n case TalerCorebankApi.MonitorTimeframeParam.day:\n return format(date.t_ms, \"EEEE\", { locale });\n case TalerCorebankApi.MonitorTimeframeParam.month:\n return format(date.t_ms, \"MMMM\", { locale });\n case TalerCorebankApi.MonitorTimeframeParam.year:\n return format(date.t_ms, \"yyyy\", { locale });\n case TalerCorebankApi.MonitorTimeframeParam.decade:\n return format(date.t_ms, \"yyyy\", { locale });\n }\n assertUnreachable(timeframe);\n}\n\nfunction getDateForTimeframeEnd(\n date: AbsoluteTime,\n timeframe: TalerCorebankApi.MonitorTimeframeParam,\n locale: Locale,\n): string {\n if (date.t_ms === \"never\") return \"--\";\n switch (timeframe) {\n case TalerCorebankApi.MonitorTimeframeParam.hour: {\n const end = AbsoluteTime.addDuration(\n date,\n Duration.fromSpec({ hours: 1 }),\n );\n if (end.t_ms === \"never\")\n throw Error(`abs time plus 1 hour duration can't be 'never'`);\n return `${format(end.t_ms, \"HH:00\", { locale })}hs`;\n }\n case TalerCorebankApi.MonitorTimeframeParam.day: {\n const end = AbsoluteTime.addDuration(\n date,\n Duration.fromSpec({ days: 1 }),\n );\n if (end.t_ms === \"never\")\n throw Error(`abs time plus 1 day duration can't be 'never'`);\n return format(end.t_ms, \"EEEE\", { locale });\n }\n case TalerCorebankApi.MonitorTimeframeParam.month: {\n const end = AbsoluteTime.addDuration(\n date,\n Duration.fromSpec({ months: 1 }),\n );\n if (end.t_ms === \"never\")\n throw Error(`abs time plus 1 month duration can't be 'never'`);\n return format(end.t_ms, \"MMMM\", { locale });\n }\n case TalerCorebankApi.MonitorTimeframeParam.year: {\n const end = AbsoluteTime.addDuration(\n date,\n Duration.fromSpec({ years: 1 }),\n );\n if (end.t_ms === \"never\")\n throw Error(`abs time plus 1 year duration can't be 'never'`);\n return format(end.t_ms, \"yyyy\", { locale });\n }\n case TalerCorebankApi.MonitorTimeframeParam.decade: {\n const end = AbsoluteTime.addDuration(\n date,\n Duration.fromSpec({ years: 10 }),\n );\n if (end.t_ms === \"never\")\n throw Error(`abs time plus 10 years duration can't be 'never'`);\n return format(end.t_ms, \"yyyy\", { locale });\n }\n }\n assertUnreachable(timeframe);\n}\n\nexport function getTimeframesForDate(\n time: Date,\n timeframe: TalerCorebankApi.MonitorTimeframeParam,\n): { current: AbsoluteTime; previous: AbsoluteTime } {\n switch (timeframe) {\n case TalerCorebankApi.MonitorTimeframeParam.hour:\n return {\n current: AbsoluteTime.fromMilliseconds(\n sub(time, { hours: 1 }).getTime(),\n ),\n previous: AbsoluteTime.fromMilliseconds(\n sub(time, { hours: 2 }).getTime(),\n ),\n };\n case TalerCorebankApi.MonitorTimeframeParam.day:\n return {\n current: AbsoluteTime.fromMilliseconds(\n sub(time, { days: 1 }).getTime(),\n ),\n previous: AbsoluteTime.fromMilliseconds(\n sub(time, { days: 2 }).getTime(),\n ),\n };\n case TalerCorebankApi.MonitorTimeframeParam.month:\n return {\n current: AbsoluteTime.fromMilliseconds(\n sub(time, { months: 1 }).getTime(),\n ),\n previous: AbsoluteTime.fromMilliseconds(\n sub(time, { months: 2 }).getTime(),\n ),\n };\n case TalerCorebankApi.MonitorTimeframeParam.year:\n return {\n current: AbsoluteTime.fromMilliseconds(\n sub(time, { years: 1 }).getTime(),\n ),\n previous: AbsoluteTime.fromMilliseconds(\n sub(time, { years: 2 }).getTime(),\n ),\n };\n case TalerCorebankApi.MonitorTimeframeParam.decade:\n return {\n current: AbsoluteTime.fromMilliseconds(\n sub(time, { years: 10 }).getTime(),\n ),\n previous: AbsoluteTime.fromMilliseconds(\n sub(time, { years: 20 }).getTime(),\n ),\n };\n default:\n assertUnreachable(timeframe);\n }\n}\n\nfunction Metrics({\n routeDownloadStats,\n}: {\n routeDownloadStats: RouteDefinition;\n}): VNode {\n const { i18n, dateLocale } = useTranslationContext();\n const [metricType, setMetricType] =\n useState(\n TalerCorebankApi.MonitorTimeframeParam.hour,\n );\n const { config } = useBankCoreApiContext();\n const respInfo = useConversionInfo();\n const params = getTimeframesForDate(new Date(), metricType);\n\n const resp = useLastMonitorInfo(params.current, params.previous, metricType);\n if (!resp) return ;\n if (resp instanceof TalerError) {\n return ;\n }\n if (respInfo && respInfo instanceof TalerError) {\n return ;\n }\n if (respInfo && respInfo.type === \"fail\") {\n switch (respInfo.case) {\n case HttpStatusCode.NotImplemented: {\n return (\n \n \n Cashout should be enabled in the configuration, the conversion\n rate should be initialized with fee(s), rates and a rounding mode.\n \n \n );\n }\n default: {\n assertUnreachable(respInfo);\n }\n }\n }\n\n if (resp.current.type !== \"ok\") {\n switch (resp.current.case) {\n case HttpStatusCode.BadRequest:\n return (\n \n The request parameters are wrong\n \n );\n case HttpStatusCode.Unauthorized:\n return (\n \n The user is unauthorized\n \n );\n default: {\n assertUnreachable(resp.current);\n }\n }\n }\n if (resp.previous.type !== \"ok\") {\n switch (resp.previous.case) {\n case HttpStatusCode.BadRequest:\n return (\n \n The request parameters are wrong\n \n );\n case HttpStatusCode.Unauthorized:\n return (\n \n The user is unauthorized\n \n );\n default: {\n assertUnreachable(resp.previous);\n }\n }\n }\n return (\n
    \n
    \n
    \n

    \n Transaction volume report\n

    \n
    \n
    \n\n
    \n \n {\n setMetricType(\n parseInt(\n e.currentTarget.value,\n 10,\n ) as TalerCorebankApi.MonitorTimeframeParam,\n );\n }}\n >\n \n Last hour\n \n \n Previous day\n \n \n Last month\n \n \n Last year\n \n \n
    \n
    \n {/* FIXME: This should be LINKS */}\n \n {\n e.preventDefault();\n setMetricType(TalerCorebankApi.MonitorTimeframeParam.hour);\n }}\n data-selected={\n metricType == TalerCorebankApi.MonitorTimeframeParam.hour\n }\n class=\"rounded-l-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10\"\n >\n \n Last hour\n \n \n \n {\n e.preventDefault();\n setMetricType(TalerCorebankApi.MonitorTimeframeParam.day);\n }}\n data-selected={\n metricType == TalerCorebankApi.MonitorTimeframeParam.day\n }\n class=\" text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10\"\n >\n \n Previous day\n \n \n \n {\n e.preventDefault();\n setMetricType(TalerCorebankApi.MonitorTimeframeParam.month);\n }}\n data-selected={\n metricType == TalerCorebankApi.MonitorTimeframeParam.month\n }\n class=\"rounded-r-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10\"\n >\n \n Last month\n \n \n \n {\n e.preventDefault();\n setMetricType(TalerCorebankApi.MonitorTimeframeParam.year);\n }}\n data-selected={\n metricType == TalerCorebankApi.MonitorTimeframeParam.year\n }\n class=\"rounded-r-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10\"\n >\n \n Last Year\n \n \n \n \n
    \n\n
    \n

    \n {i18n.str`Trading volume from ${getDateForTimeframeStart(\n params.current,\n metricType,\n dateLocale,\n )} to ${getDateForTimeframeEnd(\n params.current,\n metricType,\n dateLocale,\n )}`}\n

    \n
    \n
    \n {!respInfo ||\n resp.current.body.type !== \"with-conversions\" ||\n resp.previous.body.type !== \"with-conversions\" ? undefined : (\n \n
    \n
    \n Cashin\n
    \n \n Transferred from an external account to an account in this\n bank.\n \n
    \n
    \n \n
    \n
    \n
    \n Cashout\n
    \n
    \n \n Transferred from an account in this bank to an external\n account.\n \n
    \n \n
    \n
    \n )}\n
    \n
    \n Payin\n
    \n \n Transferred from an account to a Taler exchange.\n \n
    \n
    \n \n
    \n
    \n
    \n Payout\n
    \n \n Transferred from a Taler exchange to another account.\n \n
    \n
    \n \n
    \n
    \n
    \n Payin\n
    \n \n Transferred from an account to a Taler exchange.\n \n
    \n
    \n \n
    \n
    \n
    \n Payout\n
    \n \n Transferred from a Taler exchange to another account.\n \n
    \n
    \n \n
    \n
    \n
    \n \n Download stats as CSV\n \n
    \n
    \n );\n}\n\nfunction MetricValueAmount({\n current,\n previous,\n spec,\n}: {\n spec: CurrencySpecification;\n current: AmountString | undefined;\n previous: AmountString | undefined;\n}): VNode {\n const { i18n } = useTranslationContext();\n const cmp = current && previous ? Amounts.cmp(current, previous) : 0;\n const cv = !current ? undefined : Amounts.stringifyValue(current);\n const currAmount = !cv ? undefined : Number.parseFloat(cv);\n const prevAmount = !previous\n ? undefined\n : Number.parseFloat(Amounts.stringifyValue(previous));\n\n const rate =\n !currAmount ||\n Number.isNaN(currAmount) ||\n !prevAmount ||\n Number.isNaN(prevAmount)\n ? 0\n : cmp === -1\n ? 1 - Math.round(currAmount) / Math.round(prevAmount)\n : cmp === 1\n ? Math.round(currAmount) / Math.round(prevAmount) - 1\n : 0;\n\n const negative = cmp === 0 ? undefined : cmp === -1;\n const rateStr = `${(Math.abs(rate) * 100).toFixed(2)}%`;\n return (\n \n
    \n
    \n {!current ? (\n \"-\"\n ) : (\n \n )}\n
    \n
    \n
    \n \n previous{\" \"}\n {!previous ? (\n \"-\"\n ) : (\n \n )}\n \n
    \n {!!rate && (\n \n {negative ? (\n \n \n \n ) : (\n \n \n \n )}\n\n {negative ? (\n \n Decreased by\n \n ) : (\n \n Increased by\n \n )}\n {rateStr}\n \n )}\n
    \n
    \n
    \n );\n}\n\nfunction MetricValueNumber({\n current,\n previous,\n}: {\n current: number | undefined;\n previous: number | undefined;\n}): VNode {\n const { i18n } = useTranslationContext();\n\n const cmp = current && previous ? (current < previous ? -1 : 1) : 0;\n\n const rate =\n !current || Number.isNaN(current) || !previous || Number.isNaN(previous)\n ? 0\n : cmp === -1\n ? 1 - Math.round(current) / Math.round(previous)\n : cmp === 1\n ? Math.round(current) / Math.round(previous) - 1\n : 0;\n\n const negative = cmp === 0 ? undefined : cmp === -1;\n const rateStr = `${(Math.abs(rate) * 100).toFixed(2)}%`;\n return (\n \n
    \n
    \n {!current ? \"-\" : current}\n
    \n
    \n
    \n \n previous{\" \"}\n {!previous ? \"-\" : previous}\n \n
    \n {!!rate && (\n \n {negative ? (\n \n \n \n ) : (\n \n \n \n )}\n\n {negative ? (\n \n Decreased by\n \n ) : (\n \n Increased by\n \n )}\n {rateStr}\n \n )}\n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n Amounts,\n HttpStatusCode,\n TalerError,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n ErrorLoading,\n Loading,\n RenderAmount,\n RouteDefinition,\n useBankCoreApiContext,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\n\nimport { useBusinessAccounts } from \"../../hooks/regional.js\";\n\nconst TALER_SCREEN_ID = 121;\n\ninterface Props {\n routeCreate: RouteDefinition;\n\n routeShowAccount: RouteDefinition<{ account: string }>;\n routeRemoveAccount: RouteDefinition<{ account: string }>;\n routeUpdatePasswordAccount: RouteDefinition<{ account: string }>;\n}\n\nexport function AccountList({\n routeCreate,\n routeRemoveAccount,\n routeShowAccount,\n routeUpdatePasswordAccount,\n}: Props): VNode {\n const result = useBusinessAccounts();\n const { i18n } = useTranslationContext();\n const { config } = useBankCoreApiContext();\n\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return ;\n }\n switch (result.case) {\n case \"ok\":\n break;\n case HttpStatusCode.Unauthorized:\n return ;\n default:\n assertUnreachable(result);\n }\n\n const accounts = result.body;\n return (\n \n
    \n
    \n
    \n

    \n Accounts\n

    \n
    \n
    \n \n Create account\n \n
    \n
    \n
    \n
    \n
    \n {!accounts.length ? (\n
    {/* FIXME: ADD empty list */}
    \n ) : (\n \n \n \n {i18n.str`Username`}\n {i18n.str`Name`}\n {i18n.str`Balance`}\n \n \n \n \n {accounts.map((item, idx) => {\n const balance = !item.balance\n ? undefined\n : Amounts.parse(item.balance.amount);\n const noBalance = Amounts.isZero(item.balance.amount);\n const balanceIsDebit =\n item.balance &&\n item.balance.credit_debit_indicator == \"debit\";\n\n return (\n \n \n \n \n {!balance ? (\n i18n.str`Unknown`\n ) : (\n \n \n \n )}\n \n \n \n );\n })}\n \n
    \n {i18n.str`Actions`}\n
    \n \n {item.username}\n \n \n {item.name}\n \n {item.status === \"deleted\" ? (\n

    removed

    \n ) : (\n \n \n \n Change password\n \n \n
    \n\n {noBalance ? (\n \n Remove\n \n ) : undefined}\n
    \n )}\n
    \n )}\n
    \n \n
    \n \n First page\n \n \n Next\n \n
    \n \n
    \n
    \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024, 2026 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see void;\n}): VNode {\n const { i18n } = useTranslationContext();\n const { state: credentials } = useSessionState();\n const token =\n credentials.status !== \"loggedIn\" ? undefined : credentials.token;\n const {\n lib: { bank: api },\n } = useBankCoreApiContext();\n\n const [submitAccount, setSubmitAccount] = useState<\n TalerCorebankApi.RegisterAccountRequest | undefined\n >();\n\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const create = safeFunctionHandler(\n i18n.str`create account`,\n api.createAccount.bind(api),\n !submitAccount || !token\n ? undefined\n : [{ type: \"bearer\", token }, submitAccount],\n );\n create.onSuccess = (success, token, account) => {\n notifyInfo(i18n.str`Account created with password \"${account.password}\".`);\n onCreateSuccess();\n };\n\n create.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.BadRequest:\n return i18n.str`Server replied that phone or email is invalid`;\n case HttpStatusCode.Unauthorized:\n return i18n.str`The rights to perform the operation are not sufficient`;\n case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE:\n return i18n.str`Account username is already taken`;\n case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE:\n return i18n.str`Account ID is already taken`;\n case TalerErrorCode.BANK_UNALLOWED_DEBIT:\n return i18n.str`Bank ran out of bonus credit.`;\n case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT:\n return i18n.str`Account username can't be used because is reserved`;\n case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:\n return i18n.str`Only an administrator is allowed to set the debt limit.`;\n case TalerErrorCode.BANK_MISSING_TAN_INFO:\n return i18n.str`No information for the selected authentication channel.`;\n case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED:\n return i18n.str`Authentication channel is not supported.`;\n case TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL:\n return i18n.str`Only admin can create accounts with second factor authentication.`;\n case TalerErrorCode.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:\n return i18n.str`Only the administrator can change the conversion rate.`;\n case TalerErrorCode.BANK_CONVERSION_RATE_CLASS_UNKNOWN:\n return i18n.str`The conversion rate class doesn't exist.`;\n case TalerErrorCode.BANK_PASSWORD_TOO_SHORT:\n return i18n.str`The password is too short. Can't have less than 8 characters.`;\n case TalerErrorCode.BANK_PASSWORD_TOO_LONG:\n return i18n.str`The password is too long. Can't have more than 64 characters.`;\n default:\n assertUnreachable(fail);\n }\n };\n\n if (!(credentials.status === \"loggedIn\" && credentials.isUserAdministrator)) {\n return (\n \n \n \n Only system admin can create accounts.\n \n \n
    \n \n Close\n \n
    \n
    \n );\n }\n\n return (\n
    \n \n\n
    \n

    \n New bank account\n

    \n
    \n {\n setSubmitAccount(a);\n }}\n >\n
    \n \n Cancel\n \n \n Create\n \n
    \n \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n AccessToken,\n AmountString,\n OperationOk,\n TalerCoreBankHttpClient,\n TalerCorebankApi,\n opFixedSuccess,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ButtonBetter,\n LocalNotificationBanner,\n RouteDefinition,\n useBankCoreApiContext,\n useLocalNotificationBetter,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport { getTimeframesForDate } from \"./AdminHome.js\";\n\nconst TALER_SCREEN_ID = 124;\n\ninterface Props {\n routeCancel: RouteDefinition;\n}\n\ntype Options = {\n dayMetric: boolean;\n hourMetric: boolean;\n monthMetric: boolean;\n yearMetric: boolean;\n compareWithPrevious: boolean;\n endOnFirstFail: boolean;\n includeHeader: boolean;\n};\n\n/**\n * Show histories of public accounts.\n */\nexport function DownloadStats({ routeCancel }: Props): VNode {\n const { i18n } = useTranslationContext();\n\n const { state: credentials } = useSessionState();\n const creds =\n credentials.status !== \"loggedIn\" || !credentials.isUserAdministrator\n ? undefined\n : credentials;\n const {\n lib: { bank: api },\n } = useBankCoreApiContext();\n\n const [options, setOptions] = useState({\n compareWithPrevious: true,\n dayMetric: true,\n endOnFirstFail: false,\n hourMetric: true,\n includeHeader: true,\n monthMetric: true,\n yearMetric: true,\n });\n const [lastStep, setLastStep] = useState<{ step: number; total: number }>();\n const [downloaded, setDownloaded] = useState();\n const referenceDates = [new Date()];\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const download = safeFunctionHandler(\n i18n.str`download statistics`,\n async (token) => {\n setDownloaded(undefined);\n return fetchAllStatus(\n api,\n token,\n options,\n referenceDates,\n (step, total) => {\n setLastStep({ step, total });\n },\n );\n },\n lastStep !== undefined || !creds ? undefined : [creds.token],\n );\n download.onSuccess = (success) => {\n setDownloaded(success);\n setLastStep(undefined);\n };\n download.onFail = (fail) => {\n return undefined;\n };\n\n if (!creds) {\n return only admin can download stats;\n }\n\n return (\n
    \n
    \n \n\n
    \n

    \n Download bank stats\n

    \n
    \n\n {\n e.preventDefault();\n }}\n >\n
    \n
    \n
    \n
    \n \n \n Include hour metric\n \n \n {\n setOptions({\n ...options,\n hourMetric: !options.hourMetric,\n });\n }}\n >\n \n \n
    \n
    \n
    \n
    \n \n \n Include day metric\n \n \n {\n setOptions({ ...options, dayMetric: !options.dayMetric });\n }}\n >\n \n \n
    \n
    \n
    \n
    \n \n \n Include month metric\n \n \n {\n setOptions({\n ...options,\n monthMetric: !options.monthMetric,\n });\n }}\n >\n \n \n
    \n
    \n
    \n
    \n \n \n Include year metric\n \n \n {\n setOptions({\n ...options,\n yearMetric: !options.yearMetric,\n });\n }}\n >\n \n \n
    \n
    \n
    \n
    \n \n \n Include table header\n \n \n {\n setOptions({\n ...options,\n includeHeader: !options.includeHeader,\n });\n }}\n >\n \n \n
    \n
    \n
    \n
    \n \n \n \n Add previous metric for compare\n \n \n \n {\n setOptions({\n ...options,\n compareWithPrevious: !options.compareWithPrevious,\n });\n }}\n >\n \n \n
    \n
    \n
    \n
    \n \n \n Fail on first error\n \n \n {\n setOptions({\n ...options,\n endOnFirstFail: !options.endOnFirstFail,\n });\n }}\n >\n \n \n
    \n
    \n
    \n
    \n\n
    \n \n Cancel\n \n \n Download\n \n
    \n \n
    \n {!lastStep || lastStep.step === lastStep.total ? (\n
    \n ) : (\n
    \n
    \n \n \n \n downloading...{\" \"}\n {Math.round((lastStep.step / lastStep.total) * 100)}\n \n \n
    \n
    \n
    \n )}\n {!downloaded ? (\n
    \n ) : (\n \n \n \n Click here to save the file in your computer.\n \n \n \n )}\n
    \n );\n}\n\nasync function fetchAllStatus(\n api: TalerCoreBankHttpClient,\n token: AccessToken,\n options: Options,\n references: Date[],\n progress: (current: number, total: number) => void,\n): Promise> {\n const allMetrics: TalerCorebankApi.MonitorTimeframeParam[] = [];\n if (options.hourMetric) {\n allMetrics.push(TalerCorebankApi.MonitorTimeframeParam.hour);\n }\n if (options.dayMetric) {\n allMetrics.push(TalerCorebankApi.MonitorTimeframeParam.day);\n }\n if (options.monthMetric) {\n allMetrics.push(TalerCorebankApi.MonitorTimeframeParam.month);\n }\n if (options.yearMetric) {\n allMetrics.push(TalerCorebankApi.MonitorTimeframeParam.year);\n }\n\n /**\n * convert request into frames\n */\n const allFrames = allMetrics.flatMap((timeframe) =>\n references.map((reference) => ({\n reference,\n timeframe,\n moment: getTimeframesForDate(reference, timeframe),\n })),\n );\n const total = allFrames.length;\n\n /**\n * call API for info\n */\n const allInfo = await allFrames.reduce(\n async (prev, frame, index) => {\n const accumulatedMap = await prev;\n progress(index, total);\n // await delay()\n const previous = options.compareWithPrevious\n ? await api.getMonitor(token, {\n timeframe: frame.timeframe,\n date: frame.moment.previous,\n })\n : undefined;\n\n if (previous && previous.type === \"fail\" && options.endOnFirstFail) {\n return accumulatedMap; //skip\n }\n\n const current = await api.getMonitor(token, {\n timeframe: frame.timeframe,\n date: frame.moment.current,\n });\n\n if (current.type === \"fail\" && options.endOnFirstFail) {\n return accumulatedMap; //skip\n }\n\n const metricName =\n TalerCorebankApi.MonitorTimeframeParam[allMetrics[index]];\n accumulatedMap[metricName] = {\n reference: frame.reference,\n current: current.type !== \"ok\" ? undefined : current.body,\n previous:\n !previous || previous.type !== \"ok\" ? undefined : previous.body,\n };\n return accumulatedMap;\n },\n Promise.resolve({} as Record),\n );\n progress(total, total);\n\n /**\n * convert into table format\n *\n */\n const table: Array = [];\n if (options.includeHeader) {\n table.push([\n \"date\",\n \"metric\",\n \"reference\",\n \"talerInCount\",\n \"talerInVolume\",\n \"talerOutCount\",\n \"talerOutVolume\",\n \"cashinCount\",\n \"cashinFiatVolume\",\n \"cashinRegionalVolume\",\n \"cashoutCount\",\n \"cashoutFiatVolume\",\n \"cashoutRegionalVolume\",\n ]);\n }\n Object.entries(allInfo).forEach(([name, data]) => {\n if (data.current) {\n const row: TableRow = {\n date: data.reference.getTime(),\n metric: name,\n reference: \"current\",\n ...dataToRow(data.current),\n };\n table.push(Object.values(row) as string[]);\n }\n\n if (data.previous) {\n const row: TableRow = {\n date: data.reference.getTime(),\n metric: name,\n reference: \"previous\",\n ...dataToRow(data.previous),\n };\n table.push(Object.values(row) as string[]);\n }\n });\n\n const csv = table.reduce((acc, row) => {\n return acc + row.join(\",\") + \"\\n\";\n }, \"\");\n\n return opFixedSuccess(csv);\n}\n\ntype JustData = Omit, \"date\">, \"reference\">;\nfunction dataToRow(info: TalerCorebankApi.MonitorResponse): JustData {\n return {\n talerInCount: info.talerInCount,\n talerInVolume: info.talerInVolume,\n talerOutCount: info.talerOutCount,\n talerOutVolume: info.talerOutVolume,\n cashinCount: info.type === \"no-conversions\" ? undefined : info.cashinCount,\n cashinFiatVolume:\n info.type === \"no-conversions\" ? undefined : info.cashinFiatVolume,\n cashinRegionalVolume:\n info.type === \"no-conversions\" ? undefined : info.cashinRegionalVolume,\n cashoutCount:\n info.type === \"no-conversions\" ? undefined : info.cashoutCount,\n cashoutFiatVolume:\n info.type === \"no-conversions\" ? undefined : info.cashoutFiatVolume,\n cashoutRegionalVolume:\n info.type === \"no-conversions\" ? undefined : info.cashoutRegionalVolume,\n };\n}\n\ntype Data = {\n reference: Date;\n previous: TalerCorebankApi.MonitorResponse | undefined;\n current: TalerCorebankApi.MonitorResponse | undefined;\n};\ntype TableRow = {\n date: number;\n metric: string;\n reference: \"current\" | \"previous\";\n cashinCount?: number;\n cashinRegionalVolume?: AmountString;\n cashinFiatVolume?: AmountString;\n cashoutCount?: number;\n cashoutRegionalVolume?: AmountString;\n cashoutFiatVolume?: AmountString;\n talerInCount: number;\n talerInVolume: AmountString;\n talerOutCount: number;\n talerOutVolume: AmountString;\n};\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n Amounts,\n HttpStatusCode,\n TalerError,\n TalerErrorCode,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ButtonBetter,\n ErrorLoading,\n Loading,\n LocalNotificationBanner,\n RouteDefinition,\n ShowInputErrorLabel,\n notifyInfo,\n useBankCoreApiContext,\n useChallengeHandler,\n useLocalNotificationBetter,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { Fragment, VNode, h } from \"preact\";\nimport { useState } from \"preact/hooks\";\n\nimport { useAccountDetails } from \"../../hooks/account.js\";\nimport { useSessionState } from \"../../hooks/session.js\";\nimport { undefinedIfEmpty } from \"../../utils.js\";\nimport { LoginForm } from \"../LoginForm.js\";\nimport { doAutoFocus } from \"../PaytoWireTransferForm.js\";\nimport { SolveMFAChallenges } from \"../SolveMFA.js\";\nimport { UserAndToken } from \"@gnu-taler/taler-util\";\n\nconst TALER_SCREEN_ID = 125;\n\nexport function RemoveAccount({\n account,\n routeCancel,\n onUpdateSuccess,\n\n focus,\n}: {\n focus?: boolean;\n\n routeCancel: RouteDefinition;\n onUpdateSuccess: () => void;\n account: string;\n}): VNode {\n const { i18n } = useTranslationContext();\n const result = useAccountDetails(account);\n const [accountName, setAccountName] = useState();\n\n const { state } = useSessionState();\n const token = state.status !== \"loggedIn\" ? undefined : state.token;\n const {\n lib: { bank: api },\n } = useBankCoreApiContext();\n const [notification, safeFunctionHandler] = useLocalNotificationBetter();\n\n const mfa = useChallengeHandler();\n\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return (\n \n \n \n \n );\n }\n if (result.type === \"fail\") {\n switch (result.case) {\n case HttpStatusCode.Unauthorized:\n return ;\n case HttpStatusCode.NotFound:\n return ;\n default:\n assertUnreachable(result);\n }\n }\n\n const balance = Amounts.parse(result.body.balance.amount);\n if (!balance) {\n return (\n there was an error reading the balance\n );\n }\n const isBalanceEmpty = Amounts.isZero(balance);\n if (!isBalanceEmpty) {\n return (\n \n \n \n The account can't be delete while still holding some balance. First\n make sure that the owner make a complete cashout.\n \n \n
    \n \n Close\n \n
    \n
    \n );\n }\n\n const errors = undefinedIfEmpty({\n accountName: !accountName\n ? i18n.str`Required`\n : account !== accountName\n ? i18n.str`Name doesn't match`\n : undefined,\n });\n\n const deleteAccount = safeFunctionHandler(\n i18n.str`delete account`,\n (auth: UserAndToken, challengeIds: string[]) =>\n api.deleteAccount(auth, { challengeIds }),\n !!errors || !token ? undefined : [{ username: account, token }, []],\n );\n\n deleteAccount.onSuccess = (success) => {\n notifyInfo(i18n.str`Account removed`);\n onUpdateSuccess();\n };\n\n deleteAccount.onFail = (fail) => {\n switch (fail.case) {\n case HttpStatusCode.Unauthorized:\n return i18n.str`No enough permission to delete the account.`;\n case HttpStatusCode.NotFound:\n return i18n.str`The username was not found.`;\n case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT:\n return i18n.str`Can't delete a reserved username.`;\n case TalerErrorCode.BANK_ACCOUNT_BALANCE_NOT_ZERO:\n return i18n.str`Can't delete an account with balance different than zero.`;\n case HttpStatusCode.Accepted: {\n mfa.onChallengeRequired(fail.body);\n return i18n.str`A second factor authentication is required.`;\n }\n default:\n assertUnreachable(fail);\n }\n };\n\n const retryDeleteAccount = deleteAccount.lambda((ids: string[]) => [\n deleteAccount.args![0],\n ids,\n ]);\n\n if (mfa.pendingChallenge) {\n return (\n \n );\n }\n\n return (\n
    \n \n\n \n This step can't be undone.\n \n\n
    \n
    \n

    \n Deleting account \"{account}\"\n

    \n
    \n {\n e.preventDefault();\n }}\n >\n
    \n
    \n
    \n \n {i18n.str`Verification`}\n \n
    \n {\n setAccountName(e.currentTarget.value);\n }}\n placeholder={account}\n autocomplete=\"off\"\n />\n \n
    \n

    \n \n Enter the account name that is going to be deleted\n \n

    \n
    \n
    \n
    \n
    \n \n Cancel\n \n \n Delete\n \n
    \n \n
    \n
    \n );\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\nimport {\n AbsoluteTime,\n Amounts,\n HttpStatusCode,\n TalerError,\n assertUnreachable,\n} from \"@gnu-taler/taler-util\";\nimport {\n Attention,\n ErrorLoading,\n Loading,\n RenderAmount,\n RouteDefinition,\n Time,\n useTranslationContext,\n} from \"@gnu-taler/web-util/browser\";\nimport { VNode, h } from \"preact\";\n\nimport { useCashoutDetails, useConversionInfo } from \"../../hooks/regional.js\";\n\nconst TALER_SCREEN_ID = 128;\n\ninterface Props {\n id: string;\n routeClose: RouteDefinition;\n}\n\nShowCashoutDetails.SCREEN_ID = TALER_SCREEN_ID;\nexport function ShowCashoutDetails({ id, routeClose }: Props): VNode {\n const { i18n } = useTranslationContext();\n const cid = Number.parseInt(id, 10);\n\n const result = useCashoutDetails(Number.isNaN(cid) ? undefined : cid);\n const info = useConversionInfo();\n\n if (Number.isNaN(cid)) {\n return (\n \n );\n }\n if (!result) {\n return ;\n }\n if (result instanceof TalerError) {\n return ;\n }\n if (result.type === \"fail\") {\n switch (result.case) {\n case HttpStatusCode.NotFound:\n return (\n \n );\n case HttpStatusCode.NotImplemented:\n return (\n \n \n Cashout should be enabled in the configuration, the conversion\n rate should be initialized with fee(s), rates and a rounding mode.\n \n \n );\n default:\n assertUnreachable(result);\n }\n }\n if (!info) {\n return ;\n }\n\n if (info instanceof TalerError) {\n return ;\n }\n if (info.type === \"fail\") {\n switch (info.case) {\n case HttpStatusCode.NotImplemented: {\n return (\n \n \n Cashout should be enabled in the configuration, the conversion\n rate should be initialized with fee(s), rates and a rounding mode.\n \n \n );\n }\n default:\n assertUnreachable(info);\n }\n }\n\n const { fiat_currency_specification, regional_currency_specification } =\n info.body;\n\n return (\n
    \n
    \n
    \n

    \n Cashout detail\n

    \n
    \n
    \n
    \n Subject\n
    \n
    {result.body.subject}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n {result.body.creation_time.t_s !== \"never\" ? (\n
    \n
    \n Date\n
    \n
    \n \n
    \n
    \n ) : undefined}\n\n
    \n
    \n Debited\n
    \n
    \n \n
    \n
    \n\n
    \n
    \n \n Transferred\n \n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n \n Close\n \n
    \n
    \n );\n}\n", "\nexport interface StringsType {\n domain: string;\n lang: string;\n completeness: number;\n 'plural_forms': string;\n locale_data: {\n messages: Record;\n };\n};\nexport const strings: Record = {};\n\nstrings['uk'] = {\n \"locale_data\": {\n \"messages\": {\n \"\": {\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\",\n \"lang\": \"uk\"\n },\n \"An IBAN consists of capital letters and numbers only\": [\n \"IBAN \u043F\u043E\u0432\u0438\u043D\u0435\u043D \u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u043B\u0438\u0448\u0435 \u0432\u0435\u043B\u0438\u043A\u0456 \u043B\u0456\u0442\u0435\u0440\u0438 \u0442\u0430 \u0446\u0438\u0444\u0440\u0438\"\n ],\n \"IBAN numbers have more that 4 digits\": [\n \"\u041D\u043E\u043C\u0435\u0440\u0430 IBAN \u0437\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u043C\u0430\u044E\u0442\u044C \u0431\u0456\u043B\u044C\u0448\u0435 4-\u044C\u043E\u0445 \u0446\u0438\u0444\u0440\"\n ],\n \"IBAN numbers have less that 34 digits\": [\n \"\u041D\u043E\u043C\u0435\u0440\u0430 IBAN \u0437\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u043C\u0430\u044E\u0442\u044C \u043C\u0435\u043D\u0448\u0435 34-\u044C\u043E\u0445 \u0446\u0438\u0444\u0440\"\n ],\n \"IBAN country code not found\": [\n \"\u041A\u043E\u0434 \u043A\u0440\u0430\u0457\u043D\u0438 IBAN \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"IBAN number is not valid, checksum is wrong\": [\n \"\u041D\u043E\u043C\u0435\u0440 IBAN \u043D\u0435 \u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0438\u0439, \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430 \u0441\u0443\u043C\u0430 \u043D\u0435 \u0441\u0445\u043E\u0434\u0438\u0442\u044C\u0441\u044F\"\n ],\n \"Use letters, numbers or any of these characters: - . _ ~\": [\n \"\"\n ],\n \"Required\": [\n \"\u043E\u0431\u043E\u0432\u02BC\u044F\u0437\u043A\u043E\u0432\u043E\"\n ],\n \"confirm MFA challenge\": [\n \"\"\n ],\n \"Unknown challenge.\": [\n \"\"\n ],\n \"Failed to validate the verification code.\": [\n \"\"\n ],\n \"Too many challenges are active right now, you must wait or confirm current challenges.\": [\n \"\"\n ],\n \"Wrong authentication number.\": [\n \"\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0438\u0439 \u043D\u043E\u043C\u0435\u0440 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0457.\"\n ],\n \"Expired challenge.\": [\n \"\"\n ],\n \"Submit the transmitted code number.\": [\n \"\"\n ],\n \"The verification code sent to the email address starting with %1$s\": [\n \"\"\n ],\n \"The verification code sent to the phone number ending with %1$s\": [\n \"\"\n ],\n \"Code\": [\n \"\"\n ],\n \"Username of the account\": [\n \"\u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"It will expired at %1$s\": [\n \"\"\n ],\n \"The challenge is expired and can't be solved but you can go back and create a new challenge.\": [\n \"\"\n ],\n \"Back\": [\n \"\"\n ],\n \"Verify\": [\n \"\"\n ],\n \"send MFA challenge\": [\n \"\"\n ],\n \"Failed to send the verification code.\": [\n \"\"\n ],\n \"The request was valid, but the server is refusing action.\": [\n \"\"\n ],\n \"The backend is not aware of the specified MFA challenge.\": [\n \"\"\n ],\n \"It is too early to request another transmission of the challenge.\": [\n \"\"\n ],\n \"Code transmission failed.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u043D\u0435 \u0432\u0434\u0430\u043B\u0430\u0441\u044F.\"\n ],\n \"select challenge\": [\n \"\"\n ],\n \"Multi-factor authentication required\": [\n \"\u041F\u043E\u0442\u0440\u0456\u0431\u043D\u0430 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F\"\n ],\n \"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.\": [\n \"\"\n ],\n \"The next challenge needs to be completed to confirm the operation.\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457.\"\n ],\n \"All the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"One of the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"To an phone ending with \\\"%1$s\\\"\": [\n \"\"\n ],\n \"To an email starting with \\\" %1$s\\\"\": [\n \"\"\n ],\n \"I have a code\": [\n \"\"\n ],\n \"Send me a message\": [\n \"\"\n ],\n \"You have to wait until %1$s to send a new code.\": [\n \"\"\n ],\n \"Cancel\": [\n \"\"\n ],\n \"Complete\": [\n \"\"\n ],\n \"Unable to create a cashout\": [\n \"\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0441\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438\"\n ],\n \"The bank configuration does not support cashout operations.\": [\n \"\u041A\u043E\u043D\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044F \u0431\u0430\u043D\u043A\u0443 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0437\u0456 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438.\"\n ],\n \"Close\": [\n \"\u0417\u0430\u043A\u0440\u0438\u0442\u0438\"\n ],\n \"Cashout is disabled\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043E\"\n ],\n \"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"calculate conversion fee\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"The server didn't understand the request.\": [\n \"\u0426\u0435\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E.\"\n ],\n \"The amount is too small\": [\n \"\u041F\u0430\u0440\u043E\u043B\u0456 \u043D\u0435 \u0437\u0431\u0456\u0433\u0430\u044E\u0442\u044C\u0441\u044F\"\n ],\n \"Conversion is not implemented.\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0440\u0435\u0430\u043B\u0456\u0437\u043E\u0432\u0430\u043D\u043E\"\n ],\n \"At least debit or credit needs to be provided\": [\n \"\"\n ],\n \"The amount is malfored\": [\n \"\u0426\u0435\u0439 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u0438\u0439.\"\n ],\n \"The currency is not supported\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454\u0442\u044C\u0441\u044F\"\n ],\n \"Invalid\": [\n \"\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u043E\"\n ],\n \"Amount needs to be higher\": [\n \"\u043F\u043E\u0432\u0438\u043D\u043D\u0430 \u0431\u0443\u0442\u0438 \u0432\u0438\u0449\u043E\u044E \u0447\u0435\u0440\u0435\u0437 \u043A\u043E\u043C\u0456\u0441\u0456\u0457\"\n ],\n \"Balance is not enough\": [\n \"\u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u0456\u0439 \u0431\u0430\u043B\u0430\u043D\u0441\"\n ],\n \"It is not possible to cashout less than %1$s: %2$s\": [\n \"\"\n ],\n \"The total transfer to the destination will be zero\": [\n \"\u0437\u0430\u0433\u0430\u043B\u044C\u043D\u0430 \u0441\u0443\u043C\u0430 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443 \u043D\u0430 \u043C\u0456\u0441\u0446\u0456 \u043F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u0431\u0443\u0434\u0435 \u043D\u0443\u043B\u044C\u043E\u0432\u043E\u044E\"\n ],\n \"create cashout\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Cashout created\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043E\"\n ],\n \"Second factor authentication required.\": [\n \"\u041F\u043E\u0442\u0440\u0456\u0431\u043D\u0430 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F\"\n ],\n \"Account not found\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"Duplicated request detected, check if the operation succeeded or try again.\": [\n \"\u0412\u0438\u044F\u0432\u043B\u0435\u043D\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u0438\u0439 \u0437\u0430\u043F\u0438\u0442, \u043F\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435, \u0447\u0438 \u0431\u0443\u043B\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0443\u0441\u043F\u0456\u0448\u043D\u043E\u044E, \u0430\u0431\u043E \u0441\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u0449\u0435 \u0440\u0430\u0437.\"\n ],\n \"The conversion rate was applied incorrectly\": [\n \"\u041A\u0443\u0440\u0441 \u043E\u0431\u043C\u0456\u043D\u0443 \u0431\u0443\u043B\u043E \u0437\u0430\u0441\u0442\u043E\u0441\u043E\u0432\u0430\u043D\u043E \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\"\n ],\n \"The account does not have sufficient funds\": [\n \"\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Missing cashout URI in the profile\": [\n \"\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0456\u0439 URI \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0432 \u043F\u0440\u043E\u0444\u0456\u043B\u0456\"\n ],\n \"The amount is below the minimum amount permitted.\": [\n \"\"\n ],\n \"Sending the confirmation message failed, retry later or contact the administrator.\": [\n \"\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0437 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F\u043C, \u0441\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043F\u0456\u0437\u043D\u0456\u0448\u0435 \u0430\u0431\u043E \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430.\"\n ],\n \"The server doesn't support the current TAN channel.\": [\n \"\u0426\u0435\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E.\"\n ],\n \"Create cashout.\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Cashout\": [\n \"\u0412\u0438\u043F\u043B\u0430\u0442\u0438 \u0433\u043E\u0442\u0456\u0432\u043A\u043E\u044E\"\n ],\n \"Conversion rate\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Balance\": [\n \"\u0411\u0430\u043B\u0430\u043D\u0441\"\n ],\n \"Fee\": [\n \"\u041A\u043E\u043C\u0456\u0441\u0456\u044F\"\n ],\n \"To account\": [\n \"\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A\"\n ],\n \"Legal name\": [\n \"\"\n ],\n \"If this name doesn't match the account holder's name, your transaction may fail.\": [\n \"\"\n ],\n \"Unable to cashout\": [\n \"\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0441\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438\"\n ],\n \"Before being able to cashout to a bank account, you need to complete your profile\": [\n \"\u041F\u0435\u0440\u0448 \u043D\u0456\u0436 \u0437\u0434\u0456\u0439\u0441\u043D\u0438\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438, \u0432\u0430\u043C \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0437\u0430\u043F\u043E\u0432\u043D\u0438\u0442\u0438 \u0441\u0432\u0456\u0439 \u043F\u0440\u043E\u0444\u0456\u043B\u044C\"\n ],\n \"Transfer subject\": [\n \"\u041F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"Currency\": [\n \"\"\n ],\n \"Send %1$s\": [\n \"\"\n ],\n \"Receive %1$s\": [\n \"\u0412\u0456\u0442\u0430\u0454\u043C\u043E, %1$s\"\n ],\n \"Amount\": [\n \"\u0421\u0443\u043C\u0430\"\n ],\n \"Total cost\": [\n \"\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0430 \u0432\u0430\u0440\u0442\u0456\u0441\u0442\u044C\"\n ],\n \"Balance left\": [\n \"\u0417\u0430\u043B\u0438\u0448\u043E\u043A \u0431\u0430\u043B\u0430\u043D\u0441\u0443\"\n ],\n \"Before fee\": [\n \"\u041A\u043E\u043C\u0456\u0441\u0456\u044F \u0434\u043E\"\n ],\n \"Total cashout transfer\": [\n \"\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0430 \u0441\u0443\u043C\u0430 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438\"\n ],\n \"Not valid\": [\n \"\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439\"\n ],\n \"Does not follow the pattern\": [\n \"\u043D\u0435 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u0430\u0454 \u0448\u0430\u0431\u043B\u043E\u043D\u0443\"\n ],\n \"send transaction\": [\n \"\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0456\u0439 \u043F\u043E\u043A\u0438 \u0449\u043E \u043D\u0435\u043C\u0430\u0454.\"\n ],\n \"The wire transfer was successfully completed!\": [\n \"\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E!\"\n ],\n \"The request was invalid or the payto://-URI used unacceptable features.\": [\n \"\u0417\u0430\u043F\u0438\u0442 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439 \u0430\u0431\u043E payto://-URI \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0454 \u043D\u0435\u043F\u0440\u0438\u043F\u0443\u0441\u0442\u0438\u043C\u0456 \u0444\u0443\u043D\u043A\u0446\u0456\u0457.\"\n ],\n \"Not enough permission to complete the operation.\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457.\"\n ],\n \"The bank administrator cannot be the transfer creditor.\": [\n \"\"\n ],\n \"The destination account \\\"%1$s\\\" was not found.\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \\\"%1$s\\\" \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E.\"\n ],\n \"The origin and the destination of the transfer can't be the same.\": [\n \"\u0414\u0436\u0435\u0440\u0435\u043B\u043E \u0442\u0430 \u043C\u0456\u0441\u0446\u0435 \u043F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443 \u043D\u0435 \u043C\u043E\u0436\u0443\u0442\u044C \u0431\u0443\u0442\u0438 \u043E\u0434\u043D\u0430\u043A\u043E\u0432\u0438\u043C\u0438.\"\n ],\n \"Your balance is not sufficient for the operation.\": [\n \"\u0412\u0430\u0448 \u0431\u0430\u043B\u0430\u043D\u0441 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u0456\u0439 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457.\"\n ],\n \"The origin account \\\"%1$s\\\" was not found.\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0434\u0436\u0435\u0440\u0435\u043B\u0430 \\\"%1$s\\\" \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E.\"\n ],\n \"The attempt to create the transaction has failed. Please try again.\": [\n \"\"\n ],\n \"A second factor authentication is required.\": [\n \"\u0423\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E\"\n ],\n \"Confirm wire transfer.\": [\n \"\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\"\n ],\n \"Input wire transfer detail\": [\n \"\u0414\u0435\u0442\u0430\u043B\u0456 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"Using a form\": [\n \"\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0447\u0438 \u0444\u043E\u0440\u043C\u0443\"\n ],\n \"A special URI that specifies the amount to be transferred and the destination account.\": [\n \"\"\n ],\n \"QR code\": [\n \"\u0412\u0456\u0434\u043F\u0440\u0430\u0432\u0438\u0442\u0438 \u043A\u043E\u0434\"\n ],\n \"If your device has a camera, you can import a payto:// URI from a QR code.\": [\n \"\"\n ],\n \"Recipient\": [\n \"\u041E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\"\n ],\n \"ID of the recipient's account\": [\n \"IBAN \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"username\": [\n \"\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"IBAN of the recipient's account\": [\n \"IBAN \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"Subject\": [\n \"\u041F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F\"\n ],\n \"Some text to identify the transfer\": [\n \"\u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0457 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"Amount to transfer\": [\n \"\u0441\u0443\u043C\u0430 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"Payto URI:\": [\n \"payto URI:\"\n ],\n \"Uniform resource identifier of the target account\": [\n \"\u0443\u043D\u0456\u0444\u0456\u043A\u043E\u0432\u0430\u043D\u0438\u0439 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0440\u0435\u0441\u0443\u0440\u0441\u0443 \u0446\u0456\u043B\u044C\u043E\u0432\u043E\u0433\u043E \u0440\u0430\u0445\u0443\u043D\u043A\u0443\"\n ],\n \"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://x-taler-bank/[o\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u0431\u0430\u043D\u043A\u0443]/[p\u0430\u0445\u0443\u043D\u043E\u043A \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430]?message=[\u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u043B\u0430\u0442\u0435\u0436\u0443]&amount=[%1$s:X.Y]\"\n ],\n \"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://iban/[iban \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430]?message=[\u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u043B\u0430\u0442\u0435\u0436\u0443]&amount=[%1$s:X.Y]\"\n ],\n \"The maximum amount for a wire transfer is %1$s\": [\n \"\"\n ],\n \"Cost\": [\n \"\"\n ],\n \"Send\": [\n \"\u0417\u0434\u0456\u0439\u0441\u043D\u0438\u0442\u0438 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\"\n ],\n \"Only \\\"x-taler-bank\\\" target are supported\": [\n \"\u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u044E\u0442\u044C\u0441\u044F \u043B\u0438\u0448\u0435 \u0446\u0456\u043B\u0456 \\\"IBAN\\\"\"\n ],\n \"Only this host is allowed. Use \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Account name is missing\": [\n \"\u041E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Only \\\"IBAN\\\" target are supported\": [\n \"\u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u044E\u0442\u044C\u0441\u044F \u043B\u0438\u0448\u0435 \u0446\u0456\u043B\u0456 \\\"IBAN\\\"\"\n ],\n \"Missing \\\"amount\\\" parameter to specify the amount to be transferred\": [\n \"\u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 \\\"amount\\\", \u0449\u043E\u0431 \u0432\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u0443\u043C\u0443 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"The \\\"amount\\\" parameter is not valid\": [\n \"\u0441\u0443\u043C\u0430 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0430\"\n ],\n \"\\\"message\\\" parameters to specify a reference text for the transfer are missing\": [\n \"\u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 \\\"message\\\", \u0449\u043E\u0431 \u0432\u043A\u0430\u0437\u0430\u0442\u0438 \u0434\u043E\u0432\u0456\u0434\u043A\u043E\u0432\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"The only currency allowed is \\\"%1$s\\\"\": [\n \"\"\n ],\n \"You cannot transfer an amount of zero.\": [\n \"\u0412\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u0443\u043C\u0443, \u0449\u043E \u0434\u043E\u0440\u0456\u0432\u043D\u044E\u0454 \u043D\u0443\u043B\u044E.\"\n ],\n \"The balance is not sufficient\": [\n \"\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Please enter a longer subject\": [\n \"\u041F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"Show withdrawal confirmation\": [\n \"\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Withdraw without setting amount\": [\n \"\"\n ],\n \"Hide demo hint.\": [\n \"\"\n ],\n \"Show install wallet first\": [\n \"\u0421\u043F\u043E\u0447\u0430\u0442\u043A\u0443 \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u0438, \u044F\u043A \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C\"\n ],\n \"Currently, the bank is not accepting new registrations!\": [\n \"\u041D\u0430\u0440\u0430\u0437\u0456 \u0431\u0430\u043D\u043A \u043D\u0435 \u043F\u0440\u0438\u0439\u043C\u0430\u0454 \u043D\u043E\u0432\u0456 \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0457!\"\n ],\n \"The name is missing\": [\n \"\"\n ],\n \"Missing username\": [\n \"\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0454 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"Missing password\": [\n \"\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0456\u0439 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"The password should be longer than 8 letters\": [\n \"\u043C\u0430\u0454 \u0431\u0443\u0442\u0438 \u0431\u0456\u043B\u044C\u0448\u0438\u043C \u0437\u0430 0\"\n ],\n \"The passwords do not match\": [\n \"\u041F\u0430\u0440\u043E\u043B\u0456 \u043D\u0435 \u0437\u0431\u0456\u0433\u0430\u044E\u0442\u044C\u0441\u044F\"\n ],\n \"register new account\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Server replied with invalid phone or email.\": [\n \"\u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0432, \u0449\u043E \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u0430\u0431\u043E \u0435\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0430 \u043F\u043E\u0448\u0442\u0430 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0456.\"\n ],\n \"You are not authorised to create this account.\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043D\u044F \u0446\u044C\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443.\"\n ],\n \"Registration is disabled because the bank ran out of bonus credit.\": [\n \"\u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F \u0432\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0430, \u043E\u0441\u043A\u0456\u043B\u044C\u043A\u0438 \u0431\u0430\u043D\u043A \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u0432 \u0431\u043E\u043D\u0443\u0441\u043D\u0438\u0439 \u043A\u0440\u0435\u0434\u0438\u0442.\"\n ],\n \"That username can't be used because is reserved.\": [\n \"\u0426\u0435 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438, \u043E\u0441\u043A\u0456\u043B\u044C\u043A\u0438 \u0432\u043E\u043D\u043E \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043E\u0432\u0430\u043D\u0435.\"\n ],\n \"That username is already taken.\": [\n \"\u0426\u0435 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u0435.\"\n ],\n \"That account ID is already taken.\": [\n \"\u0426\u0435\u0439 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u0438\u0439.\"\n ],\n \"No information for the selected authentication channel.\": [\n \"\u041D\u0435\u043C\u0430\u0454 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u0457 \u043F\u0440\u043E \u043E\u0431\u0440\u0430\u043D\u0438\u0439 \u043A\u0430\u043D\u0430\u043B \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0457.\"\n ],\n \"Authentication channel is not supported.\": [\n \"\u041A\u0430\u043D\u0430\u043B \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0457 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454\u0442\u044C\u0441\u044F.\"\n ],\n \"Only an administrator is allowed to set the debt limit.\": [\n \"\u041B\u0438\u0448\u0435 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0443 \u0434\u043E\u0437\u0432\u043E\u043B\u0435\u043D\u043E \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u044E\u0432\u0430\u0442\u0438 \u043B\u0456\u043C\u0456\u0442 \u0431\u043E\u0440\u0433\u0443.\"\n ],\n \"Only the administrator can change the conversion rate.\": [\n \"\u041B\u0438\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0439 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438.\"\n ],\n \"The conversion rate class doesn't exist.\": [\n \"\u041A\u0443\u0440\u0441 \u043E\u0431\u043C\u0456\u043D\u0443 \u0431\u0443\u043B\u043E \u0437\u0430\u0441\u0442\u043E\u0441\u043E\u0432\u0430\u043D\u043E \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\"\n ],\n \"Only admin can create accounts with second factor authentication.\": [\n \"\u041B\u0438\u0448\u0435 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0437\u0430\u043F\u0438\u0441\u0438 \u0437 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u043E\u044E \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0454\u044E.\"\n ],\n \"The password is too short. Can't have less than 8 characters.\": [\n \"\u043C\u0430\u0454 \u0431\u0443\u0442\u0438 \u0431\u0456\u043B\u044C\u0448\u0438\u043C \u0437\u0430 0\"\n ],\n \"The password is too long. Can't have more than 64 characters.\": [\n \"\u043C\u0430\u0454 \u0431\u0443\u0442\u0438 \u0431\u0456\u043B\u044C\u0448\u0438\u043C \u0437\u0430 0\"\n ],\n \"Account registration\": [\n \"\u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Login username\": [\n \"\u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"account identification to login\": [\n \"\u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432 \u0431\u0430\u043D\u043A\u0443\"\n ],\n \"Password\": [\n \"\u041F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers\": [\n \"\"\n ],\n \"Repeat password\": [\n \"\u041F\u043E\u0432\u0442\u043E\u0440\u0456\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Same password\": [\n \"\u041D\u043E\u0432\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Full name\": [\n \"\"\n ],\n \"Register\": [\n \"\u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F\"\n ],\n \"Create a random temporary user\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0432\u0438\u043F\u0430\u0434\u043A\u043E\u0432\u043E\u0433\u043E \u0442\u0438\u043C\u0447\u0430\u0441\u043E\u0432\u043E\u0433\u043E \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"logout\": [\n \"\"\n ],\n \"login\": [\n \"\"\n ],\n \"The account has no rights to login.\": [\n \"\"\n ],\n \"The account is locked and cannot login. Contact administrator.\": [\n \"\"\n ],\n \"Wrong credentials for \\\"%1$s\\\"\": [\n \"\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0434\u0430\u043D\u0456 \u0434\u043B\u044F \\\"%1$s\\\"\"\n ],\n \"Account login.\": [\n \"\u041E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Session expired\": [\n \"\u0422\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0437\u0430\u043A\u0456\u043D\u0447\u0438\u0432\u0441\u044F.\"\n ],\n \"Username\": [\n \"\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"identification\": [\n \"\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F\"\n ],\n \"Password of the account\": [\n \"\u043F\u0430\u0440\u043E\u043B\u044C \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Forget\": [\n \"\"\n ],\n \"Log in\": [\n \"\u0423\u0432\u0456\u0439\u0442\u0438\"\n ],\n \"Transactions history\": [\n \"\"\n ],\n \"No transactions yet.\": [\n \"\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0456\u0439 \u043F\u043E\u043A\u0438 \u0449\u043E \u043D\u0435\u043C\u0430\u0454.\"\n ],\n \"You can make a transfer or a withdrawal to your wallet.\": [\n \"\"\n ],\n \"Date\": [\n \"\u0414\u0430\u0442\u0430\"\n ],\n \"Counterpart\": [\n \"\u041A\u043E\u043D\u0442\u0440\u0440\u0430\u0445\u0443\u043D\u043E\u043A\"\n ],\n \"sent\": [\n \"\u0432\u0456\u0434\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E\"\n ],\n \"received\": [\n \"\u043E\u0442\u0440\u0438\u043C\u0430\u043D\u043E\"\n ],\n \"Invalid value\": [\n \"\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F\"\n ],\n \"to\": [\n \"\u0434\u043E\"\n ],\n \"from\": [\n \"\u0432\u0456\u0434\"\n ],\n \"First page\": [\n \"\u041F\u0435\u0440\u0448\u0430 \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0430\"\n ],\n \"Next\": [\n \"\u0414\u0430\u043B\u0456\"\n ],\n \"confirm withdrawal\": [\n \"\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"cambiar\": [\n \"\"\n ],\n \"abort withdrawal\": [\n \"\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"The withdrawal has been aborted previously and can't be confirmed\": [\n \"\u0412\u0438\u0432\u0435\u0434\u0435\u043D\u043D\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u0431\u0443\u043B\u043E \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E \u0440\u0430\u043D\u0456\u0448\u0435 \u0456 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043E\"\n ],\n \"The withdrawal operation can't be confirmed before a wallet accepted the transaction.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438, \u0434\u043E\u043A\u0438 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C \u043D\u0435 \u043F\u0440\u0438\u0439\u043C\u0435 \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0456\u044E.\"\n ],\n \"The operation ID is invalid.\": [\n \"\u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439.\"\n ],\n \"The operation was not found.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E.\"\n ],\n \"The starting withdrawal amount and the confirmation amount differs.\": [\n \"\"\n ],\n \"The bank requires a bank account which has not been specified yet.\": [\n \"\"\n ],\n \"Bad request\": [\n \"\"\n ],\n \"The withdrawal operation has been aborted.\": [\n \"\u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"The withdrawal operation has been confirmed previously and can\u2019t be aborted.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043D\u043D\u044F \u0431\u0443\u043B\u0430 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u0430 \u0440\u0430\u043D\u0456\u0448\u0435 \u0456 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u0430\"\n ],\n \"Complete withdrawal.\": [\n \"\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Confirm the withdrawal operation\": [\n \"\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Wire transfer details\": [\n \"\u0414\u0435\u0442\u0430\u043B\u0456 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"Payment Service Provider's account number\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler\"\n ],\n \"Payment Service Provider's name\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler\"\n ],\n \"Payment Service Provider's account bank hostname\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler\"\n ],\n \"Payment Service Provider's account id\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler\"\n ],\n \"Payment Service Provider's account address\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler\"\n ],\n \"Payment Service Provider's account cyclos hostname\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler\"\n ],\n \"No amount has yet been determined.\": [\n \"\"\n ],\n \"Transfer\": [\n \"\u041F\u0435\u0440\u0435\u043A\u0430\u0437\u0430\u0442\u0438\"\n ],\n \"Authentication required\": [\n \"\u041F\u043E\u0442\u0440\u0456\u0431\u043D\u0430 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F\"\n ],\n \"This operation was created with another username\": [\n \"\u0426\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0431\u0443\u043B\u0430 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u0430 \u0437 \u0456\u043D\u0448\u0438\u043C \u0456\u043C\u0435\u043D\u0435\u043C \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"You are currently logged in with user \\\"%1$s\\\" and the operation was made with user \\\"%2$s\\\"\": [\n \"\"\n ],\n \"The reserve operation has been confirmed previously and can't be aborted\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043D\u043D\u044F \u0431\u0443\u043B\u0430 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u0430 \u0440\u0430\u043D\u0456\u0448\u0435 \u0456 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u0430\"\n ],\n \"Wire transfer completed!\": [\n \"\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E!\"\n ],\n \"Confirm withdrawal.\": [\n \"\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Unauthorized to make the operation, maybe the session has expired or the password changed.\": [\n \"\u041D\u0435 \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u043E\u0432\u0430\u043D\u043E \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457, \u043C\u043E\u0436\u043B\u0438\u0432\u043E, \u0441\u0435\u0441\u0456\u044F \u0437\u0430\u043A\u0456\u043D\u0447\u0438\u043B\u0430\u0441\u044F \u0430\u0431\u043E \u043F\u0430\u0440\u043E\u043B\u044C \u0431\u0443\u043B\u043E \u0437\u043C\u0456\u043D\u0435\u043D\u043E.\"\n ],\n \"The operation was rejected due to insufficient funds.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0431\u0443\u043B\u043E \u0432\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u043E \u0447\u0435\u0440\u0435\u0437 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u0456\u0441\u0442\u044C \u043A\u043E\u0448\u0442\u0456\u0432.\"\n ],\n \"Withdrawal confirmed\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043E\"\n ],\n \"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.\": [\n \"\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u0434\u043E \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 Taler \u0431\u0443\u043B\u043E \u0456\u043D\u0456\u0446\u0456\u0439\u043E\u0432\u0430\u043D\u043E. \u041D\u0435\u0437\u0430\u0431\u0430\u0440\u043E\u043C \u0432\u0438 \u043E\u0442\u0440\u0438\u043C\u0430\u0454\u0442\u0435 \u0437\u0430\u043F\u0438\u0442\u0430\u043D\u0443 \u0441\u0443\u043C\u0443 \u0443 \u0432\u0430\u0448 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C Taler.\"\n ],\n \"Do not show this again\": [\n \"\u0411\u0456\u043B\u044C\u0448\u0435 \u043D\u0435 \u043F\u043E\u043A\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0446\u0435\"\n ],\n \"If you have a Taler wallet installed on this device\": [\n \"\u042F\u043A\u0449\u043E \u043D\u0430 \u0446\u044C\u043E\u043C\u0443 \u043F\u0440\u0438\u0441\u0442\u0440\u043E\u0457 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C Taler\"\n ],\n \"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions\": [\n \"\u0412\u0438 \u043F\u043E\u0431\u0430\u0447\u0438\u0442\u0435 \u0434\u0435\u0442\u0430\u043B\u0456 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0443 \u0432\u0430\u0448\u043E\u043C\u0443\u0433\u0430\u043C\u0430\u043D\u0446\u0456, \u0432\u043A\u043B\u044E\u0447\u0430\u044E\u0447\u0438 \u043A\u043E\u043C\u0456\u0441\u0456\u0457 (\u044F\u043A\u0449\u043E \u0454). \u042F\u043A\u0449\u043E \u0443 \u0432\u0430\u0441 \u0439\u043E\u0433\u043E \u0449\u0435 \u043D\u0435\u043C\u0430\u0454, \u0432\u0438 \u043C\u043E\u0436\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u0439\u043E\u0433\u043E, \u0434\u043E\u0442\u0440\u0438\u043C\u0443\u044E\u0447\u0438\u0441\u044C \u0456\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0456\u0439 \u0443\"\n ],\n \"on this page\": [\n \"\u0446\u0456\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u0446\u0456\"\n ],\n \"Withdraw\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"In case you have a Taler wallet on another device\": [\n \"\u0410\u0431\u043E \u044F\u043A\u0449\u043E \u0443 \u0432\u0430\u0441 \u0454 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C \u043D\u0430 \u0456\u043D\u0448\u043E\u043C\u0443 \u043F\u0440\u0438\u0441\u0442\u0440\u043E\u0457\"\n ],\n \"Scan the QR below to start the withdrawal.\": [\n \"\u0421\u043A\u0430\u043D\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434 \u043D\u0438\u0436\u0447\u0435, \u0449\u043E\u0431 \u0440\u043E\u0437\u043F\u043E\u0447\u0430\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432.\"\n ],\n \"create withdrawal\": [\n \"\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"The server replied with an invalid taler://withdraw URI\": [\n \"\u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0432 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u043C URI \u0434\u043B\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Withdraw URI: %1$s\": [\n \"URI \u0434\u043B\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432: %1$s\"\n ],\n \"The operation was rejected due to insufficient funds\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0431\u0443\u043B\u043E \u0432\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u043E \u0447\u0435\u0440\u0435\u0437 \u0431\u0440\u0430\u043A \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Current balance is %1$s\": [\n \"\"\n ],\n \"You can withdraw up to %1$s\": [\n \"\"\n ],\n \"Continue\": [\n \"\u041F\u0440\u043E\u0434\u043E\u0432\u0436\u0438\u0442\u0438\"\n ],\n \"Use your Taler wallet\": [\n \"\u041F\u0456\u0434\u0433\u043E\u0442\u0443\u0439\u0442\u0435 \u0441\u0432\u0456\u0439 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C\"\n ],\n \"After using your wallet you will need to authorize or cancel the operation on this site.\": [\n \"\u041F\u0456\u0441\u043B\u044F \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F \u0432\u0430\u0448\u043E\u0433\u043E \u0433\u0430\u043C\u0430\u043D\u0446\u044F \u0412\u0430\u043C \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0431\u0443\u0434\u0435 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u0430\u0431\u043E \u0441\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u043D\u0430 \u0446\u044C\u043E\u043C\u0443 \u0441\u0430\u0439\u0442\u0456.\"\n ],\n \"You need a Taler wallet\": [\n \"\u0412\u0430\u043C \u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C GNU Taler\"\n ],\n \"If you don't have one yet you can follow the instruction in\": [\n \"\u042F\u043A\u0449\u043E \u0443 \u0432\u0430\u0441 \u0439\u043E\u0433\u043E \u0449\u0435 \u043D\u0435\u043C\u0430\u0454, \u0432\u0438 \u043C\u043E\u0436\u0435\u0442\u0435 \u0434\u043E\u0442\u0440\u0438\u043C\u0443\u0432\u0430\u0442\u0438\u0441\u044F \u0456\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0456\u0439 \u0443\"\n ],\n \"this page\": [\n \"\u0446\u0456\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u0446\u0456\"\n ],\n \"Send money\": [\n \"\u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u0433\u0440\u043E\u0448\u0456\"\n ],\n \"to a Taler wallet\": [\n \"\u0434\u043E \u0433\u0430\u043C\u0430\u043D\u0446\u044F %1$s\"\n ],\n \"Withdraw digital money into your mobile wallet or browser extension\": [\n \"\u0417\u043D\u0456\u043C\u0456\u0442\u044C \u0446\u0438\u0444\u0440\u043E\u0432\u0456 \u0433\u0440\u043E\u0448\u0456 \u0443 \u0412\u0430\u0448 \u043C\u043E\u0431\u0456\u043B\u044C\u043D\u0438\u0439 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C \u0430\u0431\u043E \u0440\u043E\u0437\u0448\u0438\u0440\u0435\u043D\u043D\u044F \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\"\n ],\n \"to another bank account\": [\n \"\u043D\u0430 \u0456\u043D\u0448\u0438\u0439 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u0440\u0430\u0445\u0443\u043D\u043E\u043A\"\n ],\n \"Make a wire transfer to an account with known bank account number.\": [\n \"\u0417\u0434\u0456\u0439\u0441\u043D\u0456\u0442\u044C \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u043D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A \u0456\u0437 \u0432\u0456\u0434\u043E\u043C\u0438\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u0440\u0430\u0445\u0443\u043D\u043A\u0443.\"\n ],\n \"This is a demo\": [\n \"\u0426\u0435 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0456\u0439\u043D\u0438\u0439 \u0431\u0430\u043D\u043A\"\n ],\n \"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .\": [\n \"\u0426\u044F \u0447\u0430\u0441\u0442\u0438\u043D\u0430 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0456\u0457 \u043F\u043E\u043A\u0430\u0437\u0443\u0454, \u044F\u043A \u043F\u0440\u0430\u0446\u044E\u0432\u0430\u0432 \u0431\u0438 \u0431\u0430\u043D\u043A, \u0449\u043E \u0431\u0435\u0437\u043F\u043E\u0441\u0435\u0440\u0435\u0434\u043D\u044C\u043E \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 Taler. \u041E\u043A\u0440\u0456\u043C \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F \u0432\u0430\u0448\u043E\u0433\u043E \u0432\u043B\u0430\u0441\u043D\u043E\u0433\u043E \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u0440\u0430\u0445\u0443\u043D\u043A\u0443, \u0432\u0438 \u0442\u0430\u043A\u043E\u0436 \u043C\u043E\u0436\u0435\u0442\u0435 \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0456\u0441\u0442\u043E\u0440\u0456\u044E \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0456\u0439 \u0434\u0435\u044F\u043A\u0438\u0445 %1$s.\"\n ],\n \"Here you will be able to see how a bank that supports Taler directly would work.\": [\n \"\u0426\u044F \u0447\u0430\u0441\u0442\u0438\u043D\u0430 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0456\u0457 \u043F\u043E\u043A\u0430\u0437\u0443\u0454, \u044F\u043A \u043F\u0440\u0430\u0446\u044E\u0432\u0430\u0432 \u0431\u0438 \u0431\u0430\u043D\u043A, \u0449\u043E \u0431\u0435\u0437\u043F\u043E\u0441\u0435\u0440\u0435\u0434\u043D\u044C\u043E \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 Taler.\"\n ],\n \"Internal error, please report. There should be more information in the console.\": [\n \"\"\n ],\n \"Internal error, please report.\": [\n \"\u0412\u043D\u0443\u0442\u0440\u0456\u0448\u043D\u044F \u043F\u043E\u043C\u0438\u043B\u043A\u0430, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u0442\u0435 \u043F\u0440\u043E \u0446\u0435.\"\n ],\n \"Preferences\": [\n \"\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F\"\n ],\n \"Show debug information\": [\n \"\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044E \u0434\u043B\u044F \u0432\u0456\u0434\u043B\u0430\u0434\u043A\u0438\"\n ],\n \"Welcome\": [\n \"\u0412\u0456\u0442\u0430\u0454\u043C\u043E\"\n ],\n \"Welcome, %1$s\": [\n \"\u0412\u0456\u0442\u0430\u0454\u043C\u043E, %1$s\"\n ],\n \"No enough permission to access the conversion rate list.\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457.\"\n ],\n \"Conversion list not found. Maybe conversion rate is not supported.\": [\n \"\"\n ],\n \"Conversion list not implemented.\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0440\u0435\u0430\u043B\u0456\u0437\u043E\u0432\u0430\u043D\u043E\"\n ],\n \"Conversion rate classes\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Create conversion rate class\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"No conversion rate class\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Name\": [\n \"\u041D\u0430\u0437\u0432\u0430\"\n ],\n \"Description\": [\n \"\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0434\u0435\u043C\u043E \u043E\u043F\u0438\u0441\"\n ],\n \"Cashin\": [\n \"\u041F\u043E\u043F\u043E\u0432\u043D\u0435\u043D\u043D\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u043E\u044E\"\n ],\n \"min:\": [\n \"\"\n ],\n \"fee:\": [\n \"\"\n ],\n \"Select a section\": [\n \"\u041E\u0431\u0435\u0440\u0456\u0442\u044C \u0440\u043E\u0437\u0434\u0456\u043B\"\n ],\n \"Details\": [\n \"\u0414\u0435\u0442\u0430\u043B\u0456\"\n ],\n \"Delete\": [\n \"\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438\"\n ],\n \"Credentials\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0434\u0430\u043D\u0456\"\n ],\n \"Cashouts\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438\"\n ],\n \"Conversion\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"only admin can setup conversion\": [\n \"\u041B\u0438\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0439 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438.\"\n ],\n \"calculate cashout fee\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"update conversion rate\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Wrong credentials\": [\n \"\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0434\u0430\u043D\u0456 \u0434\u043B\u044F \\\"%1$s\\\"\"\n ],\n \"Conversion is disabled\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Config cashout\": [\n \"\u0412\u0438\u043F\u043B\u0430\u0442\u0438 \u0433\u043E\u0442\u0456\u0432\u043A\u043E\u044E\"\n ],\n \"Config cashin\": [\n \"\u041F\u043E\u043F\u043E\u0432\u043D\u0435\u043D\u043D\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u043E\u044E\"\n ],\n \"Bad ratios\": [\n \"\"\n ],\n \"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.\": [\n \"\"\n ],\n \"Initial amount\": [\n \"\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430 \u0441\u0443\u043C\u0430 \u0437\u043D\u044F\u0442\u0442\u044F\"\n ],\n \"Use it to test how the conversion will affect the amount.\": [\n \"\"\n ],\n \"Sending to this bank\": [\n \"\"\n ],\n \"Converted\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Cashin after fee\": [\n \"\"\n ],\n \"Sending from this bank\": [\n \"\"\n ],\n \"Cashout after fee\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043E\"\n ],\n \"Bad configuration\": [\n \"\"\n ],\n \"This configuration allows users to cash out more of what has been cashed in.\": [\n \"\"\n ],\n \"Update\": [\n \"\u041E\u043D\u043E\u0432\u0438\u0442\u0438\"\n ],\n \"Rnvalid\": [\n \"\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u043E\"\n ],\n \"Must be > 0\": [\n \"\"\n ],\n \"Minimum amount\": [\n \"\"\n ],\n \"Only cashout operation above this threshold will be allowed.\": [\n \"\"\n ],\n \"Ratio\": [\n \"\"\n ],\n \"Conversion ratio between currencies\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Example conversion\": [\n \"\"\n ],\n \"1 %1$s will be converted into %2$s %3$s\": [\n \"\"\n ],\n \"Tiny amount\": [\n \"\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A\"\n ],\n \"Rounding mode\": [\n \"\"\n ],\n \"Zero\": [\n \"\"\n ],\n \"Amount will be round below to the largest possible value smaller than the input.\": [\n \"\"\n ],\n \"Up\": [\n \"\"\n ],\n \"Amount will be round up to the smallest possible value larger than the input.\": [\n \"\"\n ],\n \"Nearest\": [\n \"\"\n ],\n \"Amount will be round to the closest possible value.\": [\n \"\"\n ],\n \"If none specified the fallback value is \\\"%1$s \\\".\": [\n \"\"\n ],\n \"Examples\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.1\": [\n \"\"\n ],\n \"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.\": [\n \"\"\n ],\n \"With the \\\"zero\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.1\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.3\": [\n \"\"\n ],\n \"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.5\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.3\": [\n \"\"\n ],\n \"Amount to be deducted before amount is credited.\": [\n \"\"\n ],\n \"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"delete conversion rate class\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Unauthorized\": [\n \"\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"Forbidden\": [\n \"\"\n ],\n \"NotFound\": [\n \"\"\n ],\n \"NotImplemented\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0440\u0435\u0430\u043B\u0456\u0437\u043E\u0432\u0430\u043D\u043E\"\n ],\n \"update conversion rate class\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Not Found\": [\n \"\"\n ],\n \"Not implemented\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0440\u0435\u0430\u043B\u0456\u0437\u043E\u0432\u0430\u043D\u043E\"\n ],\n \"The name of the conversion is already used.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0432\u0436\u0435 \u0456\u0441\u043D\u0443\u0454\"\n ],\n \"Conversion rate class\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Accounts\": [\n \"\u0420\u0430\u0445\u0443\u043D\u043A\u0438\"\n ],\n \"Test\": [\n \"\"\n ],\n \"Users\": [\n \"\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"Can't remove the conversion rate class\": [\n \"\"\n ],\n \"There are some user associated to this class. You need to remove them first.\": [\n \"\"\n ],\n \"You are going to remove the conversion rate class\": [\n \"\u0412\u0438 \u0437\u0431\u0438\u0440\u0430\u0454\u0442\u0435\u0441\u044F \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"This step can't be undone.\": [\n \"\u0426\u0435\u0439 \u043A\u0440\u043E\u043A \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0441\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438.\"\n ],\n \"Filters\": [\n \"\"\n ],\n \"Show from other classes\": [\n \"\"\n ],\n \"Account\": [\n \"\u0420\u0430\u0445\u0443\u043D\u043E\u043A\"\n ],\n \"Group ID\": [\n \"\"\n ],\n \"No users in this conversion rate class\": [\n \"\"\n ],\n \"Class\": [\n \"\"\n ],\n \"Action\": [\n \"\u0414\u0456\u0457\"\n ],\n \"Remove\": [\n \"\u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438\"\n ],\n \"Add\": [\n \"\"\n ],\n \"Conversion rate name\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Short description of the class\": [\n \"\"\n ],\n \"create conversion rate class\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Conversion rate class created.\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"The rights to change the account are not sufficient\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0437\u043C\u0456\u043D\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"New conversion rate class\": [\n \"\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Create\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438\"\n ],\n \"History of public accounts\": [\n \"\u0406\u0441\u0442\u043E\u0440\u0456\u044F \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0438\u0445 \u0440\u0430\u0445\u0443\u043D\u043A\u0456\u0432\"\n ],\n \"Make a wire transfer\": [\n \"\u0417\u0434\u0456\u0439\u0441\u043D\u0438\u0442\u0438 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\"\n ],\n \"Scan the QR code below to start the withdrawal.\": [\n \"\u0421\u043A\u0430\u043D\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434 \u043D\u0438\u0436\u0447\u0435, \u0449\u043E\u0431 \u0440\u043E\u0437\u043F\u043E\u0447\u0430\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432.\"\n ],\n \"Operation aborted\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E\"\n ],\n \"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.\": [\n \"\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u043D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 Taler Exchange \u0431\u0443\u043B\u043E \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E, \u0432\u0430\u0448 \u0431\u0430\u043B\u0430\u043D\u0441 \u043D\u0435 \u043F\u043E\u0441\u0442\u0440\u0430\u0436\u0434\u0430\u0432.\"\n ],\n \"Go to your wallet now\": [\n \"\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0434\u043E \u0433\u0430\u043C\u0430\u043D\u0446\u044F \u0437\u0430\u0440\u0430\u0437\"\n ],\n \"The operation is marked as selected, but a process during the withdrawal failed\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u043F\u043E\u0437\u043D\u0430\u0447\u0435\u043D\u0430 \u044F\u043A '\u0432\u0438\u0431\u0440\u0430\u043D\u0430', \u0430\u043B\u0435 \u0434\u0435\u044F\u043A\u0438\u0439 \u043A\u0440\u043E\u043A \u0443 \u043F\u0440\u043E\u0446\u0435\u0441\u0456 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u0442\u0438\"\n ],\n \"A withdrawal reserve ID was not found and no account has been selected.\": [\n \"\u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E, \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u0432\u0438\u0431\u0440\u0430\u043D\u043E \u0430\u0431\u043E \u0432\u0438\u0431\u0440\u0430\u043D\u0438\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439.\"\n ],\n \"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.\": [\n \"\u0404 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432, \u0430\u043B\u0435 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u0432\u0438\u0431\u0440\u0430\u043D\u043E \u0430\u0431\u043E \u0432\u0438\u0431\u0440\u0430\u043D\u0438\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439.\"\n ],\n \"The account was selected, but no withdrawal reserve ID was found.\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0432\u0438\u0431\u0440\u0430\u043D\u043E, \u0430\u043B\u0435 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E.\"\n ],\n \"Operation not found\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.\": [\n \"\u0426\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u043D\u0435\u0432\u0456\u0434\u043E\u043C\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0443. \u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0438\u0439 \u0430\u0431\u043E \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0438\u0434\u0430\u043B\u0438\u0432 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044E \u043F\u0440\u043E \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0434\u043E \u0457\u0457 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043D\u044F.\"\n ],\n \"Continue to dashboard\": [\n \"\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0434\u043E \u043F\u0430\u043D\u0435\u043B\u0456 \u043A\u0435\u0440\u0443\u0432\u0430\u043D\u043D\u044F\"\n ],\n \"The Withdrawal URI is not valid\": [\n \"URI \u0434\u043B\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439\"\n ],\n \"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.\": [\n \"\"\n ],\n \"Latest cashouts\": [\n \"\u041E\u0441\u0442\u0430\u043D\u043D\u0456 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438\"\n ],\n \"Created\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0435\u043D\u043E\"\n ],\n \"Total debit\": [\n \"\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0438\u0439 \u0434\u0435\u0431\u0435\u0442\"\n ],\n \"Total credit\": [\n \"\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0438\u0439 \u043A\u0440\u0435\u0434\u0438\u0442\"\n ],\n \"Cashout for account %1$s\": [\n \"\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0434\u043B\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 %1$s\"\n ],\n \"Invalid email format\": [\n \"\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F\"\n ],\n \"Should start with +\": [\n \"\u043F\u043E\u0432\u0438\u043D\u0435\u043D \u043F\u043E\u0447\u0438\u043D\u0430\u0442\u0438\u0441\u044F \u0437 +\"\n ],\n \"A phone number consists of numbers only\": [\n \"\u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u043F\u043E\u0432\u0438\u043D\u0435\u043D \u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u043B\u0438\u0448\u0435 \u0446\u0438\u0444\u0440\u0438\"\n ],\n \"Account ID for authentication\": [\n \"\u0414\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0430 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F\"\n ],\n \"Name of the account holder\": [\n \"\u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Internal account\": [\n \"\u043D\u0430 \u0456\u043D\u0448\u0438\u0439 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u0440\u0430\u0445\u0443\u043D\u043E\u043A\"\n ],\n \"If this field is empty, a random account ID will be assigned\": [\n \"\u044F\u043A\u0449\u043E \u043F\u043E\u0440\u043E\u0436\u043D\u044C\u043E, \u0431\u0443\u0434\u0435 \u043F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043E \u0432\u0438\u043F\u0430\u0434\u043A\u043E\u0432\u0438\u0439 \u043D\u043E\u043C\u0435\u0440 \u0440\u0430\u0445\u0443\u043D\u043A\u0443\"\n ],\n \"You can copy and share this IBAN number in order to receive wire transfers to your bank account\": [\n \"\"\n ],\n \"Email\": [\n \"Email\"\n ],\n \"To be used when second factor authentication is enabled\": [\n \"\u0423\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E\"\n ],\n \"Phone\": [\n \"\u0422\u0435\u043B\u0435\u0444\u043E\u043D\"\n ],\n \"Enable second factor authentication\": [\n \"\u0423\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E\"\n ],\n \"Using email\": [\n \"\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0447\u0438 email\"\n ],\n \"Add an email in your profile to enable this option\": [\n \"\u0434\u043E\u0434\u0430\u0439\u0442\u0435 \u0435\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0443 \u043F\u043E\u0448\u0442\u0443 \u0443 \u0432\u0430\u0448\u043E\u043C\u0443 \u043F\u0440\u043E\u0444\u0456\u043B\u0456, \u0449\u043E\u0431 \u0443\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0446\u044E \u043E\u043F\u0446\u0456\u044E\"\n ],\n \"Using SMS\": [\n \"\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0447\u0438 SMS\"\n ],\n \"Add a phone number in your profile to enable this option\": [\n \"\u0434\u043E\u0434\u0430\u0439\u0442\u0435 \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u0443 \u0432\u0430\u0448\u043E\u043C\u0443 \u043F\u0440\u043E\u0444\u0456\u043B\u0456, \u0449\u043E\u0431 \u0443\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0446\u044E \u043E\u043F\u0446\u0456\u044E\"\n ],\n \"Cashout account\": [\n \"\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0456\u0439 \u0440\u0430\u0445\u0443\u043D\u043E\u043A \u0434\u043B\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438\"\n ],\n \"External account number where the money is going to be sent when doing cashouts\": [\n \"\u043D\u043E\u043C\u0435\u0440 \u0440\u0430\u0445\u0443\u043D\u043A\u0443, \u043D\u0430 \u044F\u043A\u0438\u0439 \u0431\u0443\u0434\u0443\u0442\u044C \u0432\u0456\u0434\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0456 \u0433\u0440\u043E\u0448\u0456 \u043F\u0440\u0438 \u0437\u043D\u044F\u0442\u0442\u0456 \u0433\u043E\u0442\u0456\u0432\u043A\u0438\"\n ],\n \"Max debt\": [\n \"\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0438\u0439 \u0431\u043E\u0440\u0433\"\n ],\n \"How much the balance can go below zero.\": [\n \"\"\n ],\n \"Is this account public?\": [\n \"\u0426\u0435\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0454 \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0438\u043C?\"\n ],\n \"Public accounts have their balance publicly accessible\": [\n \"\u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0456 \u0440\u0430\u0445\u0443\u043D\u043A\u0438 \u043C\u0430\u044E\u0442\u044C \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u043E \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u0431\u0430\u043B\u0430\u043D\u0441\"\n ],\n \"Does this account belong to a Payment Service Provider?\": [\n \"\u0426\u0435\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0454 \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0438\u043C?\"\n ],\n \"update account\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Account updated\": [\n \"\u0420\u0430\u0445\u0443\u043D\u043E\u043A \u043E\u043D\u043E\u0432\u043B\u0435\u043D\u043E\"\n ],\n \"The username was not found\": [\n \"\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"You can't change the legal name, please contact the your account administrator.\": [\n \"\u0412\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u044E\u0440\u0438\u0434\u0438\u0447\u043D\u0435 \u0456\u043C'\u044F, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0430\u0448\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443.\"\n ],\n \"You can't change the debt limit, please contact the your account administrator.\": [\n \"\u0412\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043B\u0456\u043C\u0456\u0442 \u0431\u043E\u0440\u0433\u0443, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0430\u0448\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443.\"\n ],\n \"You can't change the cashout address, please contact the your account administrator.\": [\n \"\u0412\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0430\u0448\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443.\"\n ],\n \"Update account information.\": [\n \"\u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Account \\\"%1$s\\\"\": [\n \"\u0420\u0430\u0445\u0443\u043D\u043E\u043A \\\"%1$s\\\"\"\n ],\n \"Removed\": [\n \"\u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438\"\n ],\n \"This account can't be used.\": [\n \"\u0426\u0435\u0439 \u043A\u0440\u043E\u043A \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0441\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438.\"\n ],\n \"Change details\": [\n \"\u0417\u043C\u0456\u043D\u0430 \u0440\u0435\u043A\u0432\u0456\u0437\u0438\u0442\u0456\u0432\"\n ],\n \"Merchant integration\": [\n \"\u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the \\\"import\\\" button in the \\\"bank account\\\" section.\": [\n \"\"\n ],\n \"Account type\": [\n \"\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Method to use for wire transfer.\": [\n \"\u0417\u0434\u0456\u0439\u0441\u043D\u0438\u0442\u0438 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\"\n ],\n \"IBAN\": [\n \"\"\n ],\n \"International Bank Account Number.\": [\n \"\"\n ],\n \"Account name\": [\n \"\u041E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443\"\n ],\n \"Bank host where the service is located.\": [\n \"\"\n ],\n \"Bank account identifier for wire transfers.\": [\n \"\u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0434\u043B\u044F \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443\"\n ],\n \"Address\": [\n \"\"\n ],\n \"Owner's name\": [\n \"\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430\"\n ],\n \"Legal name of the person holding the account.\": [\n \"\u0456\u043C'\u044F \u043E\u0441\u043E\u0431\u0438, \u044F\u043A\u0456\u0439 \u043D\u0430\u043B\u0435\u0436\u0438\u0442\u044C \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Account info URL\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"From where the merchant can download information about incoming wire transfers to this account.\": [\n \"\"\n ],\n \"Repeated password doesn't match\": [\n \"\u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0441\u043F\u0456\u0432\u043F\u0430\u0434\u0430\u0454\"\n ],\n \"update password\": [\n \"\u041E\u043D\u043E\u0432\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Password changed\": [\n \"\u041F\u0430\u0440\u043E\u043B\u044C \u0437\u043C\u0456\u043D\u0435\u043D\u043E\"\n ],\n \"Not authorized to change the password, maybe the session is invalid.\": [\n \"\u041D\u0435\u043C\u0430\u0454 \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0437\u043C\u0456\u043D\u0438 \u043F\u0430\u0440\u043E\u043B\u044F, \u043C\u043E\u0436\u043B\u0438\u0432\u043E, \u0441\u0435\u0430\u043D\u0441 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439.\"\n ],\n \"You need to provide the old password. If you don't have it contact your account administrator.\": [\n \"\u0412\u0430\u043C \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u043D\u0430\u0434\u0430\u0442\u0438 \u0441\u0442\u0430\u0440\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C. \u042F\u043A\u0449\u043E \u0443 \u0432\u0430\u0441 \u0439\u043E\u0433\u043E \u043D\u0435\u043C\u0430\u0454, \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0430\u0448\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443.\"\n ],\n \"Your current password doesn't match, can't change to a new password.\": [\n \"\u0412\u0430\u0448 \u043F\u043E\u0442\u043E\u0447\u043D\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0437\u0431\u0456\u0433\u0430\u0454\u0442\u044C\u0441\u044F, \u043D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043D\u0430 \u043D\u043E\u0432\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C.\"\n ],\n \"You don't have the rights to change the password.\": [\n \"\"\n ],\n \"Update account password.\": [\n \"\u041E\u043D\u043E\u0432\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Update password\": [\n \"\u041E\u043D\u043E\u0432\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Current password\": [\n \"\u041F\u043E\u0442\u043E\u0447\u043D\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Your current password, for security\": [\n \"\u0432\u0430\u0448 \u043F\u043E\u0442\u043E\u0447\u043D\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C, \u0434\u043B\u044F \u0431\u0435\u0437\u043F\u0435\u043A\u0438\"\n ],\n \"New password\": [\n \"\u041D\u043E\u0432\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Type it again\": [\n \"\u0412\u0432\u0435\u0434\u0456\u0442\u044C \u0439\u043E\u0433\u043E \u0449\u0435 \u0440\u0430\u0437\"\n ],\n \"Repeat the same password\": [\n \"\u043F\u043E\u0432\u0442\u043E\u0440\u0456\u0442\u044C \u0442\u043E\u0439 \u0441\u0430\u043C\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Change\": [\n \"\u0417\u043C\u0456\u043D\u0438\u0442\u0438\"\n ],\n \"Create account\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Actions\": [\n \"\u0414\u0456\u0457\"\n ],\n \"Unknown\": [\n \"\u043D\u0435\u0432\u0456\u0434\u043E\u043C\u043E\"\n ],\n \"Change password\": [\n \"\u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Querying for the current stats failed\": [\n \"\"\n ],\n \"The request parameters are wrong\": [\n \"\"\n ],\n \"The user is unauthorized\": [\n \"\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"Querying for the previous stats failed\": [\n \"\"\n ],\n \"Transaction volume report\": [\n \"\"\n ],\n \"Last hour\": [\n \"\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0433\u043E\u0434\u0438\u043D\u0430\"\n ],\n \"Previous day\": [\n \"\"\n ],\n \"Last month\": [\n \"\u041E\u0441\u0442\u0430\u043D\u043D\u0456\u0439 \u043C\u0456\u0441\u044F\u0446\u044C\"\n ],\n \"Last year\": [\n \"\u041E\u0441\u0442\u0430\u043D\u043D\u0456\u0439 \u0440\u0456\u043A\"\n ],\n \"Last Year\": [\n \"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u0440\u0456\u043A\"\n ],\n \"Trading volume from %1$s to %2$s\": [\n \"\u041E\u0431\u0441\u044F\u0433 \u0442\u043E\u0440\u0433\u0456\u0432 \u043D\u0430 %1$s \u043F\u043E\u0440\u0456\u0432\u043D\u044F\u043D\u043E \u0437 %2$s\"\n ],\n \"Transferred from an external account to an account in this bank.\": [\n \"\"\n ],\n \"Transferred from an account in this bank to an external account.\": [\n \"\u0417\u0434\u0456\u0439\u0441\u043D\u0456\u0442\u044C \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u043D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A \u0456\u0437 \u0432\u0456\u0434\u043E\u043C\u0438\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u0440\u0430\u0445\u0443\u043D\u043A\u0443.\"\n ],\n \"Payin\": [\n \"\u0412\u043D\u0435\u0441\u0435\u043D\u043D\u044F \u043A\u043E\u0448\u0442\u0456\u0432\"\n ],\n \"Transferred from an account to a Taler exchange.\": [\n \"\"\n ],\n \"Payout\": [\n \"\u0412\u0438\u043F\u043B\u0430\u0442\u0430\"\n ],\n \"Transferred from a Taler exchange to another account.\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler\"\n ],\n \"Download stats as CSV\": [\n \"\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0443 \u0444\u043E\u0440\u043C\u0430\u0442\u0456 CSV\"\n ],\n \"previous\": [\n \"\"\n ],\n \"Decreased by\": [\n \"\u0417\u043C\u0435\u043D\u0448\u0438\u043B\u043E\u0441\u044C \u043D\u0430\"\n ],\n \"Increased by\": [\n \"\u0417\u0431\u0456\u043B\u044C\u0448\u0438\u043B\u043E\u0441\u044C \u043D\u0430\"\n ],\n \"create account\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Account created with password \\\"%1$s\\\".\": [\n \"\"\n ],\n \"Server replied that phone or email is invalid\": [\n \"\u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0432, \u0449\u043E \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u0430\u0431\u043E \u0435\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0430 \u043F\u043E\u0448\u0442\u0430 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0456\"\n ],\n \"The rights to perform the operation are not sufficient\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457\"\n ],\n \"Account username is already taken\": [\n \"\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u043E\"\n ],\n \"Account ID is already taken\": [\n \"\u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u0438\u0439\"\n ],\n \"Bank ran out of bonus credit.\": [\n \"\u0423 \u0431\u0430\u043D\u043A\u0443 \u0437\u0430\u043A\u0456\u043D\u0447\u0438\u0432\u0441\u044F \u0431\u043E\u043D\u0443\u0441\u043D\u0438\u0439 \u043A\u0440\u0435\u0434\u0438\u0442.\"\n ],\n \"Account username can't be used because is reserved\": [\n \"\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438, \u043E\u0441\u043A\u0456\u043B\u044C\u043A\u0438 \u0432\u043E\u043D\u043E \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043E\u0432\u0430\u043D\u0435\"\n ],\n \"Can't create accounts\": [\n \"\u041D\u0435 \u0432\u0434\u0430\u0454\u0442\u044C\u0441\u044F \u0441\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438\"\n ],\n \"Only system admin can create accounts.\": [\n \"\u041B\u0438\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0439 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438.\"\n ],\n \"New bank account\": [\n \"\u041D\u043E\u0432\u0438\u0439 \u0431\u0456\u0437\u043D\u0435\u0441 \u0440\u0430\u0445\u0443\u043D\u043E\u043A\"\n ],\n \"download statistics\": [\n \"\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0443 \u0444\u043E\u0440\u043C\u0430\u0442\u0456 CSV\"\n ],\n \"only admin can download stats\": [\n \"\u041B\u0438\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0439 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438.\"\n ],\n \"Download bank stats\": [\n \"\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0431\u0430\u043D\u043A\u0443\"\n ],\n \"Include hour metric\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u0447\u0430\u0441\u043E\u0432\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443\"\n ],\n \"Include day metric\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u0434\u043E\u0431\u043E\u0432\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443\"\n ],\n \"Include month metric\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u043C\u0456\u0441\u044F\u0447\u043D\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443\"\n ],\n \"Include year metric\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u0440\u0456\u0447\u043D\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443\"\n ],\n \"Include table header\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0442\u0430\u0431\u043B\u0438\u0446\u0456\"\n ],\n \"Add previous metric for compare\": [\n \"\u0414\u043E\u0434\u0430\u0442\u0438 \u043F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443 \u0434\u043B\u044F \u043F\u043E\u0440\u0456\u0432\u043D\u044F\u043D\u043D\u044F\"\n ],\n \"Fail on first error\": [\n \"\u0417\u0431\u0456\u0439 \u043D\u0430 \u043F\u0435\u0440\u0448\u0456\u0439 \u043F\u043E\u043C\u0438\u043B\u0446\u0456\"\n ],\n \"Download\": [\n \"\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438\"\n ],\n \"downloading... %1$s\": [\n \"\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F...%1$s\"\n ],\n \"Download completed\": [\n \"\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E\"\n ],\n \"Click here to save the file in your computer.\": [\n \"\u043D\u0430\u0442\u0438\u0441\u043D\u0456\u0442\u044C \u0442\u0443\u0442, \u0449\u043E\u0431 \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0444\u0430\u0439\u043B \u043D\u0430 \u0432\u0430\u0448\u043E\u043C\u0443 \u043A\u043E\u043C\u043F'\u044E\u0442\u0435\u0440\u0456\"\n ],\n \"there was an error reading the balance\": [\n \"\"\n ],\n \"Can't delete the account\": [\n \"\u041D\u0435 \u0432\u0434\u0430\u0454\u0442\u044C\u0441\u044F \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438, \u043F\u043E\u043A\u0438 \u043D\u0430 \u043D\u044C\u043E\u043C\u0443 \u0454 \u0431\u0430\u043B\u0430\u043D\u0441. \u0421\u043F\u043E\u0447\u0430\u0442\u043A\u0443 \u043F\u0435\u0440\u0435\u043A\u043E\u043D\u0430\u0439\u0442\u0435\u0441\u044F, \u0449\u043E \u0432\u043B\u0430\u0441\u043D\u0438\u043A \u0437\u0440\u043E\u0431\u0438\u0432 \u043F\u043E\u0432\u043D\u0435 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432.\"\n ],\n \"Name doesn't match\": [\n \"\u0456\u043C'\u044F \u043D\u0435 \u0437\u0431\u0456\u0433\u0430\u0454\u0442\u044C\u0441\u044F\"\n ],\n \"delete account\": [\n \"\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Account removed\": [\n \"\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043E\"\n ],\n \"No enough permission to delete the account.\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443.\"\n ],\n \"The username was not found.\": [\n \"\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E.\"\n ],\n \"Can't delete a reserved username.\": [\n \"\u041D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043E\u0432\u0430\u043D\u0435 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430.\"\n ],\n \"Can't delete an account with balance different than zero.\": [\n \"\u041D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0437 \u0431\u0430\u043B\u0430\u043D\u0441\u043E\u043C, \u0432\u0456\u0434\u043C\u0456\u043D\u043D\u0438\u043C \u0432\u0456\u0434 \u043D\u0443\u043B\u044F.\"\n ],\n \"Remove account.\": [\n \"\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A\"\n ],\n \"You are going to remove the account\": [\n \"\u0412\u0438 \u0437\u0431\u0438\u0440\u0430\u0454\u0442\u0435\u0441\u044F \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\"\n ],\n \"Deleting account \\\"%1$s\\\"\": [\n \"\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \\\"%1$s\\\"\"\n ],\n \"Verification\": [\n \"\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F\"\n ],\n \"Enter the account name that is going to be deleted\": [\n \"\u0432\u0432\u0435\u0434\u0456\u0442\u044C \u0456\u043C'\u044F \u0440\u0430\u0445\u0443\u043D\u043A\u0443, \u044F\u043A\u0438\u0439 \u0431\u0443\u0434\u0435 \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043E\"\n ],\n \"Cashout id should be a number\": [\n \"\u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043F\u043E\u0432\u0438\u043D\u0435\u043D \u0431\u0443\u0442\u0438 \u0447\u0438\u0441\u043B\u043E\u043C\"\n ],\n \"This cashout not found. Maybe already aborted.\": [\n \"\u0426\u0435 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E. \u041C\u043E\u0436\u043B\u0438\u0432\u043E, \u0439\u043E\u0433\u043E \u0432\u0436\u0435 \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E.\"\n ],\n \"Cashout detail\": [\n \"\u0414\u0435\u0442\u0430\u043B\u0456 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438\"\n ],\n \"Debited\": [\n \"\u0414\u0435\u0431\u0435\u0442\u043E\u0432\u0430\u043D\u043E\"\n ],\n \"Transferred\": [\n \"\u041F\u0435\u0440\u0435\u043A\u0430\u0437\u0430\u0442\u0438\"\n ],\n \"You have no permission to this account.\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443.\"\n ],\n \"This account is locked. If you have a active session you can change the password or contact the administrator.\": [\n \"\"\n ],\n \"New web session\": [\n \"\"\n ],\n \"Welcome to %1$s!\": [\n \"\u041B\u0430\u0441\u043A\u0430\u0432\u043E \u043F\u0440\u043E\u0441\u0438\u043C\u043E \u0434\u043E %1$s!\"\n ]\n }\n },\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\",\n \"lang\": \"uk\",\n \"completeness\": 72\n};\n\nstrings['ru'] = {\n \"locale_data\": {\n \"messages\": {\n \"\": {\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\",\n \"lang\": \"ru\"\n },\n \"An IBAN consists of capital letters and numbers only\": [\n \"IBAN \u0434\u043E\u043B\u0436\u0435\u043D \u0441\u043E\u0441\u0442\u043E\u044F\u0442\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u0438\u0437 \u043F\u0440\u043E\u043F\u0438\u0441\u043D\u044B\u0445 \u0431\u0443\u043A\u0432 \u0438 \u0446\u0438\u0444\u0440\"\n ],\n \"IBAN numbers have more that 4 digits\": [\n \"\u041D\u043E\u043C\u0435\u0440\u0430 IBAN \u043E\u0431\u044B\u0447\u043D\u043E \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442 \u0431\u043E\u043B\u0435\u0435 4 \u0446\u0438\u0444\u0440\"\n ],\n \"IBAN numbers have less that 34 digits\": [\n \"\u041D\u043E\u043C\u0435\u0440\u0430 IBAN \u043E\u0431\u044B\u0447\u043D\u043E \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442 \u043C\u0435\u043D\u0435\u0435 34 \u0446\u0438\u0444\u0440\"\n ],\n \"IBAN country code not found\": [\n \"\u041A\u043E\u0434 \u0441\u0442\u0440\u0430\u043D\u044B IBAN \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\"\n ],\n \"IBAN number is not valid, checksum is wrong\": [\n \"\u041D\u043E\u043C\u0435\u0440 IBAN \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D, \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0441\u0443\u043C\u043C\u0430 \u043D\u0435\u0432\u0435\u0440\u043D\u0430\"\n ],\n \"Use letters, numbers or any of these characters: - . _ ~\": [\n \"\"\n ],\n \"Required\": [\n \"\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E\"\n ],\n \"confirm MFA challenge\": [\n \"\"\n ],\n \"Unknown challenge.\": [\n \"\"\n ],\n \"Failed to validate the verification code.\": [\n \"\"\n ],\n \"Too many challenges are active right now, you must wait or confirm current challenges.\": [\n \"\"\n ],\n \"Wrong authentication number.\": [\n \"\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 \u043D\u043E\u043C\u0435\u0440 \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438.\"\n ],\n \"Expired challenge.\": [\n \"\"\n ],\n \"Submit the transmitted code number.\": [\n \"\"\n ],\n \"The verification code sent to the email address starting with %1$s\": [\n \"\"\n ],\n \"The verification code sent to the phone number ending with %1$s\": [\n \"\"\n ],\n \"Code\": [\n \"\"\n ],\n \"Username of the account\": [\n \"\u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"It will expired at %1$s\": [\n \"\"\n ],\n \"The challenge is expired and can't be solved but you can go back and create a new challenge.\": [\n \"\"\n ],\n \"Back\": [\n \"\"\n ],\n \"Verify\": [\n \"\"\n ],\n \"send MFA challenge\": [\n \"\"\n ],\n \"Failed to send the verification code.\": [\n \"\"\n ],\n \"The request was valid, but the server is refusing action.\": [\n \"\"\n ],\n \"The backend is not aware of the specified MFA challenge.\": [\n \"\"\n ],\n \"It is too early to request another transmission of the challenge.\": [\n \"\"\n ],\n \"Code transmission failed.\": [\n \"\"\n ],\n \"select challenge\": [\n \"\"\n ],\n \"Multi-factor authentication required\": [\n \"\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\"\n ],\n \"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.\": [\n \"\"\n ],\n \"The next challenge needs to be completed to confirm the operation.\": [\n \"\u041D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u0434\u043B\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438.\"\n ],\n \"All the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"One of the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"To an phone ending with \\\"%1$s\\\"\": [\n \"\"\n ],\n \"To an email starting with \\\" %1$s\\\"\": [\n \"\"\n ],\n \"I have a code\": [\n \"\"\n ],\n \"Send me a message\": [\n \"\"\n ],\n \"You have to wait until %1$s to send a new code.\": [\n \"\"\n ],\n \"Cancel\": [\n \"\u041E\u0442\u043C\u0435\u043D\u0430\"\n ],\n \"Complete\": [\n \"\"\n ],\n \"Unable to create a cashout\": [\n \"\u041D\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044F \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u0432\u044B\u043F\u043B\u0430\u0442\u0443\"\n ],\n \"The bank configuration does not support cashout operations.\": [\n \"\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F \u0431\u0430\u043D\u043A\u0430 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u044B\u043F\u043B\u0430\u0442\u044B.\"\n ],\n \"Close\": [\n \"\u0417\u0430\u043A\u0440\u044B\u0442\u044C\"\n ],\n \"Cashout is disabled\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0430\"\n ],\n \"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"calculate conversion fee\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"The server didn't understand the request.\": [\n \"\u042D\u0442\u043E\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E.\"\n ],\n \"The amount is too small\": [\n \"\u041F\u0430\u0440\u043E\u043B\u044C \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u044B\u0439.\"\n ],\n \"Conversion is not implemented.\": [\n \"\u041E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0430 \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u0430\"\n ],\n \"At least debit or credit needs to be provided\": [\n \"\"\n ],\n \"The amount is malfored\": [\n \"\u042D\u0442\u043E\u0442 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0441\u0447\u0451\u0442\u0430 \u0443\u0436\u0435 \u0437\u0430\u043D\u044F\u0442.\"\n ],\n \"The currency is not supported\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u044B \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F\"\n ],\n \"Invalid\": [\n \"\u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E\"\n ],\n \"Amount needs to be higher\": [\n \"\u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u0432\u044B\u0448\u0435 \u0438\u0437-\u0437\u0430 \u043A\u043E\u043C\u0438\u0441\u0441\u0438\u0439\"\n ],\n \"Balance is not enough\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043D\u0430 \u0431\u0430\u043B\u0430\u043D\u0441\u0435\"\n ],\n \"It is not possible to cashout less than %1$s: %2$s\": [\n \"\"\n ],\n \"The total transfer to the destination will be zero\": [\n \"\u043E\u0431\u0449\u0430\u044F \u0441\u0443\u043C\u043C\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0432 \u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0432\u043D\u0430 \u043D\u0443\u043B\u044E\"\n ],\n \"create cashout\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C\"\n ],\n \"Cashout created\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0430\"\n ],\n \"Second factor authentication required.\": [\n \"\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\"\n ],\n \"Account not found\": [\n \"\u0423\u0447\u0451\u0442\u043D\u0430\u044F \u0437\u0430\u043F\u0438\u0441\u044C \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430\"\n ],\n \"Duplicated request detected, check if the operation succeeded or try again.\": [\n \"\u041E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D \u0434\u0443\u0431\u043B\u0438\u043A\u0430\u0442 \u0437\u0430\u043F\u0440\u043E\u0441\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435, \u0443\u0441\u043F\u0435\u0448\u043D\u043E \u043B\u0438 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F, \u0438\u043B\u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u043F\u044B\u0442\u043A\u0443.\"\n ],\n \"The conversion rate was applied incorrectly\": [\n \"\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D \u043A\u0443\u0440\u0441 \u043A\u043E\u043D\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438\"\n ],\n \"The account does not have sufficient funds\": [\n \"\u041D\u0430 \u0441\u0447\u0435\u0442\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0441\u0440\u0435\u0434\u0441\u0442\u0432\"\n ],\n \"Missing cashout URI in the profile\": [\n \"\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0439 URI \u0432\u044B\u043B\u0430\u0442 \u0432 \u043F\u0440\u043E\u0444\u0438\u043B\u0435\"\n ],\n \"The amount is below the minimum amount permitted.\": [\n \"\"\n ],\n \"Sending the confirmation message failed, retry later or contact the administrator.\": [\n \"\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0441 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0435\u043C, \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u043F\u044B\u0442\u043A\u0443 \u043F\u043E\u0437\u0436\u0435 \u0438\u043B\u0438 \u043E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0443.\"\n ],\n \"The server doesn't support the current TAN channel.\": [\n \"\u042D\u0442\u043E\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E.\"\n ],\n \"Create cashout.\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C\"\n ],\n \"Cashout\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u0430\"\n ],\n \"Conversion rate\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Balance\": [\n \"\u0411\u0430\u043B\u0430\u043D\u0441\"\n ],\n \"Fee\": [\n \"\u041A\u043E\u043C\u0438\u0441\u0441\u0438\u044F\"\n ],\n \"To account\": [\n \"\u041D\u0430 \u0441\u0447\u0451\u0442\"\n ],\n \"Legal name\": [\n \"\"\n ],\n \"If this name doesn't match the account holder's name, your transaction may fail.\": [\n \"\"\n ],\n \"Unable to cashout\": [\n \"\u041D\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044F \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u0432\u044B\u043F\u043B\u0430\u0442\u0443\"\n ],\n \"Before being able to cashout to a bank account, you need to complete your profile\": [\n \"\u041F\u0435\u0440\u0435\u0434 \u0442\u0435\u043C, \u043A\u0430\u043A \u0441\u0434\u0435\u043B\u0430\u0442\u044C \u0432\u044B\u043F\u043B\u0430\u0442\u0443, \u0432\u0430\u043C \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u0437\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u0441\u0432\u043E\u0439 \u043F\u0440\u043E\u0444\u0438\u043B\u044C\"\n ],\n \"Transfer subject\": [\n \"\u041F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"Currency\": [\n \"\"\n ],\n \"Send %1$s\": [\n \"\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C %1$s\"\n ],\n \"Receive %1$s\": [\n \"\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C %1$s\"\n ],\n \"Amount\": [\n \"\u0421\u0443\u043C\u043C\u0430\"\n ],\n \"Total cost\": [\n \"\u041E\u0431\u0449\u0430\u044F \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C\"\n ],\n \"Balance left\": [\n \"\u041E\u0441\u0442\u0430\u0442\u043E\u043A \u0431\u0430\u043B\u0430\u043D\u0441\u0430\"\n ],\n \"Before fee\": [\n \"\u041A\u043E\u043C\u0438\u0441\u0441\u0438\u044F \u0434\u043E\"\n ],\n \"Total cashout transfer\": [\n \"\u041E\u0431\u0449\u0438\u0439 \u0441\u0443\u043C\u043C\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0432\u044B\u043F\u043B\u0430\u0442\u044B\"\n ],\n \"Not valid\": [\n \"\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439\"\n ],\n \"Does not follow the pattern\": [\n \"\u043D\u0435 \u0441\u043B\u0435\u0434\u0443\u0435\u0442 \u0448\u0430\u0431\u043B\u043E\u043D\u0443\"\n ],\n \"send transaction\": [\n \"\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u0439 \u043F\u043E\u043A\u0430 \u043D\u0435\u0442.\"\n ],\n \"The wire transfer was successfully completed!\": [\n \"\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430!\"\n ],\n \"The request was invalid or the payto://-URI used unacceptable features.\": [\n \"\u0417\u0430\u043F\u0440\u043E\u0441 \u0431\u044B\u043B \u043D\u0435\u0432\u0435\u0440\u043D\u044B\u043C \u0438\u043B\u0438 payto://-URI \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043B \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u0443\u044E \u0444\u0443\u043D\u043A\u0446\u0438\u043E\u043D\u0430\u043B\u044C\u043D\u043E\u0441\u0442\u044C.\"\n ],\n \"Not enough permission to complete the operation.\": [\n \"\u041D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u0434\u043B\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438.\"\n ],\n \"The bank administrator cannot be the transfer creditor.\": [\n \"\"\n ],\n \"The destination account \\\"%1$s\\\" was not found.\": [\n \"\u0426\u0435\u043B\u0435\u0432\u043E\u0439 \u0441\u0447\u0435\u0442 \\\"%1$s\\\" \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.\"\n ],\n \"The origin and the destination of the transfer can't be the same.\": [\n \"\u041F\u0443\u043D\u043A\u0442 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F \u0438 \u043F\u0443\u043D\u043A\u0442 \u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u043D\u0435 \u043C\u043E\u0433\u0443\u0442 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0442\u044C.\"\n ],\n \"Your balance is not sufficient for the operation.\": [\n \"\u0412\u0430\u0448\u0435\u0433\u043E \u0431\u0430\u043B\u0430\u043D\u0441\u0430 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0434\u0435\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438.\"\n ],\n \"The origin account \\\"%1$s\\\" was not found.\": [\n \"\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u0430\u043A\u043A\u0430\u0443\u043D\u0442 \\\"%1$s\\\" \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.\"\n ],\n \"The attempt to create the transaction has failed. Please try again.\": [\n \"\"\n ],\n \"A second factor authentication is required.\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E\"\n ],\n \"Confirm wire transfer.\": [\n \"\u041F\u0435\u0440\u0435\u0432\u043E\u0434\"\n ],\n \"Input wire transfer detail\": [\n \"\u0414\u0435\u0442\u0430\u043B\u0438 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"Using a form\": [\n \"\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F \u0444\u043E\u0440\u043C\u0443\"\n ],\n \"A special URI that specifies the amount to be transferred and the destination account.\": [\n \"\"\n ],\n \"QR code\": [\n \"\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u043A\u043E\u0434\"\n ],\n \"If your device has a camera, you can import a payto:// URI from a QR code.\": [\n \"\"\n ],\n \"Recipient\": [\n \"\u041F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044C\"\n ],\n \"ID of the recipient's account\": [\n \"IBAN \u0441\u0447\u0435\u0442\u0430 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"username\": [\n \"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"IBAN of the recipient's account\": [\n \"IBAN \u0441\u0447\u0435\u0442\u0430 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"Subject\": [\n \"\u041F\u0440\u0438\u0447\u0438\u043D\u0430\"\n ],\n \"Some text to identify the transfer\": [\n \"\u043A\u0430\u043A\u043E\u0439-\u0442\u043E \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"Amount to transfer\": [\n \"\u0441\u0443\u043C\u043C\u0430 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"Payto URI:\": [\n \"payto URI:\"\n ],\n \"Uniform resource identifier of the target account\": [\n \"\u0443\u043D\u0438\u0444\u0438\u0446\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0446\u0435\u043B\u0435\u0432\u043E\u0439 \u0443\u0447\u0435\u0442\u043D\u043E\u0439 \u0437\u0430\u043F\u0438\u0441\u0438\"\n ],\n \"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://x-taler-bank/[o\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u0431\u0430\u043D\u043A\u0430]/[c\u0447\u0435\u0442 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F]?message=[\u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u043B\u0430\u0442\u0435\u0436\u0430]&amount=[%1$s:X.Y]\"\n ],\n \"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://iban/[iban \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F]?message=[\u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u043B\u0430\u0442\u0435\u0436\u0430]&amount=[%1$s:X.Y]\"\n ],\n \"The maximum amount for a wire transfer is %1$s\": [\n \"\"\n ],\n \"Cost\": [\n \"\"\n ],\n \"Send\": [\n \"\u041E\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044C \u043F\u0435\u0440\u0435\u0432\u043E\u0434\"\n ],\n \"Only \\\"x-taler-bank\\\" target are supported\": [\n \"\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \\\"IBAN\\\"\"\n ],\n \"Only this host is allowed. Use \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Account name is missing\": [\n \"\u041E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Only \\\"IBAN\\\" target are supported\": [\n \"\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \\\"IBAN\\\"\"\n ],\n \"Missing \\\"amount\\\" parameter to specify the amount to be transferred\": [\n \"\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 \\\"\u0421\u0443\u043C\u043C\u0430\\\" \u0434\u043B\u044F \u0443\u043A\u0430\u0437\u0430\u043D\u0438\u044F \u0441\u0443\u043C\u043C\u044B \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"The \\\"amount\\\" parameter is not valid\": [\n \"\u0441\u0443\u043C\u043C\u0430 \u043D\u0435 \u044F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0439\"\n ],\n \"\\\"message\\\" parameters to specify a reference text for the transfer are missing\": [\n \"\u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 \\\"message\\\" \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u0430 \u043F\u0440\u0438\u0447\u0438\u043D\u044B \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"The only currency allowed is \\\"%1$s\\\"\": [\n \"\"\n ],\n \"You cannot transfer an amount of zero.\": [\n \"\"\n ],\n \"The balance is not sufficient\": [\n \"\u041D\u0430 \u0441\u0447\u0435\u0442\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0441\u0440\u0435\u0434\u0441\u0442\u0432\"\n ],\n \"Please enter a longer subject\": [\n \"\u041F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"Show withdrawal confirmation\": [\n \"\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0435 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\"\n ],\n \"Withdraw without setting amount\": [\n \"\"\n ],\n \"Hide demo hint.\": [\n \"\"\n ],\n \"Show install wallet first\": [\n \"\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043A\u0430\u043A \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043A\u043E\u0448\u0435\u043B\u0451\u043A\"\n ],\n \"Currently, the bank is not accepting new registrations!\": [\n \"\u0412 \u043D\u0430\u0441\u0442\u043E\u044F\u0449\u0435\u0435 \u0432\u0440\u0435\u043C\u044F \u0431\u0430\u043D\u043A \u043D\u0435 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442 \u043D\u043E\u0432\u044B\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438!\"\n ],\n \"The name is missing\": [\n \"\"\n ],\n \"Missing username\": [\n \"\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"Missing password\": [\n \"\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"The password should be longer than 8 letters\": [\n \"\u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 0\"\n ],\n \"The passwords do not match\": [\n \"\u041F\u0430\u0440\u043E\u043B\u0438 \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u044E\u0442\"\n ],\n \"register new account\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C\"\n ],\n \"Server replied with invalid phone or email.\": [\n \"\u0421\u0435\u0440\u0432\u0435\u0440 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0447\u0442\u043E \u0442\u0435\u043B\u0435\u0444\u043E\u043D \u0438\u043B\u0438 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u0430 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B.\"\n ],\n \"You are not authorised to create this account.\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u0439 \u0434\u043B\u044F \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u044D\u0442\u043E\u0433\u043E \u0441\u0447\u0451\u0442\u0430.\"\n ],\n \"Registration is disabled because the bank ran out of bonus credit.\": [\n \"\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F \u043E\u0442\u043A\u043B\u044E\u0447\u0435\u043D\u0430, \u0442\u0430\u043A \u043A\u0430\u043A \u0432 \u0431\u0430\u043D\u043A\u0435 \u0437\u0430\u043A\u043E\u043D\u0447\u0438\u043B\u0441\u044F \u0431\u043E\u043D\u0443\u0441\u043D\u044B\u0439 \u043A\u0440\u0435\u0434\u0438\u0442.\"\n ],\n \"That username can't be used because is reserved.\": [\n \"\u042D\u0442\u043E \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u043E, \u0442\u0430\u043A \u043A\u0430\u043A \u043E\u043D\u043E \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u043E.\"\n ],\n \"That username is already taken.\": [\n \"\u042D\u0442\u043E \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u0443\u0436\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F.\"\n ],\n \"That account ID is already taken.\": [\n \"\u042D\u0442\u043E\u0442 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0441\u0447\u0451\u0442\u0430 \u0443\u0436\u0435 \u0437\u0430\u043D\u044F\u0442.\"\n ],\n \"No information for the selected authentication channel.\": [\n \"\u041D\u0435\u0442 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u0438 \u043E \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u043E\u043C \u043A\u0430\u043D\u0430\u043B\u0435 \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438.\"\n ],\n \"Authentication channel is not supported.\": [\n \"\u041A\u0430\u043D\u0430\u043B \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F.\"\n ],\n \"Only an administrator is allowed to set the debt limit.\": [\n \"\u0422\u043E\u043B\u044C\u043A\u043E \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435\u0442 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043B\u0438\u043C\u0438\u0442 \u0437\u0430\u0434\u043E\u043B\u0436\u0435\u043D\u043D\u043E\u0441\u0442\u0438.\"\n ],\n \"Only the administrator can change the conversion rate.\": [\n \"\"\n ],\n \"The conversion rate class doesn't exist.\": [\n \"\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D \u043A\u0443\u0440\u0441 \u043A\u043E\u043D\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438\"\n ],\n \"Only admin can create accounts with second factor authentication.\": [\n \"\u0422\u043E\u043B\u044C\u043A\u043E \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435\u0442 \u0441\u043E\u0437\u0434\u0430\u0432\u0430\u0442\u044C \u0443\u0447\u0435\u0442\u043D\u044B\u0435 \u0437\u0430\u043F\u0438\u0441\u0438 \u0441\u043E \u0432\u0442\u043E\u0440\u043E\u0439 \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0435\u0439.\"\n ],\n \"The password is too short. Can't have less than 8 characters.\": [\n \"\u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 0\"\n ],\n \"The password is too long. Can't have more than 64 characters.\": [\n \"\u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 0\"\n ],\n \"Account registration\": [\n \"\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Login username\": [\n \"\u0418\u043C\u044F \u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"account identification to login\": [\n \"\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F \u0441\u0447\u0435\u0442\u0430 \u0432 \u0431\u0430\u043D\u043A\u0435\"\n ],\n \"Password\": [\n \"\u041F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers\": [\n \"\"\n ],\n \"Repeat password\": [\n \"\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u041F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Same password\": [\n \"\u041D\u043E\u0432\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Full name\": [\n \"\"\n ],\n \"Register\": [\n \"\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F\"\n ],\n \"Create a random temporary user\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u043E\u0433\u043E \u0432\u0440\u0435\u043C\u0435\u043D\u043D\u043E\u0433\u043E \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"logout\": [\n \"\"\n ],\n \"login\": [\n \"\"\n ],\n \"The account has no rights to login.\": [\n \"\"\n ],\n \"The account is locked and cannot login. Contact administrator.\": [\n \"\"\n ],\n \"Wrong credentials for \\\"%1$s\\\"\": [\n \"\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0435 \u0443\u0447\u0435\u0442\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0434\u043B\u044F \u00AB%1$s\u00BB \u200E\"\n ],\n \"Account login.\": [\n \"\u041E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Session expired\": [\n \"\"\n ],\n \"Username\": [\n \"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"identification\": [\n \"\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430\"\n ],\n \"Password of the account\": [\n \"\u043F\u0430\u0440\u043E\u043B\u044C \u043E\u0442 \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Forget\": [\n \"\"\n ],\n \"Log in\": [\n \"\u0412\u043E\u0439\u0442\u0438\"\n ],\n \"Transactions history\": [\n \"\"\n ],\n \"No transactions yet.\": [\n \"\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u0439 \u043F\u043E\u043A\u0430 \u043D\u0435\u0442.\"\n ],\n \"You can make a transfer or a withdrawal to your wallet.\": [\n \"\"\n ],\n \"Date\": [\n \"\u0414\u0430\u0442\u0430\"\n ],\n \"Counterpart\": [\n \"\u041A\u043E\u043D\u0442\u0440\u0430\u0441\u0447\u0435\u0442\"\n ],\n \"sent\": [\n \"\u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E\"\n ],\n \"received\": [\n \"\u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E\"\n ],\n \"Invalid value\": [\n \"\u041D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435\"\n ],\n \"to\": [\n \"\u043A\"\n ],\n \"from\": [\n \"\u043E\u0442\"\n ],\n \"First page\": [\n \"\u041F\u0435\u0440\u0432\u0430\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430\"\n ],\n \"Next\": [\n \"\u0414\u0430\u043B\u0435\u0435\"\n ],\n \"confirm withdrawal\": [\n \"\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430\"\n ],\n \"cambiar\": [\n \"\"\n ],\n \"abort withdrawal\": [\n \"\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430\"\n ],\n \"The withdrawal has been aborted previously and can't be confirmed\": [\n \"\u0412\u044B\u0432\u043E\u0434 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u0431\u044B\u043B \u043F\u0440\u0435\u0440\u0432\u0430\u043D \u0440\u0430\u043D\u0435\u0435 \u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\"\n ],\n \"The withdrawal operation can't be confirmed before a wallet accepted the transaction.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043F\u043E \u0432\u044B\u0432\u043E\u0434\u0443 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0430 \u0434\u043E \u0442\u043E\u0433\u043E \u043A\u0430\u043A \u043A\u043E\u0448\u0451\u043B\u0435\u043A \u043F\u0440\u0438\u043C\u0435\u0442 \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u044E.\"\n ],\n \"The operation ID is invalid.\": [\n \"\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D.\"\n ],\n \"The operation was not found.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430.\"\n ],\n \"The starting withdrawal amount and the confirmation amount differs.\": [\n \"\"\n ],\n \"The bank requires a bank account which has not been specified yet.\": [\n \"\"\n ],\n \"Bad request\": [\n \"\"\n ],\n \"The withdrawal operation has been aborted.\": [\n \"\u041E\u0436\u0438\u0434\u0430\u043D\u0438\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\"\n ],\n \"The withdrawal operation has been confirmed previously and can\u2019t be aborted.\": [\n \"\u0420\u0435\u0437\u0435\u0440\u0432\u043D\u0430\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0431\u044B\u043B\u0430 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0430 \u0440\u0430\u043D\u0435\u0435 \u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430\"\n ],\n \"Complete withdrawal.\": [\n \"\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430\"\n ],\n \"Confirm the withdrawal operation\": [\n \"\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430\"\n ],\n \"Wire transfer details\": [\n \"\u0414\u0435\u0442\u0430\u043B\u0438 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"Payment Service Provider's account number\": [\n \"\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler\"\n ],\n \"Payment Service Provider's name\": [\n \"\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler\"\n ],\n \"Payment Service Provider's account bank hostname\": [\n \"\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler\"\n ],\n \"Payment Service Provider's account id\": [\n \"\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler\"\n ],\n \"Payment Service Provider's account address\": [\n \"\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler\"\n ],\n \"Payment Service Provider's account cyclos hostname\": [\n \"\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler\"\n ],\n \"No amount has yet been determined.\": [\n \"\"\n ],\n \"Transfer\": [\n \"\u041F\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438\"\n ],\n \"Authentication required\": [\n \"\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\"\n ],\n \"This operation was created with another username\": [\n \"\u042D\u0442\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0431\u044B\u043B\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0430 \u0441 \u0434\u0440\u0443\u0433\u0438\u043C \u0438\u043C\u0435\u043D\u0435\u043C \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"You are currently logged in with user \\\"%1$s\\\" and the operation was made with user \\\"%2$s\\\"\": [\n \"\"\n ],\n \"The reserve operation has been confirmed previously and can't be aborted\": [\n \"\u0420\u0435\u0437\u0435\u0440\u0432\u043D\u0430\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0431\u044B\u043B\u0430 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0430 \u0440\u0430\u043D\u0435\u0435 \u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430\"\n ],\n \"Wire transfer completed!\": [\n \"\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430!\"\n ],\n \"Confirm withdrawal.\": [\n \"\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430\"\n ],\n \"Unauthorized to make the operation, maybe the session has expired or the password changed.\": [\n \"\u041D\u0435\u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0438\u0441\u0442\u0435\u043A \u0441\u0435\u0430\u043D\u0441 \u0438\u043B\u0438 \u0438\u0437\u043C\u0435\u043D\u0451\u043D \u043F\u0430\u0440\u043E\u043B\u044C.\"\n ],\n \"The operation was rejected due to insufficient funds.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043E\u0442\u043A\u043B\u043E\u043D\u0435\u043D\u0430 \u0438\u0437-\u0437\u0430 \u043D\u0435\u0445\u0432\u0430\u0442\u043A\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432.\"\n ],\n \"Withdrawal confirmed\": [\n \"\u0412\u044B\u0432\u043E\u0434 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D\"\n ],\n \"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.\": [\n \"\u0418\u043D\u0438\u0446\u0438\u0438\u0440\u043E\u0432\u0430\u043D \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0443 Taler. \u0412\u0441\u043A\u043E\u0440\u0435 \u0432\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u0435 \u0437\u0430\u043F\u0440\u043E\u0448\u0435\u043D\u043D\u0443\u044E \u0441\u0443\u043C\u043C\u0443 \u043D\u0430 \u0441\u0432\u043E\u0439 \u043A\u043E\u0448\u0435\u043B\u0451\u043A Taler.\"\n ],\n \"Do not show this again\": [\n \"\u041D\u0435 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0441\u043D\u043E\u0432\u0430\"\n ],\n \"If you have a Taler wallet installed on this device\": [\n \"\u0415\u0441\u043B\u0438 \u0432 \u044D\u0442\u043E\u043C \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D \u043A\u043E\u0448\u0435\u043B\u0451\u043A Taler\"\n ],\n \"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions\": [\n \"\u0412\u044B \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043F\u043E\u0434\u0440\u043E\u0431\u043D\u043E\u0441\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0432 \u0441\u0432\u043E\u0435\u043C \u043A\u043E\u0448\u0435\u043B\u044C\u043A\u0435, \u0432\u043A\u043B\u044E\u0447\u0430\u044F \u043A\u043E\u043C\u0438\u0441\u0441\u0438\u044E (\u0435\u0441\u043B\u0438 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u043C\u043E). \u0415\u0441\u043B\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0433\u043E \u0435\u0449\u0435 \u043D\u0435\u0442, \u0432\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u0435\u0433\u043E \u0441\u043B\u0435\u0434\u0443\u044F \u0438\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u044F\u043C \u043D\u0430\"\n ],\n \"on this page\": [\n \"\u044D\u0442\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435\"\n ],\n \"Withdraw\": [\n \"\u0421\u043D\u044F\u0442\u044C \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\"\n ],\n \"In case you have a Taler wallet on another device\": [\n \"\u0418\u043B\u0438 \u0435\u0441\u043B\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044C \u043A\u043E\u0448\u0435\u043B\u0451\u043A \u0432 \u0434\u0440\u0443\u0433\u043E\u043C \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0435\"\n ],\n \"Scan the QR below to start the withdrawal.\": [\n \"\u041E\u0442\u0441\u043A\u0430\u043D\u0438\u0440\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434 \u043D\u0438\u0436\u0435 \u0447\u0442\u043E\u0431\u044B \u043D\u0430\u0447\u0430\u0442\u044C \u0432\u044B\u0432\u043E\u0434 \u0441\u0440\u0435\u0434\u0441\u0442\u0432.\"\n ],\n \"create withdrawal\": [\n \"\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430\"\n ],\n \"The server replied with an invalid taler://withdraw URI\": [\n \"\u0421\u0435\u0440\u0432\u0435\u0440 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0441 \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u043C URI \u0432\u044B\u0432\u043E\u0434\u0430\"\n ],\n \"Withdraw URI: %1$s\": [\n \"URI \u0432\u044B\u0432\u043E\u0434\u0430: %1$s\"\n ],\n \"The operation was rejected due to insufficient funds\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043E\u0442\u043A\u043B\u043E\u043D\u0435\u043D\u0430 \u0438\u0437-\u0437\u0430 \u043D\u0435\u0445\u0432\u0430\u0442\u043A\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432.\"\n ],\n \"Current balance is %1$s\": [\n \"\"\n ],\n \"You can withdraw up to %1$s\": [\n \"\"\n ],\n \"Continue\": [\n \"\u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C\"\n ],\n \"Use your Taler wallet\": [\n \"\u041F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u044C\u0442\u0435 \u0441\u0432\u043E\u0439 \u043A\u043E\u0448\u0435\u043B\u0451\u043A\"\n ],\n \"After using your wallet you will need to authorize or cancel the operation on this site.\": [\n \"\u041F\u043E\u0441\u043B\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u043A\u043E\u0448\u0435\u043B\u044C\u043A\u0430 \u0432\u0430\u043C \u043D\u0443\u0436\u043D\u043E \u0431\u0443\u0434\u0435\u0442 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u0438\u043B\u0438 \u043E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u043D\u0430 \u044D\u0442\u043E\u043C \u0441\u0430\u0439\u0442\u0435.\"\n ],\n \"You need a Taler wallet\": [\n \"\u0412\u0430\u043C \u043D\u0443\u0436\u0435\u043D \u043A\u043E\u0448\u0435\u043B\u0451\u043A Taler\"\n ],\n \"If you don't have one yet you can follow the instruction in\": [\n \"\u0415\u0441\u043B\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0433\u043E \u0435\u0449\u0435 \u043D\u0435\u0442, \u0432\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0441\u043B\u0435\u0434\u043E\u0432\u0430\u0442\u044C \u0438\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u044F\u043C \u043D\u0430\"\n ],\n \"this page\": [\n \"\u044D\u0442\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435\"\n ],\n \"Send money\": [\n \"\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0434\u0435\u043D\u044C\u0433\u0438\"\n ],\n \"to a Taler wallet\": [\n \"\u043D\u0430 \u043A\u043E\u0448\u0435\u043B\u0435\u043A Taler\"\n ],\n \"Withdraw digital money into your mobile wallet or browser extension\": [\n \"\u0412\u044B\u0432\u043E\u0434\u0438\u0442\u0435 \u0446\u0438\u0444\u0440\u043E\u0432\u044B\u0435 \u0434\u0435\u043D\u044C\u0433\u0438 \u043D\u0430 \u0441\u0432\u043E\u0439 \u043C\u043E\u0431\u0438\u043B\u044C\u043D\u044B\u0439 \u043A\u043E\u0448\u0435\u043B\u0451\u043A \u0438\u043B\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\"\n ],\n \"to another bank account\": [\n \"\u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u0439 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u0441\u0447\u0435\u0442\"\n ],\n \"Make a wire transfer to an account with known bank account number.\": [\n \"\u0421\u0434\u0435\u043B\u0430\u0439\u0442\u0435 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u043D\u0430 \u0441\u0447\u0435\u0442 \u0441 \u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u0441\u0447\u0435\u0442\u0430.\"\n ],\n \"This is a demo\": [\n \"\u042D\u0442\u043E \u0434\u0435\u043C\u043E-\u0431\u0430\u043D\u043A\"\n ],\n \"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .\": [\n \"\u0412 \u044D\u0442\u043E\u0439 \u0447\u0430\u0441\u0442\u0438 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043F\u043E\u043A\u0430\u0437\u0430\u043D\u043E \u043A\u0430\u043A \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C \u0431\u0430\u043D\u043A \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0449\u0438\u0439 Taler \u043D\u0430\u043F\u0440\u044F\u043C\u0443\u044E. \u041F\u043E\u043C\u0438\u043C\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u0441\u043E\u0431\u0441\u0442\u0432\u0435\u043D\u043D\u043E\u0433\u043E \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u0441\u0447\u0451\u0442\u0430, \u0432\u044B \u0442\u0430\u043A\u0436\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C \u0438\u0441\u0442\u043E\u0440\u0438\u044E \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u0439 \u043D\u0435\u043A\u043E\u0442\u043E\u0440\u044B\u0445 %1$s.\"\n ],\n \"Here you will be able to see how a bank that supports Taler directly would work.\": [\n \"\u0412 \u044D\u0442\u043E\u0439 \u0447\u0430\u0441\u0442\u0438 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043F\u043E\u043A\u0430\u0437\u0430\u043D\u043E \u043A\u0430\u043A \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C \u0431\u0430\u043D\u043A \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0449\u0438\u0439 Taler \u043D\u0430\u043F\u0440\u044F\u043C\u0443\u044E.\"\n ],\n \"Internal error, please report. There should be more information in the console.\": [\n \"\"\n ],\n \"Internal error, please report.\": [\n \"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u043E\u0448\u0438\u0431\u043A\u0430, \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0441\u043E\u043E\u0431\u0449\u0438\u0442\u0435.\"\n ],\n \"Preferences\": [\n \"\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438\"\n ],\n \"Show debug information\": [\n \"\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044E \u0434\u043B\u044F \u043E\u0442\u043B\u0430\u0434\u043A\u0438\"\n ],\n \"Welcome\": [\n \"\u0414\u043E\u0431\u0440\u043E \u043F\u043E\u0436\u0430\u043B\u043E\u0432\u0430\u0442\u044C\"\n ],\n \"Welcome, %1$s\": [\n \"\u0414\u043E\u0431\u0440\u043E \u043F\u043E\u0436\u0430\u043B\u043E\u0432\u0430\u0442\u044C, %1$s\"\n ],\n \"No enough permission to access the conversion rate list.\": [\n \"\u041D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u0434\u043B\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438.\"\n ],\n \"Conversion list not found. Maybe conversion rate is not supported.\": [\n \"\"\n ],\n \"Conversion list not implemented.\": [\n \"\u041E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0430 \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u0430\"\n ],\n \"Conversion rate classes\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Create conversion rate class\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"No conversion rate class\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Name\": [\n \"\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435\"\n ],\n \"Description\": [\n \"\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0434\u0435\u043C\u043E\"\n ],\n \"Cashin\": [\n \"\u0412\u043D\u0435\u0441\u0435\u043D\u0438\u044F\"\n ],\n \"min:\": [\n \"\"\n ],\n \"fee:\": [\n \"\"\n ],\n \"Select a section\": [\n \"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0440\u0430\u0437\u0434\u0435\u043B\"\n ],\n \"Details\": [\n \"\u041F\u043E\u0434\u0440\u043E\u0431\u043D\u043E\u0441\u0442\u0438\"\n ],\n \"Delete\": [\n \"\u0423\u0434\u0430\u043B\u0438\u0442\u044C\"\n ],\n \"Credentials\": [\n \"\u0423\u0447\u0435\u0442\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435\"\n ],\n \"Cashouts\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u044B\"\n ],\n \"Conversion\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"only admin can setup conversion\": [\n \"\"\n ],\n \"calculate cashout fee\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C\"\n ],\n \"update conversion rate\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Wrong credentials\": [\n \"\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0435 \u0443\u0447\u0435\u0442\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0434\u043B\u044F \u00AB%1$s\u00BB \u200E\"\n ],\n \"Conversion is disabled\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Config cashout\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u0430\"\n ],\n \"Config cashin\": [\n \"\u0412\u043D\u0435\u0441\u0435\u043D\u0438\u044F\"\n ],\n \"Bad ratios\": [\n \"\"\n ],\n \"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.\": [\n \"\"\n ],\n \"Initial amount\": [\n \"\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0441\u0443\u043C\u043C\u0430 \u0432\u044B\u0432\u043E\u0434\u0430\"\n ],\n \"Use it to test how the conversion will affect the amount.\": [\n \"\"\n ],\n \"Sending to this bank\": [\n \"\"\n ],\n \"Converted\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Cashin after fee\": [\n \"\"\n ],\n \"Sending from this bank\": [\n \"\"\n ],\n \"Cashout after fee\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0430\"\n ],\n \"Bad configuration\": [\n \"\"\n ],\n \"This configuration allows users to cash out more of what has been cashed in.\": [\n \"\"\n ],\n \"Update\": [\n \"\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C\"\n ],\n \"Rnvalid\": [\n \"\u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E\"\n ],\n \"Must be > 0\": [\n \"\"\n ],\n \"Minimum amount\": [\n \"\"\n ],\n \"Only cashout operation above this threshold will be allowed.\": [\n \"\"\n ],\n \"Ratio\": [\n \"\"\n ],\n \"Conversion ratio between currencies\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Example conversion\": [\n \"\"\n ],\n \"1 %1$s will be converted into %2$s %3$s\": [\n \"\"\n ],\n \"Tiny amount\": [\n \"\u041D\u0430 \u0441\u0447\u0451\u0442\"\n ],\n \"Rounding mode\": [\n \"\"\n ],\n \"Zero\": [\n \"\"\n ],\n \"Amount will be round below to the largest possible value smaller than the input.\": [\n \"\"\n ],\n \"Up\": [\n \"\"\n ],\n \"Amount will be round up to the smallest possible value larger than the input.\": [\n \"\"\n ],\n \"Nearest\": [\n \"\"\n ],\n \"Amount will be round to the closest possible value.\": [\n \"\"\n ],\n \"If none specified the fallback value is \\\"%1$s \\\".\": [\n \"\"\n ],\n \"Examples\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.1\": [\n \"\"\n ],\n \"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.\": [\n \"\"\n ],\n \"With the \\\"zero\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.1\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.3\": [\n \"\"\n ],\n \"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.5\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.3\": [\n \"\"\n ],\n \"Amount to be deducted before amount is credited.\": [\n \"\"\n ],\n \"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"delete conversion rate class\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Unauthorized\": [\n \"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"Forbidden\": [\n \"\"\n ],\n \"NotFound\": [\n \"\"\n ],\n \"NotImplemented\": [\n \"\u041E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0430 \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u0430\"\n ],\n \"update conversion rate class\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Not Found\": [\n \"\"\n ],\n \"Not implemented\": [\n \"\u041E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0430 \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u0430\"\n ],\n \"The name of the conversion is already used.\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0443\u0436\u0435 \u0438\u0434\u0435\u0442\"\n ],\n \"Conversion rate class\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Accounts\": [\n \"\u0421\u0447\u0435\u0442\u0430\"\n ],\n \"Test\": [\n \"\"\n ],\n \"Users\": [\n \"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"Can't remove the conversion rate class\": [\n \"\"\n ],\n \"There are some user associated to this class. You need to remove them first.\": [\n \"\"\n ],\n \"You are going to remove the conversion rate class\": [\n \"\"\n ],\n \"This step can't be undone.\": [\n \"\"\n ],\n \"Filters\": [\n \"\"\n ],\n \"Show from other classes\": [\n \"\"\n ],\n \"Account\": [\n \"\u0421\u0447\u0451\u0442\"\n ],\n \"Group ID\": [\n \"\"\n ],\n \"No users in this conversion rate class\": [\n \"\"\n ],\n \"Class\": [\n \"\"\n ],\n \"Action\": [\n \"\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F\"\n ],\n \"Remove\": [\n \"\u0443\u0434\u0430\u043B\u0438\u0442\u044C\"\n ],\n \"Add\": [\n \"\"\n ],\n \"Conversion rate name\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Short description of the class\": [\n \"\"\n ],\n \"create conversion rate class\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Conversion rate class created.\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"The rights to change the account are not sufficient\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u043F\u0440\u0430\u0432 \u043D\u0430 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"New conversion rate class\": [\n \"\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441\"\n ],\n \"Create\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C\"\n ],\n \"History of public accounts\": [\n \"\u0418\u0441\u0442\u043E\u0440\u0438\u044F \u043F\u0443\u0431\u043B\u0438\u0447\u043D\u044B\u0445 \u0441\u0447\u0435\u0442\u043E\u0432\"\n ],\n \"Make a wire transfer\": [\n \"\u0421\u0434\u0435\u043B\u0430\u0442\u044C \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\"\n ],\n \"Scan the QR code below to start the withdrawal.\": [\n \"\u041E\u0442\u0441\u043A\u0430\u043D\u0438\u0440\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434 \u043D\u0438\u0436\u0435 \u0447\u0442\u043E\u0431\u044B \u043D\u0430\u0447\u0430\u0442\u044C \u0432\u044B\u0432\u043E\u0434 \u0441\u0440\u0435\u0434\u0441\u0442\u0432.\"\n ],\n \"Operation aborted\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430\"\n ],\n \"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.\": [\n \"\u0411\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u043D\u0430 \u0441\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler \u0431\u044B\u043B \u043F\u0440\u0435\u0440\u0432\u0430\u043D, \u0432\u0430\u0448 \u0431\u0430\u043B\u0430\u043D\u0441 \u043D\u0435 \u043F\u043E\u0441\u0442\u0440\u0430\u0434\u0430\u043B.\"\n ],\n \"Go to your wallet now\": [\n \"\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043A\u043E\u0448\u0435\u043B\u0435\u043A\"\n ],\n \"The operation is marked as selected, but a process during the withdrawal failed\": [\n \"\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043F\u043E\u043C\u0435\u0447\u0435\u043D\u0430 \u043A\u0430\u043A \u00AB\u0432\u044B\u0431\u0440\u0430\u043D\u043D\u0430\u044F\u00BB, \u043D\u043E \u043A\u0430\u043A\u043E\u0439-\u0442\u043E \u0448\u0430\u0433 \u0432 \u0432\u044B\u0432\u043E\u0434\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043D\u0435 \u0443\u0434\u0430\u043B\u0441\u044F\"\n ],\n \"A withdrawal reserve ID was not found and no account has been selected.\": [\n \"\u0415\u0441\u0442\u044C \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432, \u043D\u043E \u0441\u0447\u0451\u0442 \u043D\u0435 \u0431\u044B\u043B \u0432\u044B\u0431\u0440\u0430\u043D \u0438\u043B\u0438 \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u0441\u0447\u0451\u0442 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D.\"\n ],\n \"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.\": [\n \"\u0415\u0441\u0442\u044C \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432, \u043D\u043E \u0441\u0447\u0451\u0442 \u043D\u0435 \u0431\u044B\u043B \u0432\u044B\u0431\u0440\u0430\u043D \u0438\u043B\u0438 \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u0441\u0447\u0451\u0442 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D.\"\n ],\n \"The account was selected, but no withdrawal reserve ID was found.\": [\n \"\u0421\u0447\u0451\u0442 \u0432\u044B\u0431\u0440\u0430\u043D, \u043D\u043E \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.\"\n ],\n \"Operation not found\": [\n \"\"\n ],\n \"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.\": [\n \"\"\n ],\n \"Continue to dashboard\": [\n \"\"\n ],\n \"The Withdrawal URI is not valid\": [\n \"URI \u0432\u044B\u0432\u043E\u0434\u0430 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D\"\n ],\n \"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.\": [\n \"\"\n ],\n \"Latest cashouts\": [\n \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u043E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0438\"\n ],\n \"Created\": [\n \"\u0421\u043E\u0437\u0434\u0430\u043D\u043E\"\n ],\n \"Total debit\": [\n \"\u0412\u0441\u0435\u0433\u043E \u0434\u0435\u0431\u0435\u0442\"\n ],\n \"Total credit\": [\n \"\u0418\u0442\u043E\u0433\u043E \u043A\u0440\u0435\u0434\u0438\u0442\"\n ],\n \"Cashout for account %1$s\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0434\u043B\u044F \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u0430 %1$s\"\n ],\n \"Invalid email format\": [\n \"\u041D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435\"\n ],\n \"Should start with +\": [\n \"\u0434\u043E\u043B\u0436\u0435\u043D \u043D\u0430\u0447\u0438\u043D\u0430\u0442\u044C\u0441\u044F \u0441 +\"\n ],\n \"A phone number consists of numbers only\": [\n \"\u041D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0438\u043C\u0435\u0442\u044C \u043D\u0438\u0447\u0435\u0433\u043E, \u043A\u0440\u043E\u043C\u0435 \u0446\u0438\u0444\u0440\"\n ],\n \"Account ID for authentication\": [\n \"\u0414\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0430\u044F \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\"\n ],\n \"Name of the account holder\": [\n \"\u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Internal account\": [\n \"\u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u0439 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u0441\u0447\u0435\u0442\"\n ],\n \"If this field is empty, a random account ID will be assigned\": [\n \"\u0415\u0441\u043B\u0438 \u043F\u0443\u0441\u0442\u043E, \u0431\u0443\u0434\u0435\u0442 \u043F\u0440\u0438\u0441\u0432\u043E\u0435\u043D \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u044B\u0439 \u043D\u043E\u043C\u0435\u0440 \u0441\u0447\u0435\u0442\u0430\"\n ],\n \"You can copy and share this IBAN number in order to receive wire transfers to your bank account\": [\n \"\"\n ],\n \"Email\": [\n \"Email\"\n ],\n \"To be used when second factor authentication is enabled\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E\"\n ],\n \"Phone\": [\n \"\u0422\u0435\u043B\u0435\u0444\u043E\u043D\"\n ],\n \"Enable second factor authentication\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E\"\n ],\n \"Using email\": [\n \"\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F email\"\n ],\n \"Add an email in your profile to enable this option\": [\n \"\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0430\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B \u0432 \u0441\u0432\u043E\u0439 \u043F\u0440\u043E\u0444\u0438\u043B\u044C, \u0447\u0442\u043E\u0431\u044B \u0432\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u044D\u0442\u0443 \u043E\u043F\u0446\u0438\u044E\"\n ],\n \"Using SMS\": [\n \"\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F SMS\"\n ],\n \"Add a phone number in your profile to enable this option\": [\n \"\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430 \u0432 \u0441\u0432\u043E\u0439 \u043F\u0440\u043E\u0444\u0438\u043B\u044C, \u0447\u0442\u043E\u0431\u044B \u0432\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u044D\u0442\u0443 \u043E\u043F\u0446\u0438\u044E\"\n ],\n \"Cashout account\": [\n \"\u041D\u0435\u0442 \u0441\u0447\u0451\u0442\u0430 \u0434\u043B\u044F \u0432\u044B\u043F\u043B\u0430\u0442\"\n ],\n \"External account number where the money is going to be sent when doing cashouts\": [\n \"\u043D\u043E\u043C\u0435\u0440 \u0441\u0447\u0435\u0442\u0430, \u043D\u0430 \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0431\u0443\u0434\u0443\u0442 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u044B \u0434\u0435\u043D\u044C\u0433\u0438 \u043F\u0440\u0438 \u0432\u044B\u0432\u043E\u0434\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\"\n ],\n \"Max debt\": [\n \"\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0437\u0430\u0434\u043E\u043B\u0436\u0435\u043D\u043D\u043E\u0441\u0442\u044C\"\n ],\n \"How much the balance can go below zero.\": [\n \"\"\n ],\n \"Is this account public?\": [\n \"\u042F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u043B\u0438 \u044D\u0442\u043E\u0442 \u0441\u0447\u0451\u0442 \u043E\u0431\u0449\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u043C?\"\n ],\n \"Public accounts have their balance publicly accessible\": [\n \"\u0411\u0430\u043B\u0430\u043D\u0441 \u043F\u0443\u0431\u043B\u0438\u0447\u043D\u044B\u0445 \u0441\u0447\u0451\u0442\u043E\u0432 \u043D\u0430\u0445\u043E\u0434\u0438\u0442\u0441\u044F \u0432 \u043E\u0442\u043A\u0440\u044B\u0442\u043E\u043C \u0434\u043E\u0441\u0442\u0443\u043F\u0435\"\n ],\n \"Does this account belong to a Payment Service Provider?\": [\n \"\u042F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u043B\u0438 \u044D\u0442\u043E\u0442 \u0441\u0447\u0451\u0442 \u043E\u0431\u0449\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u043C?\"\n ],\n \"update account\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C\"\n ],\n \"Account updated\": [\n \"\u0421\u0447\u0451\u0442 \u043E\u0431\u043D\u043E\u0432\u043B\u0451\u043D\"\n ],\n \"The username was not found\": [\n \"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"You can't change the legal name, please contact the your account administrator.\": [\n \"\u0412\u044B \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043E\u0444\u0438\u0446\u0438\u0430\u043B\u044C\u043D\u043E\u0435 \u0438\u043C\u044F, \u043E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0443 \u0432\u0430\u0448\u0435\u0439 \u0443\u0447\u0435\u0442\u043D\u043E\u0439 \u0437\u0430\u043F\u0438\u0441\u0438.\"\n ],\n \"You can't change the debt limit, please contact the your account administrator.\": [\n \"\u0412\u044B \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043B\u0438\u043C\u0438\u0442 \u0437\u0430\u0434\u043E\u043B\u0436\u0435\u043D\u043D\u043E\u0441\u0442\u0438, \u043E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0443 \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u0430.\"\n ],\n \"You can't change the cashout address, please contact the your account administrator.\": [\n \"\u0412\u044B \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0430\u0434\u0440\u0435\u0441 \u0434\u043B\u044F \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432, \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u044F\u0436\u0438\u0442\u0435\u0441\u044C \u0441 \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u043E\u043C \u0432\u0430\u0448\u0435\u0433\u043E \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u0430.\"\n ],\n \"Update account information.\": [\n \"\u041E\u0436\u0438\u0434\u0430\u043D\u0438\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Account \\\"%1$s\\\"\": [\n \"\u0421\u0447\u0435\u0442 \\\"%1$s\\\"\"\n ],\n \"Removed\": [\n \"\u0443\u0434\u0430\u043B\u0438\u0442\u044C\"\n ],\n \"This account can't be used.\": [\n \"\"\n ],\n \"Change details\": [\n \"\u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435 \u0440\u0435\u043A\u0432\u0438\u0437\u0438\u0442\u043E\u0432\"\n ],\n \"Merchant integration\": [\n \"\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the \\\"import\\\" button in the \\\"bank account\\\" section.\": [\n \"\"\n ],\n \"Account type\": [\n \"\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Method to use for wire transfer.\": [\n \"\u0421\u0434\u0435\u043B\u0430\u0442\u044C \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\"\n ],\n \"IBAN\": [\n \"\"\n ],\n \"International Bank Account Number.\": [\n \"\"\n ],\n \"Account name\": [\n \"\u041E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Bank host where the service is located.\": [\n \"\"\n ],\n \"Bank account identifier for wire transfers.\": [\n \"\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F \u0441\u0447\u0435\u0442\u0430 \u0434\u043B\u044F \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430\"\n ],\n \"Address\": [\n \"\"\n ],\n \"Owner's name\": [\n \"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\"\n ],\n \"Legal name of the person holding the account.\": [\n \"\u0438\u043C\u044F \u0432\u043B\u0430\u0434\u0435\u043B\u044C\u0446\u0430 \u0441\u0447\u0451\u0442\u0430\"\n ],\n \"Account info URL\": [\n \"\u0423\u0447\u0451\u0442\u043D\u0430\u044F \u0437\u0430\u043F\u0438\u0441\u044C \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430\"\n ],\n \"From where the merchant can download information about incoming wire transfers to this account.\": [\n \"\"\n ],\n \"Repeated password doesn't match\": [\n \"\u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0435\u0442\"\n ],\n \"update password\": [\n \"\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Password changed\": [\n \"\u041F\u0430\u0440\u043E\u043B\u044C \u0438\u0437\u043C\u0435\u043D\u0435\u043D\"\n ],\n \"Not authorized to change the password, maybe the session is invalid.\": [\n \"\"\n ],\n \"You need to provide the old password. If you don't have it contact your account administrator.\": [\n \"\"\n ],\n \"Your current password doesn't match, can't change to a new password.\": [\n \"\"\n ],\n \"You don't have the rights to change the password.\": [\n \"\"\n ],\n \"Update account password.\": [\n \"\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Update password\": [\n \"\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Current password\": [\n \"\u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Your current password, for security\": [\n \"\"\n ],\n \"New password\": [\n \"\u041D\u043E\u0432\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Type it again\": [\n \"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043E \u0435\u0449\u0451 \u0440\u0430\u0437\"\n ],\n \"Repeat the same password\": [\n \"\u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u044D\u0442\u043E\u0442 \u0436\u0435 \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Change\": [\n \"\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C\"\n ],\n \"Create account\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C\"\n ],\n \"Actions\": [\n \"\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F\"\n ],\n \"Unknown\": [\n \"\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u043E\"\n ],\n \"Change password\": [\n \"\u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C\"\n ],\n \"Querying for the current stats failed\": [\n \"\"\n ],\n \"The request parameters are wrong\": [\n \"\"\n ],\n \"The user is unauthorized\": [\n \"\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E\"\n ],\n \"Querying for the previous stats failed\": [\n \"\"\n ],\n \"Transaction volume report\": [\n \"\"\n ],\n \"Last hour\": [\n \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u0447\u0430\u0441\"\n ],\n \"Previous day\": [\n \"\"\n ],\n \"Last month\": [\n \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u043C\u0435\u0441\u044F\u0446\"\n ],\n \"Last year\": [\n \"\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u0433\u043E\u0434\"\n ],\n \"Last Year\": [\n \"\u041F\u0440\u043E\u0448\u043B\u044B\u0439 \u0433\u043E\u0434\"\n ],\n \"Trading volume from %1$s to %2$s\": [\n \"\u041E\u0431\u044A\u0435\u043C \u0442\u043E\u0440\u0433\u043E\u0432 \u043D\u0430 %1$s \u043F\u043E \u0441\u0440\u0430\u0432\u043D\u0435\u043D\u0438\u044E \u0441 %2$s\"\n ],\n \"Transferred from an external account to an account in this bank.\": [\n \"\"\n ],\n \"Transferred from an account in this bank to an external account.\": [\n \"\u0421\u0434\u0435\u043B\u0430\u0439\u0442\u0435 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u043D\u0430 \u0441\u0447\u0435\u0442 \u0441 \u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u0441\u0447\u0435\u0442\u0430.\"\n ],\n \"Payin\": [\n \"\u041E\u0442\u043F\u043B\u0430\u0442\u0430\"\n ],\n \"Transferred from an account to a Taler exchange.\": [\n \"\"\n ],\n \"Payout\": [\n \"\u0412\u044B\u043F\u043B\u0430\u0442\u0430\"\n ],\n \"Transferred from a Taler exchange to another account.\": [\n \"\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler\"\n ],\n \"Download stats as CSV\": [\n \"\u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435 CSV\"\n ],\n \"previous\": [\n \"\"\n ],\n \"Decreased by\": [\n \"\u0423\u043C\u0435\u043D\u044C\u0448\u0438\u043B\u043E\u0441\u044C \u043D\u0430\"\n ],\n \"Increased by\": [\n \"\u0423\u0432\u0435\u043B\u0438\u0447\u0435\u043D\u0438\u0435 \u043D\u0430\"\n ],\n \"create account\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C\"\n ],\n \"Account created with password \\\"%1$s\\\".\": [\n \"\"\n ],\n \"Server replied that phone or email is invalid\": [\n \"\"\n ],\n \"The rights to perform the operation are not sufficient\": [\n \"\"\n ],\n \"Account username is already taken\": [\n \"\"\n ],\n \"Account ID is already taken\": [\n \"\u042D\u0442\u043E\u0442 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0441\u0447\u0451\u0442\u0430 \u0443\u0436\u0435 \u0437\u0430\u043D\u044F\u0442.\"\n ],\n \"Bank ran out of bonus credit.\": [\n \"\"\n ],\n \"Account username can't be used because is reserved\": [\n \"\"\n ],\n \"Can't create accounts\": [\n \"\"\n ],\n \"Only system admin can create accounts.\": [\n \"\"\n ],\n \"New bank account\": [\n \"\u041D\u043E\u0432\u044B\u0439 \u0431\u0438\u0437\u043D\u0435\u0441 \u0441\u0447\u0451\u0442\"\n ],\n \"download statistics\": [\n \"\u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435 CSV\"\n ],\n \"only admin can download stats\": [\n \"\"\n ],\n \"Download bank stats\": [\n \"\u0421\u043A\u0430\u0447\u0438\u0432\u0430\u0442\u044C \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0431\u0430\u043D\u043A\u0430\"\n ],\n \"Include hour metric\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0447\u0430\u0441\u043E\u0432\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443\"\n ],\n \"Include day metric\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0434\u043D\u0435\u0432\u043D\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443\"\n ],\n \"Include month metric\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043C\u0435\u0441\u044F\u0447\u043D\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443\"\n ],\n \"Include year metric\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0433\u043E\u0434\u043E\u0432\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443\"\n ],\n \"Include table header\": [\n \"\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0442\u0430\u0431\u043B\u0438\u0446\u044B\"\n ],\n \"Add previous metric for compare\": [\n \"\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443 \u0434\u043B\u044F \u0441\u0440\u0430\u0432\u043D\u0435\u043D\u0438\u044F\"\n ],\n \"Fail on first error\": [\n \"\u0421\u0431\u043E\u0439 \u043F\u0440\u0438 \u043F\u0435\u0440\u0432\u043E\u0439 \u043E\u0448\u0438\u0431\u043A\u0435\"\n ],\n \"Download\": [\n \"\u0421\u043A\u0430\u0447\u0438\u0432\u0430\u0442\u044C\"\n ],\n \"downloading... %1$s\": [\n \"\u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u0435... %1$s\"\n ],\n \"Download completed\": [\n \"\u0421\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E\"\n ],\n \"Click here to save the file in your computer.\": [\n \"\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044C, \u0447\u0442\u043E\u0431\u044B \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u043D\u0430 \u0441\u0432\u043E\u0435\u043C \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435\"\n ],\n \"there was an error reading the balance\": [\n \"\"\n ],\n \"Can't delete the account\": [\n \"\"\n ],\n \"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.\": [\n \"\"\n ],\n \"Name doesn't match\": [\n \"\u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0435\u0442\"\n ],\n \"delete account\": [\n \"\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C\"\n ],\n \"Account removed\": [\n \"\"\n ],\n \"No enough permission to delete the account.\": [\n \"\"\n ],\n \"The username was not found.\": [\n \"\"\n ],\n \"Can't delete a reserved username.\": [\n \"\"\n ],\n \"Can't delete an account with balance different than zero.\": [\n \"\"\n ],\n \"Remove account.\": [\n \"\u041D\u0430 \u0441\u0447\u0451\u0442\"\n ],\n \"You are going to remove the account\": [\n \"\"\n ],\n \"Deleting account \\\"%1$s\\\"\": [\n \"\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430 \\\"%1$s\\\"\"\n ],\n \"Verification\": [\n \"\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430\"\n ],\n \"Enter the account name that is going to be deleted\": [\n \"\"\n ],\n \"Cashout id should be a number\": [\n \"\"\n ],\n \"This cashout not found. Maybe already aborted.\": [\n \"\"\n ],\n \"Cashout detail\": [\n \"\u041F\u043E\u0434\u0440\u043E\u0431\u043D\u043E\u0441\u0442\u0438 \u043E\u0431\u043D\u0430\u043B\u0438\u0447\u0438\u0432\u0430\u043D\u0438\u044F\"\n ],\n \"Debited\": [\n \"\u0414\u0435\u0431\u0435\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u043E\"\n ],\n \"Transferred\": [\n \"\u041F\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438\"\n ],\n \"You have no permission to this account.\": [\n \"\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u0439 \u0434\u043B\u044F \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u044D\u0442\u043E\u0433\u043E \u0441\u0447\u0451\u0442\u0430.\"\n ],\n \"This account is locked. If you have a active session you can change the password or contact the administrator.\": [\n \"\"\n ],\n \"New web session\": [\n \"\"\n ],\n \"Welcome to %1$s!\": [\n \"\u0414\u043E\u0431\u0440\u043E \u043F\u043E\u0436\u0430\u043B\u043E\u0432\u0430\u0442\u044C \u0432 %1$s!\"\n ]\n }\n },\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\",\n \"lang\": \"ru\",\n \"completeness\": 66\n};\n\nstrings['it'] = {\n \"locale_data\": {\n \"messages\": {\n \"\": {\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n != 1;\",\n \"lang\": \"it\"\n },\n \"An IBAN consists of capital letters and numbers only\": [\n \"\"\n ],\n \"IBAN numbers have more that 4 digits\": [\n \"\"\n ],\n \"IBAN numbers have less that 34 digits\": [\n \"\"\n ],\n \"IBAN country code not found\": [\n \"\"\n ],\n \"IBAN number is not valid, checksum is wrong\": [\n \"\"\n ],\n \"Use letters, numbers or any of these characters: - . _ ~\": [\n \"\"\n ],\n \"Required\": [\n \"\"\n ],\n \"confirm MFA challenge\": [\n \"\"\n ],\n \"Unknown challenge.\": [\n \"\"\n ],\n \"Failed to validate the verification code.\": [\n \"\"\n ],\n \"Too many challenges are active right now, you must wait or confirm current challenges.\": [\n \"\"\n ],\n \"Wrong authentication number.\": [\n \"\"\n ],\n \"Expired challenge.\": [\n \"\"\n ],\n \"Submit the transmitted code number.\": [\n \"\"\n ],\n \"The verification code sent to the email address starting with %1$s\": [\n \"\"\n ],\n \"The verification code sent to the phone number ending with %1$s\": [\n \"\"\n ],\n \"Code\": [\n \"\"\n ],\n \"Username of the account\": [\n \"Trasferisci fondi a un altro conto di questa banca:\"\n ],\n \"It will expired at %1$s\": [\n \"\"\n ],\n \"The challenge is expired and can't be solved but you can go back and create a new challenge.\": [\n \"\"\n ],\n \"Back\": [\n \"\"\n ],\n \"Verify\": [\n \"\"\n ],\n \"send MFA challenge\": [\n \"\"\n ],\n \"Failed to send the verification code.\": [\n \"\"\n ],\n \"The request was valid, but the server is refusing action.\": [\n \"\"\n ],\n \"The backend is not aware of the specified MFA challenge.\": [\n \"\"\n ],\n \"It is too early to request another transmission of the challenge.\": [\n \"\"\n ],\n \"Code transmission failed.\": [\n \"Operazione non riuscita.\"\n ],\n \"select challenge\": [\n \"\"\n ],\n \"Multi-factor authentication required\": [\n \"\"\n ],\n \"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.\": [\n \"\"\n ],\n \"The next challenge needs to be completed to confirm the operation.\": [\n \"La banca sta creando l'operazione...\"\n ],\n \"All the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"One of the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"To an phone ending with \\\"%1$s\\\"\": [\n \"\"\n ],\n \"To an email starting with \\\" %1$s\\\"\": [\n \"\"\n ],\n \"I have a code\": [\n \"\"\n ],\n \"Send me a message\": [\n \"\"\n ],\n \"You have to wait until %1$s to send a new code.\": [\n \"\"\n ],\n \"Cancel\": [\n \"\"\n ],\n \"Complete\": [\n \"\"\n ],\n \"Unable to create a cashout\": [\n \"\"\n ],\n \"The bank configuration does not support cashout operations.\": [\n \"\"\n ],\n \"Close\": [\n \"\"\n ],\n \"Cashout is disabled\": [\n \"\"\n ],\n \"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"calculate conversion fee\": [\n \"\"\n ],\n \"The server didn't understand the request.\": [\n \"\"\n ],\n \"The amount is too small\": [\n \"Questo ritiro \u00E8 stato annullato!\"\n ],\n \"Conversion is not implemented.\": [\n \"\"\n ],\n \"At least debit or credit needs to be provided\": [\n \"\"\n ],\n \"The amount is malfored\": [\n \"\"\n ],\n \"The currency is not supported\": [\n \"\"\n ],\n \"Invalid\": [\n \"\"\n ],\n \"Amount needs to be higher\": [\n \"Somma da ritirare\"\n ],\n \"Balance is not enough\": [\n \"\"\n ],\n \"It is not possible to cashout less than %1$s: %2$s\": [\n \"\"\n ],\n \"The total transfer to the destination will be zero\": [\n \"\"\n ],\n \"create cashout\": [\n \"Ultime transazioni:\"\n ],\n \"Cashout created\": [\n \"\"\n ],\n \"Second factor authentication required.\": [\n \"\"\n ],\n \"Account not found\": [\n \"\"\n ],\n \"Duplicated request detected, check if the operation succeeded or try again.\": [\n \"\"\n ],\n \"The conversion rate was applied incorrectly\": [\n \"\"\n ],\n \"The account does not have sufficient funds\": [\n \"\"\n ],\n \"Missing cashout URI in the profile\": [\n \"\"\n ],\n \"The amount is below the minimum amount permitted.\": [\n \"\"\n ],\n \"Sending the confirmation message failed, retry later or contact the administrator.\": [\n \"\"\n ],\n \"The server doesn't support the current TAN channel.\": [\n \"\"\n ],\n \"Create cashout.\": [\n \"Ultime transazioni:\"\n ],\n \"Cashout\": [\n \"\"\n ],\n \"Conversion rate\": [\n \"\"\n ],\n \"Balance\": [\n \"\"\n ],\n \"Fee\": [\n \"\"\n ],\n \"To account\": [\n \"Al conto\"\n ],\n \"Legal name\": [\n \"\"\n ],\n \"If this name doesn't match the account holder's name, your transaction may fail.\": [\n \"\"\n ],\n \"Unable to cashout\": [\n \"Ultime transazioni:\"\n ],\n \"Before being able to cashout to a bank account, you need to complete your profile\": [\n \"\"\n ],\n \"Transfer subject\": [\n \"Trasferisci fondi a un altro conto di questa banca:\"\n ],\n \"Currency\": [\n \"\"\n ],\n \"Send %1$s\": [\n \"\"\n ],\n \"Receive %1$s\": [\n \"\"\n ],\n \"Amount\": [\n \"Importo\"\n ],\n \"Total cost\": [\n \"\"\n ],\n \"Balance left\": [\n \"\"\n ],\n \"Before fee\": [\n \"\"\n ],\n \"Total cashout transfer\": [\n \"\"\n ],\n \"Not valid\": [\n \"\"\n ],\n \"Does not follow the pattern\": [\n \"\"\n ],\n \"send transaction\": [\n \"Ancora nessuna transazione.\"\n ],\n \"The wire transfer was successfully completed!\": [\n \"Il bonifico bancario \u00E8 stato completato con successo!\"\n ],\n \"The request was invalid or the payto://-URI used unacceptable features.\": [\n \"\"\n ],\n \"Not enough permission to complete the operation.\": [\n \"La banca sta creando l'operazione...\"\n ],\n \"The bank administrator cannot be the transfer creditor.\": [\n \"\"\n ],\n \"The destination account \\\"%1$s\\\" was not found.\": [\n \"Lista conti pubblici non trovata.\"\n ],\n \"The origin and the destination of the transfer can't be the same.\": [\n \"\"\n ],\n \"Your balance is not sufficient for the operation.\": [\n \"\"\n ],\n \"The origin account \\\"%1$s\\\" was not found.\": [\n \"Lista conti pubblici non trovata.\"\n ],\n \"The attempt to create the transaction has failed. Please try again.\": [\n \"\"\n ],\n \"A second factor authentication is required.\": [\n \"\"\n ],\n \"Confirm wire transfer.\": [\n \"Bonifico\"\n ],\n \"Input wire transfer detail\": [\n \"Inserite qui i dettagli del bonifico\"\n ],\n \"Using a form\": [\n \"\"\n ],\n \"A special URI that specifies the amount to be transferred and the destination account.\": [\n \"\"\n ],\n \"QR code\": [\n \"\"\n ],\n \"If your device has a camera, you can import a payto:// URI from a QR code.\": [\n \"\"\n ],\n \"Recipient\": [\n \"\"\n ],\n \"ID of the recipient's account\": [\n \"Storico dei conti pubblici\"\n ],\n \"username\": [\n \"\"\n ],\n \"IBAN of the recipient's account\": [\n \"\"\n ],\n \"Subject\": [\n \"Soggetto\"\n ],\n \"Some text to identify the transfer\": [\n \"\"\n ],\n \"Amount to transfer\": [\n \"Somma da trasferire\"\n ],\n \"Payto URI:\": [\n \"\"\n ],\n \"Uniform resource identifier of the target account\": [\n \"\"\n ],\n \"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"\"\n ],\n \"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"\"\n ],\n \"The maximum amount for a wire transfer is %1$s\": [\n \"\"\n ],\n \"Cost\": [\n \"\"\n ],\n \"Send\": [\n \"\"\n ],\n \"Only \\\"x-taler-bank\\\" target are supported\": [\n \"\"\n ],\n \"Only this host is allowed. Use \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Account name is missing\": [\n \"Importo\"\n ],\n \"Only \\\"IBAN\\\" target are supported\": [\n \"\"\n ],\n \"Missing \\\"amount\\\" parameter to specify the amount to be transferred\": [\n \"\"\n ],\n \"The \\\"amount\\\" parameter is not valid\": [\n \"Questo ritiro \u00E8 stato annullato!\"\n ],\n \"\\\"message\\\" parameters to specify a reference text for the transfer are missing\": [\n \"\"\n ],\n \"The only currency allowed is \\\"%1$s\\\"\": [\n \"\"\n ],\n \"You cannot transfer an amount of zero.\": [\n \"\"\n ],\n \"The balance is not sufficient\": [\n \"\"\n ],\n \"Please enter a longer subject\": [\n \"Trasferisci fondi a un altro conto di questa banca:\"\n ],\n \"Show withdrawal confirmation\": [\n \"Questo ritiro \u00E8 stato annullato!\"\n ],\n \"Withdraw without setting amount\": [\n \"\"\n ],\n \"Hide demo hint.\": [\n \"\"\n ],\n \"Show install wallet first\": [\n \"\"\n ],\n \"Currently, the bank is not accepting new registrations!\": [\n \"\"\n ],\n \"The name is missing\": [\n \"\"\n ],\n \"Missing username\": [\n \"\"\n ],\n \"Missing password\": [\n \"\"\n ],\n \"The password should be longer than 8 letters\": [\n \"\"\n ],\n \"The passwords do not match\": [\n \"\"\n ],\n \"register new account\": [\n \"Conto interno\"\n ],\n \"Server replied with invalid phone or email.\": [\n \"\"\n ],\n \"You are not authorised to create this account.\": [\n \"\"\n ],\n \"Registration is disabled because the bank ran out of bonus credit.\": [\n \"\"\n ],\n \"That username can't be used because is reserved.\": [\n \"\"\n ],\n \"That username is already taken.\": [\n \"\"\n ],\n \"That account ID is already taken.\": [\n \"\"\n ],\n \"No information for the selected authentication channel.\": [\n \"\"\n ],\n \"Authentication channel is not supported.\": [\n \"\"\n ],\n \"Only an administrator is allowed to set the debt limit.\": [\n \"\"\n ],\n \"Only the administrator can change the conversion rate.\": [\n \"\"\n ],\n \"The conversion rate class doesn't exist.\": [\n \"\"\n ],\n \"Only admin can create accounts with second factor authentication.\": [\n \"\"\n ],\n \"The password is too short. Can't have less than 8 characters.\": [\n \"\"\n ],\n \"The password is too long. Can't have more than 64 characters.\": [\n \"\"\n ],\n \"Account registration\": [\n \"\"\n ],\n \"Login username\": [\n \"\"\n ],\n \"account identification to login\": [\n \"\"\n ],\n \"Password\": [\n \"\"\n ],\n \"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers\": [\n \"\"\n ],\n \"Repeat password\": [\n \"\"\n ],\n \"Same password\": [\n \"\"\n ],\n \"Full name\": [\n \"\"\n ],\n \"Register\": [\n \"Registrati\"\n ],\n \"Create a random temporary user\": [\n \"\"\n ],\n \"logout\": [\n \"\"\n ],\n \"login\": [\n \"Accedi\"\n ],\n \"The account has no rights to login.\": [\n \"\"\n ],\n \"The account is locked and cannot login. Contact administrator.\": [\n \"\"\n ],\n \"Wrong credentials for \\\"%1$s\\\"\": [\n \"Credenziali invalide.\"\n ],\n \"Account login.\": [\n \"Importo\"\n ],\n \"Session expired\": [\n \"\"\n ],\n \"Username\": [\n \"\"\n ],\n \"identification\": [\n \"\"\n ],\n \"Password of the account\": [\n \"Password dell'account\"\n ],\n \"Forget\": [\n \"\"\n ],\n \"Log in\": [\n \"\"\n ],\n \"Transactions history\": [\n \"\"\n ],\n \"No transactions yet.\": [\n \"Ancora nessuna transazione.\"\n ],\n \"You can make a transfer or a withdrawal to your wallet.\": [\n \"\"\n ],\n \"Date\": [\n \"Data\"\n ],\n \"Counterpart\": [\n \"Conto corrente\"\n ],\n \"sent\": [\n \"\"\n ],\n \"received\": [\n \"\"\n ],\n \"Invalid value\": [\n \"\"\n ],\n \"to\": [\n \"\"\n ],\n \"from\": [\n \"\"\n ],\n \"First page\": [\n \"\"\n ],\n \"Next\": [\n \"\"\n ],\n \"confirm withdrawal\": [\n \"Conferma il ritiro\"\n ],\n \"cambiar\": [\n \"\"\n ],\n \"abort withdrawal\": [\n \"Conferma il ritiro\"\n ],\n \"The withdrawal has been aborted previously and can't be confirmed\": [\n \"\"\n ],\n \"The withdrawal operation can't be confirmed before a wallet accepted the transaction.\": [\n \"\"\n ],\n \"The operation ID is invalid.\": [\n \"L'ID dell'operazione non \u00E8 valido.\"\n ],\n \"The operation was not found.\": [\n \"L'operazione non \u00E8 stata trovata.\"\n ],\n \"The starting withdrawal amount and the confirmation amount differs.\": [\n \"\"\n ],\n \"The bank requires a bank account which has not been specified yet.\": [\n \"\"\n ],\n \"Bad request\": [\n \"\"\n ],\n \"The withdrawal operation has been aborted.\": [\n \"L'operazione non \u00E8 stata trovata.\"\n ],\n \"The withdrawal operation has been confirmed previously and can\u2019t be aborted.\": [\n \"\"\n ],\n \"Complete withdrawal.\": [\n \"Conferma il ritiro\"\n ],\n \"Confirm the withdrawal operation\": [\n \"Conferma il ritiro\"\n ],\n \"Wire transfer details\": [\n \"Bonifico\"\n ],\n \"Payment Service Provider's account number\": [\n \"\"\n ],\n \"Payment Service Provider's name\": [\n \"\"\n ],\n \"Payment Service Provider's account bank hostname\": [\n \"\"\n ],\n \"Payment Service Provider's account id\": [\n \"\"\n ],\n \"Payment Service Provider's account address\": [\n \"\"\n ],\n \"Payment Service Provider's account cyclos hostname\": [\n \"\"\n ],\n \"No amount has yet been determined.\": [\n \"\"\n ],\n \"Transfer\": [\n \"\"\n ],\n \"Authentication required\": [\n \"\"\n ],\n \"This operation was created with another username\": [\n \"Lista conti pubblici non trovata.\"\n ],\n \"You are currently logged in with user \\\"%1$s\\\" and the operation was made with user \\\"%2$s\\\"\": [\n \"\"\n ],\n \"The reserve operation has been confirmed previously and can't be aborted\": [\n \"\"\n ],\n \"Wire transfer completed!\": [\n \"Bonifico\"\n ],\n \"Confirm withdrawal.\": [\n \"Conferma il ritiro\"\n ],\n \"Unauthorized to make the operation, maybe the session has expired or the password changed.\": [\n \"\"\n ],\n \"The operation was rejected due to insufficient funds.\": [\n \"\"\n ],\n \"Withdrawal confirmed\": [\n \"Questo ritiro \u00E8 stato annullato!\"\n ],\n \"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.\": [\n \"\"\n ],\n \"Do not show this again\": [\n \"\"\n ],\n \"If you have a Taler wallet installed on this device\": [\n \"\"\n ],\n \"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions\": [\n \"\"\n ],\n \"on this page\": [\n \"\"\n ],\n \"Withdraw\": [\n \"Prelevare\"\n ],\n \"In case you have a Taler wallet on another device\": [\n \"\"\n ],\n \"Scan the QR below to start the withdrawal.\": [\n \"Chiudi il ritiro Taler\"\n ],\n \"create withdrawal\": [\n \"Conferma il ritiro\"\n ],\n \"The server replied with an invalid taler://withdraw URI\": [\n \"\"\n ],\n \"Withdraw URI: %1$s\": [\n \"Withdraw URI: %1$s\"\n ],\n \"The operation was rejected due to insufficient funds\": [\n \"\"\n ],\n \"Current balance is %1$s\": [\n \"\"\n ],\n \"You can withdraw up to %1$s\": [\n \"\"\n ],\n \"Continue\": [\n \"\"\n ],\n \"Use your Taler wallet\": [\n \"\"\n ],\n \"After using your wallet you will need to authorize or cancel the operation on this site.\": [\n \"\"\n ],\n \"You need a Taler wallet\": [\n \"Ritira contante nel portafoglio Taler\"\n ],\n \"If you don't have one yet you can follow the instruction in\": [\n \"\"\n ],\n \"this page\": [\n \"\"\n ],\n \"Send money\": [\n \"\"\n ],\n \"to a Taler wallet\": [\n \"Ritira contante nel portafoglio Taler\"\n ],\n \"Withdraw digital money into your mobile wallet or browser extension\": [\n \"\"\n ],\n \"to another bank account\": [\n \"Trasferisci fondi a un altro conto di questa banca:\"\n ],\n \"Make a wire transfer to an account with known bank account number.\": [\n \"\"\n ],\n \"This is a demo\": [\n \"\"\n ],\n \"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .\": [\n \"\"\n ],\n \"Here you will be able to see how a bank that supports Taler directly would work.\": [\n \"\"\n ],\n \"Internal error, please report. There should be more information in the console.\": [\n \"\"\n ],\n \"Internal error, please report.\": [\n \"Registrazione\"\n ],\n \"Preferences\": [\n \"\"\n ],\n \"Show debug information\": [\n \"Questo ritiro \u00E8 stato annullato!\"\n ],\n \"Welcome\": [\n \"\"\n ],\n \"Welcome, %1$s\": [\n \"\"\n ],\n \"No enough permission to access the conversion rate list.\": [\n \"La banca sta creando l'operazione...\"\n ],\n \"Conversion list not found. Maybe conversion rate is not supported.\": [\n \"\"\n ],\n \"Conversion list not implemented.\": [\n \"\"\n ],\n \"Conversion rate classes\": [\n \"Cambio\"\n ],\n \"Create conversion rate class\": [\n \"\"\n ],\n \"No conversion rate class\": [\n \"\"\n ],\n \"Name\": [\n \"\"\n ],\n \"Description\": [\n \"\"\n ],\n \"Cashin\": [\n \"\"\n ],\n \"min:\": [\n \"\"\n ],\n \"fee:\": [\n \"\"\n ],\n \"Select a section\": [\n \"\"\n ],\n \"Details\": [\n \"\"\n ],\n \"Delete\": [\n \"\"\n ],\n \"Credentials\": [\n \"Credenziali\"\n ],\n \"Cashouts\": [\n \"Incassi (Cashout)\"\n ],\n \"Conversion\": [\n \"Cambio\"\n ],\n \"only admin can setup conversion\": [\n \"\"\n ],\n \"calculate cashout fee\": [\n \"Ultime transazioni:\"\n ],\n \"update conversion rate\": [\n \"Cambio\"\n ],\n \"Wrong credentials\": [\n \"Credenziali invalide.\"\n ],\n \"Conversion is disabled\": [\n \"\"\n ],\n \"Config cashout\": [\n \"Ultime transazioni:\"\n ],\n \"Config cashin\": [\n \"\"\n ],\n \"Bad ratios\": [\n \"\"\n ],\n \"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.\": [\n \"\"\n ],\n \"Initial amount\": [\n \"Questo ritiro \u00E8 stato annullato!\"\n ],\n \"Use it to test how the conversion will affect the amount.\": [\n \"\"\n ],\n \"Sending to this bank\": [\n \"\"\n ],\n \"Converted\": [\n \"\"\n ],\n \"Cashin after fee\": [\n \"\"\n ],\n \"Sending from this bank\": [\n \"\"\n ],\n \"Cashout after fee\": [\n \"\"\n ],\n \"Bad configuration\": [\n \"\"\n ],\n \"This configuration allows users to cash out more of what has been cashed in.\": [\n \"\"\n ],\n \"Update\": [\n \"\"\n ],\n \"Rnvalid\": [\n \"\"\n ],\n \"Must be > 0\": [\n \"\"\n ],\n \"Minimum amount\": [\n \"\"\n ],\n \"Only cashout operation above this threshold will be allowed.\": [\n \"\"\n ],\n \"Ratio\": [\n \"\"\n ],\n \"Conversion ratio between currencies\": [\n \"\"\n ],\n \"Example conversion\": [\n \"\"\n ],\n \"1 %1$s will be converted into %2$s %3$s\": [\n \"\"\n ],\n \"Tiny amount\": [\n \"Al conto\"\n ],\n \"Rounding mode\": [\n \"\"\n ],\n \"Zero\": [\n \"\"\n ],\n \"Amount will be round below to the largest possible value smaller than the input.\": [\n \"\"\n ],\n \"Up\": [\n \"\"\n ],\n \"Amount will be round up to the smallest possible value larger than the input.\": [\n \"\"\n ],\n \"Nearest\": [\n \"\"\n ],\n \"Amount will be round to the closest possible value.\": [\n \"\"\n ],\n \"If none specified the fallback value is \\\"%1$s \\\".\": [\n \"\"\n ],\n \"Examples\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.1\": [\n \"\"\n ],\n \"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.\": [\n \"\"\n ],\n \"With the \\\"zero\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.1\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.3\": [\n \"\"\n ],\n \"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.5\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.3\": [\n \"\"\n ],\n \"Amount to be deducted before amount is credited.\": [\n \"\"\n ],\n \"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"delete conversion rate class\": [\n \"Cambio\"\n ],\n \"Unauthorized\": [\n \"\"\n ],\n \"Forbidden\": [\n \"\"\n ],\n \"NotFound\": [\n \"\"\n ],\n \"NotImplemented\": [\n \"\"\n ],\n \"update conversion rate class\": [\n \"Cambio\"\n ],\n \"Not Found\": [\n \"\"\n ],\n \"Not implemented\": [\n \"\"\n ],\n \"The name of the conversion is already used.\": [\n \"Questo ritiro \u00E8 stato annullato!\"\n ],\n \"Conversion rate class\": [\n \"Cambio\"\n ],\n \"Accounts\": [\n \"Importo\"\n ],\n \"Test\": [\n \"\"\n ],\n \"Users\": [\n \"\"\n ],\n \"Can't remove the conversion rate class\": [\n \"\"\n ],\n \"There are some user associated to this class. You need to remove them first.\": [\n \"\"\n ],\n \"You are going to remove the conversion rate class\": [\n \"\"\n ],\n \"This step can't be undone.\": [\n \"\"\n ],\n \"Filters\": [\n \"\"\n ],\n \"Show from other classes\": [\n \"\"\n ],\n \"Account\": [\n \"Conto\"\n ],\n \"Group ID\": [\n \"\"\n ],\n \"No users in this conversion rate class\": [\n \"\"\n ],\n \"Class\": [\n \"\"\n ],\n \"Action\": [\n \"\"\n ],\n \"Remove\": [\n \"\"\n ],\n \"Add\": [\n \"indirizzo Payto\"\n ],\n \"Conversion rate name\": [\n \"Cambio\"\n ],\n \"Short description of the class\": [\n \"\"\n ],\n \"create conversion rate class\": [\n \"Cambio\"\n ],\n \"Conversion rate class created.\": [\n \"\"\n ],\n \"The rights to change the account are not sufficient\": [\n \"\"\n ],\n \"New conversion rate class\": [\n \"\"\n ],\n \"Create\": [\n \"\"\n ],\n \"History of public accounts\": [\n \"Storico dei conti pubblici\"\n ],\n \"Make a wire transfer\": [\n \"Chiudi il bonifico\"\n ],\n \"Scan the QR code below to start the withdrawal.\": [\n \"Chiudi il ritiro Taler\"\n ],\n \"Operation aborted\": [\n \"\"\n ],\n \"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.\": [\n \"\"\n ],\n \"Go to your wallet now\": [\n \"\"\n ],\n \"The operation is marked as selected, but a process during the withdrawal failed\": [\n \"\"\n ],\n \"A withdrawal reserve ID was not found and no account has been selected.\": [\n \"\"\n ],\n \"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.\": [\n \"\"\n ],\n \"The account was selected, but no withdrawal reserve ID was found.\": [\n \"\"\n ],\n \"Operation not found\": [\n \"\"\n ],\n \"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.\": [\n \"\"\n ],\n \"Continue to dashboard\": [\n \"\"\n ],\n \"The Withdrawal URI is not valid\": [\n \"Questo ritiro \u00E8 stato annullato!\"\n ],\n \"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.\": [\n \"\"\n ],\n \"Latest cashouts\": [\n \"Ultime transazioni:\"\n ],\n \"Created\": [\n \"\"\n ],\n \"Total debit\": [\n \"\"\n ],\n \"Total credit\": [\n \"\"\n ],\n \"Cashout for account %1$s\": [\n \"\"\n ],\n \"Invalid email format\": [\n \"\"\n ],\n \"Should start with +\": [\n \"\"\n ],\n \"A phone number consists of numbers only\": [\n \"\"\n ],\n \"Account ID for authentication\": [\n \"\"\n ],\n \"Name of the account holder\": [\n \"Nome del titolare del conto corrente bancario\"\n ],\n \"Internal account\": [\n \"Conto interno\"\n ],\n \"If this field is empty, a random account ID will be assigned\": [\n \"\"\n ],\n \"You can copy and share this IBAN number in order to receive wire transfers to your bank account\": [\n \"\"\n ],\n \"Email\": [\n \"\"\n ],\n \"To be used when second factor authentication is enabled\": [\n \"\"\n ],\n \"Phone\": [\n \"\"\n ],\n \"Enable second factor authentication\": [\n \"\"\n ],\n \"Using email\": [\n \"\"\n ],\n \"Add an email in your profile to enable this option\": [\n \"\"\n ],\n \"Using SMS\": [\n \"\"\n ],\n \"Add a phone number in your profile to enable this option\": [\n \"\"\n ],\n \"Cashout account\": [\n \"Conto di incasso\"\n ],\n \"External account number where the money is going to be sent when doing cashouts\": [\n \"\"\n ],\n \"Max debt\": [\n \"\"\n ],\n \"How much the balance can go below zero.\": [\n \"\"\n ],\n \"Is this account public?\": [\n \"\"\n ],\n \"Public accounts have their balance publicly accessible\": [\n \"\"\n ],\n \"Does this account belong to a Payment Service Provider?\": [\n \"\"\n ],\n \"update account\": [\n \"Conto di incasso\"\n ],\n \"Account updated\": [\n \"\"\n ],\n \"The username was not found\": [\n \"\"\n ],\n \"You can't change the legal name, please contact the your account administrator.\": [\n \"\"\n ],\n \"You can't change the debt limit, please contact the your account administrator.\": [\n \"\"\n ],\n \"You can't change the cashout address, please contact the your account administrator.\": [\n \"\"\n ],\n \"Update account information.\": [\n \"Aggiornamento dei valori del conto\"\n ],\n \"Account \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Removed\": [\n \"\"\n ],\n \"This account can't be used.\": [\n \"\"\n ],\n \"Change details\": [\n \"\"\n ],\n \"Merchant integration\": [\n \"\"\n ],\n \"Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the \\\"import\\\" button in the \\\"bank account\\\" section.\": [\n \"\"\n ],\n \"Account type\": [\n \"Importo\"\n ],\n \"Method to use for wire transfer.\": [\n \"Chiudi il bonifico\"\n ],\n \"IBAN\": [\n \"\"\n ],\n \"International Bank Account Number.\": [\n \"\"\n ],\n \"Account name\": [\n \"Importo\"\n ],\n \"Bank host where the service is located.\": [\n \"\"\n ],\n \"Bank account identifier for wire transfers.\": [\n \"\"\n ],\n \"Address\": [\n \"indirizzo Payto\"\n ],\n \"Owner's name\": [\n \"\"\n ],\n \"Legal name of the person holding the account.\": [\n \"\"\n ],\n \"Account info URL\": [\n \"Lista conti pubblici non trovata.\"\n ],\n \"From where the merchant can download information about incoming wire transfers to this account.\": [\n \"\"\n ],\n \"Repeated password doesn't match\": [\n \"\"\n ],\n \"update password\": [\n \"Aggiornamento dei valori del conto\"\n ],\n \"Password changed\": [\n \"\"\n ],\n \"Not authorized to change the password, maybe the session is invalid.\": [\n \"\"\n ],\n \"You need to provide the old password. If you don't have it contact your account administrator.\": [\n \"\"\n ],\n \"Your current password doesn't match, can't change to a new password.\": [\n \"\"\n ],\n \"You don't have the rights to change the password.\": [\n \"\"\n ],\n \"Update account password.\": [\n \"Aggiornamento dei valori del conto\"\n ],\n \"Update password\": [\n \"\"\n ],\n \"Current password\": [\n \"\"\n ],\n \"Your current password, for security\": [\n \"\"\n ],\n \"New password\": [\n \"\"\n ],\n \"Type it again\": [\n \"\"\n ],\n \"Repeat the same password\": [\n \"\"\n ],\n \"Change\": [\n \"\"\n ],\n \"Create account\": [\n \"\"\n ],\n \"Actions\": [\n \"\"\n ],\n \"Unknown\": [\n \"\"\n ],\n \"Change password\": [\n \"\"\n ],\n \"Querying for the current stats failed\": [\n \"\"\n ],\n \"The request parameters are wrong\": [\n \"\"\n ],\n \"The user is unauthorized\": [\n \"\"\n ],\n \"Querying for the previous stats failed\": [\n \"\"\n ],\n \"Transaction volume report\": [\n \"\"\n ],\n \"Last hour\": [\n \"\"\n ],\n \"Previous day\": [\n \"\"\n ],\n \"Last month\": [\n \"\"\n ],\n \"Last year\": [\n \"\"\n ],\n \"Last Year\": [\n \"\"\n ],\n \"Trading volume from %1$s to %2$s\": [\n \"\"\n ],\n \"Transferred from an external account to an account in this bank.\": [\n \"\"\n ],\n \"Transferred from an account in this bank to an external account.\": [\n \"\"\n ],\n \"Payin\": [\n \"\"\n ],\n \"Transferred from an account to a Taler exchange.\": [\n \"\"\n ],\n \"Payout\": [\n \"\"\n ],\n \"Transferred from a Taler exchange to another account.\": [\n \"\"\n ],\n \"Download stats as CSV\": [\n \"\"\n ],\n \"previous\": [\n \"\"\n ],\n \"Decreased by\": [\n \"\"\n ],\n \"Increased by\": [\n \"\"\n ],\n \"create account\": [\n \"Al conto\"\n ],\n \"Account created with password \\\"%1$s\\\".\": [\n \"\"\n ],\n \"Server replied that phone or email is invalid\": [\n \"\"\n ],\n \"The rights to perform the operation are not sufficient\": [\n \"\"\n ],\n \"Account username is already taken\": [\n \"\"\n ],\n \"Account ID is already taken\": [\n \"\"\n ],\n \"Bank ran out of bonus credit.\": [\n \"\"\n ],\n \"Account username can't be used because is reserved\": [\n \"\"\n ],\n \"Can't create accounts\": [\n \"\"\n ],\n \"Only system admin can create accounts.\": [\n \"\"\n ],\n \"New bank account\": [\n \"Trasferisci fondi a un altro conto di questa banca:\"\n ],\n \"download statistics\": [\n \"\"\n ],\n \"only admin can download stats\": [\n \"\"\n ],\n \"Download bank stats\": [\n \"\"\n ],\n \"Include hour metric\": [\n \"\"\n ],\n \"Include day metric\": [\n \"\"\n ],\n \"Include month metric\": [\n \"\"\n ],\n \"Include year metric\": [\n \"\"\n ],\n \"Include table header\": [\n \"\"\n ],\n \"Add previous metric for compare\": [\n \"\"\n ],\n \"Fail on first error\": [\n \"\"\n ],\n \"Download\": [\n \"\"\n ],\n \"downloading... %1$s\": [\n \"\"\n ],\n \"Download completed\": [\n \"\"\n ],\n \"Click here to save the file in your computer.\": [\n \"\"\n ],\n \"there was an error reading the balance\": [\n \"\"\n ],\n \"Can't delete the account\": [\n \"\"\n ],\n \"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.\": [\n \"\"\n ],\n \"Name doesn't match\": [\n \"\"\n ],\n \"delete account\": [\n \"Al conto\"\n ],\n \"Account removed\": [\n \"\"\n ],\n \"No enough permission to delete the account.\": [\n \"\"\n ],\n \"The username was not found.\": [\n \"\"\n ],\n \"Can't delete a reserved username.\": [\n \"\"\n ],\n \"Can't delete an account with balance different than zero.\": [\n \"\"\n ],\n \"Remove account.\": [\n \"Al conto\"\n ],\n \"You are going to remove the account\": [\n \"\"\n ],\n \"Deleting account \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Verification\": [\n \"\"\n ],\n \"Enter the account name that is going to be deleted\": [\n \"\"\n ],\n \"Cashout id should be a number\": [\n \"\"\n ],\n \"This cashout not found. Maybe already aborted.\": [\n \"\"\n ],\n \"Cashout detail\": [\n \"\"\n ],\n \"Debited\": [\n \"\"\n ],\n \"Transferred\": [\n \"Trasferisci fondi a un altro conto di questa banca:\"\n ],\n \"You have no permission to this account.\": [\n \"La banca sta creando l'operazione...\"\n ],\n \"This account is locked. If you have a active session you can change the password or contact the administrator.\": [\n \"\"\n ],\n \"New web session\": [\n \"\"\n ],\n \"Welcome to %1$s!\": [\n \"\"\n ]\n }\n },\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n != 1;\",\n \"lang\": \"it\",\n \"completeness\": 19\n};\n\nstrings['he'] = {\n \"locale_data\": {\n \"messages\": {\n \"\": {\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && n % 10 == 0) ? 2 : 3));\",\n \"lang\": \"he\"\n },\n \"An IBAN consists of capital letters and numbers only\": [\n \"\"\n ],\n \"IBAN numbers have more that 4 digits\": [\n \"\"\n ],\n \"IBAN numbers have less that 34 digits\": [\n \"\"\n ],\n \"IBAN country code not found\": [\n \"\"\n ],\n \"IBAN number is not valid, checksum is wrong\": [\n \"\"\n ],\n \"Use letters, numbers or any of these characters: - . _ ~\": [\n \"\"\n ],\n \"Required\": [\n \"\"\n ],\n \"confirm MFA challenge\": [\n \"\"\n ],\n \"Unknown challenge.\": [\n \"\"\n ],\n \"Failed to validate the verification code.\": [\n \"\"\n ],\n \"Too many challenges are active right now, you must wait or confirm current challenges.\": [\n \"\"\n ],\n \"Wrong authentication number.\": [\n \"\"\n ],\n \"Expired challenge.\": [\n \"\"\n ],\n \"Submit the transmitted code number.\": [\n \"\"\n ],\n \"The verification code sent to the email address starting with %1$s\": [\n \"\"\n ],\n \"The verification code sent to the phone number ending with %1$s\": [\n \"\"\n ],\n \"Code\": [\n \"\"\n ],\n \"Username of the account\": [\n \"\"\n ],\n \"It will expired at %1$s\": [\n \"\"\n ],\n \"The challenge is expired and can't be solved but you can go back and create a new challenge.\": [\n \"\"\n ],\n \"Back\": [\n \"\"\n ],\n \"Verify\": [\n \"\"\n ],\n \"send MFA challenge\": [\n \"\"\n ],\n \"Failed to send the verification code.\": [\n \"\"\n ],\n \"The request was valid, but the server is refusing action.\": [\n \"\"\n ],\n \"The backend is not aware of the specified MFA challenge.\": [\n \"\"\n ],\n \"It is too early to request another transmission of the challenge.\": [\n \"\"\n ],\n \"Code transmission failed.\": [\n \"\"\n ],\n \"select challenge\": [\n \"\"\n ],\n \"Multi-factor authentication required\": [\n \"\"\n ],\n \"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.\": [\n \"\"\n ],\n \"The next challenge needs to be completed to confirm the operation.\": [\n \"\"\n ],\n \"All the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"One of the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"To an phone ending with \\\"%1$s\\\"\": [\n \"\"\n ],\n \"To an email starting with \\\" %1$s\\\"\": [\n \"\"\n ],\n \"I have a code\": [\n \"\"\n ],\n \"Send me a message\": [\n \"\"\n ],\n \"You have to wait until %1$s to send a new code.\": [\n \"\"\n ],\n \"Cancel\": [\n \"\"\n ],\n \"Complete\": [\n \"\"\n ],\n \"Unable to create a cashout\": [\n \"\"\n ],\n \"The bank configuration does not support cashout operations.\": [\n \"\"\n ],\n \"Close\": [\n \"\"\n ],\n \"Cashout is disabled\": [\n \"\"\n ],\n \"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"calculate conversion fee\": [\n \"\"\n ],\n \"The server didn't understand the request.\": [\n \"\"\n ],\n \"The amount is too small\": [\n \"\"\n ],\n \"Conversion is not implemented.\": [\n \"\"\n ],\n \"At least debit or credit needs to be provided\": [\n \"\"\n ],\n \"The amount is malfored\": [\n \"\"\n ],\n \"The currency is not supported\": [\n \"\"\n ],\n \"Invalid\": [\n \"\"\n ],\n \"Amount needs to be higher\": [\n \"\"\n ],\n \"Balance is not enough\": [\n \"\"\n ],\n \"It is not possible to cashout less than %1$s: %2$s\": [\n \"\"\n ],\n \"The total transfer to the destination will be zero\": [\n \"\"\n ],\n \"create cashout\": [\n \"\"\n ],\n \"Cashout created\": [\n \"\"\n ],\n \"Second factor authentication required.\": [\n \"\"\n ],\n \"Account not found\": [\n \"\"\n ],\n \"Duplicated request detected, check if the operation succeeded or try again.\": [\n \"\"\n ],\n \"The conversion rate was applied incorrectly\": [\n \"\"\n ],\n \"The account does not have sufficient funds\": [\n \"\"\n ],\n \"Missing cashout URI in the profile\": [\n \"\"\n ],\n \"The amount is below the minimum amount permitted.\": [\n \"\"\n ],\n \"Sending the confirmation message failed, retry later or contact the administrator.\": [\n \"\"\n ],\n \"The server doesn't support the current TAN channel.\": [\n \"\"\n ],\n \"Create cashout.\": [\n \"\"\n ],\n \"Cashout\": [\n \"\"\n ],\n \"Conversion rate\": [\n \"\"\n ],\n \"Balance\": [\n \"\"\n ],\n \"Fee\": [\n \"\"\n ],\n \"To account\": [\n \"\"\n ],\n \"Legal name\": [\n \"\"\n ],\n \"If this name doesn't match the account holder's name, your transaction may fail.\": [\n \"\"\n ],\n \"Unable to cashout\": [\n \"\"\n ],\n \"Before being able to cashout to a bank account, you need to complete your profile\": [\n \"\"\n ],\n \"Transfer subject\": [\n \"\"\n ],\n \"Currency\": [\n \"\"\n ],\n \"Send %1$s\": [\n \"\"\n ],\n \"Receive %1$s\": [\n \"\"\n ],\n \"Amount\": [\n \"\"\n ],\n \"Total cost\": [\n \"\"\n ],\n \"Balance left\": [\n \"\"\n ],\n \"Before fee\": [\n \"\"\n ],\n \"Total cashout transfer\": [\n \"\"\n ],\n \"Not valid\": [\n \"\"\n ],\n \"Does not follow the pattern\": [\n \"\"\n ],\n \"send transaction\": [\n \"\"\n ],\n \"The wire transfer was successfully completed!\": [\n \"\"\n ],\n \"The request was invalid or the payto://-URI used unacceptable features.\": [\n \"\"\n ],\n \"Not enough permission to complete the operation.\": [\n \"\"\n ],\n \"The bank administrator cannot be the transfer creditor.\": [\n \"\"\n ],\n \"The destination account \\\"%1$s\\\" was not found.\": [\n \"\"\n ],\n \"The origin and the destination of the transfer can't be the same.\": [\n \"\"\n ],\n \"Your balance is not sufficient for the operation.\": [\n \"\"\n ],\n \"The origin account \\\"%1$s\\\" was not found.\": [\n \"\"\n ],\n \"The attempt to create the transaction has failed. Please try again.\": [\n \"\"\n ],\n \"A second factor authentication is required.\": [\n \"\"\n ],\n \"Confirm wire transfer.\": [\n \"\"\n ],\n \"Input wire transfer detail\": [\n \"\"\n ],\n \"Using a form\": [\n \"\"\n ],\n \"A special URI that specifies the amount to be transferred and the destination account.\": [\n \"\"\n ],\n \"QR code\": [\n \"\"\n ],\n \"If your device has a camera, you can import a payto:// URI from a QR code.\": [\n \"\"\n ],\n \"Recipient\": [\n \"\"\n ],\n \"ID of the recipient's account\": [\n \"\"\n ],\n \"username\": [\n \"\"\n ],\n \"IBAN of the recipient's account\": [\n \"\"\n ],\n \"Subject\": [\n \"\"\n ],\n \"Some text to identify the transfer\": [\n \"\"\n ],\n \"Amount to transfer\": [\n \"\"\n ],\n \"Payto URI:\": [\n \"\"\n ],\n \"Uniform resource identifier of the target account\": [\n \"\"\n ],\n \"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"\"\n ],\n \"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"\"\n ],\n \"The maximum amount for a wire transfer is %1$s\": [\n \"\"\n ],\n \"Cost\": [\n \"\"\n ],\n \"Send\": [\n \"\"\n ],\n \"Only \\\"x-taler-bank\\\" target are supported\": [\n \"\"\n ],\n \"Only this host is allowed. Use \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Account name is missing\": [\n \"\"\n ],\n \"Only \\\"IBAN\\\" target are supported\": [\n \"\"\n ],\n \"Missing \\\"amount\\\" parameter to specify the amount to be transferred\": [\n \"\"\n ],\n \"The \\\"amount\\\" parameter is not valid\": [\n \"\"\n ],\n \"\\\"message\\\" parameters to specify a reference text for the transfer are missing\": [\n \"\"\n ],\n \"The only currency allowed is \\\"%1$s\\\"\": [\n \"\"\n ],\n \"You cannot transfer an amount of zero.\": [\n \"\"\n ],\n \"The balance is not sufficient\": [\n \"\"\n ],\n \"Please enter a longer subject\": [\n \"\"\n ],\n \"Show withdrawal confirmation\": [\n \"\"\n ],\n \"Withdraw without setting amount\": [\n \"\"\n ],\n \"Hide demo hint.\": [\n \"\"\n ],\n \"Show install wallet first\": [\n \"\"\n ],\n \"Currently, the bank is not accepting new registrations!\": [\n \"\"\n ],\n \"The name is missing\": [\n \"\"\n ],\n \"Missing username\": [\n \"\"\n ],\n \"Missing password\": [\n \"\"\n ],\n \"The password should be longer than 8 letters\": [\n \"\"\n ],\n \"The passwords do not match\": [\n \"\"\n ],\n \"register new account\": [\n \"\"\n ],\n \"Server replied with invalid phone or email.\": [\n \"\"\n ],\n \"You are not authorised to create this account.\": [\n \"\"\n ],\n \"Registration is disabled because the bank ran out of bonus credit.\": [\n \"\"\n ],\n \"That username can't be used because is reserved.\": [\n \"\"\n ],\n \"That username is already taken.\": [\n \"\"\n ],\n \"That account ID is already taken.\": [\n \"\"\n ],\n \"No information for the selected authentication channel.\": [\n \"\"\n ],\n \"Authentication channel is not supported.\": [\n \"\"\n ],\n \"Only an administrator is allowed to set the debt limit.\": [\n \"\"\n ],\n \"Only the administrator can change the conversion rate.\": [\n \"\"\n ],\n \"The conversion rate class doesn't exist.\": [\n \"\"\n ],\n \"Only admin can create accounts with second factor authentication.\": [\n \"\"\n ],\n \"The password is too short. Can't have less than 8 characters.\": [\n \"\"\n ],\n \"The password is too long. Can't have more than 64 characters.\": [\n \"\"\n ],\n \"Account registration\": [\n \"\"\n ],\n \"Login username\": [\n \"\"\n ],\n \"account identification to login\": [\n \"\"\n ],\n \"Password\": [\n \"\"\n ],\n \"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers\": [\n \"\"\n ],\n \"Repeat password\": [\n \"\"\n ],\n \"Same password\": [\n \"\"\n ],\n \"Full name\": [\n \"\"\n ],\n \"Register\": [\n \"\"\n ],\n \"Create a random temporary user\": [\n \"\"\n ],\n \"logout\": [\n \"\"\n ],\n \"login\": [\n \"\"\n ],\n \"The account has no rights to login.\": [\n \"\"\n ],\n \"The account is locked and cannot login. Contact administrator.\": [\n \"\"\n ],\n \"Wrong credentials for \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Account login.\": [\n \"\"\n ],\n \"Session expired\": [\n \"\"\n ],\n \"Username\": [\n \"\"\n ],\n \"identification\": [\n \"\"\n ],\n \"Password of the account\": [\n \"\"\n ],\n \"Forget\": [\n \"\"\n ],\n \"Log in\": [\n \"\"\n ],\n \"Transactions history\": [\n \"\"\n ],\n \"No transactions yet.\": [\n \"\"\n ],\n \"You can make a transfer or a withdrawal to your wallet.\": [\n \"\"\n ],\n \"Date\": [\n \"\"\n ],\n \"Counterpart\": [\n \"\"\n ],\n \"sent\": [\n \"\"\n ],\n \"received\": [\n \"\"\n ],\n \"Invalid value\": [\n \"\"\n ],\n \"to\": [\n \"\"\n ],\n \"from\": [\n \"\"\n ],\n \"First page\": [\n \"\"\n ],\n \"Next\": [\n \"\"\n ],\n \"confirm withdrawal\": [\n \"\"\n ],\n \"cambiar\": [\n \"\"\n ],\n \"abort withdrawal\": [\n \"\"\n ],\n \"The withdrawal has been aborted previously and can't be confirmed\": [\n \"\"\n ],\n \"The withdrawal operation can't be confirmed before a wallet accepted the transaction.\": [\n \"\"\n ],\n \"The operation ID is invalid.\": [\n \"\"\n ],\n \"The operation was not found.\": [\n \"\"\n ],\n \"The starting withdrawal amount and the confirmation amount differs.\": [\n \"\"\n ],\n \"The bank requires a bank account which has not been specified yet.\": [\n \"\"\n ],\n \"Bad request\": [\n \"\"\n ],\n \"The withdrawal operation has been aborted.\": [\n \"\"\n ],\n \"The withdrawal operation has been confirmed previously and can\u2019t be aborted.\": [\n \"\"\n ],\n \"Complete withdrawal.\": [\n \"\"\n ],\n \"Confirm the withdrawal operation\": [\n \"\"\n ],\n \"Wire transfer details\": [\n \"\"\n ],\n \"Payment Service Provider's account number\": [\n \"\"\n ],\n \"Payment Service Provider's name\": [\n \"\"\n ],\n \"Payment Service Provider's account bank hostname\": [\n \"\"\n ],\n \"Payment Service Provider's account id\": [\n \"\"\n ],\n \"Payment Service Provider's account address\": [\n \"\"\n ],\n \"Payment Service Provider's account cyclos hostname\": [\n \"\"\n ],\n \"No amount has yet been determined.\": [\n \"\"\n ],\n \"Transfer\": [\n \"\"\n ],\n \"Authentication required\": [\n \"\"\n ],\n \"This operation was created with another username\": [\n \"\"\n ],\n \"You are currently logged in with user \\\"%1$s\\\" and the operation was made with user \\\"%2$s\\\"\": [\n \"\"\n ],\n \"The reserve operation has been confirmed previously and can't be aborted\": [\n \"\"\n ],\n \"Wire transfer completed!\": [\n \"\"\n ],\n \"Confirm withdrawal.\": [\n \"\"\n ],\n \"Unauthorized to make the operation, maybe the session has expired or the password changed.\": [\n \"\"\n ],\n \"The operation was rejected due to insufficient funds.\": [\n \"\"\n ],\n \"Withdrawal confirmed\": [\n \"\"\n ],\n \"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.\": [\n \"\"\n ],\n \"Do not show this again\": [\n \"\"\n ],\n \"If you have a Taler wallet installed on this device\": [\n \"\"\n ],\n \"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions\": [\n \"\"\n ],\n \"on this page\": [\n \"\"\n ],\n \"Withdraw\": [\n \"\"\n ],\n \"In case you have a Taler wallet on another device\": [\n \"\"\n ],\n \"Scan the QR below to start the withdrawal.\": [\n \"\"\n ],\n \"create withdrawal\": [\n \"\"\n ],\n \"The server replied with an invalid taler://withdraw URI\": [\n \"\"\n ],\n \"Withdraw URI: %1$s\": [\n \"\"\n ],\n \"The operation was rejected due to insufficient funds\": [\n \"\"\n ],\n \"Current balance is %1$s\": [\n \"\"\n ],\n \"You can withdraw up to %1$s\": [\n \"\"\n ],\n \"Continue\": [\n \"\"\n ],\n \"Use your Taler wallet\": [\n \"\"\n ],\n \"After using your wallet you will need to authorize or cancel the operation on this site.\": [\n \"\"\n ],\n \"You need a Taler wallet\": [\n \"\"\n ],\n \"If you don't have one yet you can follow the instruction in\": [\n \"\"\n ],\n \"this page\": [\n \"\"\n ],\n \"Send money\": [\n \"\"\n ],\n \"to a Taler wallet\": [\n \"\"\n ],\n \"Withdraw digital money into your mobile wallet or browser extension\": [\n \"\"\n ],\n \"to another bank account\": [\n \"\"\n ],\n \"Make a wire transfer to an account with known bank account number.\": [\n \"\"\n ],\n \"This is a demo\": [\n \"\"\n ],\n \"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .\": [\n \"\"\n ],\n \"Here you will be able to see how a bank that supports Taler directly would work.\": [\n \"\"\n ],\n \"Internal error, please report. There should be more information in the console.\": [\n \"\"\n ],\n \"Internal error, please report.\": [\n \"\"\n ],\n \"Preferences\": [\n \"\"\n ],\n \"Show debug information\": [\n \"\"\n ],\n \"Welcome\": [\n \"\"\n ],\n \"Welcome, %1$s\": [\n \"\"\n ],\n \"No enough permission to access the conversion rate list.\": [\n \"\"\n ],\n \"Conversion list not found. Maybe conversion rate is not supported.\": [\n \"\"\n ],\n \"Conversion list not implemented.\": [\n \"\"\n ],\n \"Conversion rate classes\": [\n \"\"\n ],\n \"Create conversion rate class\": [\n \"\"\n ],\n \"No conversion rate class\": [\n \"\"\n ],\n \"Name\": [\n \"\"\n ],\n \"Description\": [\n \"\"\n ],\n \"Cashin\": [\n \"\"\n ],\n \"min:\": [\n \"\"\n ],\n \"fee:\": [\n \"\"\n ],\n \"Select a section\": [\n \"\"\n ],\n \"Details\": [\n \"\"\n ],\n \"Delete\": [\n \"\"\n ],\n \"Credentials\": [\n \"\"\n ],\n \"Cashouts\": [\n \"\"\n ],\n \"Conversion\": [\n \"\"\n ],\n \"only admin can setup conversion\": [\n \"\"\n ],\n \"calculate cashout fee\": [\n \"\"\n ],\n \"update conversion rate\": [\n \"\"\n ],\n \"Wrong credentials\": [\n \"\"\n ],\n \"Conversion is disabled\": [\n \"\"\n ],\n \"Config cashout\": [\n \"\"\n ],\n \"Config cashin\": [\n \"\"\n ],\n \"Bad ratios\": [\n \"\"\n ],\n \"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.\": [\n \"\"\n ],\n \"Initial amount\": [\n \"\"\n ],\n \"Use it to test how the conversion will affect the amount.\": [\n \"\"\n ],\n \"Sending to this bank\": [\n \"\"\n ],\n \"Converted\": [\n \"\"\n ],\n \"Cashin after fee\": [\n \"\"\n ],\n \"Sending from this bank\": [\n \"\"\n ],\n \"Cashout after fee\": [\n \"\"\n ],\n \"Bad configuration\": [\n \"\"\n ],\n \"This configuration allows users to cash out more of what has been cashed in.\": [\n \"\"\n ],\n \"Update\": [\n \"\"\n ],\n \"Rnvalid\": [\n \"\"\n ],\n \"Must be > 0\": [\n \"\"\n ],\n \"Minimum amount\": [\n \"\"\n ],\n \"Only cashout operation above this threshold will be allowed.\": [\n \"\"\n ],\n \"Ratio\": [\n \"\"\n ],\n \"Conversion ratio between currencies\": [\n \"\"\n ],\n \"Example conversion\": [\n \"\"\n ],\n \"1 %1$s will be converted into %2$s %3$s\": [\n \"\"\n ],\n \"Tiny amount\": [\n \"\"\n ],\n \"Rounding mode\": [\n \"\"\n ],\n \"Zero\": [\n \"\"\n ],\n \"Amount will be round below to the largest possible value smaller than the input.\": [\n \"\"\n ],\n \"Up\": [\n \"\"\n ],\n \"Amount will be round up to the smallest possible value larger than the input.\": [\n \"\"\n ],\n \"Nearest\": [\n \"\"\n ],\n \"Amount will be round to the closest possible value.\": [\n \"\"\n ],\n \"If none specified the fallback value is \\\"%1$s \\\".\": [\n \"\"\n ],\n \"Examples\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.1\": [\n \"\"\n ],\n \"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.\": [\n \"\"\n ],\n \"With the \\\"zero\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.1\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.3\": [\n \"\"\n ],\n \"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.5\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.3\": [\n \"\"\n ],\n \"Amount to be deducted before amount is credited.\": [\n \"\"\n ],\n \"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"delete conversion rate class\": [\n \"\"\n ],\n \"Unauthorized\": [\n \"\"\n ],\n \"Forbidden\": [\n \"\"\n ],\n \"NotFound\": [\n \"\"\n ],\n \"NotImplemented\": [\n \"\"\n ],\n \"update conversion rate class\": [\n \"\"\n ],\n \"Not Found\": [\n \"\"\n ],\n \"Not implemented\": [\n \"\"\n ],\n \"The name of the conversion is already used.\": [\n \"\"\n ],\n \"Conversion rate class\": [\n \"\"\n ],\n \"Accounts\": [\n \"\"\n ],\n \"Test\": [\n \"\"\n ],\n \"Users\": [\n \"\"\n ],\n \"Can't remove the conversion rate class\": [\n \"\"\n ],\n \"There are some user associated to this class. You need to remove them first.\": [\n \"\"\n ],\n \"You are going to remove the conversion rate class\": [\n \"\"\n ],\n \"This step can't be undone.\": [\n \"\"\n ],\n \"Filters\": [\n \"\"\n ],\n \"Show from other classes\": [\n \"\"\n ],\n \"Account\": [\n \"\"\n ],\n \"Group ID\": [\n \"\"\n ],\n \"No users in this conversion rate class\": [\n \"\"\n ],\n \"Class\": [\n \"\"\n ],\n \"Action\": [\n \"\"\n ],\n \"Remove\": [\n \"\"\n ],\n \"Add\": [\n \"\"\n ],\n \"Conversion rate name\": [\n \"\"\n ],\n \"Short description of the class\": [\n \"\"\n ],\n \"create conversion rate class\": [\n \"\"\n ],\n \"Conversion rate class created.\": [\n \"\"\n ],\n \"The rights to change the account are not sufficient\": [\n \"\"\n ],\n \"New conversion rate class\": [\n \"\"\n ],\n \"Create\": [\n \"\"\n ],\n \"History of public accounts\": [\n \"\"\n ],\n \"Make a wire transfer\": [\n \"\"\n ],\n \"Scan the QR code below to start the withdrawal.\": [\n \"\"\n ],\n \"Operation aborted\": [\n \"\"\n ],\n \"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.\": [\n \"\"\n ],\n \"Go to your wallet now\": [\n \"\"\n ],\n \"The operation is marked as selected, but a process during the withdrawal failed\": [\n \"\"\n ],\n \"A withdrawal reserve ID was not found and no account has been selected.\": [\n \"\"\n ],\n \"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.\": [\n \"\"\n ],\n \"The account was selected, but no withdrawal reserve ID was found.\": [\n \"\"\n ],\n \"Operation not found\": [\n \"\"\n ],\n \"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.\": [\n \"\"\n ],\n \"Continue to dashboard\": [\n \"\"\n ],\n \"The Withdrawal URI is not valid\": [\n \"\"\n ],\n \"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.\": [\n \"\"\n ],\n \"Latest cashouts\": [\n \"\"\n ],\n \"Created\": [\n \"\"\n ],\n \"Total debit\": [\n \"\"\n ],\n \"Total credit\": [\n \"\"\n ],\n \"Cashout for account %1$s\": [\n \"\"\n ],\n \"Invalid email format\": [\n \"\"\n ],\n \"Should start with +\": [\n \"\"\n ],\n \"A phone number consists of numbers only\": [\n \"\"\n ],\n \"Account ID for authentication\": [\n \"\"\n ],\n \"Name of the account holder\": [\n \"\"\n ],\n \"Internal account\": [\n \"\"\n ],\n \"If this field is empty, a random account ID will be assigned\": [\n \"\"\n ],\n \"You can copy and share this IBAN number in order to receive wire transfers to your bank account\": [\n \"\"\n ],\n \"Email\": [\n \"\"\n ],\n \"To be used when second factor authentication is enabled\": [\n \"\"\n ],\n \"Phone\": [\n \"\"\n ],\n \"Enable second factor authentication\": [\n \"\"\n ],\n \"Using email\": [\n \"\"\n ],\n \"Add an email in your profile to enable this option\": [\n \"\"\n ],\n \"Using SMS\": [\n \"\"\n ],\n \"Add a phone number in your profile to enable this option\": [\n \"\"\n ],\n \"Cashout account\": [\n \"\"\n ],\n \"External account number where the money is going to be sent when doing cashouts\": [\n \"\"\n ],\n \"Max debt\": [\n \"\"\n ],\n \"How much the balance can go below zero.\": [\n \"\"\n ],\n \"Is this account public?\": [\n \"\"\n ],\n \"Public accounts have their balance publicly accessible\": [\n \"\"\n ],\n \"Does this account belong to a Payment Service Provider?\": [\n \"\"\n ],\n \"update account\": [\n \"\"\n ],\n \"Account updated\": [\n \"\"\n ],\n \"The username was not found\": [\n \"\"\n ],\n \"You can't change the legal name, please contact the your account administrator.\": [\n \"\"\n ],\n \"You can't change the debt limit, please contact the your account administrator.\": [\n \"\"\n ],\n \"You can't change the cashout address, please contact the your account administrator.\": [\n \"\"\n ],\n \"Update account information.\": [\n \"\"\n ],\n \"Account \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Removed\": [\n \"\"\n ],\n \"This account can't be used.\": [\n \"\"\n ],\n \"Change details\": [\n \"\"\n ],\n \"Merchant integration\": [\n \"\"\n ],\n \"Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the \\\"import\\\" button in the \\\"bank account\\\" section.\": [\n \"\"\n ],\n \"Account type\": [\n \"\"\n ],\n \"Method to use for wire transfer.\": [\n \"\"\n ],\n \"IBAN\": [\n \"\"\n ],\n \"International Bank Account Number.\": [\n \"\"\n ],\n \"Account name\": [\n \"\"\n ],\n \"Bank host where the service is located.\": [\n \"\"\n ],\n \"Bank account identifier for wire transfers.\": [\n \"\"\n ],\n \"Address\": [\n \"\"\n ],\n \"Owner's name\": [\n \"\"\n ],\n \"Legal name of the person holding the account.\": [\n \"\"\n ],\n \"Account info URL\": [\n \"\"\n ],\n \"From where the merchant can download information about incoming wire transfers to this account.\": [\n \"\"\n ],\n \"Repeated password doesn't match\": [\n \"\"\n ],\n \"update password\": [\n \"\"\n ],\n \"Password changed\": [\n \"\"\n ],\n \"Not authorized to change the password, maybe the session is invalid.\": [\n \"\"\n ],\n \"You need to provide the old password. If you don't have it contact your account administrator.\": [\n \"\"\n ],\n \"Your current password doesn't match, can't change to a new password.\": [\n \"\"\n ],\n \"You don't have the rights to change the password.\": [\n \"\"\n ],\n \"Update account password.\": [\n \"\"\n ],\n \"Update password\": [\n \"\"\n ],\n \"Current password\": [\n \"\"\n ],\n \"Your current password, for security\": [\n \"\"\n ],\n \"New password\": [\n \"\"\n ],\n \"Type it again\": [\n \"\"\n ],\n \"Repeat the same password\": [\n \"\"\n ],\n \"Change\": [\n \"\"\n ],\n \"Create account\": [\n \"\"\n ],\n \"Actions\": [\n \"\"\n ],\n \"Unknown\": [\n \"\"\n ],\n \"Change password\": [\n \"\"\n ],\n \"Querying for the current stats failed\": [\n \"\"\n ],\n \"The request parameters are wrong\": [\n \"\"\n ],\n \"The user is unauthorized\": [\n \"\"\n ],\n \"Querying for the previous stats failed\": [\n \"\"\n ],\n \"Transaction volume report\": [\n \"\"\n ],\n \"Last hour\": [\n \"\"\n ],\n \"Previous day\": [\n \"\"\n ],\n \"Last month\": [\n \"\"\n ],\n \"Last year\": [\n \"\"\n ],\n \"Last Year\": [\n \"\"\n ],\n \"Trading volume from %1$s to %2$s\": [\n \"\"\n ],\n \"Transferred from an external account to an account in this bank.\": [\n \"\"\n ],\n \"Transferred from an account in this bank to an external account.\": [\n \"\"\n ],\n \"Payin\": [\n \"\"\n ],\n \"Transferred from an account to a Taler exchange.\": [\n \"\"\n ],\n \"Payout\": [\n \"\"\n ],\n \"Transferred from a Taler exchange to another account.\": [\n \"\"\n ],\n \"Download stats as CSV\": [\n \"\"\n ],\n \"previous\": [\n \"\"\n ],\n \"Decreased by\": [\n \"\"\n ],\n \"Increased by\": [\n \"\"\n ],\n \"create account\": [\n \"\"\n ],\n \"Account created with password \\\"%1$s\\\".\": [\n \"\"\n ],\n \"Server replied that phone or email is invalid\": [\n \"\"\n ],\n \"The rights to perform the operation are not sufficient\": [\n \"\"\n ],\n \"Account username is already taken\": [\n \"\"\n ],\n \"Account ID is already taken\": [\n \"\"\n ],\n \"Bank ran out of bonus credit.\": [\n \"\"\n ],\n \"Account username can't be used because is reserved\": [\n \"\"\n ],\n \"Can't create accounts\": [\n \"\"\n ],\n \"Only system admin can create accounts.\": [\n \"\"\n ],\n \"New bank account\": [\n \"\"\n ],\n \"download statistics\": [\n \"\"\n ],\n \"only admin can download stats\": [\n \"\"\n ],\n \"Download bank stats\": [\n \"\"\n ],\n \"Include hour metric\": [\n \"\"\n ],\n \"Include day metric\": [\n \"\"\n ],\n \"Include month metric\": [\n \"\"\n ],\n \"Include year metric\": [\n \"\"\n ],\n \"Include table header\": [\n \"\"\n ],\n \"Add previous metric for compare\": [\n \"\"\n ],\n \"Fail on first error\": [\n \"\"\n ],\n \"Download\": [\n \"\"\n ],\n \"downloading... %1$s\": [\n \"\"\n ],\n \"Download completed\": [\n \"\"\n ],\n \"Click here to save the file in your computer.\": [\n \"\"\n ],\n \"there was an error reading the balance\": [\n \"\"\n ],\n \"Can't delete the account\": [\n \"\"\n ],\n \"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.\": [\n \"\"\n ],\n \"Name doesn't match\": [\n \"\"\n ],\n \"delete account\": [\n \"\"\n ],\n \"Account removed\": [\n \"\"\n ],\n \"No enough permission to delete the account.\": [\n \"\"\n ],\n \"The username was not found.\": [\n \"\"\n ],\n \"Can't delete a reserved username.\": [\n \"\"\n ],\n \"Can't delete an account with balance different than zero.\": [\n \"\"\n ],\n \"Remove account.\": [\n \"\"\n ],\n \"You are going to remove the account\": [\n \"\"\n ],\n \"Deleting account \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Verification\": [\n \"\"\n ],\n \"Enter the account name that is going to be deleted\": [\n \"\"\n ],\n \"Cashout id should be a number\": [\n \"\"\n ],\n \"This cashout not found. Maybe already aborted.\": [\n \"\"\n ],\n \"Cashout detail\": [\n \"\"\n ],\n \"Debited\": [\n \"\"\n ],\n \"Transferred\": [\n \"\"\n ],\n \"You have no permission to this account.\": [\n \"\"\n ],\n \"This account is locked. If you have a active session you can change the password or contact the administrator.\": [\n \"\"\n ],\n \"New web session\": [\n \"\"\n ],\n \"Welcome to %1$s!\": [\n \"\"\n ]\n }\n },\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && n % 10 == 0) ? 2 : 3));\",\n \"lang\": \"he\",\n \"completeness\": 0\n};\n\nstrings['fr'] = {\n \"locale_data\": {\n \"messages\": {\n \"\": {\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n > 1;\",\n \"lang\": \"fr\"\n },\n \"An IBAN consists of capital letters and numbers only\": [\n \"Un IBAN se compose uniquement de lettres majuscules et de chiffres\"\n ],\n \"IBAN numbers have more that 4 digits\": [\n \"Les num\u00E9ros IBAN ont plus de 4 chiffres\"\n ],\n \"IBAN numbers have less that 34 digits\": [\n \"Les num\u00E9ros IBAN ont moins de 34 chiffres\"\n ],\n \"IBAN country code not found\": [\n \"Le code pays de l'IBAN n'a pas \u00E9t\u00E9 trouv\u00E9\"\n ],\n \"IBAN number is not valid, checksum is wrong\": [\n \"Le num\u00E9ro IBAN n'est pas valide, la somme de contr\u00F4le est incorrecte\"\n ],\n \"Use letters, numbers or any of these characters: - . _ ~\": [\n \"Utilisez des lettres, des chiffres ou l'un de ces caract\u00E8res\u202F: - . _ ~\"\n ],\n \"Required\": [\n \"Obligatoire\"\n ],\n \"confirm MFA challenge\": [\n \"\"\n ],\n \"Unknown challenge.\": [\n \"\"\n ],\n \"Failed to validate the verification code.\": [\n \"\"\n ],\n \"Too many challenges are active right now, you must wait or confirm current challenges.\": [\n \"\"\n ],\n \"Wrong authentication number.\": [\n \"Num\u00E9ro d'authentification erron\u00E9.\"\n ],\n \"Expired challenge.\": [\n \"\"\n ],\n \"Submit the transmitted code number.\": [\n \"\"\n ],\n \"The verification code sent to the email address starting with %1$s\": [\n \"\"\n ],\n \"The verification code sent to the phone number ending with %1$s\": [\n \"\"\n ],\n \"Code\": [\n \"\"\n ],\n \"Username of the account\": [\n \"Nom d'utilisateur du compte\"\n ],\n \"It will expired at %1$s\": [\n \"Date d'expiration %1$s\"\n ],\n \"The challenge is expired and can't be solved but you can go back and create a new challenge.\": [\n \"\"\n ],\n \"Back\": [\n \"\"\n ],\n \"Verify\": [\n \"\"\n ],\n \"send MFA challenge\": [\n \"\"\n ],\n \"Failed to send the verification code.\": [\n \"\"\n ],\n \"The request was valid, but the server is refusing action.\": [\n \"\"\n ],\n \"The backend is not aware of the specified MFA challenge.\": [\n \"\"\n ],\n \"It is too early to request another transmission of the challenge.\": [\n \"\"\n ],\n \"Code transmission failed.\": [\n \"L\u2019op\u00E9ration a \u00E9chou\u00E9.\"\n ],\n \"select challenge\": [\n \"\"\n ],\n \"Multi-factor authentication required\": [\n \"Authentification obligatoire\"\n ],\n \"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.\": [\n \"Cette op\u00E9ration est prot\u00E9g\u00E9e par une authentification \u00E0 deuxi\u00E8me facteur. Pour la mener \u00E0 bien, nous devons v\u00E9rifier votre identit\u00E9 \u00E0 l'aide du canal d'authentification que vous avez fourni.\"\n ],\n \"The next challenge needs to be completed to confirm the operation.\": [\n \"Autorisation insuffisante pour terminer l'op\u00E9ration.\"\n ],\n \"All the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"One of the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"To an phone ending with \\\"%1$s\\\"\": [\n \"\"\n ],\n \"To an email starting with \\\" %1$s\\\"\": [\n \"\"\n ],\n \"I have a code\": [\n \"\"\n ],\n \"Send me a message\": [\n \"\"\n ],\n \"You have to wait until %1$s to send a new code.\": [\n \"\"\n ],\n \"Cancel\": [\n \"Annuler\"\n ],\n \"Complete\": [\n \"\"\n ],\n \"Unable to create a cashout\": [\n \"Impossible de cr\u00E9er un encaissement\"\n ],\n \"The bank configuration does not support cashout operations.\": [\n \"La configuration bancaire ne prend pas en charge les op\u00E9rations d'encaissement.\"\n ],\n \"Close\": [\n \"Fermer\"\n ],\n \"Cashout is disabled\": [\n \"L'encaissement est d\u00E9sactiv\u00E9\"\n ],\n \"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"Le retrait doit \u00EAtre activ\u00E9 dans la configuration, le taux de conversion doit \u00EAtre initialis\u00E9 avec des frais, des taux et un mode d'arrondi.\"\n ],\n \"calculate conversion fee\": [\n \"Taux de conversion\"\n ],\n \"The server didn't understand the request.\": [\n \"Le serveur ne prend pas en charge le canal TAN actuel.\"\n ],\n \"The amount is too small\": [\n \"Le mot de passe est trop long.\"\n ],\n \"Conversion is not implemented.\": [\n \"\"\n ],\n \"At least debit or credit needs to be provided\": [\n \"\"\n ],\n \"The amount is malfored\": [\n \"D\u00E9sol\u00E9, cet identifiant de compte est d\u00E9j\u00E0 pris.\"\n ],\n \"The currency is not supported\": [\n \"Le canal d'authentification n'est pas pris en charge.\"\n ],\n \"Invalid\": [\n \"Invalide\"\n ],\n \"Amount needs to be higher\": [\n \"Le montant doit \u00EAtre plus \u00E9lev\u00E9\"\n ],\n \"Balance is not enough\": [\n \"Le solde n'est pas suffisant\"\n ],\n \"It is not possible to cashout less than %1$s: %2$s\": [\n \"Il n'est pas possible d'encaisser moins de %1$s\"\n ],\n \"The total transfer to the destination will be zero\": [\n \"Le montant total transf\u00E9r\u00E9 vers la destination sera nul\"\n ],\n \"create cashout\": [\n \"Cr\u00E9er un compte\"\n ],\n \"Cashout created\": [\n \"Encaissement cr\u00E9\u00E9\"\n ],\n \"Second factor authentication required.\": [\n \"Authentification obligatoire\"\n ],\n \"Account not found\": [\n \"Compte non trouv\u00E9\"\n ],\n \"Duplicated request detected, check if the operation succeeded or try again.\": [\n \"Requ\u00EAte dupliqu\u00E9e d\u00E9tect\u00E9e, v\u00E9rifiez si l'op\u00E9ration a r\u00E9ussi ou r\u00E9essayez.\"\n ],\n \"The conversion rate was applied incorrectly\": [\n \"Le taux de conversion a \u00E9t\u00E9 appliqu\u00E9 de mani\u00E8re incorrecte\"\n ],\n \"The account does not have sufficient funds\": [\n \"Le compte ne dispose pas de fonds suffisants\"\n ],\n \"Missing cashout URI in the profile\": [\n \"URI d'encaissement manquante dans le profil\"\n ],\n \"The amount is below the minimum amount permitted.\": [\n \"Le montant est inf\u00E9rieur au montant minimum autoris\u00E9.\"\n ],\n \"Sending the confirmation message failed, retry later or contact the administrator.\": [\n \"L'envoi du message de confirmation a \u00E9chou\u00E9, r\u00E9essayez plus tard ou contactez l'administrateur.\"\n ],\n \"The server doesn't support the current TAN channel.\": [\n \"Le serveur ne prend pas en charge le canal TAN actuel.\"\n ],\n \"Create cashout.\": [\n \"Cr\u00E9er un compte\"\n ],\n \"Cashout\": [\n \"Retrait\"\n ],\n \"Conversion rate\": [\n \"Taux de conversion\"\n ],\n \"Balance\": [\n \"Solde\"\n ],\n \"Fee\": [\n \"Frais\"\n ],\n \"To account\": [\n \"Compte de destination\"\n ],\n \"Legal name\": [\n \"Nom l\u00E9gal du b\u00E9n\u00E9ficiaire du compte bancaire\"\n ],\n \"If this name doesn't match the account holder's name, your transaction may fail.\": [\n \"Si ce nom ne correspond pas au nom du titulaire du compte, votre transaction peut \u00E9chouer.\"\n ],\n \"Unable to cashout\": [\n \"Impossible de cr\u00E9er un encaissement\"\n ],\n \"Before being able to cashout to a bank account, you need to complete your profile\": [\n \"Avant de pouvoir effectuer un encaissement vers un compte bancaire, vous devez compl\u00E9ter votre profil\"\n ],\n \"Transfer subject\": [\n \"R\u00E9f\u00E9rence du transfert\"\n ],\n \"Currency\": [\n \"Devise\"\n ],\n \"Send %1$s\": [\n \"Envoyer %1$s\"\n ],\n \"Receive %1$s\": [\n \"Recevoir %1$s\"\n ],\n \"Amount\": [\n \"Montant\"\n ],\n \"Total cost\": [\n \"Montant total des frais\"\n ],\n \"Balance left\": [\n \"Solde restant\"\n ],\n \"Before fee\": [\n \"Avant les frais\"\n ],\n \"Total cashout transfer\": [\n \"Transfert d'encaissement total\"\n ],\n \"Not valid\": [\n \"Non valide\"\n ],\n \"Does not follow the pattern\": [\n \"Ne suit pas le mod\u00E8le\"\n ],\n \"send transaction\": [\n \"Aucune transaction n'a encore \u00E9t\u00E9 effectu\u00E9e.\"\n ],\n \"The wire transfer was successfully completed!\": [\n \"Le virement bancaire a \u00E9t\u00E9 effectu\u00E9 avec succ\u00E8s\u202F!\"\n ],\n \"The request was invalid or the payto://-URI used unacceptable features.\": [\n \"La requ\u00EAte n'\u00E9tait pas valide ou l'URI payto:// a utilis\u00E9 des fonctionnalit\u00E9s inacceptables.\"\n ],\n \"Not enough permission to complete the operation.\": [\n \"Autorisation insuffisante pour terminer l'op\u00E9ration.\"\n ],\n \"The bank administrator cannot be the transfer creditor.\": [\n \"L'administrateur de la banque ne peut pas \u00EAtre le destinataire du transfert.\"\n ],\n \"The destination account \\\"%1$s\\\" was not found.\": [\n \"Le compte de destination \\\"%1$s\\\" n'a pas \u00E9t\u00E9 trouv\u00E9.\"\n ],\n \"The origin and the destination of the transfer can't be the same.\": [\n \"L'origine et la destination du transfert ne peuvent pas \u00EAtre les m\u00EAmes.\"\n ],\n \"Your balance is not sufficient for the operation.\": [\n \"Votre solde n'est pas suffisant pour l'op\u00E9ration.\"\n ],\n \"The origin account \\\"%1$s\\\" was not found.\": [\n \"Le compte d'origine \\\"%1$s\\\" est introuvable.\"\n ],\n \"The attempt to create the transaction has failed. Please try again.\": [\n \"La tentative de cr\u00E9ation de la transaction a \u00E9chou\u00E9. Essayez \u00E0 nouveau.\"\n ],\n \"A second factor authentication is required.\": [\n \"\u00C0 utiliser lorsque l'authentification par deuxi\u00E8me facteur est activ\u00E9e\"\n ],\n \"Confirm wire transfer.\": [\n \"Effectuer un virement bancaire\"\n ],\n \"Input wire transfer detail\": [\n \"D\u00E9tail du virement d'entr\u00E9e\"\n ],\n \"Using a form\": [\n \"Utilisation d'un formulaire\"\n ],\n \"A special URI that specifies the amount to be transferred and the destination account.\": [\n \"Un URI sp\u00E9cial qui sp\u00E9cifie le montant \u00E0 transf\u00E9rer et le compte de destination.\"\n ],\n \"QR code\": [\n \"Code QR\"\n ],\n \"If your device has a camera, you can import a payto:// URI from a QR code.\": [\n \"Si votre appareil dispose d'une cam\u00E9ra, vous pouvez importer un URI-payto:// \u00E0 partir d'un code QR.\"\n ],\n \"Recipient\": [\n \"Destinataire\"\n ],\n \"ID of the recipient's account\": [\n \"Identifiant du compte du destinataire\"\n ],\n \"username\": [\n \"nom d'utilisateur\"\n ],\n \"IBAN of the recipient's account\": [\n \"IBAN du compte du destinataire\"\n ],\n \"Subject\": [\n \"R\u00E9f\u00E9rence\"\n ],\n \"Some text to identify the transfer\": [\n \"Texte permettant d'identifier le transfert\"\n ],\n \"Amount to transfer\": [\n \"Montant \u00E0 transf\u00E9rer\"\n ],\n \"Payto URI:\": [\n \"URI Payto\u202F:\"\n ],\n \"Uniform resource identifier of the target account\": [\n \"Identifiant de ressource uniforme (URI en anglais) du compte cible\"\n ],\n \"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://x-taler-bank/[serveur-de-la-banque]/[compte-destinataire]?message=[reference]&amount=[%1$s:X.Y]\"\n ],\n \"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://iban/[IBAN du destinataire]?message=[r\u00E9f\u00E9rence]&amount=[%1$s:X.Y]\"\n ],\n \"The maximum amount for a wire transfer is %1$s\": [\n \"Le montant maximum pour un virement bancaire est de %1$s\"\n ],\n \"Cost\": [\n \"Co\u00FBt\"\n ],\n \"Send\": [\n \"Envoyer\"\n ],\n \"Only \\\"x-taler-bank\\\" target are supported\": [\n \"Seule la destination \\\"x-taler-bank\\\" est prise en charge\"\n ],\n \"Only this host is allowed. Use \\\"%1$s\\\"\": [\n \"Seul cet h\u00F4te est autoris\u00E9. Utilisez \\\"%1$s\\\"\"\n ],\n \"Account name is missing\": [\n \"Le nom du compte est manquant\"\n ],\n \"Only \\\"IBAN\\\" target are supported\": [\n \"\\\"IBAN\\\" est la seule destination support\u00E9e\"\n ],\n \"Missing \\\"amount\\\" parameter to specify the amount to be transferred\": [\n \"Param\u00E8tre \\\"montant\\\" manquant pour sp\u00E9cifier le montant \u00E0 transf\u00E9rer\"\n ],\n \"The \\\"amount\\\" parameter is not valid\": [\n \"Le param\u00E8tre \\\"montant\\\" n'est pas valide\"\n ],\n \"\\\"message\\\" parameters to specify a reference text for the transfer are missing\": [\n \"Les param\u00E8tres \\\"message\\\" pour sp\u00E9cifier un texte de r\u00E9f\u00E9rence pour le transfert sont manquants\"\n ],\n \"The only currency allowed is \\\"%1$s\\\"\": [\n \"La seule devise autoris\u00E9e est \\\"%1$s\\\"\"\n ],\n \"You cannot transfer an amount of zero.\": [\n \"Vous ne pouvez pas transf\u00E9rer un montant \u00E9gal \u00E0 z\u00E9ro.\"\n ],\n \"The balance is not sufficient\": [\n \"Le solde n'est pas suffisant\"\n ],\n \"Please enter a longer subject\": [\n \"Veuillez saisir une r\u00E9f\u00E9rence plus longue\"\n ],\n \"Show withdrawal confirmation\": [\n \"Afficher la confirmation de retrait\"\n ],\n \"Withdraw without setting amount\": [\n \"Retirer sans fixer le montant\"\n ],\n \"Hide demo hint.\": [\n \"\"\n ],\n \"Show install wallet first\": [\n \"Afficher d'abord le portefeuille d'installation\"\n ],\n \"Currently, the bank is not accepting new registrations!\": [\n \"Actuellement, la banque n'accepte pas de nouvelles inscriptions\u202F!\"\n ],\n \"The name is missing\": [\n \"Nom manquant\"\n ],\n \"Missing username\": [\n \"Identifiant manquant\"\n ],\n \"Missing password\": [\n \"Mot de passe manquant\"\n ],\n \"The password should be longer than 8 letters\": [\n \"Le mot de passe doit comporter plus de 8 caract\u00E8res\"\n ],\n \"The passwords do not match\": [\n \"Les mots de passe ne correspondent pas\"\n ],\n \"register new account\": [\n \"Cr\u00E9er un compte\"\n ],\n \"Server replied with invalid phone or email.\": [\n \"Le serveur a r\u00E9pondu avec un t\u00E9l\u00E9phone ou un e-mail invalide.\"\n ],\n \"You are not authorised to create this account.\": [\n \"Vous n'\u00EAtes pas autoris\u00E9 \u00E0 cr\u00E9er ce compte.\"\n ],\n \"Registration is disabled because the bank ran out of bonus credit.\": [\n \"L'inscription est d\u00E9sactiv\u00E9e car la banque n'a plus de cr\u00E9dit bonus.\"\n ],\n \"That username can't be used because is reserved.\": [\n \"Ce nom d'utilisateur ne peut pas \u00EAtre utilis\u00E9 car il est r\u00E9serv\u00E9.\"\n ],\n \"That username is already taken.\": [\n \"D\u00E9sol\u00E9, ce nom d\u2019utilisateur est d\u00E9j\u00E0 pris.\"\n ],\n \"That account ID is already taken.\": [\n \"D\u00E9sol\u00E9, cet identifiant de compte est d\u00E9j\u00E0 pris.\"\n ],\n \"No information for the selected authentication channel.\": [\n \"Aucune information pour le canal d'authentification s\u00E9lectionn\u00E9.\"\n ],\n \"Authentication channel is not supported.\": [\n \"Le canal d'authentification n'est pas pris en charge.\"\n ],\n \"Only an administrator is allowed to set the debt limit.\": [\n \"Seul un administrateur est autoris\u00E9 \u00E0 fixer la limite d'endettement.\"\n ],\n \"Only the administrator can change the conversion rate.\": [\n \"Seul l'administrateur peut modifier la limite minimale d'encaissement.\"\n ],\n \"The conversion rate class doesn't exist.\": [\n \"Le taux de conversion a \u00E9t\u00E9 appliqu\u00E9 de mani\u00E8re incorrecte\"\n ],\n \"Only admin can create accounts with second factor authentication.\": [\n \"Seul l'administrateur peut cr\u00E9er des comptes avec l'authentification \u00E0 deuxi\u00E8me facteur.\"\n ],\n \"The password is too short. Can't have less than 8 characters.\": [\n \"Le mot de passe doit comporter plus de 8 caract\u00E8res\"\n ],\n \"The password is too long. Can't have more than 64 characters.\": [\n \"Le mot de passe doit comporter plus de 8 caract\u00E8res\"\n ],\n \"Account registration\": [\n \"Nouveau compte\"\n ],\n \"Login username\": [\n \"Nom d'utilisateur pour le login\"\n ],\n \"account identification to login\": [\n \"\"\n ],\n \"Password\": [\n \"Mot de passe\"\n ],\n \"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers\": [\n \"Utilisez un mot de passe fort\u202F: 8 caract\u00E8res minimum, n'utilisez aucune information publique vous concernant (noms, date de naissance, num\u00E9ro de t\u00E9l\u00E9phone, etc.) et m\u00E9langez minuscules, majuscules, symboles et chiffres\"\n ],\n \"Repeat password\": [\n \"R\u00E9p\u00E9tez le mot de passe\"\n ],\n \"Same password\": [\n \"Nouveau mot de passe\"\n ],\n \"Full name\": [\n \"Nom complet\"\n ],\n \"Register\": [\n \"Inscription\"\n ],\n \"Create a random temporary user\": [\n \"Cr\u00E9er un utilisateur temporaire al\u00E9atoire\"\n ],\n \"logout\": [\n \"\"\n ],\n \"login\": [\n \"\"\n ],\n \"The account has no rights to login.\": [\n \"\"\n ],\n \"The account is locked and cannot login. Contact administrator.\": [\n \"\"\n ],\n \"Wrong credentials for \\\"%1$s\\\"\": [\n \"Mauvaises informations d'identification pour \\\"%1$s\\\"\"\n ],\n \"Account login.\": [\n \"Intitul\u00E9 du compte\"\n ],\n \"Session expired\": [\n \"L'op\u00E9ration a expir\u00E9.\"\n ],\n \"Username\": [\n \"Nom d'utilisateur\"\n ],\n \"identification\": [\n \"\"\n ],\n \"Password of the account\": [\n \"Mot de passe du compte\"\n ],\n \"Forget\": [\n \"\"\n ],\n \"Log in\": [\n \"Se connecter\"\n ],\n \"Transactions history\": [\n \"Historique des transactions\"\n ],\n \"No transactions yet.\": [\n \"Aucune transaction n'a encore \u00E9t\u00E9 effectu\u00E9e.\"\n ],\n \"You can make a transfer or a withdrawal to your wallet.\": [\n \"Vous pouvez effectuer un virement ou un retrait sur votre portefeuille.\"\n ],\n \"Date\": [\n \"Date\"\n ],\n \"Counterpart\": [\n \"Contrepartie\"\n ],\n \"sent\": [\n \"envoy\u00E9\"\n ],\n \"received\": [\n \"re\u00E7u\"\n ],\n \"Invalid value\": [\n \"Valeur non valide\"\n ],\n \"to\": [\n \"vers\"\n ],\n \"from\": [\n \"de\"\n ],\n \"First page\": [\n \"Premi\u00E8re page\"\n ],\n \"Next\": [\n \"Suivante\"\n ],\n \"confirm withdrawal\": [\n \"Confirmer le retrait\"\n ],\n \"cambiar\": [\n \"\"\n ],\n \"abort withdrawal\": [\n \"Confirmer le retrait\"\n ],\n \"The withdrawal has been aborted previously and can't be confirmed\": [\n \"Le retrait a \u00E9t\u00E9 interrompu pr\u00E9c\u00E9demment et ne peut \u00EAtre confirm\u00E9\"\n ],\n \"The withdrawal operation can't be confirmed before a wallet accepted the transaction.\": [\n \"L'op\u00E9ration de retrait ne peut pas \u00EAtre confirm\u00E9e avant qu'un portefeuille n'accepte la transaction.\"\n ],\n \"The operation ID is invalid.\": [\n \"L'identifiant de l'op\u00E9ration n'est pas valide.\"\n ],\n \"The operation was not found.\": [\n \"L'op\u00E9ration est introuvable.\"\n ],\n \"The starting withdrawal amount and the confirmation amount differs.\": [\n \"Le montant du retrait de d\u00E9part et le montant de la confirmation diff\u00E8rent.\"\n ],\n \"The bank requires a bank account which has not been specified yet.\": [\n \"La banque exige un compte bancaire et il n'a pas encore \u00E9t\u00E9 sp\u00E9cifi\u00E9.\"\n ],\n \"Bad request\": [\n \"\"\n ],\n \"The withdrawal operation has been aborted.\": [\n \"Op\u00E9ration de retrait en attente\"\n ],\n \"The withdrawal operation has been confirmed previously and can\u2019t be aborted.\": [\n \"L'op\u00E9ration de r\u00E9serve a \u00E9t\u00E9 confirm\u00E9e pr\u00E9c\u00E9demment et ne peut plus \u00EAtre annul\u00E9e\"\n ],\n \"Complete withdrawal.\": [\n \"Confirmer le retrait\"\n ],\n \"Confirm the withdrawal operation\": [\n \"Confirmer l'op\u00E9ration de retrait\"\n ],\n \"Wire transfer details\": [\n \"D\u00E9tails du virement\"\n ],\n \"Payment Service Provider's account number\": [\n \"Num\u00E9ro de compte du prestataire de services de paiement\"\n ],\n \"Payment Service Provider's name\": [\n \"Nom du prestataire de services de paiement\"\n ],\n \"Payment Service Provider's account bank hostname\": [\n \"Nom du serveur de la banque du compte du prestataire de services de paiement\"\n ],\n \"Payment Service Provider's account id\": [\n \"Identifiant du compte du prestataire de services de paiement\"\n ],\n \"Payment Service Provider's account address\": [\n \"Adresse du compte du prestataire de services de paiement\"\n ],\n \"Payment Service Provider's account cyclos hostname\": [\n \"Nom du serveur de la banque du compte du prestataire de services de paiement\"\n ],\n \"No amount has yet been determined.\": [\n \"Aucun montant n'a encore \u00E9t\u00E9 d\u00E9termin\u00E9.\"\n ],\n \"Transfer\": [\n \"Transfert\"\n ],\n \"Authentication required\": [\n \"Authentification obligatoire\"\n ],\n \"This operation was created with another username\": [\n \"Cette op\u00E9ration a \u00E9t\u00E9 cr\u00E9\u00E9e avec un autre nom d'utilisateur\"\n ],\n \"You are currently logged in with user \\\"%1$s\\\" and the operation was made with user \\\"%2$s\\\"\": [\n \"\"\n ],\n \"The reserve operation has been confirmed previously and can't be aborted\": [\n \"L'op\u00E9ration de r\u00E9serve a \u00E9t\u00E9 confirm\u00E9e pr\u00E9c\u00E9demment et ne peut plus \u00EAtre annul\u00E9e\"\n ],\n \"Wire transfer completed!\": [\n \"Virement bancaire termin\u00E9\u202F!\"\n ],\n \"Confirm withdrawal.\": [\n \"Confirmer le retrait\"\n ],\n \"Unauthorized to make the operation, maybe the session has expired or the password changed.\": [\n \"Non autoris\u00E9 \u00E0 effectuer l'op\u00E9ration, peut-\u00EAtre que la session a expir\u00E9 ou que le mot de passe a \u00E9t\u00E9 modifi\u00E9.\"\n ],\n \"The operation was rejected due to insufficient funds.\": [\n \"L'op\u00E9ration a \u00E9t\u00E9 rejet\u00E9e en raison de fonds insuffisants.\"\n ],\n \"Withdrawal confirmed\": [\n \"Retrait confirm\u00E9\"\n ],\n \"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.\": [\n \"Le virement bancaire au profit du prestataire de services de paiement a \u00E9t\u00E9 enclench\u00E9. Vous recevrez sous peu le montant demand\u00E9 dans votre portefeuille Taler.\"\n ],\n \"Do not show this again\": [\n \"Ne plus afficher \u00E0 l'avenir\"\n ],\n \"If you have a Taler wallet installed on this device\": [\n \"Si vous avez un portefeuille Taler install\u00E9 sur cet appareil\"\n ],\n \"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions\": [\n \"Votre portefeuille affichera les d\u00E9tails de la transaction, y compris les frais (le cas \u00E9ch\u00E9ant). Si vous n'avez pas encore de portefeuille, veuillez suivre les instructions\"\n ],\n \"on this page\": [\n \"sur cette page\"\n ],\n \"Withdraw\": [\n \"Retirer\"\n ],\n \"In case you have a Taler wallet on another device\": [\n \"Si vous avez un portefeuille Taler sur un autre appareil\"\n ],\n \"Scan the QR below to start the withdrawal.\": [\n \"Scannez le code QR ci-dessous pour commencer le retrait.\"\n ],\n \"create withdrawal\": [\n \"Confirmer le retrait\"\n ],\n \"The server replied with an invalid taler://withdraw URI\": [\n \"Le serveur a r\u00E9pondu avec un URI taler://withdraw invalide\"\n ],\n \"Withdraw URI: %1$s\": [\n \"URI de retrait\u202F: %1$s\"\n ],\n \"The operation was rejected due to insufficient funds\": [\n \"L'op\u00E9ration a \u00E9t\u00E9 rejet\u00E9e pour cause de fonds insuffisants\"\n ],\n \"Current balance is %1$s\": [\n \"Le solde actuel est de %1$s\"\n ],\n \"You can withdraw up to %1$s\": [\n \"Vous pouvez retirer jusqu'\u00E0 %1$s\"\n ],\n \"Continue\": [\n \"Continuer\"\n ],\n \"Use your Taler wallet\": [\n \"Utilisez votre portefeuille Taler\"\n ],\n \"After using your wallet you will need to authorize or cancel the operation on this site.\": [\n \"Apr\u00E8s avoir utilis\u00E9 votre portefeuille, vous devrez autoriser ou annuler l'op\u00E9ration sur ce site.\"\n ],\n \"You need a Taler wallet\": [\n \"Vous avez besoin d'un portefeuille Taler\"\n ],\n \"If you don't have one yet you can follow the instruction in\": [\n \"Si vous n'en avez pas encore, vous pouvez suivre les instructions dans\"\n ],\n \"this page\": [\n \"cette page\"\n ],\n \"Send money\": [\n \"Envoyer de l'argent\"\n ],\n \"to a Taler wallet\": [\n \"vers un portefeuille Taler\"\n ],\n \"Withdraw digital money into your mobile wallet or browser extension\": [\n \"Retirez de l'argent num\u00E9rique dans votre portefeuille mobile ou votre extension de navigateur\"\n ],\n \"to another bank account\": [\n \"sur un autre compte bancaire\"\n ],\n \"Make a wire transfer to an account with known bank account number.\": [\n \"Effectuez un virement bancaire sur un compte dont le num\u00E9ro de compte bancaire est connu.\"\n ],\n \"This is a demo\": [\n \"Ceci est une d\u00E9mo\"\n ],\n \"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .\": [\n \"Cette partie de la d\u00E9mo montre comment fonctionnerait une banque qui supporte directement Taler. Outre l'utilisation de votre propre compte bancaire, vous pouvez \u00E9galement consulter l'historique des transactions de certains %1$s .\"\n ],\n \"Here you will be able to see how a bank that supports Taler directly would work.\": [\n \"Ici, vous pourrez voir comment une banque qui prend directement en charge Taler fonctionnerait.\"\n ],\n \"Internal error, please report. There should be more information in the console.\": [\n \"\"\n ],\n \"Internal error, please report.\": [\n \"Erreur interne, veuillez signaler.\"\n ],\n \"Preferences\": [\n \"Pr\u00E9f\u00E9rences\"\n ],\n \"Show debug information\": [\n \"Afficher les informations de d\u00E9bogage\"\n ],\n \"Welcome\": [\n \"Bienvenue\"\n ],\n \"Welcome, %1$s\": [\n \"Bienvenue, %1$s\"\n ],\n \"No enough permission to access the conversion rate list.\": [\n \"Autorisation insuffisante pour terminer l'op\u00E9ration.\"\n ],\n \"Conversion list not found. Maybe conversion rate is not supported.\": [\n \"\"\n ],\n \"Conversion list not implemented.\": [\n \"\"\n ],\n \"Conversion rate classes\": [\n \"Taux de conversion\"\n ],\n \"Create conversion rate class\": [\n \"Taux de conversion\"\n ],\n \"No conversion rate class\": [\n \"Taux de conversion\"\n ],\n \"Name\": [\n \"Nom\"\n ],\n \"Description\": [\n \"Afficher la description de la d\u00E9mo\"\n ],\n \"Cashin\": [\n \"\"\n ],\n \"min:\": [\n \"\"\n ],\n \"fee:\": [\n \"\"\n ],\n \"Select a section\": [\n \"S\u00E9lectionner une section\"\n ],\n \"Details\": [\n \"D\u00E9tails\"\n ],\n \"Delete\": [\n \"Supprimer\"\n ],\n \"Credentials\": [\n \"Identifiants\"\n ],\n \"Cashouts\": [\n \"Retraits\"\n ],\n \"Conversion\": [\n \"Conversion\"\n ],\n \"only admin can setup conversion\": [\n \"\"\n ],\n \"calculate cashout fee\": [\n \"Cr\u00E9er un compte\"\n ],\n \"update conversion rate\": [\n \"Taux de conversion\"\n ],\n \"Wrong credentials\": [\n \"\"\n ],\n \"Conversion is disabled\": [\n \"\"\n ],\n \"Config cashout\": [\n \"\"\n ],\n \"Config cashin\": [\n \"\"\n ],\n \"Bad ratios\": [\n \"\"\n ],\n \"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.\": [\n \"\"\n ],\n \"Initial amount\": [\n \"\"\n ],\n \"Use it to test how the conversion will affect the amount.\": [\n \"\"\n ],\n \"Sending to this bank\": [\n \"\"\n ],\n \"Converted\": [\n \"\"\n ],\n \"Cashin after fee\": [\n \"\"\n ],\n \"Sending from this bank\": [\n \"\"\n ],\n \"Cashout after fee\": [\n \"\"\n ],\n \"Bad configuration\": [\n \"\"\n ],\n \"This configuration allows users to cash out more of what has been cashed in.\": [\n \"\"\n ],\n \"Update\": [\n \"Modification\"\n ],\n \"Rnvalid\": [\n \"\"\n ],\n \"Must be > 0\": [\n \"\"\n ],\n \"Minimum amount\": [\n \"\"\n ],\n \"Only cashout operation above this threshold will be allowed.\": [\n \"\"\n ],\n \"Ratio\": [\n \"\"\n ],\n \"Conversion ratio between currencies\": [\n \"\"\n ],\n \"Example conversion\": [\n \"\"\n ],\n \"1 %1$s will be converted into %2$s %3$s\": [\n \"\"\n ],\n \"Tiny amount\": [\n \"Compte de destination\"\n ],\n \"Rounding mode\": [\n \"\"\n ],\n \"Zero\": [\n \"\"\n ],\n \"Amount will be round below to the largest possible value smaller than the input.\": [\n \"\"\n ],\n \"Up\": [\n \"\"\n ],\n \"Amount will be round up to the smallest possible value larger than the input.\": [\n \"\"\n ],\n \"Nearest\": [\n \"\"\n ],\n \"Amount will be round to the closest possible value.\": [\n \"\"\n ],\n \"If none specified the fallback value is \\\"%1$s \\\".\": [\n \"\"\n ],\n \"Examples\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.1\": [\n \"\"\n ],\n \"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.\": [\n \"\"\n ],\n \"With the \\\"zero\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.1\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.3\": [\n \"\"\n ],\n \"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.5\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.3\": [\n \"\"\n ],\n \"Amount to be deducted before amount is credited.\": [\n \"\"\n ],\n \"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"Le retrait doit \u00EAtre activ\u00E9 dans la configuration, le taux de conversion doit \u00EAtre initialis\u00E9 avec des frais, des taux et un mode d'arrondi.\"\n ],\n \"delete conversion rate class\": [\n \"Taux de conversion\"\n ],\n \"Unauthorized\": [\n \"L'utilisateur n'est pas autoris\u00E9\"\n ],\n \"Forbidden\": [\n \"\"\n ],\n \"NotFound\": [\n \"\"\n ],\n \"NotImplemented\": [\n \"\"\n ],\n \"update conversion rate class\": [\n \"Taux de conversion\"\n ],\n \"Not Found\": [\n \"\"\n ],\n \"Not implemented\": [\n \"\"\n ],\n \"The name of the conversion is already used.\": [\n \"Une op\u00E9ration est d\u00E9j\u00E0 en attente\"\n ],\n \"Conversion rate class\": [\n \"Taux de conversion\"\n ],\n \"Accounts\": [\n \"Comptes\"\n ],\n \"Test\": [\n \"\"\n ],\n \"Users\": [\n \"Nom d'utilisateur\"\n ],\n \"Can't remove the conversion rate class\": [\n \"\"\n ],\n \"There are some user associated to this class. You need to remove them first.\": [\n \"\"\n ],\n \"You are going to remove the conversion rate class\": [\n \"\"\n ],\n \"This step can't be undone.\": [\n \"\"\n ],\n \"Filters\": [\n \"\"\n ],\n \"Show from other classes\": [\n \"\"\n ],\n \"Account\": [\n \"Compte\"\n ],\n \"Group ID\": [\n \"\"\n ],\n \"No users in this conversion rate class\": [\n \"\"\n ],\n \"Class\": [\n \"\"\n ],\n \"Action\": [\n \"Actions\"\n ],\n \"Remove\": [\n \"Effacer\"\n ],\n \"Add\": [\n \"Adresse\"\n ],\n \"Conversion rate name\": [\n \"Taux de conversion\"\n ],\n \"Short description of the class\": [\n \"\"\n ],\n \"create conversion rate class\": [\n \"Taux de conversion\"\n ],\n \"Conversion rate class created.\": [\n \"Taux de conversion\"\n ],\n \"The rights to change the account are not sufficient\": [\n \"Les droits de modification du compte ne sont pas suffisants\"\n ],\n \"New conversion rate class\": [\n \"Taux de conversion\"\n ],\n \"Create\": [\n \"\"\n ],\n \"History of public accounts\": [\n \"Historique de comptes publiques\"\n ],\n \"Make a wire transfer\": [\n \"Effectuer un virement bancaire\"\n ],\n \"Scan the QR code below to start the withdrawal.\": [\n \"Scannez le code QR ci-dessous pour commencer le retrait.\"\n ],\n \"Operation aborted\": [\n \"Op\u00E9ration abandonn\u00E9e\"\n ],\n \"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.\": [\n \"Le virement bancaire vers le compte du prestataire de services de paiement a \u00E9t\u00E9 annul\u00E9 depuis un autre endroit, votre solde n'a pas \u00E9t\u00E9 affect\u00E9.\"\n ],\n \"Go to your wallet now\": [\n \"Acc\u00E9dez \u00E0 votre portefeuille maintenant\"\n ],\n \"The operation is marked as selected, but a process during the withdrawal failed\": [\n \"L'op\u00E9ration est marqu\u00E9e comme s\u00E9lectionn\u00E9e, mais un processus pendant le retrait a \u00E9chou\u00E9\"\n ],\n \"A withdrawal reserve ID was not found and no account has been selected.\": [\n \"Aucun identifiant de r\u00E9serve de retrait n'a \u00E9t\u00E9 trouv\u00E9 et aucun compte n'a \u00E9t\u00E9 s\u00E9lectionn\u00E9.\"\n ],\n \"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.\": [\n \"Il existe un identifiant de r\u00E9serve de retrait, mais aucun compte n'a \u00E9t\u00E9 s\u00E9lectionn\u00E9 ou le compte s\u00E9lectionn\u00E9 n'est pas valide.\"\n ],\n \"The account was selected, but no withdrawal reserve ID was found.\": [\n \"Le compte a \u00E9t\u00E9 s\u00E9lectionn\u00E9, mais aucun identifiant de r\u00E9serve de retrait n'a \u00E9t\u00E9 trouv\u00E9.\"\n ],\n \"Operation not found\": [\n \"Op\u00E9ration non trouv\u00E9e\"\n ],\n \"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.\": [\n \"Ce processus n'est pas connu du serveur. L'identifiant du processus est incorrect ou le serveur a supprim\u00E9 les informations sur le processus avant leur arriv\u00E9e ici.\"\n ],\n \"Continue to dashboard\": [\n \"Continuer vers le tableau de bord\"\n ],\n \"The Withdrawal URI is not valid\": [\n \"L'URI de retrait n'est pas valide\"\n ],\n \"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.\": [\n \"L'encaissement doit \u00EAtre activ\u00E9 dans la configuration, le taux de conversion doit \u00EAtre initialis\u00E9 avec des frais, des taux et un mode d'arrondi.\"\n ],\n \"Latest cashouts\": [\n \"Derniers encaissements\"\n ],\n \"Created\": [\n \"Cr\u00E9\u00E9e\"\n ],\n \"Total debit\": [\n \"D\u00E9bit total\"\n ],\n \"Total credit\": [\n \"Cr\u00E9dit total\"\n ],\n \"Cashout for account %1$s\": [\n \"Encaissement pour le compte %1$s\"\n ],\n \"Invalid email format\": [\n \"Valeur non valide\"\n ],\n \"Should start with +\": [\n \"Doit commencer par +\"\n ],\n \"A phone number consists of numbers only\": [\n \"Un num\u00E9ro de t\u00E9l\u00E9phone se compose uniquement de chiffres\"\n ],\n \"Account ID for authentication\": [\n \"Identifiant de compte pour l'authentification\"\n ],\n \"Name of the account holder\": [\n \"Nom du titulaire du compte\"\n ],\n \"Internal account\": [\n \"Compte interne\"\n ],\n \"If this field is empty, a random account ID will be assigned\": [\n \"Si ce champ est vide, un identifiant de compte al\u00E9atoire sera attribu\u00E9\"\n ],\n \"You can copy and share this IBAN number in order to receive wire transfers to your bank account\": [\n \"Vous pouvez copier et partager ce num\u00E9ro IBAN afin de recevoir des virements vers votre compte bancaire\"\n ],\n \"Email\": [\n \"Adresse mail\"\n ],\n \"To be used when second factor authentication is enabled\": [\n \"\u00C0 utiliser lorsque l'authentification par deuxi\u00E8me facteur est activ\u00E9e\"\n ],\n \"Phone\": [\n \"T\u00E9l\u00E9phone\"\n ],\n \"Enable second factor authentication\": [\n \"\u00C0 utiliser lorsque l'authentification par deuxi\u00E8me facteur est activ\u00E9e\"\n ],\n \"Using email\": [\n \"Vers l'email\"\n ],\n \"Add an email in your profile to enable this option\": [\n \"\"\n ],\n \"Using SMS\": [\n \"\"\n ],\n \"Add a phone number in your profile to enable this option\": [\n \"\"\n ],\n \"Cashout account\": [\n \"Compte d'encaissement\"\n ],\n \"External account number where the money is going to be sent when doing cashouts\": [\n \"Num\u00E9ro de compte externe o\u00F9 l'argent va \u00EAtre envoy\u00E9 lors des encaissements\"\n ],\n \"Max debt\": [\n \"Cr\u00E9ance maximale\"\n ],\n \"How much the balance can go below zero.\": [\n \"De combien le solde peut-il descendre en dessous de z\u00E9ro.\"\n ],\n \"Is this account public?\": [\n \"Ce compte est-il public\u202F?\"\n ],\n \"Public accounts have their balance publicly accessible\": [\n \"Le solde des comptes publics est accessible \u00E0 tous\"\n ],\n \"Does this account belong to a Payment Service Provider?\": [\n \"Ce compte appartient-il \u00E0 un prestataire de services de paiement\u202F?\"\n ],\n \"update account\": [\n \"Cr\u00E9er un compte\"\n ],\n \"Account updated\": [\n \"Compte mis \u00E0 jour\"\n ],\n \"The username was not found\": [\n \"Le nom d'utilisateur n'a pas \u00E9t\u00E9 trouv\u00E9\"\n ],\n \"You can't change the legal name, please contact the your account administrator.\": [\n \"Vous ne pouvez pas modifier le nom l\u00E9gal, veuillez contacter l'administrateur de votre compte.\"\n ],\n \"You can't change the debt limit, please contact the your account administrator.\": [\n \"Vous ne pouvez pas modifier la limite d'endettement, veuillez contacter l'administrateur de votre compte.\"\n ],\n \"You can't change the cashout address, please contact the your account administrator.\": [\n \"Vous ne pouvez pas modifier l'adresse d'encaissement, veuillez contacter l'administrateur de votre compte.\"\n ],\n \"Update account information.\": [\n \"Mise \u00E0 jour des param\u00E8tres du compte\"\n ],\n \"Account \\\"%1$s\\\"\": [\n \"Compte \\\"%1$s\\\"\"\n ],\n \"Removed\": [\n \"Supprim\u00E9\"\n ],\n \"This account can't be used.\": [\n \"Ce compte ne peut pas \u00EAtre utilis\u00E9.\"\n ],\n \"Change details\": [\n \"Modifier les d\u00E9tails\"\n ],\n \"Merchant integration\": [\n \"Int\u00E9gration des commer\u00E7ants\"\n ],\n \"Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the \\\"import\\\" button in the \\\"bank account\\\" section.\": [\n \"Utilisez ces informations pour relier votre compte Taler Merchant Backoffice au compte bancaire actuel. Vous pouvez commencer par copier les valeurs, puis vous rendre chez votre fournisseur de services de backoffice marchand, vous connecter \u00E0 votre compte et chercher le bouton \\\"importer\\\" dans la section \\\"compte bancaire\\\".\"\n ],\n \"Account type\": [\n \"Type de compte\"\n ],\n \"Method to use for wire transfer.\": [\n \"M\u00E9thode \u00E0 utiliser pour un virement bancaire.\"\n ],\n \"IBAN\": [\n \"IBAN\"\n ],\n \"International Bank Account Number.\": [\n \"Num\u00E9ro de compte bancaire international (IBAN).\"\n ],\n \"Account name\": [\n \"Intitul\u00E9 du compte\"\n ],\n \"Bank host where the service is located.\": [\n \"Serveur de la banque o\u00F9 se trouve le service.\"\n ],\n \"Bank account identifier for wire transfers.\": [\n \"Identifiant du compte bancaire pour les virements.\"\n ],\n \"Address\": [\n \"Adresse\"\n ],\n \"Owner's name\": [\n \"Nom du propri\u00E9taire\"\n ],\n \"Legal name of the person holding the account.\": [\n \"Nom l\u00E9gal de la personne titulaire du compte.\"\n ],\n \"Account info URL\": [\n \"URL d'information de compte\"\n ],\n \"From where the merchant can download information about incoming wire transfers to this account.\": [\n \"Endroit d'o\u00F9 le commer\u00E7ant peut t\u00E9l\u00E9charger des informations sur les virements entrants sur ce compte.\"\n ],\n \"Repeated password doesn't match\": [\n \"Le mot de passe r\u00E9p\u00E9t\u00E9 ne correspond pas\"\n ],\n \"update password\": [\n \"Modifier le mot de passe\"\n ],\n \"Password changed\": [\n \"Mot de passe modifi\u00E9\"\n ],\n \"Not authorized to change the password, maybe the session is invalid.\": [\n \"Pas autoris\u00E9 \u00E0 changer le mot de passe, peut-\u00EAtre que la session n'est pas valide.\"\n ],\n \"You need to provide the old password. If you don't have it contact your account administrator.\": [\n \"Vous devez fournir l'ancien mot de passe. Si vous ne l'avez pas, veuillez contacter l'administrateur.\"\n ],\n \"Your current password doesn't match, can't change to a new password.\": [\n \"Votre mot de passe actuel ne correspond pas, vous ne pouvez pas changer de mot de passe.\"\n ],\n \"You don't have the rights to change the password.\": [\n \"\"\n ],\n \"Update account password.\": [\n \"Modifier le mot de passe\"\n ],\n \"Update password\": [\n \"Modifier le mot de passe\"\n ],\n \"Current password\": [\n \"Mot de passe actuel\"\n ],\n \"Your current password, for security\": [\n \"Votre mot de passe actuel, par s\u00E9curit\u00E9\"\n ],\n \"New password\": [\n \"Nouveau mot de passe\"\n ],\n \"Type it again\": [\n \"Saisissez-le \u00E0 nouveau\"\n ],\n \"Repeat the same password\": [\n \"Confirmez le mot de passe\"\n ],\n \"Change\": [\n \"Modifier\"\n ],\n \"Create account\": [\n \"Cr\u00E9er un compte\"\n ],\n \"Actions\": [\n \"Actions\"\n ],\n \"Unknown\": [\n \"Inconnu\"\n ],\n \"Change password\": [\n \"Changer le mot de passe\"\n ],\n \"Querying for the current stats failed\": [\n \"\u00C9chec de la requ\u00EAte pour les statistiques actuelles\"\n ],\n \"The request parameters are wrong\": [\n \"Les param\u00E8tres de la requ\u00EAte sont erron\u00E9s\"\n ],\n \"The user is unauthorized\": [\n \"L'utilisateur n'est pas autoris\u00E9\"\n ],\n \"Querying for the previous stats failed\": [\n \"\"\n ],\n \"Transaction volume report\": [\n \"\"\n ],\n \"Last hour\": [\n \"\"\n ],\n \"Previous day\": [\n \"\"\n ],\n \"Last month\": [\n \"\"\n ],\n \"Last year\": [\n \"\"\n ],\n \"Last Year\": [\n \"\"\n ],\n \"Trading volume from %1$s to %2$s\": [\n \"\"\n ],\n \"Transferred from an external account to an account in this bank.\": [\n \"\"\n ],\n \"Transferred from an account in this bank to an external account.\": [\n \"\"\n ],\n \"Payin\": [\n \"\"\n ],\n \"Transferred from an account to a Taler exchange.\": [\n \"\"\n ],\n \"Payout\": [\n \"\"\n ],\n \"Transferred from a Taler exchange to another account.\": [\n \"\"\n ],\n \"Download stats as CSV\": [\n \"\"\n ],\n \"previous\": [\n \"\"\n ],\n \"Decreased by\": [\n \"\"\n ],\n \"Increased by\": [\n \"\"\n ],\n \"create account\": [\n \"Cr\u00E9er un compte\"\n ],\n \"Account created with password \\\"%1$s\\\".\": [\n \"\"\n ],\n \"Server replied that phone or email is invalid\": [\n \"\"\n ],\n \"The rights to perform the operation are not sufficient\": [\n \"\"\n ],\n \"Account username is already taken\": [\n \"\"\n ],\n \"Account ID is already taken\": [\n \"D\u00E9sol\u00E9, cet identifiant de compte est d\u00E9j\u00E0 pris.\"\n ],\n \"Bank ran out of bonus credit.\": [\n \"\"\n ],\n \"Account username can't be used because is reserved\": [\n \"\"\n ],\n \"Can't create accounts\": [\n \"\"\n ],\n \"Only system admin can create accounts.\": [\n \"\"\n ],\n \"New bank account\": [\n \"\"\n ],\n \"download statistics\": [\n \"\"\n ],\n \"only admin can download stats\": [\n \"\"\n ],\n \"Download bank stats\": [\n \"\"\n ],\n \"Include hour metric\": [\n \"\"\n ],\n \"Include day metric\": [\n \"\"\n ],\n \"Include month metric\": [\n \"\"\n ],\n \"Include year metric\": [\n \"\"\n ],\n \"Include table header\": [\n \"\"\n ],\n \"Add previous metric for compare\": [\n \"\"\n ],\n \"Fail on first error\": [\n \"\"\n ],\n \"Download\": [\n \"\"\n ],\n \"downloading... %1$s\": [\n \"\"\n ],\n \"Download completed\": [\n \"\"\n ],\n \"Click here to save the file in your computer.\": [\n \"\"\n ],\n \"there was an error reading the balance\": [\n \"\"\n ],\n \"Can't delete the account\": [\n \"\"\n ],\n \"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.\": [\n \"\"\n ],\n \"Name doesn't match\": [\n \"\"\n ],\n \"delete account\": [\n \"Cr\u00E9er un compte\"\n ],\n \"Account removed\": [\n \"\"\n ],\n \"No enough permission to delete the account.\": [\n \"\"\n ],\n \"The username was not found.\": [\n \"\"\n ],\n \"Can't delete a reserved username.\": [\n \"\"\n ],\n \"Can't delete an account with balance different than zero.\": [\n \"\"\n ],\n \"Remove account.\": [\n \"Suppression du compte\"\n ],\n \"You are going to remove the account\": [\n \"\"\n ],\n \"Deleting account \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Verification\": [\n \"\"\n ],\n \"Enter the account name that is going to be deleted\": [\n \"\"\n ],\n \"Cashout id should be a number\": [\n \"\"\n ],\n \"This cashout not found. Maybe already aborted.\": [\n \"\"\n ],\n \"Cashout detail\": [\n \"\"\n ],\n \"Debited\": [\n \"\"\n ],\n \"Transferred\": [\n \"Transfert\"\n ],\n \"You have no permission to this account.\": [\n \"Vous n'\u00EAtes pas autoris\u00E9 \u00E0 cr\u00E9er ce compte.\"\n ],\n \"This account is locked. If you have a active session you can change the password or contact the administrator.\": [\n \"\"\n ],\n \"New web session\": [\n \"\"\n ],\n \"Welcome to %1$s!\": [\n \"\"\n ]\n }\n },\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n > 1;\",\n \"lang\": \"fr\",\n \"completeness\": 66\n};\n\nstrings['es'] = {\n \"locale_data\": {\n \"messages\": {\n \"\": {\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n != 1;\",\n \"lang\": \"es_AR\"\n },\n \"An IBAN consists of capital letters and numbers only\": [\n \"Un IBAN debe contener solo letras may\u00FAsculas y n\u00FAmeros\"\n ],\n \"IBAN numbers have more that 4 digits\": [\n \"Los n\u00FAmeros IBAN tienen m\u00E1s de 4 d\u00EDgitos\"\n ],\n \"IBAN numbers have less that 34 digits\": [\n \"Los n\u00FAmeros IBAN tienen menos de 34 d\u00EDgitos\"\n ],\n \"IBAN country code not found\": [\n \"C\u00F3digo de pa\u00EDs del IBAN no encontrado\"\n ],\n \"IBAN number is not valid, checksum is wrong\": [\n \"El n\u00FAmero IBAN no es v\u00E1lido, fall\u00F3 la verificaci\u00F3n\"\n ],\n \"Use letters, numbers or any of these characters: - . _ ~\": [\n \"Us\u00E1 letras, n\u00FAmeros o cualquiera de estos caracteres: - . _ ~\"\n ],\n \"Required\": [\n \"Requerido\"\n ],\n \"confirm MFA challenge\": [\n \"Confiormar desaf\u00EDo.\"\n ],\n \"Unknown challenge.\": [\n \"Desaf\u00EDo desconocido.\"\n ],\n \"Failed to validate the verification code.\": [\n \"No se pudo validar el c\u00F3digo de verificaci\u00F3n.\"\n ],\n \"Too many challenges are active right now, you must wait or confirm current challenges.\": [\n \"Hay demasiados desaf\u00EDos activos en este momento, ten\u00E9s que esperar o confirmar los desaf\u00EDos actuales.\"\n ],\n \"Wrong authentication number.\": [\n \"N\u00FAmero de autenticaci\u00F3n incorrecto.\"\n ],\n \"Expired challenge.\": [\n \"Desaf\u00EDo expirado.\"\n ],\n \"Submit the transmitted code number.\": [\n \"Ingres\u00E1 el c\u00F3digo que te fue enviado.\"\n ],\n \"The verification code sent to the email address starting with %1$s\": [\n \"El c\u00F3digo de verificaci\u00F3n enviado a la direcci\u00F3n de correo que empieza con %1$s\"\n ],\n \"The verification code sent to the phone number ending with %1$s\": [\n \"El c\u00F3digo de verificaci\u00F3n enviado al n\u00FAmero de tel\u00E9fono que empieza con %1$s\"\n ],\n \"Code\": [\n \"C\u00F3digo\"\n ],\n \"Username of the account\": [\n \"Nombre de usuario de la cuenta\"\n ],\n \"It will expired at %1$s\": [\n \"Expirar\u00E1 el %1$s\"\n ],\n \"The challenge is expired and can't be solved but you can go back and create a new challenge.\": [\n \"El desaf\u00EDo expir\u00F3 y no puede resolverse, pero pod\u00E9s volver atr\u00E1s y crear uno nuevo.\"\n ],\n \"Back\": [\n \"Volver\"\n ],\n \"Verify\": [\n \"Verificar\"\n ],\n \"send MFA challenge\": [\n \"Env\u00EDo de desaf\u00EDo\"\n ],\n \"Failed to send the verification code.\": [\n \"No se pudo enviar el c\u00F3digo de verificaci\u00F3n.\"\n ],\n \"The request was valid, but the server is refusing action.\": [\n \"El pedido era v\u00E1lido, pero el servidor est\u00E1 rechazando la acci\u00F3n.\"\n ],\n \"The backend is not aware of the specified MFA challenge.\": [\n \"El servidor no reconoce el desaf\u00EDo MFA especificado.\"\n ],\n \"It is too early to request another transmission of the challenge.\": [\n \"Es demasiado pronto para solicitar otro env\u00EDo del desaf\u00EDo.\"\n ],\n \"Code transmission failed.\": [\n \"El env\u00EDo del c\u00F3digo fall\u00F3.\"\n ],\n \"select challenge\": [\n \"Seleccionar desaf\u00EDo\"\n ],\n \"Multi-factor authentication required\": [\n \"Se requiere autenticaci\u00F3n de m\u00FAltiples factores\"\n ],\n \"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.\": [\n \"Esta operaci\u00F3n est\u00E1 protegida con autenticaci\u00F3n de segundo factor. Para completarla necesitamos verificar tu identidad usando el canal de autenticaci\u00F3n que proporcionaste.\"\n ],\n \"The next challenge needs to be completed to confirm the operation.\": [\n \"El siguiente desaf\u00EDo debe completarse para confirmar la operaci\u00F3n.\"\n ],\n \"All the next challenges need to be completed to confirm the operation.\": [\n \"Todos los desaf\u00EDos siguientes deben completarse para confirmar la operaci\u00F3n.\"\n ],\n \"One of the next challenges need to be completed to confirm the operation.\": [\n \"Uno de los siguientes desaf\u00EDos debe completarse para confirmar la operaci\u00F3n.\"\n ],\n \"To an phone ending with \\\"%1$s\\\"\": [\n \"A un tel\u00E9fono que empieza con \\\"%1$s\\\"\"\n ],\n \"To an email starting with \\\" %1$s\\\"\": [\n \"A un correo que empieza con \\\"%1$s\\\"\"\n ],\n \"I have a code\": [\n \"Tengo un c\u00F3digo\"\n ],\n \"Send me a message\": [\n \"Enviame un mensaje\"\n ],\n \"You have to wait until %1$s to send a new code.\": [\n \"Ten\u00E9s que esperar hasta el %1$s para enviar un nuevo c\u00F3digo.\"\n ],\n \"Cancel\": [\n \"Cancelar\"\n ],\n \"Complete\": [\n \"Completar\"\n ],\n \"Unable to create a cashout\": [\n \"No se puede crear un egreso\"\n ],\n \"The bank configuration does not support cashout operations.\": [\n \"La configuraci\u00F3n del banco no soporta operaciones de egreso.\"\n ],\n \"Close\": [\n \"Cerrar\"\n ],\n \"Cashout is disabled\": [\n \"El egreso est\u00E1 deshabilitado\"\n ],\n \"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"El egreso debe estar habilitado en la configuraci\u00F3n, la tasa de conversi\u00F3n debe estar inicializada con comisi\u00F3n(es), tasas y un modo de redondeo.\"\n ],\n \"calculate conversion fee\": [\n \"Calcular tasa de conversi\u00F3n.\"\n ],\n \"The server didn't understand the request.\": [\n \"El servidor no pudo entender el pedido.\"\n ],\n \"The amount is too small\": [\n \"El monto es demasiado peque\u00F1o\"\n ],\n \"Conversion is not implemented.\": [\n \"La conversi\u00F3n no est\u00E1 implementada.\"\n ],\n \"At least debit or credit needs to be provided\": [\n \"Se debe indicar al menos el d\u00E9bito o el cr\u00E9dito\"\n ],\n \"The amount is malfored\": [\n \"El monto tiene un formato incorrecto\"\n ],\n \"The currency is not supported\": [\n \"La moneda no est\u00E1 soportada\"\n ],\n \"Invalid\": [\n \"Inv\u00E1lido\"\n ],\n \"Amount needs to be higher\": [\n \"El monto debe ser mayor\"\n ],\n \"Balance is not enough\": [\n \"El saldo no es suficiente\"\n ],\n \"It is not possible to cashout less than %1$s: %2$s\": [\n \"No es posible retirar menos de %1$s: %2$s\"\n ],\n \"The total transfer to the destination will be zero\": [\n \"El total de la transferencia al destino ser\u00E1 cero\"\n ],\n \"create cashout\": [\n \"Crear egreso.\"\n ],\n \"Cashout created\": [\n \"Egreso creado\"\n ],\n \"Second factor authentication required.\": [\n \"Se requiere autenticaci\u00F3n de segundo factor.\"\n ],\n \"Account not found\": [\n \"Cuenta no encontrada\"\n ],\n \"Duplicated request detected, check if the operation succeeded or try again.\": [\n \"Se detect\u00F3 una petici\u00F3n duplicada, verific\u00E1 si la operaci\u00F3n tuvo \u00E9xito o intent\u00E1 nuevamente.\"\n ],\n \"The conversion rate was applied incorrectly\": [\n \"La tasa de conversi\u00F3n se aplic\u00F3 de forma incorrecta\"\n ],\n \"The account does not have sufficient funds\": [\n \"La cuenta no tiene fondos suficientes\"\n ],\n \"Missing cashout URI in the profile\": [\n \"Falta la direcci\u00F3n de egreso en el perfil\"\n ],\n \"The amount is below the minimum amount permitted.\": [\n \"El monto est\u00E1 por debajo del m\u00EDnimo permitido.\"\n ],\n \"Sending the confirmation message failed, retry later or contact the administrator.\": [\n \"El env\u00EDo del mensaje de confirmaci\u00F3n fall\u00F3, intent\u00E1 m\u00E1s tarde o contact\u00E1 al administrador.\"\n ],\n \"The server doesn't support the current TAN channel.\": [\n \"El servidor no soporta el canal TAN actual.\"\n ],\n \"Create cashout.\": [\n \"Crear egreso.\"\n ],\n \"Cashout\": [\n \"Egreso\"\n ],\n \"Conversion rate\": [\n \"Tasa de conversi\u00F3n\"\n ],\n \"Balance\": [\n \"Saldo\"\n ],\n \"Fee\": [\n \"Comisi\u00F3n\"\n ],\n \"To account\": [\n \"Hacia la cuenta\"\n ],\n \"Legal name\": [\n \"Nombre legal\"\n ],\n \"If this name doesn't match the account holder's name, your transaction may fail.\": [\n \"Si este nombre no coincide con el titular de la cuenta, tu transacci\u00F3n podr\u00EDa fallar.\"\n ],\n \"Unable to cashout\": [\n \"No se puede realizar el egreso\"\n ],\n \"Before being able to cashout to a bank account, you need to complete your profile\": [\n \"Antes de poder hacer un egreso a una cuenta bancaria, necesit\u00E1s completar tu perfil\"\n ],\n \"Transfer subject\": [\n \"Asunto de la transferencia\"\n ],\n \"Currency\": [\n \"Moneda\"\n ],\n \"Send %1$s\": [\n \"Enviar %1$s\"\n ],\n \"Receive %1$s\": [\n \"Recibir %1$s\"\n ],\n \"Amount\": [\n \"Monto\"\n ],\n \"Total cost\": [\n \"Costo total\"\n ],\n \"Balance left\": [\n \"Saldo restante\"\n ],\n \"Before fee\": [\n \"Antes de la comisi\u00F3n\"\n ],\n \"Total cashout transfer\": [\n \"Total del egreso\"\n ],\n \"Not valid\": [\n \"No v\u00E1lido\"\n ],\n \"Does not follow the pattern\": [\n \"No sigue el formato esperado\"\n ],\n \"send transaction\": [\n \"Env\u00EDo de transaccion\"\n ],\n \"The wire transfer was successfully completed!\": [\n \"\u00A1La transferencia bancaria se complet\u00F3 con \u00E9xito!\"\n ],\n \"The request was invalid or the payto://-URI used unacceptable features.\": [\n \"El pedido era inv\u00E1lido o el URI payto:// usado tiene caracter\u00EDsticas inaceptables.\"\n ],\n \"Not enough permission to complete the operation.\": [\n \"No ten\u00E9s permisos suficientes para completar la operaci\u00F3n.\"\n ],\n \"The bank administrator cannot be the transfer creditor.\": [\n \"El administrador del banco no puede ser el destinatario de la transferencia.\"\n ],\n \"The destination account \\\"%1$s\\\" was not found.\": [\n \"La cuenta de destino \\\"%1$s\\\" no fue encontrada.\"\n ],\n \"The origin and the destination of the transfer can't be the same.\": [\n \"El origen y el destino de la transferencia no pueden ser iguales.\"\n ],\n \"Your balance is not sufficient for the operation.\": [\n \"Tu saldo no es suficiente para la operaci\u00F3n.\"\n ],\n \"The origin account \\\"%1$s\\\" was not found.\": [\n \"La cuenta origen \\\"%1$s\\\" no fue encontrada.\"\n ],\n \"The attempt to create the transaction has failed. Please try again.\": [\n \"El intento de crear la transacci\u00F3n fall\u00F3. Por favor intent\u00E1 nuevamente.\"\n ],\n \"A second factor authentication is required.\": [\n \"Se requiere autenticaci\u00F3n de segundo factor.\"\n ],\n \"Confirm wire transfer.\": [\n \"Confirm\u00E1 la transferencia bancaria.\"\n ],\n \"Input wire transfer detail\": [\n \"Ingres\u00E1 los datos de la transferencia bancaria\"\n ],\n \"Using a form\": [\n \"Usando un formulario\"\n ],\n \"A special URI that specifies the amount to be transferred and the destination account.\": [\n \"Un URI especial que indica el monto a transferir y la cuenta de destino.\"\n ],\n \"QR code\": [\n \"C\u00F3digo QR\"\n ],\n \"If your device has a camera, you can import a payto:// URI from a QR code.\": [\n \"Si tu dispositivo tiene c\u00E1mara, pod\u00E9s importar un URI payto:// desde un c\u00F3digo QR.\"\n ],\n \"Recipient\": [\n \"Destinatario\"\n ],\n \"ID of the recipient's account\": [\n \"ID de la cuenta del destinatario\"\n ],\n \"username\": [\n \"nombre de usuario\"\n ],\n \"IBAN of the recipient's account\": [\n \"IBAN de la cuenta del destinatario\"\n ],\n \"Subject\": [\n \"Asunto\"\n ],\n \"Some text to identify the transfer\": [\n \"Alg\u00FAn texto para identificar la transferencia\"\n ],\n \"Amount to transfer\": [\n \"Monto a transferir\"\n ],\n \"Payto URI:\": [\n \"URI payto:\"\n ],\n \"Uniform resource identifier of the target account\": [\n \"Identificador de recurso uniforme de la cuenta destino\"\n ],\n \"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://x-taler-bank/[operador bancario]/[cuenta bancaria del destinatario]?message=[asunto]&amount=[%1$s:X.Y]\"\n ],\n \"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://iban/[IBAN del destinatario]?message=[asunto]&amount=[%1$s:X.Y]\"\n ],\n \"The maximum amount for a wire transfer is %1$s\": [\n \"El monto m\u00E1ximo para una transferencia bancaria es %1$s\"\n ],\n \"Cost\": [\n \"Costo\"\n ],\n \"Send\": [\n \"Enviar\"\n ],\n \"Only \\\"x-taler-bank\\\" target are supported\": [\n \"Solo se soportan destinos \\\"x-taler-bank\\\"\"\n ],\n \"Only this host is allowed. Use \\\"%1$s\\\"\": [\n \"Solo este host est\u00E1 permitido. Us\u00E1 \\\"%1$s\\\"\"\n ],\n \"Account name is missing\": [\n \"Falta el nombre de la cuenta\"\n ],\n \"Only \\\"IBAN\\\" target are supported\": [\n \"Solo se soportan destinos \\\"IBAN\\\"\"\n ],\n \"Missing \\\"amount\\\" parameter to specify the amount to be transferred\": [\n \"Falta el par\u00E1metro \\\"amount\\\" para indicar el monto a transferir\"\n ],\n \"The \\\"amount\\\" parameter is not valid\": [\n \"El par\u00E1metro \\\"amount\\\" no es v\u00E1lido\"\n ],\n \"\\\"message\\\" parameters to specify a reference text for the transfer are missing\": [\n \"Falta el par\u00E1metro \\\"message\\\" para indicar un texto de referencia en la transferencia\"\n ],\n \"The only currency allowed is \\\"%1$s\\\"\": [\n \"La \u00FAnica moneda permitida es \\\"%1$s\\\"\"\n ],\n \"You cannot transfer an amount of zero.\": [\n \"No pod\u00E9s transferir un monto de cero.\"\n ],\n \"The balance is not sufficient\": [\n \"El saldo no es suficiente\"\n ],\n \"Please enter a longer subject\": [\n \"Por favor ingres\u00E1 un asunto m\u00E1s largo\"\n ],\n \"Show withdrawal confirmation\": [\n \"Mostrar confirmaci\u00F3n de extracci\u00F3n\"\n ],\n \"Withdraw without setting amount\": [\n \"Retirar sin especificar monto\"\n ],\n \"Hide demo hint.\": [\n \"Ocultar la sugerencia de demo.\"\n ],\n \"Show install wallet first\": [\n \"Mostrar primero la instalaci\u00F3n de la billetera\"\n ],\n \"Currently, the bank is not accepting new registrations!\": [\n \"\u00A1El banco no est\u00E1 aceptando nuevos registros en este momento!\"\n ],\n \"The name is missing\": [\n \"Falta el nombre\"\n ],\n \"Missing username\": [\n \"Falta el nombre de usuario\"\n ],\n \"Missing password\": [\n \"Falta la contrase\u00F1a\"\n ],\n \"The password should be longer than 8 letters\": [\n \"La contrase\u00F1a debe tener m\u00E1s de 8 caracteres\"\n ],\n \"The passwords do not match\": [\n \"Las contrase\u00F1as no coinciden\"\n ],\n \"register new account\": [\n \"Registrar nueva cuenta\"\n ],\n \"Server replied with invalid phone or email.\": [\n \"El servidor respondi\u00F3 con un tel\u00E9fono o correo electr\u00F3nico inv\u00E1lido.\"\n ],\n \"You are not authorised to create this account.\": [\n \"No est\u00E1s autorizado a crear esta cuenta.\"\n ],\n \"Registration is disabled because the bank ran out of bonus credit.\": [\n \"El registro est\u00E1 deshabilitado porque el banco se qued\u00F3 sin cr\u00E9dito de bonificaci\u00F3n.\"\n ],\n \"That username can't be used because is reserved.\": [\n \"Ese nombre de usuario no puede usarse porque est\u00E1 reservado.\"\n ],\n \"That username is already taken.\": [\n \"Ese nombre de usuario ya est\u00E1 en uso.\"\n ],\n \"That account ID is already taken.\": [\n \"Ese ID de cuenta ya est\u00E1 en uso.\"\n ],\n \"No information for the selected authentication channel.\": [\n \"No hay informaci\u00F3n para el canal de autenticaci\u00F3n seleccionado.\"\n ],\n \"Authentication channel is not supported.\": [\n \"El canal de autenticaci\u00F3n no est\u00E1 soportado.\"\n ],\n \"Only an administrator is allowed to set the debt limit.\": [\n \"Solo un administrador puede establecer el l\u00EDmite de deuda.\"\n ],\n \"Only the administrator can change the conversion rate.\": [\n \"Solo el administrador puede cambiar la tasa de conversi\u00F3n.\"\n ],\n \"The conversion rate class doesn't exist.\": [\n \"La clase de tasa de conversi\u00F3n no existe.\"\n ],\n \"Only admin can create accounts with second factor authentication.\": [\n \"Solo el administrador puede crear cuentas con autenticaci\u00F3n de segundo factor.\"\n ],\n \"The password is too short. Can't have less than 8 characters.\": [\n \"La contrase\u00F1a es demasiado corta. Debe tener al menos 8 caracteres.\"\n ],\n \"The password is too long. Can't have more than 64 characters.\": [\n \"La contrase\u00F1a es demasiado larga. No puede tener m\u00E1s de 64 caracteres.\"\n ],\n \"Account registration\": [\n \"Registro de cuenta\"\n ],\n \"Login username\": [\n \"Nombre de usuario\"\n ],\n \"account identification to login\": [\n \"Identificacion de cuenta para acceder\"\n ],\n \"Password\": [\n \"Contrase\u00F1a\"\n ],\n \"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers\": [\n \"Us\u00E1 una contrase\u00F1a segura: m\u00EDnimo 8 caracteres, no uses informaci\u00F3n p\u00FAblica sobre vos (nombre, fecha de nacimiento, tel\u00E9fono, etc.) y combin\u00E1 min\u00FAsculas, may\u00FAsculas, s\u00EDmbolos y n\u00FAmeros\"\n ],\n \"Repeat password\": [\n \"Repetir contrase\u00F1a\"\n ],\n \"Same password\": [\n \"Misma contrase\u00F1a\"\n ],\n \"Full name\": [\n \"Nombre completo\"\n ],\n \"Register\": [\n \"Registrarse\"\n ],\n \"Create a random temporary user\": [\n \"Crear un usuario temporal aleatorio\"\n ],\n \"logout\": [\n \"\"\n ],\n \"login\": [\n \"Iniciar sesi\u00F3n\"\n ],\n \"The account has no rights to login.\": [\n \"La cuenta no tiene permisos para iniciar sesi\u00F3n.\"\n ],\n \"The account is locked and cannot login. Contact administrator.\": [\n \"Esta cuenta est\u00E1 bloqueada y no puede iniciar sesi\u00F3n. Contact\u00E1 al administrador.\"\n ],\n \"Wrong credentials for \\\"%1$s\\\"\": [\n \"Credenciales incorrectas para \\\"%1$s\\\"\"\n ],\n \"Account login.\": [\n \"Inicio de sesi\u00F3n.\"\n ],\n \"Session expired\": [\n \"La sesi\u00F3n expir\u00F3\"\n ],\n \"Username\": [\n \"Usuario\"\n ],\n \"identification\": [\n \"Identificaci\u00F3n\"\n ],\n \"Password of the account\": [\n \"Contrase\u00F1a de la cuenta\"\n ],\n \"Forget\": [\n \"Olvid\u00E9 mi contrase\u00F1a\"\n ],\n \"Log in\": [\n \"Ingresar\"\n ],\n \"Transactions history\": [\n \"Historial de transacciones\"\n ],\n \"No transactions yet.\": [\n \"A\u00FAn no hay transacciones.\"\n ],\n \"You can make a transfer or a withdrawal to your wallet.\": [\n \"Pod\u00E9s hacer una transferencia o un retiro a tu billetera.\"\n ],\n \"Date\": [\n \"Fecha\"\n ],\n \"Counterpart\": [\n \"Contraparte\"\n ],\n \"sent\": [\n \"enviado\"\n ],\n \"received\": [\n \"recibido\"\n ],\n \"Invalid value\": [\n \"Valor inv\u00E1lido\"\n ],\n \"to\": [\n \"hacia\"\n ],\n \"from\": [\n \"desde\"\n ],\n \"First page\": [\n \"Primera p\u00E1gina\"\n ],\n \"Next\": [\n \"Siguiente\"\n ],\n \"confirm withdrawal\": [\n \"Confirm\u00E1 la extracci\u00F3n.\"\n ],\n \"cambiar\": [\n \"\"\n ],\n \"abort withdrawal\": [\n \"Interrumpir la extracci\u00F3n.\"\n ],\n \"The withdrawal has been aborted previously and can't be confirmed\": [\n \"La extracci\u00F3n fue cancelada anteriormente y no puede confirmarse\"\n ],\n \"The withdrawal operation can't be confirmed before a wallet accepted the transaction.\": [\n \"La operaci\u00F3n de extracci\u00F3n no puede confirmarse antes de que una billetera acepte la transacci\u00F3n.\"\n ],\n \"The operation ID is invalid.\": [\n \"El ID de operaci\u00F3n es inv\u00E1lido.\"\n ],\n \"The operation was not found.\": [\n \"La operaci\u00F3n no fue encontrada.\"\n ],\n \"The starting withdrawal amount and the confirmation amount differs.\": [\n \"El monto inicial de la extracci\u00F3n y el monto de confirmaci\u00F3n son distintos.\"\n ],\n \"The bank requires a bank account which has not been specified yet.\": [\n \"El banco requiere una cuenta bancaria que a\u00FAn no fue especificada.\"\n ],\n \"Bad request\": [\n \"Pedido incorrecto\"\n ],\n \"The withdrawal operation has been aborted.\": [\n \"La operaci\u00F3n de extracci\u00F3n fue cancelada.\"\n ],\n \"The withdrawal operation has been confirmed previously and can\u2019t be aborted.\": [\n \"La operaci\u00F3n de extracci\u00F3n ya fue confirmada previamente y no puede cancelarse.\"\n ],\n \"Complete withdrawal.\": [\n \"Completar la extracci\u00F3n.\"\n ],\n \"Confirm the withdrawal operation\": [\n \"Confirm\u00E1 la operaci\u00F3n de extracci\u00F3n\"\n ],\n \"Wire transfer details\": [\n \"Datos de la transferencia bancaria\"\n ],\n \"Payment Service Provider's account number\": [\n \"N\u00FAmero de cuenta del Proveedor de Servicios de Pago\"\n ],\n \"Payment Service Provider's name\": [\n \"Nombre del Proveedor de Servicios de Pago\"\n ],\n \"Payment Service Provider's account bank hostname\": [\n \"Nombre del host bancario del Proveedor de Servicios de Pago\"\n ],\n \"Payment Service Provider's account id\": [\n \"ID de cuenta del Proveedor de Servicios de Pago\"\n ],\n \"Payment Service Provider's account address\": [\n \"Direcci\u00F3n de cuenta del Proveedor de Servicios de Pago\"\n ],\n \"Payment Service Provider's account cyclos hostname\": [\n \"Nombre del host bancario del Proveedor de Servicios de Pago\"\n ],\n \"No amount has yet been determined.\": [\n \"A\u00FAn no se determin\u00F3 el monto.\"\n ],\n \"Transfer\": [\n \"Transferencia\"\n ],\n \"Authentication required\": [\n \"Se requiere autenticaci\u00F3n\"\n ],\n \"This operation was created with another username\": [\n \"Esta operaci\u00F3n fue creada con otro nombre de usuario\"\n ],\n \"You are currently logged in with user \\\"%1$s\\\" and the operation was made with user \\\"%2$s\\\"\": [\n \"Actualmente est\u00E1s conectado con el usuario \\\"%1$s\\\" pero la operaci\u00F3n fue realizada con el usuario \\\"%2$s\\\"\"\n ],\n \"The reserve operation has been confirmed previously and can't be aborted\": [\n \"La operaci\u00F3n de reserva ya fue confirmada previamente y no puede cancelarse\"\n ],\n \"Wire transfer completed!\": [\n \"\u00A1Transferencia bancaria completada!\"\n ],\n \"Confirm withdrawal.\": [\n \"Confirm\u00E1 la extracci\u00F3n.\"\n ],\n \"Unauthorized to make the operation, maybe the session has expired or the password changed.\": [\n \"No est\u00E1s autorizado para realizar la operaci\u00F3n, quiz\u00E1s la sesi\u00F3n expir\u00F3 o la contrase\u00F1a cambi\u00F3.\"\n ],\n \"The operation was rejected due to insufficient funds.\": [\n \"La operaci\u00F3n fue rechazada por fondos insuficientes.\"\n ],\n \"Withdrawal confirmed\": [\n \"Extracci\u00F3n confirmada\"\n ],\n \"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.\": [\n \"Se inici\u00F3 la transferencia bancaria al Proveedor de Servicios de Pago. En breve vas a recibir el monto solicitado en tu billetera Taler.\"\n ],\n \"Do not show this again\": [\n \"No mostrar de nuevo\"\n ],\n \"If you have a Taler wallet installed on this device\": [\n \"Si ten\u00E9s una billetera Taler instalada en este dispositivo\"\n ],\n \"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions\": [\n \"Tu billetera va a mostrar los detalles de la transacci\u00F3n, incluyendo las comisiones (si corresponde). Si todav\u00EDa no ten\u00E9s una, segu\u00ED las instrucciones\"\n ],\n \"on this page\": [\n \"en esta p\u00E1gina\"\n ],\n \"Withdraw\": [\n \"Retirar\"\n ],\n \"In case you have a Taler wallet on another device\": [\n \"Si ten\u00E9s la billetera Taler en otro dispositivo\"\n ],\n \"Scan the QR below to start the withdrawal.\": [\n \"Escane\u00E1 el c\u00F3digo QR de abajo para iniciar la extracci\u00F3n.\"\n ],\n \"create withdrawal\": [\n \"Completar la extracci\u00F3n.\"\n ],\n \"The server replied with an invalid taler://withdraw URI\": [\n \"El servidor respondi\u00F3 con un URI taler://withdraw inv\u00E1lido\"\n ],\n \"Withdraw URI: %1$s\": [\n \"URI de extracci\u00F3n: %1$s\"\n ],\n \"The operation was rejected due to insufficient funds\": [\n \"La operaci\u00F3n fue rechazada por fondos insuficientes\"\n ],\n \"Current balance is %1$s\": [\n \"El saldo actual es %1$s\"\n ],\n \"You can withdraw up to %1$s\": [\n \"Pod\u00E9s retirar hasta %1$s\"\n ],\n \"Continue\": [\n \"Continuar\"\n ],\n \"Use your Taler wallet\": [\n \"Us\u00E1 tu billetera Taler\"\n ],\n \"After using your wallet you will need to authorize or cancel the operation on this site.\": [\n \"Despu\u00E9s de usar tu billetera, vas a necesitar autorizar o cancelar la operaci\u00F3n en este sitio.\"\n ],\n \"You need a Taler wallet\": [\n \"Necesit\u00E1s una billetera Taler\"\n ],\n \"If you don't have one yet you can follow the instruction in\": [\n \"Si todav\u00EDa no ten\u00E9s una, pod\u00E9s seguir las instrucciones en\"\n ],\n \"this page\": [\n \"esta p\u00E1gina\"\n ],\n \"Send money\": [\n \"Enviar dinero\"\n ],\n \"to a Taler wallet\": [\n \"a una billetera Taler\"\n ],\n \"Withdraw digital money into your mobile wallet or browser extension\": [\n \"Retir\u00E1 dinero digital a tu billetera m\u00F3vil o extensi\u00F3n del navegador\"\n ],\n \"to another bank account\": [\n \"a otra cuenta bancaria\"\n ],\n \"Make a wire transfer to an account with known bank account number.\": [\n \"Realiz\u00E1 una transferencia bancaria a una cuenta con n\u00FAmero de cuenta conocido.\"\n ],\n \"This is a demo\": [\n \"Esto es una demostraci\u00F3n\"\n ],\n \"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .\": [\n \"Esta parte de la demostraci\u00F3n muestra c\u00F3mo funcionar\u00EDa un banco que soporta Taler directamente. Adem\u00E1s de usar tu propia cuenta, tambi\u00E9n pod\u00E9s ver el historial de transacciones de algunas %1$s.\"\n ],\n \"Here you will be able to see how a bank that supports Taler directly would work.\": [\n \"Ac\u00E1 vas a poder ver c\u00F3mo funcionar\u00EDa un banco que soporta Taler directamente.\"\n ],\n \"Internal error, please report. There should be more information in the console.\": [\n \"Error interno, por favor reportalo. Deber\u00EDa haber m\u00E1s informaci\u00F3n en la consola.\"\n ],\n \"Internal error, please report.\": [\n \"Error interno, por favor reportalo.\"\n ],\n \"Preferences\": [\n \"Preferencias\"\n ],\n \"Show debug information\": [\n \"Mostrar informaci\u00F3n de depuraci\u00F3n.\"\n ],\n \"Welcome\": [\n \"Bienvenido/a\"\n ],\n \"Welcome, %1$s\": [\n \"Bienvenido/a, %1$s\"\n ],\n \"No enough permission to access the conversion rate list.\": [\n \"No ten\u00E9s permisos suficientes para acceder a la lista de tasas de conversi\u00F3n.\"\n ],\n \"Conversion list not found. Maybe conversion rate is not supported.\": [\n \"Lista de conversiones no encontrada. Puede que la tasa de conversi\u00F3n no est\u00E9 soportada.\"\n ],\n \"Conversion list not implemented.\": [\n \"La lista de conversiones no est\u00E1 implementada.\"\n ],\n \"Conversion rate classes\": [\n \"Clases de tasa de conversi\u00F3n\"\n ],\n \"Create conversion rate class\": [\n \"Crear clase de tasa de conversi\u00F3n\"\n ],\n \"No conversion rate class\": [\n \"Sin clases de tasa de conversi\u00F3n\"\n ],\n \"Name\": [\n \"Nombre\"\n ],\n \"Description\": [\n \"Descripci\u00F3n\"\n ],\n \"Cashin\": [\n \"Ingreso\"\n ],\n \"min:\": [\n \"m\u00EDn:\"\n ],\n \"fee:\": [\n \"comisi\u00F3n:\"\n ],\n \"Select a section\": [\n \"Seleccion\u00E1 una secci\u00F3n\"\n ],\n \"Details\": [\n \"Detalles\"\n ],\n \"Delete\": [\n \"Eliminar\"\n ],\n \"Credentials\": [\n \"Credenciales\"\n ],\n \"Cashouts\": [\n \"Egresos\"\n ],\n \"Conversion\": [\n \"Conversi\u00F3n\"\n ],\n \"only admin can setup conversion\": [\n \"Solo el administrador puede configurar la conversi\u00F3n\"\n ],\n \"calculate cashout fee\": [\n \"Crear tasa de egreso.\"\n ],\n \"update conversion rate\": [\n \"Actualizar tasa de conversi\u00F3n\"\n ],\n \"Wrong credentials\": [\n \"Credenciales incorrectas\"\n ],\n \"Conversion is disabled\": [\n \"La conversi\u00F3n est\u00E1 deshabilitada\"\n ],\n \"Config cashout\": [\n \"Configurar egreso\"\n ],\n \"Config cashin\": [\n \"Configurar ingreso\"\n ],\n \"Bad ratios\": [\n \"Tasas incorrectas\"\n ],\n \"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.\": [\n \"Una de las tasas debe ser mayor o igual a 1 y la otra debe ser menor o igual a 1.\"\n ],\n \"Initial amount\": [\n \"Monto inicial\"\n ],\n \"Use it to test how the conversion will affect the amount.\": [\n \"Usalo para probar c\u00F3mo la conversi\u00F3n afectar\u00E1 el monto.\"\n ],\n \"Sending to this bank\": [\n \"Enviando a este banco\"\n ],\n \"Converted\": [\n \"Convertido\"\n ],\n \"Cashin after fee\": [\n \"Ingreso despu\u00E9s de la comisi\u00F3n\"\n ],\n \"Sending from this bank\": [\n \"Enviando desde este banco\"\n ],\n \"Cashout after fee\": [\n \"Egreso despu\u00E9s de la comisi\u00F3n\"\n ],\n \"Bad configuration\": [\n \"Configuraci\u00F3n incorrecta\"\n ],\n \"This configuration allows users to cash out more of what has been cashed in.\": [\n \"Esta configuraci\u00F3n permite a los usuarios retirar m\u00E1s de lo que ingresaron.\"\n ],\n \"Update\": [\n \"Actualizar\"\n ],\n \"Rnvalid\": [\n \"Inv\u00E1lido\"\n ],\n \"Must be > 0\": [\n \"Debe ser mayor que 0\"\n ],\n \"Minimum amount\": [\n \"Monto m\u00EDnimo\"\n ],\n \"Only cashout operation above this threshold will be allowed.\": [\n \"Solo se permitir\u00E1n operaciones de egreso por encima de este umbral.\"\n ],\n \"Ratio\": [\n \"Tasa\"\n ],\n \"Conversion ratio between currencies\": [\n \"Tasa de conversi\u00F3n entre monedas\"\n ],\n \"Example conversion\": [\n \"Ejemplo de conversi\u00F3n\"\n ],\n \"1 %1$s will be converted into %2$s %3$s\": [\n \"1 %1$s se convertir\u00E1 en %2$s %3$s\"\n ],\n \"Tiny amount\": [\n \"Monto m\u00EDnimo de redondeo\"\n ],\n \"Rounding mode\": [\n \"Modo de redondeo\"\n ],\n \"Zero\": [\n \"Hacia cero\"\n ],\n \"Amount will be round below to the largest possible value smaller than the input.\": [\n \"El monto se redondear\u00E1 hacia abajo al mayor valor posible menor que el ingresado.\"\n ],\n \"Up\": [\n \"Hacia arriba\"\n ],\n \"Amount will be round up to the smallest possible value larger than the input.\": [\n \"El monto se redondear\u00E1 hacia arriba al menor valor posible mayor que el ingresado.\"\n ],\n \"Nearest\": [\n \"Al m\u00E1s cercano\"\n ],\n \"Amount will be round to the closest possible value.\": [\n \"El monto se redondear\u00E1 al valor m\u00E1s cercano posible.\"\n ],\n \"If none specified the fallback value is \\\"%1$s \\\".\": [\n \"Si no se especifica ninguno, el valor por defecto es \\\"%1$s\\\".\"\n ],\n \"Examples\": [\n \"Ejemplos\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.1\": [\n \"Redondeo de un monto de 1,24 con valor de redondeo 0,1\"\n ],\n \"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.\": [\n \"Con un valor de redondeo de 0,1, los valores m\u00E1s cercanos a 1,24 son: 1,1; 1,2; 1,3; 1,4.\"\n ],\n \"With the \\\"zero\\\" mode the value will be rounded to 1.2\": [\n \"Con el modo \\\"hacia cero\\\" el valor se redondear\u00E1 a 1,2\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.2\": [\n \"Con el modo \\\"al m\u00E1s cercano\\\" el valor se redondear\u00E1 a 1,2\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.3\": [\n \"Con el modo \\\"hacia arriba\\\" el valor se redondear\u00E1 a 1,3\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.1\": [\n \"Redondeo de un monto de 1,26 con valor de redondeo 0,1\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.3\": [\n \"Con el modo \\\"al m\u00E1s cercano\\\" el valor se redondear\u00E1 a 1,3\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.3\": [\n \"Redondeo de un monto de 1,24 con valor de redondeo 0,3\"\n ],\n \"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.\": [\n \"Con un valor de redondeo de 0,3, los valores m\u00E1s cercanos a 1,24 son: 0,9; 1,2; 1,5; 1,8.\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.5\": [\n \"Con el modo \\\"hacia arriba\\\" el valor se redondear\u00E1 a 1,5\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.3\": [\n \"Redondeo de un monto de 1,26 con valor de redondeo 0,3\"\n ],\n \"Amount to be deducted before amount is credited.\": [\n \"Monto a deducir antes de acreditar el importe.\"\n ],\n \"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"La conversi\u00F3n debe estar habilitada en la configuraci\u00F3n, y la tasa de conversi\u00F3n debe estar inicializada con comisi\u00F3n(es), tasas y modo de redondeo.\"\n ],\n \"delete conversion rate class\": [\n \"Eliminar tasa de conversi\u00F3n\"\n ],\n \"Unauthorized\": [\n \"No autorizado\"\n ],\n \"Forbidden\": [\n \"Prohibido\"\n ],\n \"NotFound\": [\n \"No encontrado\"\n ],\n \"NotImplemented\": [\n \"No implementado\"\n ],\n \"update conversion rate class\": [\n \"Crear clase de tasa de conversi\u00F3n\"\n ],\n \"Not Found\": [\n \"No encontrado\"\n ],\n \"Not implemented\": [\n \"No implementado\"\n ],\n \"The name of the conversion is already used.\": [\n \"El nombre de la conversi\u00F3n ya est\u00E1 en uso.\"\n ],\n \"Conversion rate class\": [\n \"Clase de tasa de conversi\u00F3n\"\n ],\n \"Accounts\": [\n \"Cuentas\"\n ],\n \"Test\": [\n \"Probar\"\n ],\n \"Users\": [\n \"Usuarios\"\n ],\n \"Can't remove the conversion rate class\": [\n \"No se puede eliminar la clase de tasa de conversi\u00F3n\"\n ],\n \"There are some user associated to this class. You need to remove them first.\": [\n \"Hay usuarios asociados a esta clase. Primero ten\u00E9s que eliminarlos.\"\n ],\n \"You are going to remove the conversion rate class\": [\n \"Est\u00E1s por eliminar la clase de tasa de conversi\u00F3n\"\n ],\n \"This step can't be undone.\": [\n \"Este paso no puede deshacerse.\"\n ],\n \"Filters\": [\n \"Filtros\"\n ],\n \"Show from other classes\": [\n \"Mostrar de otras clases\"\n ],\n \"Account\": [\n \"Cuenta\"\n ],\n \"Group ID\": [\n \"ID de grupo\"\n ],\n \"No users in this conversion rate class\": [\n \"No hay usuarios en esta clase de tasa de conversi\u00F3n\"\n ],\n \"Class\": [\n \"Clase\"\n ],\n \"Action\": [\n \"Acci\u00F3n\"\n ],\n \"Remove\": [\n \"Eliminar\"\n ],\n \"Add\": [\n \"Agregar\"\n ],\n \"Conversion rate name\": [\n \"Nombre de la tasa de conversi\u00F3n\"\n ],\n \"Short description of the class\": [\n \"Descripci\u00F3n breve de la clase\"\n ],\n \"create conversion rate class\": [\n \"Crear clase de tasa de conversi\u00F3n\"\n ],\n \"Conversion rate class created.\": [\n \"Clase de tasa de conversi\u00F3n creada.\"\n ],\n \"The rights to change the account are not sufficient\": [\n \"Los permisos para modificar la cuenta no son suficientes\"\n ],\n \"New conversion rate class\": [\n \"Nueva clase de tasa de conversi\u00F3n\"\n ],\n \"Create\": [\n \"Crear\"\n ],\n \"History of public accounts\": [\n \"Historial de cuentas p\u00FAblicas\"\n ],\n \"Make a wire transfer\": [\n \"Realizar una transferencia bancaria\"\n ],\n \"Scan the QR code below to start the withdrawal.\": [\n \"Escane\u00E1 el c\u00F3digo QR de abajo para iniciar la extracci\u00F3n.\"\n ],\n \"Operation aborted\": [\n \"Operaci\u00F3n cancelada\"\n ],\n \"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.\": [\n \"La transferencia bancaria a la cuenta del Proveedor de Servicios de Pago fue cancelada desde otro lugar; tu saldo no fue afectado.\"\n ],\n \"Go to your wallet now\": [\n \"Ir a tu billetera ahora\"\n ],\n \"The operation is marked as selected, but a process during the withdrawal failed\": [\n \"La operaci\u00F3n est\u00E1 marcada como seleccionada, pero un proceso durante la extracci\u00F3n fall\u00F3\"\n ],\n \"A withdrawal reserve ID was not found and no account has been selected.\": [\n \"No se encontr\u00F3 un ID de reserva de extracci\u00F3n y no se seleccion\u00F3 ninguna cuenta.\"\n ],\n \"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.\": [\n \"Hay un ID de reserva de extracci\u00F3n pero no se seleccion\u00F3 ninguna cuenta o la cuenta seleccionada es inv\u00E1lida.\"\n ],\n \"The account was selected, but no withdrawal reserve ID was found.\": [\n \"La cuenta fue seleccionada, pero no se encontr\u00F3 el ID de reserva de extracci\u00F3n.\"\n ],\n \"Operation not found\": [\n \"Operaci\u00F3n no encontrada\"\n ],\n \"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.\": [\n \"Este proceso no es conocido por el servidor. El ID de proceso es incorrecto o el servidor elimin\u00F3 la informaci\u00F3n del proceso antes de que llegara aqu\u00ED.\"\n ],\n \"Continue to dashboard\": [\n \"Ir al panel principal\"\n ],\n \"The Withdrawal URI is not valid\": [\n \"El URI de extracci\u00F3n no es v\u00E1lido\"\n ],\n \"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.\": [\n \"El egreso debe habilitarse en la configuraci\u00F3n y la tasa de conversi\u00F3n debe estar inicializada con comisi\u00F3n, tasa y modo de redondeo.\"\n ],\n \"Latest cashouts\": [\n \"\u00DAltimos egresos\"\n ],\n \"Created\": [\n \"Creado\"\n ],\n \"Total debit\": [\n \"D\u00E9bito total\"\n ],\n \"Total credit\": [\n \"Cr\u00E9dito total\"\n ],\n \"Cashout for account %1$s\": [\n \"Egreso para la cuenta %1$s\"\n ],\n \"Invalid email format\": [\n \"Formato de email inv\u00E1lido\"\n ],\n \"Should start with +\": [\n \"Debe comenzar con +\"\n ],\n \"A phone number consists of numbers only\": [\n \"Un n\u00FAmero de tel\u00E9fono solo puede contener n\u00FAmeros\"\n ],\n \"Account ID for authentication\": [\n \"ID de cuenta para autenticaci\u00F3n\"\n ],\n \"Name of the account holder\": [\n \"Nombre del titular de la cuenta\"\n ],\n \"Internal account\": [\n \"Cuenta interna\"\n ],\n \"If this field is empty, a random account ID will be assigned\": [\n \"Si este campo est\u00E1 vac\u00EDo, se asignar\u00E1 un ID de cuenta aleatorio\"\n ],\n \"You can copy and share this IBAN number in order to receive wire transfers to your bank account\": [\n \"Pod\u00E9s copiar y compartir este n\u00FAmero IBAN para recibir transferencias bancarias en tu cuenta\"\n ],\n \"Email\": [\n \"Correo electr\u00F3nico\"\n ],\n \"To be used when second factor authentication is enabled\": [\n \"Se usa cuando la autenticaci\u00F3n de segundo factor est\u00E1 habilitada\"\n ],\n \"Phone\": [\n \"Tel\u00E9fono\"\n ],\n \"Enable second factor authentication\": [\n \"Habilitar autenticaci\u00F3n de segundo factor\"\n ],\n \"Using email\": [\n \"Usando correo electr\u00F3nico\"\n ],\n \"Add an email in your profile to enable this option\": [\n \"Agreg\u00E1 un correo electr\u00F3nico en tu perfil para habilitar esta opci\u00F3n\"\n ],\n \"Using SMS\": [\n \"Usando SMS\"\n ],\n \"Add a phone number in your profile to enable this option\": [\n \"Agreg\u00E1 un n\u00FAmero de tel\u00E9fono en tu perfil para habilitar esta opci\u00F3n\"\n ],\n \"Cashout account\": [\n \"Cuenta de egreso\"\n ],\n \"External account number where the money is going to be sent when doing cashouts\": [\n \"N\u00FAmero de cuenta externa a la que se enviar\u00E1 el dinero al realizar egresos\"\n ],\n \"Max debt\": [\n \"Deuda m\u00E1xima\"\n ],\n \"How much the balance can go below zero.\": [\n \"Cu\u00E1nto puede quedar el saldo por debajo de cero.\"\n ],\n \"Is this account public?\": [\n \"\u00BFEsta cuenta es p\u00FAblica?\"\n ],\n \"Public accounts have their balance publicly accessible\": [\n \"Las cuentas p\u00FAblicas tienen su saldo accesible para todos\"\n ],\n \"Does this account belong to a Payment Service Provider?\": [\n \"\u00BFEsta cuenta pertenece a un Proveedor de Servicios de Pago?\"\n ],\n \"update account\": [\n \"Actualizar cuenta\"\n ],\n \"Account updated\": [\n \"Cuenta actualizada\"\n ],\n \"The username was not found\": [\n \"El nombre de usuario no fue encontrado\"\n ],\n \"You can't change the legal name, please contact the your account administrator.\": [\n \"No pod\u00E9s cambiar el nombre legal; por favor contact\u00E1 al administrador de tu cuenta.\"\n ],\n \"You can't change the debt limit, please contact the your account administrator.\": [\n \"No pod\u00E9s cambiar el l\u00EDmite de deuda; por favor contact\u00E1 al administrador de tu cuenta.\"\n ],\n \"You can't change the cashout address, please contact the your account administrator.\": [\n \"No pod\u00E9s cambiar la direcci\u00F3n de egreso; por favor contact\u00E1 al administrador de tu cuenta.\"\n ],\n \"Update account information.\": [\n \"Actualizar informaci\u00F3n de la cuenta.\"\n ],\n \"Account \\\"%1$s\\\"\": [\n \"Cuenta \\\"%1$s\\\"\"\n ],\n \"Removed\": [\n \"Eliminada\"\n ],\n \"This account can't be used.\": [\n \"Esta cuenta no puede usarse.\"\n ],\n \"Change details\": [\n \"Cambiar datos\"\n ],\n \"Merchant integration\": [\n \"Integraci\u00F3n con comercio\"\n ],\n \"Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the \\\"import\\\" button in the \\\"bank account\\\" section.\": [\n \"Us\u00E1 esta informaci\u00F3n para vincular tu cuenta de Taler Merchant Backoffice con la cuenta bancaria actual. Pod\u00E9s comenzar copiando los valores, luego ir a tu proveedor de backoffice de comercio, iniciar sesi\u00F3n y buscar el bot\u00F3n \\\"importar\\\" en la secci\u00F3n \\\"cuenta bancaria\\\".\"\n ],\n \"Account type\": [\n \"Tipo de cuenta\"\n ],\n \"Method to use for wire transfer.\": [\n \"M\u00E9todo a usar para la transferencia bancaria.\"\n ],\n \"IBAN\": [\n \"IBAN\"\n ],\n \"International Bank Account Number.\": [\n \"N\u00FAmero de Cuenta Bancaria Internacional.\"\n ],\n \"Account name\": [\n \"Nombre de la cuenta\"\n ],\n \"Bank host where the service is located.\": [\n \"Host bancario donde se encuentra el servicio.\"\n ],\n \"Bank account identifier for wire transfers.\": [\n \"Identificador de cuenta bancaria para transferencias.\"\n ],\n \"Address\": [\n \"Direcci\u00F3n\"\n ],\n \"Owner's name\": [\n \"Nombre del titular\"\n ],\n \"Legal name of the person holding the account.\": [\n \"Nombre legal de la persona titular de la cuenta.\"\n ],\n \"Account info URL\": [\n \"URL de informaci\u00F3n de la cuenta\"\n ],\n \"From where the merchant can download information about incoming wire transfers to this account.\": [\n \"Desde donde el comercio puede descargar informaci\u00F3n sobre las transferencias bancarias entrantes a esta cuenta.\"\n ],\n \"Repeated password doesn't match\": [\n \"La contrase\u00F1a repetida no coincide\"\n ],\n \"update password\": [\n \"Actualizar contrase\u00F1a\"\n ],\n \"Password changed\": [\n \"Contrase\u00F1a cambiada\"\n ],\n \"Not authorized to change the password, maybe the session is invalid.\": [\n \"No est\u00E1s autorizado a cambiar la contrase\u00F1a, quiz\u00E1s la sesi\u00F3n es inv\u00E1lida.\"\n ],\n \"You need to provide the old password. If you don't have it contact your account administrator.\": [\n \"Necesit\u00E1s ingresar la contrase\u00F1a anterior. Si no la ten\u00E9s, contact\u00E1 al administrador de tu cuenta.\"\n ],\n \"Your current password doesn't match, can't change to a new password.\": [\n \"Tu contrase\u00F1a actual no coincide, no se puede cambiar a una nueva.\"\n ],\n \"You don't have the rights to change the password.\": [\n \"No ten\u00E9s permisos para cambiar la contrase\u00F1a.\"\n ],\n \"Update account password.\": [\n \"Actualizar contrase\u00F1a de la cuenta.\"\n ],\n \"Update password\": [\n \"Actualizar contrase\u00F1a\"\n ],\n \"Current password\": [\n \"Contrase\u00F1a actual\"\n ],\n \"Your current password, for security\": [\n \"Tu contrase\u00F1a actual, por seguridad\"\n ],\n \"New password\": [\n \"Nueva contrase\u00F1a\"\n ],\n \"Type it again\": [\n \"Escribila de nuevo\"\n ],\n \"Repeat the same password\": [\n \"Repet\u00ED la misma contrase\u00F1a\"\n ],\n \"Change\": [\n \"Cambiar\"\n ],\n \"Create account\": [\n \"Crear cuenta\"\n ],\n \"Actions\": [\n \"Acciones\"\n ],\n \"Unknown\": [\n \"Desconocido\"\n ],\n \"Change password\": [\n \"Cambiar contrase\u00F1a\"\n ],\n \"Querying for the current stats failed\": [\n \"Fall\u00F3 la consulta de estad\u00EDsticas actuales\"\n ],\n \"The request parameters are wrong\": [\n \"Los par\u00E1metros del pedido son incorrectos\"\n ],\n \"The user is unauthorized\": [\n \"El usuario no est\u00E1 autorizado\"\n ],\n \"Querying for the previous stats failed\": [\n \"Fall\u00F3 la consulta de estad\u00EDsticas anteriores\"\n ],\n \"Transaction volume report\": [\n \"Reporte de volumen de transacciones\"\n ],\n \"Last hour\": [\n \"\u00DAltima hora\"\n ],\n \"Previous day\": [\n \"D\u00EDa anterior\"\n ],\n \"Last month\": [\n \"\u00DAltimo mes\"\n ],\n \"Last year\": [\n \"\u00DAltimo a\u00F1o\"\n ],\n \"Last Year\": [\n \"\u00DAltimo a\u00F1o\"\n ],\n \"Trading volume from %1$s to %2$s\": [\n \"Volumen de operaciones del %1$s al %2$s\"\n ],\n \"Transferred from an external account to an account in this bank.\": [\n \"Transferido desde una cuenta externa a una cuenta en este banco.\"\n ],\n \"Transferred from an account in this bank to an external account.\": [\n \"Transferido desde una cuenta de este banco a una cuenta externa.\"\n ],\n \"Payin\": [\n \"Env\u00EDos de dinero\"\n ],\n \"Transferred from an account to a Taler exchange.\": [\n \"Transferido desde una cuenta a un exchange Taler.\"\n ],\n \"Payout\": [\n \"Recibos de dinero\"\n ],\n \"Transferred from a Taler exchange to another account.\": [\n \"Transferido desde un exchange Taler a otra cuenta.\"\n ],\n \"Download stats as CSV\": [\n \"Descargar estad\u00EDsticas en CSV\"\n ],\n \"previous\": [\n \"anterior\"\n ],\n \"Decreased by\": [\n \"Disminuy\u00F3 en\"\n ],\n \"Increased by\": [\n \"Aument\u00F3 en\"\n ],\n \"create account\": [\n \"Crear cuenta\"\n ],\n \"Account created with password \\\"%1$s\\\".\": [\n \"Cuenta creada con la contrase\u00F1a \\\"%1$s\\\".\"\n ],\n \"Server replied that phone or email is invalid\": [\n \"El servidor respondi\u00F3 que el tel\u00E9fono o el correo electr\u00F3nico son inv\u00E1lidos\"\n ],\n \"The rights to perform the operation are not sufficient\": [\n \"Los permisos para ejecutar la operaci\u00F3n no son suficientes\"\n ],\n \"Account username is already taken\": [\n \"El nombre de usuario de la cuenta ya est\u00E1 en uso\"\n ],\n \"Account ID is already taken\": [\n \"El ID de cuenta ya est\u00E1 en uso\"\n ],\n \"Bank ran out of bonus credit.\": [\n \"El banco se qued\u00F3 sin cr\u00E9dito de bonificaci\u00F3n.\"\n ],\n \"Account username can't be used because is reserved\": [\n \"El nombre de usuario de la cuenta no puede usarse porque est\u00E1 reservado\"\n ],\n \"Can't create accounts\": [\n \"No se pueden crear cuentas\"\n ],\n \"Only system admin can create accounts.\": [\n \"Solo el administrador del sistema puede crear cuentas.\"\n ],\n \"New bank account\": [\n \"Nueva cuenta bancaria\"\n ],\n \"download statistics\": [\n \"Descargar estad\u00EDsticas\"\n ],\n \"only admin can download stats\": [\n \"Solo el administrador puede descargar estad\u00EDsticas\"\n ],\n \"Download bank stats\": [\n \"Descargar estad\u00EDsticas del banco\"\n ],\n \"Include hour metric\": [\n \"Incluir m\u00E9trica por hora\"\n ],\n \"Include day metric\": [\n \"Incluir m\u00E9trica diaria\"\n ],\n \"Include month metric\": [\n \"Incluir m\u00E9trica mensual\"\n ],\n \"Include year metric\": [\n \"Incluir m\u00E9trica anual\"\n ],\n \"Include table header\": [\n \"Incluir encabezado de tabla\"\n ],\n \"Add previous metric for compare\": [\n \"Agregar m\u00E9trica anterior para comparar\"\n ],\n \"Fail on first error\": [\n \"Detener en el primer error\"\n ],\n \"Download\": [\n \"Descargar\"\n ],\n \"downloading... %1$s\": [\n \"descargando... %1$s\"\n ],\n \"Download completed\": [\n \"Descarga completada\"\n ],\n \"Click here to save the file in your computer.\": [\n \"Hac\u00E9 clic ac\u00E1 para guardar el archivo en tu computadora.\"\n ],\n \"there was an error reading the balance\": [\n \"hubo un error al leer el saldo\"\n ],\n \"Can't delete the account\": [\n \"No se puede eliminar la cuenta\"\n ],\n \"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.\": [\n \"La cuenta no puede eliminarse mientras tenga saldo. Primero asegurate de que el titular realice un egreso completo.\"\n ],\n \"Name doesn't match\": [\n \"El nombre no coincide\"\n ],\n \"delete account\": [\n \"Eliminar cuenta\"\n ],\n \"Account removed\": [\n \"Cuenta eliminada\"\n ],\n \"No enough permission to delete the account.\": [\n \"No ten\u00E9s permisos suficientes para eliminar la cuenta.\"\n ],\n \"The username was not found.\": [\n \"El nombre de usuario no fue encontrado.\"\n ],\n \"Can't delete a reserved username.\": [\n \"No se puede eliminar un nombre de usuario reservado.\"\n ],\n \"Can't delete an account with balance different than zero.\": [\n \"No se puede eliminar una cuenta con saldo distinto de cero.\"\n ],\n \"Remove account.\": [\n \"Eliminar cuenta.\"\n ],\n \"You are going to remove the account\": [\n \"Est\u00E1s por eliminar la cuenta\"\n ],\n \"Deleting account \\\"%1$s\\\"\": [\n \"Eliminando la cuenta \\\"%1$s\\\"\"\n ],\n \"Verification\": [\n \"Verificaci\u00F3n\"\n ],\n \"Enter the account name that is going to be deleted\": [\n \"Ingres\u00E1 el nombre de la cuenta que va a ser eliminada\"\n ],\n \"Cashout id should be a number\": [\n \"El ID de egreso debe ser un n\u00FAmero\"\n ],\n \"This cashout not found. Maybe already aborted.\": [\n \"Este egreso no fue encontrado. Quiz\u00E1s ya fue cancelado.\"\n ],\n \"Cashout detail\": [\n \"Detalle del egreso\"\n ],\n \"Debited\": [\n \"Debitado\"\n ],\n \"Transferred\": [\n \"Transferido\"\n ],\n \"You have no permission to this account.\": [\n \"No ten\u00E9s permisos para acceder a esta cuenta.\"\n ],\n \"This account is locked. If you have a active session you can change the password or contact the administrator.\": [\n \"Esta cuenta est\u00E1 bloqueada. Si ten\u00E9s una sesi\u00F3n activa pod\u00E9s cambiar la contrase\u00F1a o contactar al administrador.\"\n ],\n \"New web session\": [\n \"Nueva sesi\u00F3n web\"\n ],\n \"Welcome to %1$s!\": [\n \"\u00A1Hola %1$s!\"\n ]\n }\n },\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n != 1;\",\n \"lang\": \"es_AR\",\n \"completeness\": 99\n};\n\nstrings['de'] = {\n \"locale_data\": {\n \"messages\": {\n \"\": {\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n != 1;\",\n \"lang\": \"de\"\n },\n \"An IBAN consists of capital letters and numbers only\": [\n \"Eine IBAN besteht nur aus Gro\u00DFbuchstaben und Zahlen\"\n ],\n \"IBAN numbers have more that 4 digits\": [\n \"Eine IBAN besteht normalerweise aus mehr als 4 Ziffern\"\n ],\n \"IBAN numbers have less that 34 digits\": [\n \"Eine IBAN besteht normalerweise aus weniger als 34 Ziffern\"\n ],\n \"IBAN country code not found\": [\n \"Der IBAN-L\u00E4ndercode wurde nicht gefunden\"\n ],\n \"IBAN number is not valid, checksum is wrong\": [\n \"Die IBAN-Nummer ist ung\u00FCltig, die Pr\u00FCfsumme ist falsch\"\n ],\n \"Use letters, numbers or any of these characters: - . _ ~\": [\n \"Verwenden Sie nur Buchstaben und Zahlen sowie als Sonderzeichen - . _ ~\"\n ],\n \"Required\": [\n \"Erforderlich\"\n ],\n \"confirm MFA challenge\": [\n \"\"\n ],\n \"Unknown challenge.\": [\n \"\"\n ],\n \"Failed to validate the verification code.\": [\n \"\"\n ],\n \"Too many challenges are active right now, you must wait or confirm current challenges.\": [\n \"\"\n ],\n \"Wrong authentication number.\": [\n \"Falsche Authentifizierung.\"\n ],\n \"Expired challenge.\": [\n \"\"\n ],\n \"Submit the transmitted code number.\": [\n \"\"\n ],\n \"The verification code sent to the email address starting with %1$s\": [\n \"\"\n ],\n \"The verification code sent to the phone number ending with %1$s\": [\n \"\"\n ],\n \"Code\": [\n \"\"\n ],\n \"Username of the account\": [\n \"Nutzername des Kontos\"\n ],\n \"It will expired at %1$s\": [\n \"Ende der G\u00FCltigkeit %1$s\"\n ],\n \"The challenge is expired and can't be solved but you can go back and create a new challenge.\": [\n \"Das Pr\u00FCfverfahren zur gesicherten Anmeldung ist abgelaufen und kann nicht mehr verwendet werden, es ist jedoch m\u00F6glich, ein neues Pr\u00FCfverfahren anzufordern (bitte gehen Sie im Browser einen Schritt zur\u00FCck).\"\n ],\n \"Back\": [\n \"Zur\u00FCck\"\n ],\n \"Verify\": [\n \"Pr\u00FCfen\"\n ],\n \"send MFA challenge\": [\n \"\"\n ],\n \"Failed to send the verification code.\": [\n \"Das Versenden des Best\u00E4tigungscodes hat nicht funktioniert.\"\n ],\n \"The request was valid, but the server is refusing action.\": [\n \"Die Anfrage war g\u00FCltig, aber der Server verweigert die Bearbeitung.\"\n ],\n \"The backend is not aware of the specified MFA challenge.\": [\n \"Dieser Anwendung ist die angegebene Multi-Faktor-\u00DCberpr\u00FCfung nicht bekannt.\"\n ],\n \"It is too early to request another transmission of the challenge.\": [\n \"Es muss noch gewartet werden, um eine weitere \u00DCbertragung des \u00DCberpr\u00FCfungscodes zu verlangen.\"\n ],\n \"Code transmission failed.\": [\n \"Die Code-\u00DCbertragung ist fehlgeschlagen.\"\n ],\n \"select challenge\": [\n \"\"\n ],\n \"Multi-factor authentication required\": [\n \"Authentifizierung erforderlich\"\n ],\n \"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.\": [\n \"Dieser Vorgang wird durch eine Zwei-Faktor-Authentifizierung gesch\u00FCtzt. Um ihn abschlie\u00DFen zu k\u00F6nnen, m\u00FCssen wir Ihre Identit\u00E4t durch das von Ihnen gew\u00E4hlte Authentifizierungsverfahren \u00FCberpr\u00FCfen.\"\n ],\n \"The next challenge needs to be completed to confirm the operation.\": [\n \"Es besteht keine ausreichende Berechtigung, um den Vorgang abzuschlie\u00DFen.\"\n ],\n \"All the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"One of the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"To an phone ending with \\\"%1$s\\\"\": [\n \"\"\n ],\n \"To an email starting with \\\" %1$s\\\"\": [\n \"\"\n ],\n \"I have a code\": [\n \"Ich habe bereits einen g\u00FCltigen Best\u00E4tigungscode\"\n ],\n \"Send me a message\": [\n \"Best\u00E4tigungscode zusenden\"\n ],\n \"You have to wait until %1$s to send a new code.\": [\n \"Sie m\u00FCssen bis %1$s warten, damit ein neuer Best\u00E4tigungscode gesendet werden kann.\"\n ],\n \"Cancel\": [\n \"Abbrechen\"\n ],\n \"Complete\": [\n \"Abschliessen\"\n ],\n \"Unable to create a cashout\": [\n \"Es war nicht m\u00F6glich, eine Einzahlung auszuf\u00FChren\"\n ],\n \"The bank configuration does not support cashout operations.\": [\n \"Die Konfiguration der Bankverbindung unterst\u00FCtzt keine Einzahlungen.\"\n ],\n \"Close\": [\n \"Schlie\u00DFen\"\n ],\n \"Cashout is disabled\": [\n \"Einzahlungen aufs Konto sind deaktiviert\"\n ],\n \"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"In den Einstellungen m\u00FCssen die Einzahlungen aufs Konto aktiviert und der Umrechnungskurs einschlie\u00DFlich aller Geb\u00FChren, Kurse und einem Rundungsverfahren initialisiert worden sein.\"\n ],\n \"calculate conversion fee\": [\n \"Beispiel einer W\u00E4hrungsumrechnung\"\n ],\n \"The server didn't understand the request.\": [\n \"Der Server unterst\u00FCtzt nicht die aktuell gew\u00E4hlte TAN-Methode.\"\n ],\n \"The amount is too small\": [\n \"Das Passwort ist zu lang.\"\n ],\n \"Conversion is not implemented.\": [\n \"Umrechnungen sind deaktiviert\"\n ],\n \"At least debit or credit needs to be provided\": [\n \"\"\n ],\n \"The amount is malfored\": [\n \"Diese Konto-ID ist bereits vergeben.\"\n ],\n \"The currency is not supported\": [\n \"Das gew\u00E4hlte Authentifizierungsverfahren wird nicht unterst\u00FCtzt.\"\n ],\n \"Invalid\": [\n \"Ung\u00FCltig\"\n ],\n \"Amount needs to be higher\": [\n \"Es muss ein h\u00F6herer Betrag gew\u00E4hlt werden\"\n ],\n \"Balance is not enough\": [\n \"Das Guthaben reicht nicht aus\"\n ],\n \"It is not possible to cashout less than %1$s: %2$s\": [\n \"Es ist nicht m\u00F6glich, einen geringeren Betrag als %1$s: %2$s einzuzahlen\"\n ],\n \"The total transfer to the destination will be zero\": [\n \"Der zu \u00FCbertragende Gesamtbetrag betr\u00E4gt Null\"\n ],\n \"create cashout\": [\n \"Konto anlegen\"\n ],\n \"Cashout created\": [\n \"Die Einzahlung wurde erstellt\"\n ],\n \"Second factor authentication required.\": [\n \"Es ist die Eingabe einer weiteren Information erforderlich (zweiter Faktor der Anmeldeberechtigung).\"\n ],\n \"Account not found\": [\n \"Konto nicht gefunden\"\n ],\n \"Duplicated request detected, check if the operation succeeded or try again.\": [\n \"Eine gleichartige Anfrage wurde bereits gestellt, bitte \u00FCberpr\u00FCfen Sie den Vorgang oder versuchen Sie es erneut.\"\n ],\n \"The conversion rate was applied incorrectly\": [\n \"Der Umrechnungskurs wurde fehlerhaft angewendet\"\n ],\n \"The account does not have sufficient funds\": [\n \"Das Konto verf\u00FCgt \u00FCber kein ausreichendes Guthaben\"\n ],\n \"Missing cashout URI in the profile\": [\n \"Die Einzahlungs-URI dieses Profils fehlt\"\n ],\n \"The amount is below the minimum amount permitted.\": [\n \"Der Betrag ist unterhalb des zul\u00E4ssigen Minimums.\"\n ],\n \"Sending the confirmation message failed, retry later or contact the administrator.\": [\n \"Der Versand der Best\u00E4tigung ist fehlgeschlagen, versuchen Sie den Vorgang bittesp\u00E4ter erneut oder kontaktieren Sie den Administrator.\"\n ],\n \"The server doesn't support the current TAN channel.\": [\n \"Der Server unterst\u00FCtzt nicht die aktuell gew\u00E4hlte TAN-Methode.\"\n ],\n \"Create cashout.\": [\n \"Konto anlegen\"\n ],\n \"Cashout\": [\n \"Auszahlung (Cashout)\"\n ],\n \"Conversion rate\": [\n \"Umrechnungskurs\"\n ],\n \"Balance\": [\n \"Salden\"\n ],\n \"Fee\": [\n \"Geb\u00FChr\"\n ],\n \"To account\": [\n \"Auf Bankkonto\"\n ],\n \"Legal name\": [\n \"Offizieller Name des Empf\u00E4ngers (wirtschaftlich Berechtigter des empfangenden Bankkontos)\"\n ],\n \"If this name doesn't match the account holder's name, your transaction may fail.\": [\n \"Falls dieser Name nicht mit dem des wirtschaftlich Berechtigten des Bankkontos \u00FCbereinstimmt, k\u00F6nnte Ihre \u00DCberweisung fehlschlagen.\"\n ],\n \"Unable to cashout\": [\n \"Es war nicht m\u00F6glich, eine Einzahlung auszuf\u00FChren\"\n ],\n \"Before being able to cashout to a bank account, you need to complete your profile\": [\n \"Bevor Sie auf ein Bankkonto einzahlen k\u00F6nnen, m\u00FCssen Sie Ihr Profil vervollst\u00E4ndigen\"\n ],\n \"Transfer subject\": [\n \"Buchungsvermerk der \u00DCberweisung\"\n ],\n \"Currency\": [\n \"W\u00E4hrung\"\n ],\n \"Send %1$s\": [\n \"%1$s \u00FCbertragen\"\n ],\n \"Receive %1$s\": [\n \"%1$s erhalten\"\n ],\n \"Amount\": [\n \"Betrag\"\n ],\n \"Total cost\": [\n \"Gesamte Geb\u00FChren\"\n ],\n \"Balance left\": [\n \"Verbleibendes Guthaben\"\n ],\n \"Before fee\": [\n \"Vor Abzug von Geb\u00FChren\"\n ],\n \"Total cashout transfer\": [\n \"Gesamter Einzahlungsbetrag\"\n ],\n \"Not valid\": [\n \"Nicht g\u00FCltig\"\n ],\n \"Does not follow the pattern\": [\n \"Weicht vom Muster ab\"\n ],\n \"send transaction\": [\n \"Es liegen noch keine Transaktionen vor.\"\n ],\n \"The wire transfer was successfully completed!\": [\n \"Die Bank\u00FCberweisung wurde erfolgreich durchgef\u00FChrt!\"\n ],\n \"The request was invalid or the payto://-URI used unacceptable features.\": [\n \"Die Anfrage war ung\u00FCltig oder die payto://-URI nutzte inakzeptable Merkmale.\"\n ],\n \"Not enough permission to complete the operation.\": [\n \"Es besteht keine ausreichende Berechtigung, um den Vorgang abzuschlie\u00DFen.\"\n ],\n \"The bank administrator cannot be the transfer creditor.\": [\n \"Der Bankbetreiber kann nicht gleichzeitig Beg\u00FCnstigter von \u00DCberweisungen sein.\"\n ],\n \"The destination account \\\"%1$s\\\" was not found.\": [\n \"Das Empf\u00E4ngerkonto \\\"%1$s\\\" wurde nicht gefunden.\"\n ],\n \"The origin and the destination of the transfer can't be the same.\": [\n \"Ursprung und Ziel des Transfers k\u00F6nnen nicht gleich sein.\"\n ],\n \"Your balance is not sufficient for the operation.\": [\n \"Das Guthaben reicht f\u00FCr den Vorgang nicht aus.\"\n ],\n \"The origin account \\\"%1$s\\\" was not found.\": [\n \"Das Ursprungskonto \\\"%1$s\\\" wurde nicht gefunden.\"\n ],\n \"The attempt to create the transaction has failed. Please try again.\": [\n \"Die Vorbereitung der Transaktion hat nicht funktioniert. Bitte versuchen Sie es erneut.\"\n ],\n \"A second factor authentication is required.\": [\n \"Dies wird verwendet, wenn die Zwei-Faktor-Authentifizierung aktiviert ist\"\n ],\n \"Confirm wire transfer.\": [\n \"Bank\u00FCberweisung durchf\u00FChren\"\n ],\n \"Input wire transfer detail\": [\n \"\u00DCberweisungsdetails einf\u00FCgen\"\n ],\n \"Using a form\": [\n \"Mithilfe eines Formulars\"\n ],\n \"A special URI that specifies the amount to be transferred and the destination account.\": [\n \"Uniform Resource Identifier (URI) zum Bestimmen des Werts, der an das Empf\u00E4ngerkonto \u00FCbertragen wird.\"\n ],\n \"QR code\": [\n \"QR-Code\"\n ],\n \"If your device has a camera, you can import a payto:// URI from a QR code.\": [\n \"Wenn Ihr Ger\u00E4t \u00FCber eine Kamera verf\u00FCgt, k\u00F6nnen Sie automatisch eine payto-Zahlungsanweisung (payto://-URI) aus einem QR-Code erstellen.\"\n ],\n \"Recipient\": [\n \"Empf\u00E4ngerkonto\"\n ],\n \"ID of the recipient's account\": [\n \"ID des Empf\u00E4ngerkontos\"\n ],\n \"username\": [\n \"Name des Nutzers\"\n ],\n \"IBAN of the recipient's account\": [\n \"IBAN des Empf\u00E4ngerkontos\"\n ],\n \"Subject\": [\n \"Buchungsvermerk\"\n ],\n \"Some text to identify the transfer\": [\n \"Eine Zeichenkette, um die \u00DCberweisung eindeutig zu benennen\"\n ],\n \"Amount to transfer\": [\n \"Zu \u00FCberweisender Betrag\"\n ],\n \"Payto URI:\": [\n \"payto-URI:\"\n ],\n \"Uniform resource identifier of the target account\": [\n \"URI (Uniform Resource Identifier) des Empf\u00E4ngerkontos\"\n ],\n \"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://x-taler-bank/[Bankbetreiber]/[Empf\u00E4ngerkonto]?message=[Buchungsvermerk]&amount=[%1$s:X.Y]\"\n ],\n \"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"payto://iban/[IBAN des Empf\u00E4ngers]?message=[Buchungsvermerk]&amount=[%1$s:X.Y]\"\n ],\n \"The maximum amount for a wire transfer is %1$s\": [\n \"Der H\u00F6chstbetrag f\u00FCr eine \u00DCberweisung betr\u00E4gt %1$s\"\n ],\n \"Cost\": [\n \"Kosten\"\n ],\n \"Send\": [\n \"\u00DCberweisen\"\n ],\n \"Only \\\"x-taler-bank\\\" target are supported\": [\n \"Nur \\\"x-taler-bank\\\"-Ziele werden unterst\u00FCtzt\"\n ],\n \"Only this host is allowed. Use \\\"%1$s\\\"\": [\n \"Nur dieser Bankbetreiber ist zul\u00E4ssig. Bitte verwenden Sie \\\"%1$s\\\"\"\n ],\n \"Account name is missing\": [\n \"Name oder Bezeichnung des Kontos fehlt\"\n ],\n \"Only \\\"IBAN\\\" target are supported\": [\n \"Nur IBAN-Ziele werden unterst\u00FCtzt\"\n ],\n \"Missing \\\"amount\\\" parameter to specify the amount to be transferred\": [\n \"Bitte geben Sie einen Betrag an, der \u00FCbertragen werden soll\"\n ],\n \"The \\\"amount\\\" parameter is not valid\": [\n \"Der Betrag ist nicht g\u00FCltig\"\n ],\n \"\\\"message\\\" parameters to specify a reference text for the transfer are missing\": [\n \"Es fehlen Parameter f\u00FCr einen Referenz-Buchungsvermerk der \u00DCberweisungen\"\n ],\n \"The only currency allowed is \\\"%1$s\\\"\": [\n \"Die einzig zul\u00E4ssige W\u00E4hrung ist \\\"%1$s\\\"\"\n ],\n \"You cannot transfer an amount of zero.\": [\n \"Sie k\u00F6nnen keinen Betrag \u00FCberweisen, der Null ist.\"\n ],\n \"The balance is not sufficient\": [\n \"Das Guthaben ist nicht ausreichend\"\n ],\n \"Please enter a longer subject\": [\n \"Bitte geben Sie einen l\u00E4ngeren Buchungsvermerk der \u00DCberweisung an\"\n ],\n \"Show withdrawal confirmation\": [\n \"Zeige Best\u00E4tigung der Abhebung\"\n ],\n \"Withdraw without setting amount\": [\n \"Abheben ohne festgelegten Betrag\"\n ],\n \"Hide demo hint.\": [\n \"\"\n ],\n \"Show install wallet first\": [\n \"Hilfstext: Zuerst Wallet installieren\"\n ],\n \"Currently, the bank is not accepting new registrations!\": [\n \"Im Augenblick nimmt die Bank keine Neuregistrierungen an!\"\n ],\n \"The name is missing\": [\n \"Der Nutzername fehlt\"\n ],\n \"Missing username\": [\n \"Fehlender Nutzername\"\n ],\n \"Missing password\": [\n \"Fehlendes Passwort\"\n ],\n \"The password should be longer than 8 letters\": [\n \"Das Passwort sollte l\u00E4nger als 8 Zeichen sein\"\n ],\n \"The passwords do not match\": [\n \"Die Passw\u00F6rter stimmen nicht \u00FCberein\"\n ],\n \"register new account\": [\n \"Konto anlegen\"\n ],\n \"Server replied with invalid phone or email.\": [\n \"Der Server gab an, dass Telefonnummer oder E-Mail-Adresse ung\u00FCltig seien.\"\n ],\n \"You are not authorised to create this account.\": [\n \"Sie sind nicht berechtigt, dieses Konto zu erstellen.\"\n ],\n \"Registration is disabled because the bank ran out of bonus credit.\": [\n \"Die Registrierung ist nicht m\u00F6glich, da die Bank \u00FCber kein ausreichendes Bonusguthaben verf\u00FCgt.\"\n ],\n \"That username can't be used because is reserved.\": [\n \"Dieser Nutzername kann nicht verwendet werden, da er schon reserviert ist.\"\n ],\n \"That username is already taken.\": [\n \"Dieser Nutzername ist leider bereits vergeben.\"\n ],\n \"That account ID is already taken.\": [\n \"Diese Konto-ID ist bereits vergeben.\"\n ],\n \"No information for the selected authentication channel.\": [\n \"Es sind keine Informationen f\u00FCr das gew\u00E4hlte Authentifizierungsverfahren verf\u00FCgbar.\"\n ],\n \"Authentication channel is not supported.\": [\n \"Das gew\u00E4hlte Authentifizierungsverfahren wird nicht unterst\u00FCtzt.\"\n ],\n \"Only an administrator is allowed to set the debt limit.\": [\n \"Nur ein Administrator ist befugt, die Kredith\u00F6he festzulegen.\"\n ],\n \"Only the administrator can change the conversion rate.\": [\n \"Nur der Administrator kann die geringste H\u00F6he einer Auszahlung \u00E4ndern.\"\n ],\n \"The conversion rate class doesn't exist.\": [\n \"Der Umrechnungskurs wurde fehlerhaft angewendet\"\n ],\n \"Only admin can create accounts with second factor authentication.\": [\n \"Nur der Administrator kann Konten mit Zwei-Faktor-Authentifizierung erstellen.\"\n ],\n \"The password is too short. Can't have less than 8 characters.\": [\n \"Das Passwort sollte l\u00E4nger als 8 Zeichen sein\"\n ],\n \"The password is too long. Can't have more than 64 characters.\": [\n \"Das Passwort sollte l\u00E4nger als 8 Zeichen sein\"\n ],\n \"Account registration\": [\n \"Kontoregistrierung\"\n ],\n \"Login username\": [\n \"Nutzername zum Anmelden\"\n ],\n \"account identification to login\": [\n \"\"\n ],\n \"Password\": [\n \"Passwort\"\n ],\n \"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers\": [\n \"Verwenden Sie ein starkes Passwort: Mindestens 8 Zeichen bestehend aus Kleinbuchstaben, Gro\u00DFbuchstaben, Symbolen und Zahlen und ohne \u00F6ffentlich bekannte Informationen (wie Namen, Geburtstage, Telefonnummern usw.)\"\n ],\n \"Repeat password\": [\n \"Passwort wiederholen\"\n ],\n \"Same password\": [\n \"Neues Passwort\"\n ],\n \"Full name\": [\n \"Vollst\u00E4ndiger Name\"\n ],\n \"Register\": [\n \"Registrieren\"\n ],\n \"Create a random temporary user\": [\n \"Einen zuf\u00E4lligen tempor\u00E4ren Nutzer anlegen\"\n ],\n \"logout\": [\n \"Abmelden\"\n ],\n \"login\": [\n \"\"\n ],\n \"The account has no rights to login.\": [\n \"\"\n ],\n \"The account is locked and cannot login. Contact administrator.\": [\n \"\"\n ],\n \"Wrong credentials for \\\"%1$s\\\"\": [\n \"Falsche Zugangsdaten f\u00FCr \\\"%1$s\\\"\"\n ],\n \"Account login.\": [\n \"Kontenname\"\n ],\n \"Session expired\": [\n \"Dieser Vorgang ist abgelaufen.\"\n ],\n \"Username\": [\n \"Nutzername\"\n ],\n \"identification\": [\n \"\u00DCberpr\u00FCfung\"\n ],\n \"Password of the account\": [\n \"Passwort des Kontos\"\n ],\n \"Forget\": [\n \"\"\n ],\n \"Log in\": [\n \"Anmelden\"\n ],\n \"Transactions history\": [\n \"Transaktions\u00FCbersicht\"\n ],\n \"No transactions yet.\": [\n \"Es liegen noch keine Transaktionen vor.\"\n ],\n \"You can make a transfer or a withdrawal to your wallet.\": [\n \"Sie k\u00F6nnen Geld in Ihre Wallet-App \u00FCbertragen oder abheben lassen.\"\n ],\n \"Date\": [\n \"Datum\"\n ],\n \"Counterpart\": [\n \"Gegenkonto\"\n ],\n \"sent\": [\n \"gesendet\"\n ],\n \"received\": [\n \"empfangen\"\n ],\n \"Invalid value\": [\n \"Ung\u00FCltiger Wert\"\n ],\n \"to\": [\n \"an\"\n ],\n \"from\": [\n \"von\"\n ],\n \"First page\": [\n \"Erste Seite\"\n ],\n \"Next\": [\n \"N\u00E4chste Seite\"\n ],\n \"confirm withdrawal\": [\n \"Best\u00E4tigung der Abhebung\"\n ],\n \"cambiar\": [\n \"\"\n ],\n \"abort withdrawal\": [\n \"Best\u00E4tigung der Abhebung\"\n ],\n \"The withdrawal has been aborted previously and can't be confirmed\": [\n \"Die Abhebung wurde zuvor abgebrochen und konnte daher nicht durchgef\u00FChrt werden\"\n ],\n \"The withdrawal operation can't be confirmed before a wallet accepted the transaction.\": [\n \"Der Abhebevorgang kann nicht best\u00E4tigt werden, bevor eine Taler Wallet-App die Transaktion angenommen hat.\"\n ],\n \"The operation ID is invalid.\": [\n \"Die Vorgangs-ID ist ung\u00FCltig.\"\n ],\n \"The operation was not found.\": [\n \"Der Vorgang konnte nicht gefunden werden.\"\n ],\n \"The starting withdrawal amount and the confirmation amount differs.\": [\n \"Der Betrag der Abhebung und der empfangene Betrag unterscheiden sich.\"\n ],\n \"The bank requires a bank account which has not been specified yet.\": [\n \"Die Bank ben\u00F6tigt ein Bankkonto, das noch nicht festgelegt wurde.\"\n ],\n \"Bad request\": [\n \"\"\n ],\n \"The withdrawal operation has been aborted.\": [\n \"Abhebevorgang in Bearbeitung\"\n ],\n \"The withdrawal operation has been confirmed previously and can\u2019t be aborted.\": [\n \"Der Vorgang wurde vom Verrechnungskonto bereits best\u00E4tigt und kann daher nicht mehr abgebrochen werden\"\n ],\n \"Complete withdrawal.\": [\n \"Best\u00E4tigung der Abhebung\"\n ],\n \"Confirm the withdrawal operation\": [\n \"Best\u00E4tigen Sie den Abhebevorgang\"\n ],\n \"Wire transfer details\": [\n \"Details der Bank\u00FCberweisung\"\n ],\n \"Payment Service Provider's account number\": [\n \"Bankkontonummer des Zahlungsdiensts\"\n ],\n \"Payment Service Provider's name\": [\n \"Name des Zahlungsdiensts\"\n ],\n \"Payment Service Provider's account bank hostname\": [\n \"Bezeichnung des Bankkontos des Zahlungsdiensts (PSP hostname)\"\n ],\n \"Payment Service Provider's account id\": [\n \"Konto-ID des Zahlungsdiensts\"\n ],\n \"Payment Service Provider's account address\": [\n \"Kontenadresse des Zahlungsdiensts\"\n ],\n \"Payment Service Provider's account cyclos hostname\": [\n \"Bezeichnung des Bankkontos des Zahlungsdiensts (PSP hostname)\"\n ],\n \"No amount has yet been determined.\": [\n \"Es wurde bisher noch kein Betrag ermittelt.\"\n ],\n \"Transfer\": [\n \"\u00DCberweisung\"\n ],\n \"Authentication required\": [\n \"Authentifizierung erforderlich\"\n ],\n \"This operation was created with another username\": [\n \"Dieser Vorgang wurde mit einem anderen Nutzernamen erstellt\"\n ],\n \"You are currently logged in with user \\\"%1$s\\\" and the operation was made with user \\\"%2$s\\\"\": [\n \"\"\n ],\n \"The reserve operation has been confirmed previously and can't be aborted\": [\n \"Der Vorgang wurde vom Verrechnungskonto bereits best\u00E4tigt und kann daher nicht mehr abgebrochen werden\"\n ],\n \"Wire transfer completed!\": [\n \"Bank\u00FCberweisung abgeschlossen!\"\n ],\n \"Confirm withdrawal.\": [\n \"Best\u00E4tigung der Abhebung\"\n ],\n \"Unauthorized to make the operation, maybe the session has expired or the password changed.\": [\n \"Sie sind nicht berechtigt, den Vorgang durchzuf\u00FChren, vielleicht ist die Sitzung abgelaufen oder das Passwort wurde ge\u00E4ndert.\"\n ],\n \"The operation was rejected due to insufficient funds.\": [\n \"Der Vorgang wurde wegen unzureichendem Guthaben zur\u00FCckgewiesen.\"\n ],\n \"Withdrawal confirmed\": [\n \"Abhebung best\u00E4tigt\"\n ],\n \"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.\": [\n \"Die \u00DCberweisung an den Zahlungsdienst wurde eingeleitet. Ihre Taler-Wallet-App wird den angeforderten Betrag baldm\u00F6glichst abrufen.\"\n ],\n \"Do not show this again\": [\n \"Diese Meldung nicht mehr anzeigen\"\n ],\n \"If you have a Taler wallet installed on this device\": [\n \"Falls Sie eine Taler-Wallet-App auf diesem Ger\u00E4t installiert haben\"\n ],\n \"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions\": [\n \"In Ihrer Taler-Wallet-App werden die Details der Transaktion einschlie\u00DFlich der Geb\u00FChren (falls diese verlangt wurden) angezeigt. Wenn Sie noch keine Taler-Wallet-App haben, folgen Sie bitte den Anweisungen\"\n ],\n \"on this page\": [\n \"auf dieser Seite\"\n ],\n \"Withdraw\": [\n \"Abheben\"\n ],\n \"In case you have a Taler wallet on another device\": [\n \"Falls Sie eine Taler-Wallet-App auf einem anderen Ger\u00E4t als diesem haben\"\n ],\n \"Scan the QR below to start the withdrawal.\": [\n \"Scannen Sie den QR-Code, um die Abhebung zu beginnen.\"\n ],\n \"create withdrawal\": [\n \"Best\u00E4tigung der Abhebung\"\n ],\n \"The server replied with an invalid taler://withdraw URI\": [\n \"Der Server antwortete mit einem ung\u00FCltigen taler://withdraw URI\"\n ],\n \"Withdraw URI: %1$s\": [\n \"Abhebe-URI: %1$s\"\n ],\n \"The operation was rejected due to insufficient funds\": [\n \"Der Vorgang wurde wegen unzureichendem Guthaben zur\u00FCckgewiesen\"\n ],\n \"Current balance is %1$s\": [\n \"Das aktuelle Guthaben betr\u00E4gt %1$s\"\n ],\n \"You can withdraw up to %1$s\": [\n \"Sie k\u00F6nnen bis zu %1$s abheben\"\n ],\n \"Continue\": [\n \"Weiter\"\n ],\n \"Use your Taler wallet\": [\n \"Aktivieren Sie Ihr Taler-Wallet\"\n ],\n \"After using your wallet you will need to authorize or cancel the operation on this site.\": [\n \"Nachdem Sie Ihre Taler-Wallet-App aktiviert haben, m\u00FCssen Sie auf dieser Website den Vorgang entweder mit Ihrer Freigabe best\u00E4tigen oder ihn abbrechen.\"\n ],\n \"You need a Taler wallet\": [\n \"Sie ben\u00F6tigen eine Taler-Wallet-App\"\n ],\n \"If you don't have one yet you can follow the instruction in\": [\n \"Wenn Sie noch keine haben, folgen Sie bitte den Anweisungen in\"\n ],\n \"this page\": [\n \"diese Seite\"\n ],\n \"Send money\": [\n \"Geld senden\"\n ],\n \"to a Taler wallet\": [\n \"an ein Taler-Wallet (App oder WebExtension)\"\n ],\n \"Withdraw digital money into your mobile wallet or browser extension\": [\n \"Elektronisches Bargeld in eine Smartphone-App oder in eine Browser-Erweiterung (WebExtension) abheben\"\n ],\n \"to another bank account\": [\n \"an ein anderes Bankkonto\"\n ],\n \"Make a wire transfer to an account with known bank account number.\": [\n \"Sie \u00FCberweisen auf ein Konto mit einer Ihnen bekannten Bankkontonummer.\"\n ],\n \"This is a demo\": [\n \"Dies ist eine Demo-Version\"\n ],\n \"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .\": [\n \"Dieser Teil der Demo-Version zeigt die Rolle einer Kundenbank, die Zahlungen mit dem Taler-System unterst\u00FCtzt. Sie sehen in der Demonstration Ihr eigenes Bankkonto und den %1$s-Transaktionsverlauf.\"\n ],\n \"Here you will be able to see how a bank that supports Taler directly would work.\": [\n \"Damit k\u00F6nnen Sie nachvollziehen, wie eine Kundenbank, die Zahlungen mit dem Taler-System unterst\u00FCtzt, funktionieren w\u00FCrde.\"\n ],\n \"Internal error, please report. There should be more information in the console.\": [\n \"\"\n ],\n \"Internal error, please report.\": [\n \"Interner Fehler, um dessen Mitteilung wir Sie freundlich bitten.\"\n ],\n \"Preferences\": [\n \"Pr\u00E4ferenzen\"\n ],\n \"Show debug information\": [\n \"Debugging-Informationen anzeigen\"\n ],\n \"Welcome\": [\n \"Willkommen\"\n ],\n \"Welcome, %1$s\": [\n \"Herzlich willkommen, %1$s\"\n ],\n \"No enough permission to access the conversion rate list.\": [\n \"Es besteht keine ausreichende Berechtigung, um den Vorgang abzuschlie\u00DFen.\"\n ],\n \"Conversion list not found. Maybe conversion rate is not supported.\": [\n \"\"\n ],\n \"Conversion list not implemented.\": [\n \"Umrechnungen sind deaktiviert\"\n ],\n \"Conversion rate classes\": [\n \"Umrechnungskurs\"\n ],\n \"Create conversion rate class\": [\n \"Umrechnungskurs\"\n ],\n \"No conversion rate class\": [\n \"Umrechnungskurs\"\n ],\n \"Name\": [\n \"Name\"\n ],\n \"Description\": [\n \"Beschreibung\"\n ],\n \"Cashin\": [\n \"Auszahlung (Cash-In)\"\n ],\n \"min:\": [\n \"\"\n ],\n \"fee:\": [\n \"\"\n ],\n \"Select a section\": [\n \"Bitte w\u00E4hlen Sie einen Bereich aus\"\n ],\n \"Details\": [\n \"Detail-Angaben\"\n ],\n \"Delete\": [\n \"L\u00F6schen\"\n ],\n \"Credentials\": [\n \"Anmeldedaten\"\n ],\n \"Cashouts\": [\n \"Auszahlungen (Cashout)\"\n ],\n \"Conversion\": [\n \"Umrechnung (von W\u00E4hrungen)\"\n ],\n \"only admin can setup conversion\": [\n \"Nur ein Administrator kann Umrechnungskurse einrichten\"\n ],\n \"calculate cashout fee\": [\n \"Konto anlegen\"\n ],\n \"update conversion rate\": [\n \"Umrechnungskurs\"\n ],\n \"Wrong credentials\": [\n \"Ung\u00FCltige Zugangsdaten\"\n ],\n \"Conversion is disabled\": [\n \"Umrechnungen sind deaktiviert\"\n ],\n \"Config cashout\": [\n \"Einzahlungen einrichten\"\n ],\n \"Config cashin\": [\n \"Auszahlungen einrichten (Cash-In)\"\n ],\n \"Bad ratios\": [\n \"Das Verh\u00E4ltnis passt nicht\"\n ],\n \"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.\": [\n \"F\u00FCr ein stimmiges Verh\u00E4ltnis sollte die eine W\u00E4hrung h\u00F6her oder gleich 1 sein und die andere W\u00E4hrung niedriger oder gleich 1 sein.\"\n ],\n \"Initial amount\": [\n \"Guthaben bei Erstanlage des Kontos\"\n ],\n \"Use it to test how the conversion will affect the amount.\": [\n \"Hier testen Sie, um die Auswirkung des Umrechnungskurses auf einen Betrag zu pr\u00FCfen.\"\n ],\n \"Sending to this bank\": [\n \"An diese Bank senden\"\n ],\n \"Converted\": [\n \"Umgetauscht\"\n ],\n \"Cashin after fee\": [\n \"Auszahlung nach Abzug von Geb\u00FChren\"\n ],\n \"Sending from this bank\": [\n \"Senden von dieser Bank\"\n ],\n \"Cashout after fee\": [\n \"Einzahlung nach Abzug von Geb\u00FChren\"\n ],\n \"Bad configuration\": [\n \"Fehlerhafte Konfiguration\"\n ],\n \"This configuration allows users to cash out more of what has been cashed in.\": [\n \"Diese Einstellung erlaubt Nutzern, h\u00F6here Betr\u00E4ge auf ihre Konten einzuzahlen als sie eingenommen haben.\"\n ],\n \"Update\": [\n \"Aktualisieren\"\n ],\n \"Rnvalid\": [\n \"Ung\u00FCltig\"\n ],\n \"Must be > 0\": [\n \"\"\n ],\n \"Minimum amount\": [\n \"Minimaler Betrag\"\n ],\n \"Only cashout operation above this threshold will be allowed.\": [\n \"Es werden nur Einzahlungen oberhalb dieses Werts erlaubt\"\n ],\n \"Ratio\": [\n \"Verh\u00E4ltnis\"\n ],\n \"Conversion ratio between currencies\": [\n \"Umrechnungsverh\u00E4ltnis zwischen den W\u00E4hrungen\"\n ],\n \"Example conversion\": [\n \"Beispiel einer W\u00E4hrungsumrechnung\"\n ],\n \"1 %1$s will be converted into %2$s %3$s\": [\n \"1 %1$s wird getauscht zu %2$s %3$s\"\n ],\n \"Tiny amount\": [\n \"Minimaler Betrag\"\n ],\n \"Rounding mode\": [\n \"Rundungsmethode\"\n ],\n \"Zero\": [\n \"Null\"\n ],\n \"Amount will be round below to the largest possible value smaller than the input.\": [\n \"Der Betrag wird auf den gr\u00F6\u00DFtm\u00F6glichen Wert abgerundet, der kleiner als die Eingabe ist.\"\n ],\n \"Up\": [\n \"Aufrunden\"\n ],\n \"Amount will be round up to the smallest possible value larger than the input.\": [\n \"Der Betrag wird auf den geringstm\u00F6glichen Wert aufgerundet, der gr\u00F6\u00DFer als die Eingabe ist.\"\n ],\n \"Nearest\": [\n \"Am n\u00E4hesten\"\n ],\n \"Amount will be round to the closest possible value.\": [\n \"Der Betrag wird auf den n\u00E4chstm\u00F6glichen Wert gerundet.\"\n ],\n \"If none specified the fallback value is \\\"%1$s \\\".\": [\n \"\"\n ],\n \"Examples\": [\n \"Beispiele\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.1\": [\n \"Rundung eines Betrags von 1,24 mit Rundungswert 0,1\"\n ],\n \"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.\": [\n \"Angesichts des Rundungswertes von 0,1 sind die m\u00F6glichen Werte, die am n\u00E4chsten an 1,24 liegen, folgende: 1.1, 1.2, 1.3, 1.4.\"\n ],\n \"With the \\\"zero\\\" mode the value will be rounded to 1.2\": [\n \"Mit der Methode \u201ENull\u201C wird der Wert auf 1,2 gerundet\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.2\": [\n \"Mit der Methode \u201EN\u00E4hestens\u201C wird der Wert auf 1,2 gerundet\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.3\": [\n \"Mit der Methode \u201EAufrunden\u201C wird der Wert auf 1,3 gerundet\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.1\": [\n \"Rundung eines Betrags von 1,26 mit Rundungswert 0,1\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.3\": [\n \"Mit der Methode \u201EN\u00E4hestens\u201C wird der Wert auf 1,3 gerundet\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.3\": [\n \"Rundung eines Betrags von 1,24 mit Rundungswert 0,3\"\n ],\n \"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.\": [\n \"Mit einem Rundungswert von 0,3 sind die m\u00F6glichen Werte, die am n\u00E4hesten an 1,24 liegen, folgende: 0,9, 1,2, 1,5 und 1,8.\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.5\": [\n \"Mit der Methode \u201EAufrunden\u201C wird der Wert auf 1,5 gerundet\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.3\": [\n \"Rundung eines Betrags von 1,26 mit Rundungswert 0,3\"\n ],\n \"Amount to be deducted before amount is credited.\": [\n \"Betrag, der vor der Gutschrift abzuziehen ist.\"\n ],\n \"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"In den Einstellungen m\u00FCssen die Einzahlungen aufs Konto aktiviert und der Umrechnungskurs einschlie\u00DFlich aller Geb\u00FChren, Kurse und einem Rundungsverfahren initialisiert worden sein.\"\n ],\n \"delete conversion rate class\": [\n \"Umrechnungskurs\"\n ],\n \"Unauthorized\": [\n \"Unberechtigter Zugriff\"\n ],\n \"Forbidden\": [\n \"Verboten\"\n ],\n \"NotFound\": [\n \"\"\n ],\n \"NotImplemented\": [\n \"\"\n ],\n \"update conversion rate class\": [\n \"Umrechnungskurs\"\n ],\n \"Not Found\": [\n \"\"\n ],\n \"Not implemented\": [\n \"\"\n ],\n \"The name of the conversion is already used.\": [\n \"Es ist bereits ein Vorgang in Bearbeitung\"\n ],\n \"Conversion rate class\": [\n \"Umrechnungskurs\"\n ],\n \"Accounts\": [\n \"Konten\"\n ],\n \"Test\": [\n \"\"\n ],\n \"Users\": [\n \"Nutzername\"\n ],\n \"Can't remove the conversion rate class\": [\n \"\"\n ],\n \"There are some user associated to this class. You need to remove them first.\": [\n \"\"\n ],\n \"You are going to remove the conversion rate class\": [\n \"Sie sind gerade dabei, das Konto zu l\u00F6schen\"\n ],\n \"This step can't be undone.\": [\n \"Dieser Schritt kann sp\u00E4ter nicht mehr r\u00FCckg\u00E4ngig gemacht werden.\"\n ],\n \"Filters\": [\n \"\"\n ],\n \"Show from other classes\": [\n \"\"\n ],\n \"Account\": [\n \"Konto\"\n ],\n \"Group ID\": [\n \"\"\n ],\n \"No users in this conversion rate class\": [\n \"\"\n ],\n \"Class\": [\n \"\"\n ],\n \"Action\": [\n \"Aktionen\"\n ],\n \"Remove\": [\n \"Entfernen\"\n ],\n \"Add\": [\n \"Hinzuf\u00FCgen\"\n ],\n \"Conversion rate name\": [\n \"Umrechnungskurs\"\n ],\n \"Short description of the class\": [\n \"\"\n ],\n \"create conversion rate class\": [\n \"Umrechnungskurs\"\n ],\n \"Conversion rate class created.\": [\n \"Umrechnungskurs\"\n ],\n \"The rights to change the account are not sufficient\": [\n \"Es besteht keine ausreichende Berechtigung zum \u00C4ndern des Kontos\"\n ],\n \"New conversion rate class\": [\n \"Umrechnungskurs\"\n ],\n \"Create\": [\n \"Anlegen\"\n ],\n \"History of public accounts\": [\n \"Buchungen auf \u00F6ffentlich sichtbaren Konten\"\n ],\n \"Make a wire transfer\": [\n \"Eine Bank\u00FCberweisung durchf\u00FChren\"\n ],\n \"Scan the QR code below to start the withdrawal.\": [\n \"Scannen Sie den QR-Code, um die Abhebung zu beginnen.\"\n ],\n \"Operation aborted\": [\n \"Vorgang abgebrochen\"\n ],\n \"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.\": [\n \"Die \u00DCberweisung auf das Konto des Zahlungsdiensts wurde an einer anderen Stelle abgebrochen. Ihr Guthaben ist jedoch sicher und geht nicht verloren.\"\n ],\n \"Go to your wallet now\": [\n \"Geh jetzt zu deiner Wallet\"\n ],\n \"The operation is marked as selected, but a process during the withdrawal failed\": [\n \"Der Vorgang wurde als ausgew\u00E4hlt markiert, aber ein Schritt w\u00E4hrend des Abhebevorgangs ist gescheitert\"\n ],\n \"A withdrawal reserve ID was not found and no account has been selected.\": [\n \"Es wurde keine Abhebe-ID gefunden und daher ist kein Bankkonto ausgew\u00E4hlt worden.\"\n ],\n \"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.\": [\n \"Es gibt eine Abhebe-ID, aber es wurde kein Bankkonto ausgew\u00E4hlt oder das gew\u00E4hlte Bankkonto ist nicht g\u00FCltig.\"\n ],\n \"The account was selected, but no withdrawal reserve ID was found.\": [\n \"Das Konto wurde ausgew\u00E4hlt, aber es wurde keine Abhebe-ID gefunden.\"\n ],\n \"Operation not found\": [\n \"Vorgang nicht gefunden\"\n ],\n \"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.\": [\n \"Dieser Vorgang ist dem Server nicht bekannt. Die Vorgangs-ID stimmt nicht oder der Server hat die Informationen zum Vorgang gel\u00F6scht, bevor sie hier ankamen.\"\n ],\n \"Continue to dashboard\": [\n \"Weiter zum Dashboard\"\n ],\n \"The Withdrawal URI is not valid\": [\n \"Die URI f\u00FCr die Abhebung ist nicht g\u00FCltig\"\n ],\n \"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.\": [\n \"In den Einstellungen m\u00FCssen die Einzahlungen aufs Konto aktiviert und der Umrechnungskurs einschlie\u00DFlich aller Geb\u00FChren, Kurse und einem Rundungsverfahren initialisiert worden sein.\"\n ],\n \"Latest cashouts\": [\n \"Letzte Einzahlungen\"\n ],\n \"Created\": [\n \"Erzeugt\"\n ],\n \"Total debit\": [\n \"Gesamtbetrag der Belastung\"\n ],\n \"Total credit\": [\n \"Gesamtbetrag der Gutschrift\"\n ],\n \"Cashout for account %1$s\": [\n \"Einzahlung an Konto %1$s\"\n ],\n \"Invalid email format\": [\n \"Ung\u00FCltiger Wert\"\n ],\n \"Should start with +\": [\n \"Die Nummer sollte mit + beginnen\"\n ],\n \"A phone number consists of numbers only\": [\n \"Eine Telefonnummer besteht nur aus Ziffern\"\n ],\n \"Account ID for authentication\": [\n \"Konto-ID zur Authentifizierung\"\n ],\n \"Name of the account holder\": [\n \"Name des Kontoinhabers\"\n ],\n \"Internal account\": [\n \"Internes Konto\"\n ],\n \"If this field is empty, a random account ID will be assigned\": [\n \"Wenn dieses Feld leer bleibt, wird eine zuf\u00E4llige Konto-ID vergeben\"\n ],\n \"You can copy and share this IBAN number in order to receive wire transfers to your bank account\": [\n \"Sie k\u00F6nnen diese IBAN kopieren und \u00FCbertragen, um \u00DCberweisungen an Ihr Bankkonto zu erhalten\"\n ],\n \"Email\": [\n \"E-Mail\"\n ],\n \"To be used when second factor authentication is enabled\": [\n \"Dies wird verwendet, wenn die Zwei-Faktor-Authentifizierung aktiviert ist\"\n ],\n \"Phone\": [\n \"Telefon\"\n ],\n \"Enable second factor authentication\": [\n \"Dies wird verwendet, wenn die Zwei-Faktor-Authentifizierung aktiviert ist\"\n ],\n \"Using email\": [\n \"an die Emailadresse\"\n ],\n \"Add an email in your profile to enable this option\": [\n \"\"\n ],\n \"Using SMS\": [\n \"\"\n ],\n \"Add a phone number in your profile to enable this option\": [\n \"\"\n ],\n \"Cashout account\": [\n \"Auszahlungskonto\"\n ],\n \"External account number where the money is going to be sent when doing cashouts\": [\n \"Kontonummer f\u00FCr Einzahlungen aufs eigene Bankkonto (gew\u00F6hnlich eine IBAN)\"\n ],\n \"Max debt\": [\n \"Maximale Kredith\u00F6he\"\n ],\n \"How much the balance can go below zero.\": [\n \"Dieser Wert gibt an, wie weit der Saldo ins Minus gehen kann.\"\n ],\n \"Is this account public?\": [\n \"Ist dieses Konto ein \u00F6ffentliches?\"\n ],\n \"Public accounts have their balance publicly accessible\": [\n \"\u00D6ffentliche Konten zeigen ihre Salden und Bewegungen offen einsehbar\"\n ],\n \"Does this account belong to a Payment Service Provider?\": [\n \"Geh\u00F6rt dieses Konto dem Anbieter eines Zahlungsdiensts?\"\n ],\n \"update account\": [\n \"Konto anlegen\"\n ],\n \"Account updated\": [\n \"Das Konto wurde aktualisiert\"\n ],\n \"The username was not found\": [\n \"Der Name des Nutzers konnte nicht gefunden werden\"\n ],\n \"You can't change the legal name, please contact the your account administrator.\": [\n \"Sie k\u00F6nnen den Namen des wirtschaftlichen Berechtigten nicht \u00E4ndern, bitte benachrichtigen Sie den Administrator des Kontos.\"\n ],\n \"You can't change the debt limit, please contact the your account administrator.\": [\n \"Sie sind nicht befugt, die Kredith\u00F6he zu \u00E4ndern, bitte verst\u00E4ndigen Sie den Administrator des Kontos.\"\n ],\n \"You can't change the cashout address, please contact the your account administrator.\": [\n \"Sie k\u00F6nnen die Adresse f\u00FCr Einzahlungen nicht \u00E4ndern, bitte benachrichtigen Sie Ihren Administrator des Kontos.\"\n ],\n \"Update account information.\": [\n \"Aktualisieren der Kontoeinstellungen\"\n ],\n \"Account \\\"%1$s\\\"\": [\n \"Konto \\\"%1$s\\\"\"\n ],\n \"Removed\": [\n \"Entfernt\"\n ],\n \"This account can't be used.\": [\n \"Dieses Konto kann nicht genutzt werden.\"\n ],\n \"Change details\": [\n \"Details \u00E4ndern\"\n ],\n \"Merchant integration\": [\n \"H\u00E4ndler-Integration\"\n ],\n \"Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the \\\"import\\\" button in the \\\"bank account\\\" section.\": [\n \"Verwenden Sie diese Information, um Ihr Konto im Taler Merchant-Backend mit dem normalen Bankkonto zu verkn\u00FCpfen. Sie k\u00F6nnen daf\u00FCr die im Onlinebanking angezeigten Angaben kopieren und mit der \\\"Import\\\"-Taste im Abschnitt \\\"Bankkonto\\\" des Taler Merchant-Backend selbst einf\u00FCgen bzw. Ihren Dienste-Verwalter eintragen lassen.\"\n ],\n \"Account type\": [\n \"Kontentyp\"\n ],\n \"Method to use for wire transfer.\": [\n \"F\u00FCr \u00DCberweisungen zu verwendende Methode.\"\n ],\n \"IBAN\": [\n \"IBAN\"\n ],\n \"International Bank Account Number.\": [\n \"IBAN (Internationale Bankkontonummer).\"\n ],\n \"Account name\": [\n \"Kontobezeichnung\"\n ],\n \"Bank host where the service is located.\": [\n \"Adresse des Bankservers, der den Dienst anbietet.\"\n ],\n \"Bank account identifier for wire transfers.\": [\n \"Kennung des Bankkontos f\u00FCr \u00DCberweisungen.\"\n ],\n \"Address\": [\n \"Adresse\"\n ],\n \"Owner's name\": [\n \"Name des Kontoinhabers\"\n ],\n \"Legal name of the person holding the account.\": [\n \"Rechtsg\u00FCltiger Name des Kontoinhabers.\"\n ],\n \"Account info URL\": [\n \"URL f\u00FCr Kontoinformationen\"\n ],\n \"From where the merchant can download information about incoming wire transfers to this account.\": [\n \"Von wo der H\u00E4ndler Informationen \u00FCber eingehende \u00DCberweisungen auf dieses Konto herunterladen kann.\"\n ],\n \"Repeated password doesn't match\": [\n \"Das Passwort stimmt nicht mit dem ersten \u00FCberein\"\n ],\n \"update password\": [\n \"Passwort erneuern\"\n ],\n \"Password changed\": [\n \"Passwort ge\u00E4ndert\"\n ],\n \"Not authorized to change the password, maybe the session is invalid.\": [\n \"Sie sind zum \u00C4ndern des Passworts nicht berechtigt, m\u00F6glicherweise ist die Sitzung nicht mehr g\u00FCltig.\"\n ],\n \"You need to provide the old password. If you don't have it contact your account administrator.\": [\n \"Sie m\u00FCssen das alte Passwort eingeben, sollten Sie es nicht mehr haben, verst\u00E4ndigen Sie bitte Ihren Administrator des Kontos.\"\n ],\n \"Your current password doesn't match, can't change to a new password.\": [\n \"Dies stimmt nicht mit dem bisherigen Passwort \u00FCberein, daher kann kein neues Passwort vergeben werden.\"\n ],\n \"You don't have the rights to change the password.\": [\n \"\"\n ],\n \"Update account password.\": [\n \"Passwort erneuern\"\n ],\n \"Update password\": [\n \"Passwort erneuern\"\n ],\n \"Current password\": [\n \"Aktuelles Passwort dieser Instanz\"\n ],\n \"Your current password, for security\": [\n \"Zur Sicherheit bitte ihr bisheriges Passwort\"\n ],\n \"New password\": [\n \"Neues Passwort\"\n ],\n \"Type it again\": [\n \"Bitte das Passwort wiederholen\"\n ],\n \"Repeat the same password\": [\n \"Geben Sie das gleiche Passwort noch einmal ein\"\n ],\n \"Change\": [\n \"\u00C4ndern\"\n ],\n \"Create account\": [\n \"Konto anlegen\"\n ],\n \"Actions\": [\n \"Aktionen\"\n ],\n \"Unknown\": [\n \"Unbekannt\"\n ],\n \"Change password\": [\n \"Passwort \u00E4ndern\"\n ],\n \"Querying for the current stats failed\": [\n \"Die Abfrage der aktuellen Statistik ist fehlgeschlagen\"\n ],\n \"The request parameters are wrong\": [\n \"Die Abfrageparameter sind falsch\"\n ],\n \"The user is unauthorized\": [\n \"Dieser Nutzer ist nicht berechtigt\"\n ],\n \"Querying for the previous stats failed\": [\n \"Die Abfrage der vorherigen Statistik ist fehlgeschlagen\"\n ],\n \"Transaction volume report\": [\n \"Umsatzbericht\"\n ],\n \"Last hour\": [\n \"Vergangene Stunde\"\n ],\n \"Previous day\": [\n \"Tag zuvor\"\n ],\n \"Last month\": [\n \"Vergangener Monat\"\n ],\n \"Last year\": [\n \"Letztes Jahr\"\n ],\n \"Last Year\": [\n \"Vergangenes Jahr\"\n ],\n \"Trading volume from %1$s to %2$s\": [\n \"Umsatzvolumen von %1$s bis %2$s\"\n ],\n \"Transferred from an external account to an account in this bank.\": [\n \"\u00DCberwiesen von einem externen Bankkonto auf das Konto dieser Bank.\"\n ],\n \"Transferred from an account in this bank to an external account.\": [\n \"\u00DCberwiesen von einem Konto dieser Bank auf ein externes Bankkonto.\"\n ],\n \"Payin\": [\n \"Auszahlung (Pay-In)\"\n ],\n \"Transferred from an account to a Taler exchange.\": [\n \"\u00DCberwiesen von einem Bankkonto an einen Taler Exchange (der Zahlungsdienst dieses Bezahlsystems).\"\n ],\n \"Payout\": [\n \"Einzahlung (Pay-Out)\"\n ],\n \"Transferred from a Taler exchange to another account.\": [\n \"\u00DCberwiesen von einem Taler Exchange (Zahlungsdienst dieses Bezahlsystems) auf ein anderes Bankkonto.\"\n ],\n \"Download stats as CSV\": [\n \"Statistik herunterladen als CSV-Datei\"\n ],\n \"previous\": [\n \"vorherige\"\n ],\n \"Decreased by\": [\n \"Verringert um\"\n ],\n \"Increased by\": [\n \"Vermehrt um\"\n ],\n \"create account\": [\n \"Konto anlegen\"\n ],\n \"Account created with password \\\"%1$s\\\".\": [\n \"Das Konto wurde angelegt mit dem Passwort \\\"%1$s\\\".\"\n ],\n \"Server replied that phone or email is invalid\": [\n \"Der Server meldete zur\u00FCck, dass die Telefonnummer oder die Emailadresse falsch seien\"\n ],\n \"The rights to perform the operation are not sufficient\": [\n \"Die Berechtigung zum Durchf\u00FChren des Vorgangs ist unzureichend\"\n ],\n \"Account username is already taken\": [\n \"Dieser Nutzername ist bereits vergeben\"\n ],\n \"Account ID is already taken\": [\n \"Diese Konto-ID ist bereits vergeben\"\n ],\n \"Bank ran out of bonus credit.\": [\n \"Die Bank verf\u00FCgt \u00FCber kein Bonusguthaben mehr.\"\n ],\n \"Account username can't be used because is reserved\": [\n \"Dieser Nutzername kann f\u00FCr das Konto nicht verwendet werden, da er bereits reserviert ist\"\n ],\n \"Can't create accounts\": [\n \"Die Anlage von Konten ist nicht m\u00F6glich\"\n ],\n \"Only system admin can create accounts.\": [\n \"Nur ein Systemadministrator kann Konten anlegen.\"\n ],\n \"New bank account\": [\n \"Neues Konto\"\n ],\n \"download statistics\": [\n \"Statistik herunterladen als CSV-Datei\"\n ],\n \"only admin can download stats\": [\n \"Nur ein Administrator kann Umrechnungskurse einrichten\"\n ],\n \"Download bank stats\": [\n \"Bankstatistik herunterladen\"\n ],\n \"Include hour metric\": [\n \"Stunden-Metrik einbeziehen\"\n ],\n \"Include day metric\": [\n \"Tages-Metrik einbeziehen\"\n ],\n \"Include month metric\": [\n \"Monats-Metrik einbeziehen\"\n ],\n \"Include year metric\": [\n \"Jahres-Metrik einbeziehen\"\n ],\n \"Include table header\": [\n \"Tabellenkopfzeilen einbeziehen\"\n ],\n \"Add previous metric for compare\": [\n \"Vorherige Metrik zum Vergleich hinzuf\u00FCgen\"\n ],\n \"Fail on first error\": [\n \"Beim ersten Fehler abbrechen\"\n ],\n \"Download\": [\n \"Herunterladen\"\n ],\n \"downloading... %1$s\": [\n \"Beim Herunterladen... %1$s\"\n ],\n \"Download completed\": [\n \"Download abgeschlossen\"\n ],\n \"Click here to save the file in your computer.\": [\n \"Hier klicken zum Speichern der Datei auf Ihrem Rechner.\"\n ],\n \"there was an error reading the balance\": [\n \"\"\n ],\n \"Can't delete the account\": [\n \"Es war nicht m\u00F6glich, das Konto zu l\u00F6schen\"\n ],\n \"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.\": [\n \"Das Konto kann nicht gel\u00F6scht werden, solange es noch ein Guthaben aufweist. Bitte sorgen Sie daf\u00FCr, dass der Konteninhaber eine vollst\u00E4ndige Einzahlung auf das eigene Bankkonto durchf\u00FChrt.\"\n ],\n \"Name doesn't match\": [\n \"Der Name stimmt nicht \u00FCberein\"\n ],\n \"delete account\": [\n \"Konto anlegen\"\n ],\n \"Account removed\": [\n \"Das Konto wurde gel\u00F6scht\"\n ],\n \"No enough permission to delete the account.\": [\n \"Es besteht keine ausreichende Berechtigung zum L\u00F6schen des Kontos.\"\n ],\n \"The username was not found.\": [\n \"Der Nutzername wurde nicht gefunden.\"\n ],\n \"Can't delete a reserved username.\": [\n \"Es ist nicht m\u00F6glich, den reservierten Nutzernamen zu entfernen.\"\n ],\n \"Can't delete an account with balance different than zero.\": [\n \"Es ist nicht m\u00F6glich, ein Konto mit einem Saldo ungleich Null zu l\u00F6schen.\"\n ],\n \"Remove account.\": [\n \"Das Konto wird gel\u00F6scht\"\n ],\n \"You are going to remove the account\": [\n \"Sie sind gerade dabei, das Konto zu l\u00F6schen\"\n ],\n \"Deleting account \\\"%1$s\\\"\": [\n \"Das Konto \\\"%1$s\\\" wird gel\u00F6scht\"\n ],\n \"Verification\": [\n \"\u00DCberpr\u00FCfung\"\n ],\n \"Enter the account name that is going to be deleted\": [\n \"Zum L\u00F6schen geben Sie den Namen des Kontos an\"\n ],\n \"Cashout id should be a number\": [\n \"Die Einzahlungs-ID sollte eine Zahl sein\"\n ],\n \"This cashout not found. Maybe already aborted.\": [\n \"Diese Einzahlung konnte nicht gefunden werden, vielleicht wurde sie bereits abgebrochen.\"\n ],\n \"Cashout detail\": [\n \"Einzahlungsdetails\"\n ],\n \"Debited\": [\n \"Belastet\"\n ],\n \"Transferred\": [\n \"\u00DCberweisung\"\n ],\n \"You have no permission to this account.\": [\n \"Es besteht keine ausreichende Berechtigung zum L\u00F6schen des Kontos.\"\n ],\n \"This account is locked. If you have a active session you can change the password or contact the administrator.\": [\n \"\"\n ],\n \"New web session\": [\n \"\"\n ],\n \"Welcome to %1$s!\": [\n \"Willkommen bei %1$s!\"\n ]\n }\n },\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n != 1;\",\n \"lang\": \"de\",\n \"completeness\": 90\n};\n\nstrings['ca'] = {\n \"locale_data\": {\n \"messages\": {\n \"\": {\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n != 1;\",\n \"lang\": \"ca\"\n },\n \"An IBAN consists of capital letters and numbers only\": [\n \"\"\n ],\n \"IBAN numbers have more that 4 digits\": [\n \"\"\n ],\n \"IBAN numbers have less that 34 digits\": [\n \"\"\n ],\n \"IBAN country code not found\": [\n \"\"\n ],\n \"IBAN number is not valid, checksum is wrong\": [\n \"\"\n ],\n \"Use letters, numbers or any of these characters: - . _ ~\": [\n \"\"\n ],\n \"Required\": [\n \"\"\n ],\n \"confirm MFA challenge\": [\n \"\"\n ],\n \"Unknown challenge.\": [\n \"\"\n ],\n \"Failed to validate the verification code.\": [\n \"\"\n ],\n \"Too many challenges are active right now, you must wait or confirm current challenges.\": [\n \"\"\n ],\n \"Wrong authentication number.\": [\n \"\"\n ],\n \"Expired challenge.\": [\n \"\"\n ],\n \"Submit the transmitted code number.\": [\n \"\"\n ],\n \"The verification code sent to the email address starting with %1$s\": [\n \"\"\n ],\n \"The verification code sent to the phone number ending with %1$s\": [\n \"\"\n ],\n \"Code\": [\n \"\"\n ],\n \"Username of the account\": [\n \"\"\n ],\n \"It will expired at %1$s\": [\n \"\"\n ],\n \"The challenge is expired and can't be solved but you can go back and create a new challenge.\": [\n \"\"\n ],\n \"Back\": [\n \"\"\n ],\n \"Verify\": [\n \"\"\n ],\n \"send MFA challenge\": [\n \"\"\n ],\n \"Failed to send the verification code.\": [\n \"\"\n ],\n \"The request was valid, but the server is refusing action.\": [\n \"\"\n ],\n \"The backend is not aware of the specified MFA challenge.\": [\n \"\"\n ],\n \"It is too early to request another transmission of the challenge.\": [\n \"\"\n ],\n \"Code transmission failed.\": [\n \"\"\n ],\n \"select challenge\": [\n \"\"\n ],\n \"Multi-factor authentication required\": [\n \"\"\n ],\n \"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.\": [\n \"\"\n ],\n \"The next challenge needs to be completed to confirm the operation.\": [\n \"\"\n ],\n \"All the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"One of the next challenges need to be completed to confirm the operation.\": [\n \"\"\n ],\n \"To an phone ending with \\\"%1$s\\\"\": [\n \"\"\n ],\n \"To an email starting with \\\" %1$s\\\"\": [\n \"\"\n ],\n \"I have a code\": [\n \"\"\n ],\n \"Send me a message\": [\n \"\"\n ],\n \"You have to wait until %1$s to send a new code.\": [\n \"\"\n ],\n \"Cancel\": [\n \"\"\n ],\n \"Complete\": [\n \"\"\n ],\n \"Unable to create a cashout\": [\n \"\"\n ],\n \"The bank configuration does not support cashout operations.\": [\n \"\"\n ],\n \"Close\": [\n \"\"\n ],\n \"Cashout is disabled\": [\n \"\"\n ],\n \"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"calculate conversion fee\": [\n \"\"\n ],\n \"The server didn't understand the request.\": [\n \"\"\n ],\n \"The amount is too small\": [\n \"\"\n ],\n \"Conversion is not implemented.\": [\n \"\"\n ],\n \"At least debit or credit needs to be provided\": [\n \"\"\n ],\n \"The amount is malfored\": [\n \"\"\n ],\n \"The currency is not supported\": [\n \"\"\n ],\n \"Invalid\": [\n \"\"\n ],\n \"Amount needs to be higher\": [\n \"\"\n ],\n \"Balance is not enough\": [\n \"\"\n ],\n \"It is not possible to cashout less than %1$s: %2$s\": [\n \"\"\n ],\n \"The total transfer to the destination will be zero\": [\n \"\"\n ],\n \"create cashout\": [\n \"\"\n ],\n \"Cashout created\": [\n \"\"\n ],\n \"Second factor authentication required.\": [\n \"\"\n ],\n \"Account not found\": [\n \"\"\n ],\n \"Duplicated request detected, check if the operation succeeded or try again.\": [\n \"\"\n ],\n \"The conversion rate was applied incorrectly\": [\n \"\"\n ],\n \"The account does not have sufficient funds\": [\n \"\"\n ],\n \"Missing cashout URI in the profile\": [\n \"\"\n ],\n \"The amount is below the minimum amount permitted.\": [\n \"\"\n ],\n \"Sending the confirmation message failed, retry later or contact the administrator.\": [\n \"\"\n ],\n \"The server doesn't support the current TAN channel.\": [\n \"\"\n ],\n \"Create cashout.\": [\n \"\"\n ],\n \"Cashout\": [\n \"\"\n ],\n \"Conversion rate\": [\n \"\"\n ],\n \"Balance\": [\n \"\"\n ],\n \"Fee\": [\n \"\"\n ],\n \"To account\": [\n \"\"\n ],\n \"Legal name\": [\n \"\"\n ],\n \"If this name doesn't match the account holder's name, your transaction may fail.\": [\n \"\"\n ],\n \"Unable to cashout\": [\n \"\"\n ],\n \"Before being able to cashout to a bank account, you need to complete your profile\": [\n \"\"\n ],\n \"Transfer subject\": [\n \"\"\n ],\n \"Currency\": [\n \"\"\n ],\n \"Send %1$s\": [\n \"\"\n ],\n \"Receive %1$s\": [\n \"\"\n ],\n \"Amount\": [\n \"\"\n ],\n \"Total cost\": [\n \"\"\n ],\n \"Balance left\": [\n \"\"\n ],\n \"Before fee\": [\n \"\"\n ],\n \"Total cashout transfer\": [\n \"\"\n ],\n \"Not valid\": [\n \"\"\n ],\n \"Does not follow the pattern\": [\n \"\"\n ],\n \"send transaction\": [\n \"\"\n ],\n \"The wire transfer was successfully completed!\": [\n \"\"\n ],\n \"The request was invalid or the payto://-URI used unacceptable features.\": [\n \"\"\n ],\n \"Not enough permission to complete the operation.\": [\n \"\"\n ],\n \"The bank administrator cannot be the transfer creditor.\": [\n \"\"\n ],\n \"The destination account \\\"%1$s\\\" was not found.\": [\n \"\"\n ],\n \"The origin and the destination of the transfer can't be the same.\": [\n \"\"\n ],\n \"Your balance is not sufficient for the operation.\": [\n \"\"\n ],\n \"The origin account \\\"%1$s\\\" was not found.\": [\n \"\"\n ],\n \"The attempt to create the transaction has failed. Please try again.\": [\n \"\"\n ],\n \"A second factor authentication is required.\": [\n \"\"\n ],\n \"Confirm wire transfer.\": [\n \"\"\n ],\n \"Input wire transfer detail\": [\n \"\"\n ],\n \"Using a form\": [\n \"\"\n ],\n \"A special URI that specifies the amount to be transferred and the destination account.\": [\n \"\"\n ],\n \"QR code\": [\n \"\"\n ],\n \"If your device has a camera, you can import a payto:// URI from a QR code.\": [\n \"\"\n ],\n \"Recipient\": [\n \"\"\n ],\n \"ID of the recipient's account\": [\n \"\"\n ],\n \"username\": [\n \"\"\n ],\n \"IBAN of the recipient's account\": [\n \"\"\n ],\n \"Subject\": [\n \"\"\n ],\n \"Some text to identify the transfer\": [\n \"\"\n ],\n \"Amount to transfer\": [\n \"\"\n ],\n \"Payto URI:\": [\n \"\"\n ],\n \"Uniform resource identifier of the target account\": [\n \"\"\n ],\n \"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"\"\n ],\n \"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]\": [\n \"\"\n ],\n \"The maximum amount for a wire transfer is %1$s\": [\n \"\"\n ],\n \"Cost\": [\n \"\"\n ],\n \"Send\": [\n \"\"\n ],\n \"Only \\\"x-taler-bank\\\" target are supported\": [\n \"\"\n ],\n \"Only this host is allowed. Use \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Account name is missing\": [\n \"\"\n ],\n \"Only \\\"IBAN\\\" target are supported\": [\n \"\"\n ],\n \"Missing \\\"amount\\\" parameter to specify the amount to be transferred\": [\n \"\"\n ],\n \"The \\\"amount\\\" parameter is not valid\": [\n \"\"\n ],\n \"\\\"message\\\" parameters to specify a reference text for the transfer are missing\": [\n \"\"\n ],\n \"The only currency allowed is \\\"%1$s\\\"\": [\n \"\"\n ],\n \"You cannot transfer an amount of zero.\": [\n \"\"\n ],\n \"The balance is not sufficient\": [\n \"\"\n ],\n \"Please enter a longer subject\": [\n \"\"\n ],\n \"Show withdrawal confirmation\": [\n \"Mostrar informaci\u00F3 de retirada\"\n ],\n \"Withdraw without setting amount\": [\n \"Retirar sense fixar un import\"\n ],\n \"Hide demo hint.\": [\n \"\"\n ],\n \"Show install wallet first\": [\n \"\"\n ],\n \"Currently, the bank is not accepting new registrations!\": [\n \"\"\n ],\n \"The name is missing\": [\n \"\"\n ],\n \"Missing username\": [\n \"\"\n ],\n \"Missing password\": [\n \"\"\n ],\n \"The password should be longer than 8 letters\": [\n \"\"\n ],\n \"The passwords do not match\": [\n \"\"\n ],\n \"register new account\": [\n \"\"\n ],\n \"Server replied with invalid phone or email.\": [\n \"\"\n ],\n \"You are not authorised to create this account.\": [\n \"\"\n ],\n \"Registration is disabled because the bank ran out of bonus credit.\": [\n \"\"\n ],\n \"That username can't be used because is reserved.\": [\n \"\"\n ],\n \"That username is already taken.\": [\n \"\"\n ],\n \"That account ID is already taken.\": [\n \"\"\n ],\n \"No information for the selected authentication channel.\": [\n \"\"\n ],\n \"Authentication channel is not supported.\": [\n \"\"\n ],\n \"Only an administrator is allowed to set the debt limit.\": [\n \"\"\n ],\n \"Only the administrator can change the conversion rate.\": [\n \"\"\n ],\n \"The conversion rate class doesn't exist.\": [\n \"\"\n ],\n \"Only admin can create accounts with second factor authentication.\": [\n \"\"\n ],\n \"The password is too short. Can't have less than 8 characters.\": [\n \"\"\n ],\n \"The password is too long. Can't have more than 64 characters.\": [\n \"\"\n ],\n \"Account registration\": [\n \"\"\n ],\n \"Login username\": [\n \"\"\n ],\n \"account identification to login\": [\n \"\"\n ],\n \"Password\": [\n \"\"\n ],\n \"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers\": [\n \"\"\n ],\n \"Repeat password\": [\n \"\"\n ],\n \"Same password\": [\n \"\"\n ],\n \"Full name\": [\n \"\"\n ],\n \"Register\": [\n \"\"\n ],\n \"Create a random temporary user\": [\n \"\"\n ],\n \"logout\": [\n \"\"\n ],\n \"login\": [\n \"\"\n ],\n \"The account has no rights to login.\": [\n \"\"\n ],\n \"The account is locked and cannot login. Contact administrator.\": [\n \"\"\n ],\n \"Wrong credentials for \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Account login.\": [\n \"\"\n ],\n \"Session expired\": [\n \"\"\n ],\n \"Username\": [\n \"\"\n ],\n \"identification\": [\n \"\"\n ],\n \"Password of the account\": [\n \"\"\n ],\n \"Forget\": [\n \"\"\n ],\n \"Log in\": [\n \"\"\n ],\n \"Transactions history\": [\n \"\"\n ],\n \"No transactions yet.\": [\n \"\"\n ],\n \"You can make a transfer or a withdrawal to your wallet.\": [\n \"\"\n ],\n \"Date\": [\n \"\"\n ],\n \"Counterpart\": [\n \"\"\n ],\n \"sent\": [\n \"\"\n ],\n \"received\": [\n \"\"\n ],\n \"Invalid value\": [\n \"\"\n ],\n \"to\": [\n \"\"\n ],\n \"from\": [\n \"\"\n ],\n \"First page\": [\n \"\"\n ],\n \"Next\": [\n \"\"\n ],\n \"confirm withdrawal\": [\n \"\"\n ],\n \"cambiar\": [\n \"\"\n ],\n \"abort withdrawal\": [\n \"\"\n ],\n \"The withdrawal has been aborted previously and can't be confirmed\": [\n \"\"\n ],\n \"The withdrawal operation can't be confirmed before a wallet accepted the transaction.\": [\n \"\"\n ],\n \"The operation ID is invalid.\": [\n \"\"\n ],\n \"The operation was not found.\": [\n \"\"\n ],\n \"The starting withdrawal amount and the confirmation amount differs.\": [\n \"\"\n ],\n \"The bank requires a bank account which has not been specified yet.\": [\n \"\"\n ],\n \"Bad request\": [\n \"\"\n ],\n \"The withdrawal operation has been aborted.\": [\n \"\"\n ],\n \"The withdrawal operation has been confirmed previously and can\u2019t be aborted.\": [\n \"\"\n ],\n \"Complete withdrawal.\": [\n \"\"\n ],\n \"Confirm the withdrawal operation\": [\n \"\"\n ],\n \"Wire transfer details\": [\n \"\"\n ],\n \"Payment Service Provider's account number\": [\n \"\"\n ],\n \"Payment Service Provider's name\": [\n \"\"\n ],\n \"Payment Service Provider's account bank hostname\": [\n \"\"\n ],\n \"Payment Service Provider's account id\": [\n \"\"\n ],\n \"Payment Service Provider's account address\": [\n \"\"\n ],\n \"Payment Service Provider's account cyclos hostname\": [\n \"\"\n ],\n \"No amount has yet been determined.\": [\n \"\"\n ],\n \"Transfer\": [\n \"\"\n ],\n \"Authentication required\": [\n \"\"\n ],\n \"This operation was created with another username\": [\n \"\"\n ],\n \"You are currently logged in with user \\\"%1$s\\\" and the operation was made with user \\\"%2$s\\\"\": [\n \"\"\n ],\n \"The reserve operation has been confirmed previously and can't be aborted\": [\n \"\"\n ],\n \"Wire transfer completed!\": [\n \"\"\n ],\n \"Confirm withdrawal.\": [\n \"\"\n ],\n \"Unauthorized to make the operation, maybe the session has expired or the password changed.\": [\n \"\"\n ],\n \"The operation was rejected due to insufficient funds.\": [\n \"\"\n ],\n \"Withdrawal confirmed\": [\n \"\"\n ],\n \"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.\": [\n \"\"\n ],\n \"Do not show this again\": [\n \"\"\n ],\n \"If you have a Taler wallet installed on this device\": [\n \"\"\n ],\n \"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions\": [\n \"\"\n ],\n \"on this page\": [\n \"\"\n ],\n \"Withdraw\": [\n \"\"\n ],\n \"In case you have a Taler wallet on another device\": [\n \"\"\n ],\n \"Scan the QR below to start the withdrawal.\": [\n \"\"\n ],\n \"create withdrawal\": [\n \"\"\n ],\n \"The server replied with an invalid taler://withdraw URI\": [\n \"\"\n ],\n \"Withdraw URI: %1$s\": [\n \"\"\n ],\n \"The operation was rejected due to insufficient funds\": [\n \"\"\n ],\n \"Current balance is %1$s\": [\n \"\"\n ],\n \"You can withdraw up to %1$s\": [\n \"\"\n ],\n \"Continue\": [\n \"\"\n ],\n \"Use your Taler wallet\": [\n \"\"\n ],\n \"After using your wallet you will need to authorize or cancel the operation on this site.\": [\n \"\"\n ],\n \"You need a Taler wallet\": [\n \"\"\n ],\n \"If you don't have one yet you can follow the instruction in\": [\n \"\"\n ],\n \"this page\": [\n \"\"\n ],\n \"Send money\": [\n \"\"\n ],\n \"to a Taler wallet\": [\n \"\"\n ],\n \"Withdraw digital money into your mobile wallet or browser extension\": [\n \"\"\n ],\n \"to another bank account\": [\n \"\"\n ],\n \"Make a wire transfer to an account with known bank account number.\": [\n \"\"\n ],\n \"This is a demo\": [\n \"\"\n ],\n \"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .\": [\n \"\"\n ],\n \"Here you will be able to see how a bank that supports Taler directly would work.\": [\n \"\"\n ],\n \"Internal error, please report. There should be more information in the console.\": [\n \"\"\n ],\n \"Internal error, please report.\": [\n \"\"\n ],\n \"Preferences\": [\n \"\"\n ],\n \"Show debug information\": [\n \"Mostrar informaci\u00F3 de retirada\"\n ],\n \"Welcome\": [\n \"\"\n ],\n \"Welcome, %1$s\": [\n \"\"\n ],\n \"No enough permission to access the conversion rate list.\": [\n \"\"\n ],\n \"Conversion list not found. Maybe conversion rate is not supported.\": [\n \"\"\n ],\n \"Conversion list not implemented.\": [\n \"\"\n ],\n \"Conversion rate classes\": [\n \"\"\n ],\n \"Create conversion rate class\": [\n \"\"\n ],\n \"No conversion rate class\": [\n \"\"\n ],\n \"Name\": [\n \"\"\n ],\n \"Description\": [\n \"Mostrar descripci\u00F3 de demostraci\u00F3\"\n ],\n \"Cashin\": [\n \"\"\n ],\n \"min:\": [\n \"\"\n ],\n \"fee:\": [\n \"\"\n ],\n \"Select a section\": [\n \"\"\n ],\n \"Details\": [\n \"\"\n ],\n \"Delete\": [\n \"\"\n ],\n \"Credentials\": [\n \"\"\n ],\n \"Cashouts\": [\n \"\"\n ],\n \"Conversion\": [\n \"\"\n ],\n \"only admin can setup conversion\": [\n \"\"\n ],\n \"calculate cashout fee\": [\n \"\"\n ],\n \"update conversion rate\": [\n \"\"\n ],\n \"Wrong credentials\": [\n \"\"\n ],\n \"Conversion is disabled\": [\n \"\"\n ],\n \"Config cashout\": [\n \"\"\n ],\n \"Config cashin\": [\n \"\"\n ],\n \"Bad ratios\": [\n \"\"\n ],\n \"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.\": [\n \"\"\n ],\n \"Initial amount\": [\n \"\"\n ],\n \"Use it to test how the conversion will affect the amount.\": [\n \"\"\n ],\n \"Sending to this bank\": [\n \"\"\n ],\n \"Converted\": [\n \"\"\n ],\n \"Cashin after fee\": [\n \"\"\n ],\n \"Sending from this bank\": [\n \"\"\n ],\n \"Cashout after fee\": [\n \"\"\n ],\n \"Bad configuration\": [\n \"\"\n ],\n \"This configuration allows users to cash out more of what has been cashed in.\": [\n \"\"\n ],\n \"Update\": [\n \"\"\n ],\n \"Rnvalid\": [\n \"\"\n ],\n \"Must be > 0\": [\n \"\"\n ],\n \"Minimum amount\": [\n \"\"\n ],\n \"Only cashout operation above this threshold will be allowed.\": [\n \"\"\n ],\n \"Ratio\": [\n \"\"\n ],\n \"Conversion ratio between currencies\": [\n \"\"\n ],\n \"Example conversion\": [\n \"\"\n ],\n \"1 %1$s will be converted into %2$s %3$s\": [\n \"\"\n ],\n \"Tiny amount\": [\n \"\"\n ],\n \"Rounding mode\": [\n \"\"\n ],\n \"Zero\": [\n \"\"\n ],\n \"Amount will be round below to the largest possible value smaller than the input.\": [\n \"\"\n ],\n \"Up\": [\n \"\"\n ],\n \"Amount will be round up to the smallest possible value larger than the input.\": [\n \"\"\n ],\n \"Nearest\": [\n \"\"\n ],\n \"Amount will be round to the closest possible value.\": [\n \"\"\n ],\n \"If none specified the fallback value is \\\"%1$s \\\".\": [\n \"\"\n ],\n \"Examples\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.1\": [\n \"\"\n ],\n \"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.\": [\n \"\"\n ],\n \"With the \\\"zero\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.2\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.1\": [\n \"\"\n ],\n \"With the \\\"nearest\\\" mode the value will be rounded to 1.3\": [\n \"\"\n ],\n \"Rounding an amount of 1.24 with rounding value 0.3\": [\n \"\"\n ],\n \"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.\": [\n \"\"\n ],\n \"With the \\\"up\\\" mode the value will be rounded to 1.5\": [\n \"\"\n ],\n \"Rounding an amount of 1.26 with rounding value 0.3\": [\n \"\"\n ],\n \"Amount to be deducted before amount is credited.\": [\n \"\"\n ],\n \"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.\": [\n \"\"\n ],\n \"delete conversion rate class\": [\n \"\"\n ],\n \"Unauthorized\": [\n \"\"\n ],\n \"Forbidden\": [\n \"\"\n ],\n \"NotFound\": [\n \"\"\n ],\n \"NotImplemented\": [\n \"\"\n ],\n \"update conversion rate class\": [\n \"\"\n ],\n \"Not Found\": [\n \"\"\n ],\n \"Not implemented\": [\n \"\"\n ],\n \"The name of the conversion is already used.\": [\n \"\"\n ],\n \"Conversion rate class\": [\n \"\"\n ],\n \"Accounts\": [\n \"\"\n ],\n \"Test\": [\n \"\"\n ],\n \"Users\": [\n \"\"\n ],\n \"Can't remove the conversion rate class\": [\n \"\"\n ],\n \"There are some user associated to this class. You need to remove them first.\": [\n \"\"\n ],\n \"You are going to remove the conversion rate class\": [\n \"\"\n ],\n \"This step can't be undone.\": [\n \"\"\n ],\n \"Filters\": [\n \"\"\n ],\n \"Show from other classes\": [\n \"\"\n ],\n \"Account\": [\n \"\"\n ],\n \"Group ID\": [\n \"\"\n ],\n \"No users in this conversion rate class\": [\n \"\"\n ],\n \"Class\": [\n \"\"\n ],\n \"Action\": [\n \"\"\n ],\n \"Remove\": [\n \"\"\n ],\n \"Add\": [\n \"\"\n ],\n \"Conversion rate name\": [\n \"\"\n ],\n \"Short description of the class\": [\n \"\"\n ],\n \"create conversion rate class\": [\n \"\"\n ],\n \"Conversion rate class created.\": [\n \"\"\n ],\n \"The rights to change the account are not sufficient\": [\n \"\"\n ],\n \"New conversion rate class\": [\n \"\"\n ],\n \"Create\": [\n \"\"\n ],\n \"History of public accounts\": [\n \"\"\n ],\n \"Make a wire transfer\": [\n \"\"\n ],\n \"Scan the QR code below to start the withdrawal.\": [\n \"\"\n ],\n \"Operation aborted\": [\n \"\"\n ],\n \"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.\": [\n \"\"\n ],\n \"Go to your wallet now\": [\n \"\"\n ],\n \"The operation is marked as selected, but a process during the withdrawal failed\": [\n \"\"\n ],\n \"A withdrawal reserve ID was not found and no account has been selected.\": [\n \"\"\n ],\n \"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.\": [\n \"\"\n ],\n \"The account was selected, but no withdrawal reserve ID was found.\": [\n \"\"\n ],\n \"Operation not found\": [\n \"\"\n ],\n \"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.\": [\n \"\"\n ],\n \"Continue to dashboard\": [\n \"\"\n ],\n \"The Withdrawal URI is not valid\": [\n \"\"\n ],\n \"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.\": [\n \"\"\n ],\n \"Latest cashouts\": [\n \"\"\n ],\n \"Created\": [\n \"\"\n ],\n \"Total debit\": [\n \"\"\n ],\n \"Total credit\": [\n \"\"\n ],\n \"Cashout for account %1$s\": [\n \"\"\n ],\n \"Invalid email format\": [\n \"\"\n ],\n \"Should start with +\": [\n \"\"\n ],\n \"A phone number consists of numbers only\": [\n \"\"\n ],\n \"Account ID for authentication\": [\n \"\"\n ],\n \"Name of the account holder\": [\n \"\"\n ],\n \"Internal account\": [\n \"\"\n ],\n \"If this field is empty, a random account ID will be assigned\": [\n \"\"\n ],\n \"You can copy and share this IBAN number in order to receive wire transfers to your bank account\": [\n \"\"\n ],\n \"Email\": [\n \"\"\n ],\n \"To be used when second factor authentication is enabled\": [\n \"\"\n ],\n \"Phone\": [\n \"\"\n ],\n \"Enable second factor authentication\": [\n \"\"\n ],\n \"Using email\": [\n \"\"\n ],\n \"Add an email in your profile to enable this option\": [\n \"\"\n ],\n \"Using SMS\": [\n \"\"\n ],\n \"Add a phone number in your profile to enable this option\": [\n \"\"\n ],\n \"Cashout account\": [\n \"\"\n ],\n \"External account number where the money is going to be sent when doing cashouts\": [\n \"\"\n ],\n \"Max debt\": [\n \"\"\n ],\n \"How much the balance can go below zero.\": [\n \"\"\n ],\n \"Is this account public?\": [\n \"\"\n ],\n \"Public accounts have their balance publicly accessible\": [\n \"\"\n ],\n \"Does this account belong to a Payment Service Provider?\": [\n \"\"\n ],\n \"update account\": [\n \"\"\n ],\n \"Account updated\": [\n \"\"\n ],\n \"The username was not found\": [\n \"\"\n ],\n \"You can't change the legal name, please contact the your account administrator.\": [\n \"\"\n ],\n \"You can't change the debt limit, please contact the your account administrator.\": [\n \"\"\n ],\n \"You can't change the cashout address, please contact the your account administrator.\": [\n \"\"\n ],\n \"Update account information.\": [\n \"\"\n ],\n \"Account \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Removed\": [\n \"\"\n ],\n \"This account can't be used.\": [\n \"\"\n ],\n \"Change details\": [\n \"\"\n ],\n \"Merchant integration\": [\n \"\"\n ],\n \"Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the \\\"import\\\" button in the \\\"bank account\\\" section.\": [\n \"\"\n ],\n \"Account type\": [\n \"\"\n ],\n \"Method to use for wire transfer.\": [\n \"\"\n ],\n \"IBAN\": [\n \"\"\n ],\n \"International Bank Account Number.\": [\n \"\"\n ],\n \"Account name\": [\n \"\"\n ],\n \"Bank host where the service is located.\": [\n \"\"\n ],\n \"Bank account identifier for wire transfers.\": [\n \"\"\n ],\n \"Address\": [\n \"\"\n ],\n \"Owner's name\": [\n \"\"\n ],\n \"Legal name of the person holding the account.\": [\n \"\"\n ],\n \"Account info URL\": [\n \"\"\n ],\n \"From where the merchant can download information about incoming wire transfers to this account.\": [\n \"\"\n ],\n \"Repeated password doesn't match\": [\n \"\"\n ],\n \"update password\": [\n \"\"\n ],\n \"Password changed\": [\n \"\"\n ],\n \"Not authorized to change the password, maybe the session is invalid.\": [\n \"\"\n ],\n \"You need to provide the old password. If you don't have it contact your account administrator.\": [\n \"\"\n ],\n \"Your current password doesn't match, can't change to a new password.\": [\n \"\"\n ],\n \"You don't have the rights to change the password.\": [\n \"\"\n ],\n \"Update account password.\": [\n \"\"\n ],\n \"Update password\": [\n \"\"\n ],\n \"Current password\": [\n \"\"\n ],\n \"Your current password, for security\": [\n \"\"\n ],\n \"New password\": [\n \"\"\n ],\n \"Type it again\": [\n \"\"\n ],\n \"Repeat the same password\": [\n \"\"\n ],\n \"Change\": [\n \"\"\n ],\n \"Create account\": [\n \"\"\n ],\n \"Actions\": [\n \"\"\n ],\n \"Unknown\": [\n \"\"\n ],\n \"Change password\": [\n \"\"\n ],\n \"Querying for the current stats failed\": [\n \"\"\n ],\n \"The request parameters are wrong\": [\n \"\"\n ],\n \"The user is unauthorized\": [\n \"\"\n ],\n \"Querying for the previous stats failed\": [\n \"\"\n ],\n \"Transaction volume report\": [\n \"\"\n ],\n \"Last hour\": [\n \"\"\n ],\n \"Previous day\": [\n \"\"\n ],\n \"Last month\": [\n \"\"\n ],\n \"Last year\": [\n \"\"\n ],\n \"Last Year\": [\n \"\"\n ],\n \"Trading volume from %1$s to %2$s\": [\n \"\"\n ],\n \"Transferred from an external account to an account in this bank.\": [\n \"\"\n ],\n \"Transferred from an account in this bank to an external account.\": [\n \"\"\n ],\n \"Payin\": [\n \"\"\n ],\n \"Transferred from an account to a Taler exchange.\": [\n \"\"\n ],\n \"Payout\": [\n \"\"\n ],\n \"Transferred from a Taler exchange to another account.\": [\n \"\"\n ],\n \"Download stats as CSV\": [\n \"\"\n ],\n \"previous\": [\n \"\"\n ],\n \"Decreased by\": [\n \"\"\n ],\n \"Increased by\": [\n \"\"\n ],\n \"create account\": [\n \"\"\n ],\n \"Account created with password \\\"%1$s\\\".\": [\n \"\"\n ],\n \"Server replied that phone or email is invalid\": [\n \"\"\n ],\n \"The rights to perform the operation are not sufficient\": [\n \"\"\n ],\n \"Account username is already taken\": [\n \"\"\n ],\n \"Account ID is already taken\": [\n \"\"\n ],\n \"Bank ran out of bonus credit.\": [\n \"\"\n ],\n \"Account username can't be used because is reserved\": [\n \"\"\n ],\n \"Can't create accounts\": [\n \"\"\n ],\n \"Only system admin can create accounts.\": [\n \"\"\n ],\n \"New bank account\": [\n \"\"\n ],\n \"download statistics\": [\n \"\"\n ],\n \"only admin can download stats\": [\n \"\"\n ],\n \"Download bank stats\": [\n \"\"\n ],\n \"Include hour metric\": [\n \"\"\n ],\n \"Include day metric\": [\n \"\"\n ],\n \"Include month metric\": [\n \"\"\n ],\n \"Include year metric\": [\n \"\"\n ],\n \"Include table header\": [\n \"\"\n ],\n \"Add previous metric for compare\": [\n \"\"\n ],\n \"Fail on first error\": [\n \"\"\n ],\n \"Download\": [\n \"\"\n ],\n \"downloading... %1$s\": [\n \"\"\n ],\n \"Download completed\": [\n \"\"\n ],\n \"Click here to save the file in your computer.\": [\n \"\"\n ],\n \"there was an error reading the balance\": [\n \"\"\n ],\n \"Can't delete the account\": [\n \"\"\n ],\n \"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.\": [\n \"\"\n ],\n \"Name doesn't match\": [\n \"\"\n ],\n \"delete account\": [\n \"\"\n ],\n \"Account removed\": [\n \"\"\n ],\n \"No enough permission to delete the account.\": [\n \"\"\n ],\n \"The username was not found.\": [\n \"\"\n ],\n \"Can't delete a reserved username.\": [\n \"\"\n ],\n \"Can't delete an account with balance different than zero.\": [\n \"\"\n ],\n \"Remove account.\": [\n \"\"\n ],\n \"You are going to remove the account\": [\n \"\"\n ],\n \"Deleting account \\\"%1$s\\\"\": [\n \"\"\n ],\n \"Verification\": [\n \"\"\n ],\n \"Enter the account name that is going to be deleted\": [\n \"\"\n ],\n \"Cashout id should be a number\": [\n \"\"\n ],\n \"This cashout not found. Maybe already aborted.\": [\n \"\"\n ],\n \"Cashout detail\": [\n \"\"\n ],\n \"Debited\": [\n \"\"\n ],\n \"Transferred\": [\n \"\"\n ],\n \"You have no permission to this account.\": [\n \"\"\n ],\n \"This account is locked. If you have a active session you can change the password or contact the administrator.\": [\n \"\"\n ],\n \"New web session\": [\n \"\"\n ],\n \"Welcome to %1$s!\": [\n \"\"\n ]\n }\n },\n \"domain\": \"messages\",\n \"plural_forms\": \"nplurals=2; plural=n != 1;\",\n \"lang\": \"ca\",\n \"completeness\": 0\n};\n\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport {\n Codec,\n buildCodecForObject,\n canonicalizeBaseUrl,\n codecForBoolean,\n codecForMap,\n codecForNumber,\n codecForString,\n codecOptional,\n} from \"@gnu-taler/taler-util\";\n\nexport interface UiSettings {\n // Where libeufin backend is localted\n // default: window.origin without \"webui/\"\n backendBaseURL?: string;\n // Shows a button \"create random account\" in the registration form\n // Useful for testing\n // default: false\n allowRandomAccountCreation?: boolean;\n // URL where the user is going to be redirected after\n // clicking in Taler Logo\n // default: home page\n iconLinkURL?: string;\n // Mapping for every link shown in the top navitation bar\n // - key: link label, what the user will read\n // - value: link target, where the user is going to be redirected\n // default: empty list\n topNavSites?: Record;\n // When the withdrawal form use the suggested amount the bank\n // will send a default value that the user can change.\n // default: 10\n defaultSuggestedAmount?: number;\n // Show a \"This is a demo\" info in the home screen.\n // default: false\n showDemoDescription?: boolean;\n}\n\n/**\n * Global settings for the bank UI.\n */\nconst defaultSettings: UiSettings = {\n backendBaseURL: buildDefaultBackendBaseURL(),\n iconLinkURL: undefined,\n allowRandomAccountCreation: false,\n showDemoDescription: false,\n topNavSites: {},\n defaultSuggestedAmount: 10,\n};\n\nconst codecForUISettings = (): Codec =>\n buildCodecForObject()\n .property(\"backendBaseURL\", codecOptional(codecForString()))\n .property(\"allowRandomAccountCreation\", codecOptional(codecForBoolean()))\n .property(\"showDemoDescription\", codecOptional(codecForBoolean()))\n .property(\"defaultSuggestedAmount\", codecOptional(codecForNumber()))\n .property(\"iconLinkURL\", codecOptional(codecForString()))\n .property(\"topNavSites\", codecOptional(codecForMap(codecForString())))\n .build(\"UiSettings\");\n\nfunction removeUndefineField(obj: T): T {\n const keys = Object.keys(obj) as Array;\n return keys.reduce((prev, cur) => {\n if (typeof prev[cur] === \"undefined\") {\n delete prev[cur];\n }\n return prev;\n }, obj);\n}\n\nexport function fetchSettings(listener: (s: UiSettings) => void): void {\n fetch(\"./settings.json\")\n .then((resp) => resp.json())\n .then((json) => codecForUISettings().decode(json))\n .then((result) =>\n listener({\n ...defaultSettings,\n ...removeUndefineField(result),\n }),\n )\n .catch((e) => {\n console.log(\"failed to fetch settings\", e);\n listener(defaultSettings);\n });\n}\n\nfunction buildDefaultBackendBaseURL(): string | undefined {\n if (typeof window !== \"undefined\") {\n const currentLocation = new URL(\n window.location.pathname,\n window.location.origin,\n ).href;\n /**\n * By default, bank backend serves the html content\n * from the /webui root.\n */\n return canonicalizeBaseUrl(currentLocation.replace(\"/webui\", \"\"));\n }\n throw Error(\"No default URL\");\n}\n", "/*\n This file is part of GNU Taler\n (C) 2022-2024 Taler Systems S.A.\n\n GNU Taler is free software; you can redistribute it and/or modify it under the\n terms of the GNU General Public License as published by the Free Software\n Foundation; either version 3, or (at your option) any later version.\n\n GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY\n WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License along with\n GNU Taler; see the file COPYING. If not, see \n */\n\nimport { App } from \"./app.js\";\nimport { h, render, VNode } from \"preact\";\nimport \"./scss/main.css\";\n\nfunction getState(node: VNode) {\n const component = node.type as any;\n return { key: node.key, props: node.props, screen: component.SCREEN_ID };\n}\n\nconst element = document.getElementById(\"app\");\nif (element) {\n const vnode = ;\n // @ts-expect-error unknown var\n window.showPreactState = () => {\n console.log(JSON.stringify(getState(vnode), undefined, 2));\n };\n render(vnode, element);\n} else {\n console.error(\"HTML element with id 'app' not found.\");\n}\n"], "mappings": "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G,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAA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CACR,WAAY,CACV,IAAK,WACL,MAAO,mBACT,EACA,gBAAiB,CACf,IAAK,WACL,MAAO,mBACT,CACF,EACA,YAAa,CACX,WAAY,CACV,IAAK,gBACL,MAAO,wBACT,EACA,gBAAiB,CACf,IAAK,gBACL,MAAO,wBACT,CACF,EACA,OAAQ,CACN,WAAY,CACV,IAAK,WACL,MAAO,mBACT,EACA,gBAAiB,CACf,IAAK,WACL,MAAO,mBACT,CACF,EACA,MAAO,CACL,WAAY,CACV,IAAK,QACL,MAAO,gBACT,EACA,gBAAiB,CACf,IAAK,QACL,MAAO,iBACT,CACF,EACA,YAAa,CACX,WAAY,CACV,IAAK,eACL,MAAO,uBACT,EACA,gBAAiB,CACf,IAAK,eACL,MAAO,uBACT,CACF,EACA,OAAQ,CACN,WAAY,CACV,IAAK,UACL,MAAO,kBACT,EACA,gBAAiB,CACf,IAAK,UACL,MAAO,kBACT,CACF,EACA,aAAc,CACZ,WAAY,CACV,IAAK,eACL,MAAO,uBACT,EACA,gBAAiB,CACf,IAAK,eACL,MAAO,wBACT,CACF,EACA,QAAS,CACP,WAAY,CACV,IAAK,UACL,MAAO,kBACT,EACA,gBAAiB,CACf,IAAK,UACL,MAAO,mBACT,CACF,EACA,YAAa,CACX,WAAY,CACV,IAAK,cACL,MAAO,sBACT,EACA,gBAAiB,CACf,IAAK,cACL,MAAO,uBACT,CACF,EACA,OAAQ,CACN,WAAY,CACV,IAAK,SACL,MAAO,iBACT,EACA,gBAAiB,CACf,IAAK,SACL,MAAO,kBACT,CACF,EACA,WAAY,CACV,WAAY,CACV,IAAK,kBACL,MAAO,0BACT,EACA,gBAAiB,CACf,IAAK,kBACL,MAAO,2BACT,CACF,EACA,aAAc,CACZ,WAAY,CACV,IAAK,cACL,MAAO,sBACT,EACA,gBAAiB,CACf,IAAK,cACL,MAAO,uBACT,CACF,CACF,EAEIC,GAAiB,SAAwBC,EAAOC,EAAOC,EAAS,CAClE,IAAIjI,EACAkI,EAAaD,GAAY,MAA8BA,EAAQ,UAAYJ,GAAqBE,CAAK,EAAE,gBAAkBF,GAAqBE,CAAK,EAAE,WAUzJ,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ACzE,IAAMC,EAAW,CAAE,GAAGN,EAAO,CAACI,CAAC,EAAGC,CAAE,EACpCJ,EAAOK,CAAQ,CACjB,CACA,MAAO,CAACN,EAAOG,CAAW,CAC5B,CAEO,SAASI,GACdC,EAC0B,CAC1B,OAAIA,EAAS,oBACJ,CACL,WACA,oBACA,wBACA,oBACF,EAEK,CAAC,oBAAqB,wBAAyB,oBAAoB,CAC5E,CAEO,SAASC,GACdL,EACAM,EACkB,CAClB,OAAQN,EAAG,CACT,IAAK,wBACH,OAAOM,EAAK,kCACd,IAAK,qBACH,OAAOA,EAAK,qCACd,IAAK,WACH,OAAOA,EAAK,qBACd,IAAK,oBACH,OAAOA,EAAK,8BAGhB,CACF,CC7FA,IAAMC,GAAO,CACX,SACA,UACA,MACA,MACA,QACA,cACA,MACA,MACA,SACA,aACA,SACA,SACA,WACA,OACA,OACA,SACA,QACA,SACA,UACA,SACA,OACA,OACA,gBACA,SACA,MACA,OACA,aACA,UACA,WACA,UACA,YACA,QACA,UACA,YACA,OACA,WACA,aACA,UACA,UACA,SACA,OACA,UACA,OACA,cACA,aACA,OACA,UACA,WACA,QACA,WACA,QACA,QACA,OACA,YACA,aACA,SACA,UACA,cACA,WACA,aACA,SACA,UACA,QACA,OACA,WACA,UACA,OACA,QACA,eACA,YACA,UACA,WACA,SACA,SACA,UACA,QACA,YACA,YACA,WACA,aACA,OACA,SACA,UACA,QACA,cACA,QACA,WACA,QACA,QACA,YACA,aACA,UACA,UACA,aACA,aACA,OACA,OACA,WACA,UACA,SACA,SACA,WACA,OACA,cACA,UACA,UACA,WACA,aACA,UACA,gBACA,QACA,YACA,UACA,OACA,SACA,SACA,OACA,OACA,OACA,cACA,WACA,UACA,WACA,YACA,YACA,OACA,SACA,WACA,WACA,YACA,WACA,QACA,WACA,WACA,UACA,OACA,cACA,eACA,gBACA,SACA,aACA,YACA,OACA,WACA,YACA,UACA,eACA,cACA,cACA,SACA,SACA,SACA,WACA,YACA,eACA,WACA,OACA,SACA,UACA,OACA,SACA,UACA,QACA,QACA,aACA,cACA,UACA,WACA,QACA,aACA,UACA,YACA,YACA,OACA,QACA,SACA,QACA,SACA,aACA,aACA,UACA,UACA,UACA,iBACA,YACA,QACA,YACA,SACA,cACA,OACA,SACA,QACA,SACA,aACA,cACA,QACA,cACA,QACA,SACA,SACA,QACA,aACA,aACA,cACA,UACA,aACA,WACA,UACA,KACA,SACA,UACA,aACA,YACA,OACA,cACA,SACA,WACA,YACA,WACA,iBACA,SACA,WACA,WACA,cACA,aACA,iBACA,WACA,YACA,UACA,UACA,UACA,WACA,YACA,WACA,WACA,UACA,OACA,aACA,aACA,cACA,QACA,QACA,YACA,SACA,WACA,aACA,cACA,QACA,cACA,UACA,aACA,SACA,WACA,YACA,QACA,QACA,YACA,WACA,SACA,aACA,QACA,WACA,SACA,WACA,WACA,QACA,QACA,WACA,aACA,aACA,UACA,YACA,UACA,aACA,YACA,OACA,QACA,YACA,UACA,aACA,YACA,eACA,WACA,UACA,WACA,WACA,QACA,SACA,aACA,OACA,UACA,YACA,YACA,SACA,iBACA,UACA,SACA,WACA,SACA,aACA,aACA,SACA,WACA,SACA,WACA,SACA,MACA,UACA,aACA,eACA,YACA,aACA,eACA,aACA,UACA,UACA,SACA,SACA,SACA,QACA,UACA,YACA,SACA,UACA,SACA,SACA,UACA,OACA,UACA,aACA,WACA,MACA,cACA,OACA,MACA,SACA,SACA,SACA,cACA,YACA,QACA,QACA,WACA,aACA,eACA,SACA,YACA,eACA,OACA,QACA,OACA,UACA,SACA,OACA,WACA,UACA,cACA,UACA,aACA,WACA,UACA,YACA,eACA,WACA,aACA,QACA,cACA,SACA,OACA,OACA,OACA,YACA,WACA,SACA,cACA,cACA,eACA,OACA,aACA,MACA,OACA,WACA,WACA,YACA,cACA,aACA,QACA,MACA,SACA,MACA,UACA,UACA,SACA,SACA,SACA,aACA,SACA,QACA,QACA,YACA,aACA,eACA,SACA,UACA,MACA,OACA,SACA,gBACA,cACA,UACA,UACA,QACA,aACA,cACA,eACA,SACA,aACA,YACA,OACA,SACA,OACA,UACA,QACA,SACA,aACA,YACA,WACA,WACA,cACA,QACA,SACA,cACA,SACA,WACA,UACA,SACA,WACA,UACA,QACA,aACA,YACA,WACA,UACA,OACA,WACA,cACA,eACA,QACA,SACA,cACA,YACA,UACA,OACA,MACA,UACA,aACA,UACA,OACA,aACA,MACA,aACA,YACA,OACA,WACA,cACA,aACA,YACA,QACA,WACA,OACA,YACA,cACA,aACA,QACA,MACA,UACA,WACA,UACA,WACA,OACA,SACA,UACA,QACA,QACA,OACA,OACA,OACA,QACA,QACA,UACA,QACA,WACA,QACA,OACA,OACA,OACA,MACA,MACA,QACA,SACA,OACA,QACA,OACA,OACA,UACA,OACA,OACA,aACA,MACA,OACA,MACA,QACA,OACA,OACA,UACA,QACA,OACA,SACA,QACA,WACA,QACA,QACA,SACA,UACA,QACA,OACA,OACA,OACA,OACA,QACA,OACA,OACA,QACA,OACA,OACA,MACA,QACA,MACA,QACA,WACA,OACA,SACA,MACA,SACA,QACA,QACA,WACA,WACA,QACA,UACA,QACA,MACA,OACA,QACA,MACA,QACA,OACA,OACA,OACA,SACA,QACA,QACA,SACA,OACA,OACA,QACA,MACA,UACA,SACA,SACA,QACA,OACA,SACA,SACA,OACA,SACA,WACA,QACA,OACA,QACA,QACA,SACA,MACA,MACA,OACA,SACA,SACA,UACA,WACA,QACA,OACA,QACA,UACA,SACA,OACA,QACA,MACA,OACA,UACA,QACA,OACA,QACA,UACA,SACA,SACA,MACA,QACA,SACA,YACA,QACA,UACA,UACA,SACA,UACA,OACA,WACA,UACA,WACA,OACA,OACA,MACA,QACA,MACA,MACA,SACA,QACA,MACA,OACA,SACA,OACA,QACA,QACA,MACA,OACA,QACA,OACA,SACA,UACA,WACA,MACA,WACA,MACA,OACA,WACA,WACA,SACA,YACA,UACA,MACA,QACA,QACA,OACA,QACA,OACA,OACA,QACA,QACA,SACA,OACA,SACA,YACA,OACA,UACA,OACA,aACA,SACA,QACA,UACA,MACA,QACA,SACA,SACA,OACA,SACA,UACA,QACA,OACA,OACA,UACA,UACA,SACA,UACA,UACA,MACA,OACA,QACA,OACA,YACA,UACA,SACA,MACA,OACA,MACA,UACA,QACA,SACA,UACA,OACA,SACA,OACA,OACA,OACA,QACA,UACA,YACA,SACA,OACA,OACA,QACA,SACA,SACA,OACA,QACA,WACA,OACA,SACA,QACA,UACA,OACA,SACA,QACA,QACA,QACA,OACA,QACA,SACA,QACA,SACA,OACA,MACA,YACA,SACA,OACA,OACA,OACA,SACA,WACA,UACA,OACA,UACA,QACA,QACA,SACA,OACA,SACA,SACA,SACA,WACA,OACA,SACA,SACA,SACA,UACA,QACA,YACA,WACA,MACA,QACA,QACA,QACA,UACA,OACA,SACA,WACA,YACA,OACA,OACA,WACA,MACA,SACA,OACA,UACA,QACA,SACA,OACA,OACA,SACA,UACA,OACA,OACA,SACA,OACA,aACA,QACA,OACA,SACA,QACA,QACA,QACA,SACA,SACA,MACA,WACA,UACA,OACA,YACA,SACA,QACA,OACA,QACA,UACA,OACA,MACA,SACA,MACA,QACA,YACA,WACA,OACA,SACA,SACA,SACA,SACA,OACA,OACA,OACA,QACA,aACA,OACA,OACA,UACA,OACA,WACA,UACA,MACA,QACA,SACA,QACA,SACA,OACA,QACA,OACA,YACA,aACA,WACA,SACA,SACA,MACA,QACA,OACA,QACA,SACA,MACA,UACA,OACA,QACA,QACA,OACA,OACA,QACA,QACA,OACA,OACA,SACA,QACA,YACA,OACA,QACA,YACA,MACA,QACA,QACA,QACA,QACA,gBACA,QACA,OACA,SACA,OACA,YACA,MACA,OACA,QACA,UACA,OACA,WACA,QACA,QACA,MACA,OACA,SACA,OACA,OACA,SACA,QACA,OACA,QACA,OACA,WACA,MACA,OACA,UACA,SACA,QACA,MACA,WACA,OACA,OACA,SACA,SACA,YACA,OACA,OACA,YACA,QACA,UACA,MACA,SACA,UACA,OACA,UACA,UACA,UACA,UACA,OACA,UACA,WACA,WACA,YACA,MACA,SACA,UACA,MACA,SACA,MACA,OACA,SACA,OACA,OACA,QACA,WACA,YACA,QACA,OACA,YACA,UACA,YACA,OACA,QACA,MACA,QACA,UACA,SACA,QACA,OACA,UACA,OACA,UACA,WACA,OACA,QACA,WACA,UACA,UACA,QACA,SACA,QACA,OACA,SACA,OACA,WACA,WACA,QACA,UACA,SACA,UACA,QACA,WACA,OACA,QACA,OACA,MACA,QACA,YACA,MACA,OACA,SACA,SACA,SACA,UACA,QACA,QACA,OACA,QACA,QACA,WACA,QACA,OACA,SACA,QACA,MACA,OACA,QACA,OACA,QACA,QACA,YACA,SACA,OACA,OACA,SACA,UACA,SACA,UACA,MACA,OACA,QACA,UACA,SACA,QACA,UACA,OACA,SACA,SACA,OACA,QACA,SACA,OACA,MACA,OACA,OACA,QACA,MACA,QACA,QACA,SACA,OACA,SACA,UACA,aACA,QACA,OACA,OACA,OACA,QACA,SACA,QACA,UACA,WACA,QACA,OACA,QACA,OACA,QACA,SACA,MACA,WACA,QACA,QACA,QACA,WACA,OACA,aACA,UACA,UACA,OACA,QACA,OACA,UACA,OACA,QACA,SACA,QACA,SACA,QACA,QACA,UACA,UACA,SACA,cACA,OACA,OACA,SACA,UACA,OACA,SACA,OACA,UACA,QACA,SACA,OACA,OACA,QACA,QACA,OACA,aACA,SACA,SACA,QACA,OACA,OACA,QACA,QACA,MACA,SACA,OACA,MACA,OACA,QACA,SACA,MACA,WACA,UACA,QACA,UACA,MACA,QACA,WACA,WACA,QACA,QACA,MACA,OACA,YACA,WACA,SACA,OACA,OACA,MACA,MACA,OACA,QACA,QACA,UACA,MACA,QACA,SACA,QACA,UACA,WACA,SACA,OACA,OACA,OACA,OACA,SACA,SACA,OACA,UACA,MACA,QACA,QACA,UACA,IACA,MACA,KACA,MACA,OACA,KACA,MACA,OACA,OACA,QACA,MACA,OACA,OACA,OACA,OACA,KACA,QACA,QACA,MACA,QACA,QACA,SACA,OACA,OACA,QACA,OACA,QACA,QACA,UACA,MACA,WACA,OACA,OACA,OACA,OACA,UACA,MACA,SACA,MACA,SACA,SACA,OACA,MACA,WACA,aACA,QACA,QACA,WACA,UACA,WACA,MACA,UACA,WACA,OACA,MACA,QACA,SACA,OACA,OACA,MACA,MACA,WACA,SACA,aACA,OACA,MACA,MACA,QACA,OACA,OACA,QACA,YACA,eACA,gBACA,SACA,OACA,cACA,YACA,UACA,UACA,QACA,QACA,SACA,OACA,aACA,MACA,WACA,OACA,UACA,QACA,OACA,YACA,WACA,UACA,SACA,UACA,QACA,OACA,WACA,OACA,OACA,QACA,QACA,UACA,OACA,SACA,SACA,MACA,UACA,MACA,YACA,SACA,UACA,UACA,cACA,QACA,WACA,QACA,OACA,QACA,QACA,YACA,SACA,SACA,QACA,WACA,OACA,OACA,QACA,SACA,SACA,QACA,SACA,OACA,OACA,QACA,SACA,SACA,OACA,SACA,WACA,UACA,QACA,OACA,MACA,UACA,OACA,QACA,UACA,UACA,WACA,MACA,WACA,QACA,cACA,OACA,QACA,OACA,OACA,QACA,QACA,OACA,QACA,QACA,OACA,SACA,WACA,QACA,SACA,UACA,OACA,UACA,OACA,SACA,SACA,QACA,OACA,SACA,SACA,SACA,QACA,OACA,QACA,OACA,UACA,OACA,MACA,YACA,QACA,QACA,SACA,WACA,MACA,OACA,UACA,OACA,WACA,MACA,OACA,SACA,OACA,OACA,WACA,OACA,QACA,SACA,QACA,QACA,OACA,QACA,OACA,OACA,UACA,QACA,QACA,QACA,YACA,UACA,WACA,UACA,OACA,SACA,OACA,QACA,MACA,OACA,WACA,OACA,OACA,YACA,MACA,MACA,SACA,QACA,WACA,OACA,QACA,QACA,QACA,OACA,MACA,OACA,QACA,OACA,QACA,SACA,SACA,QACA,OACA,QACA,OACA,UACA,UACA,SACA,SACA,QACA,OACA,QACA,QACA,UACA,OACA,UACA,UACA,MACA,SACA,aACA,OACA,OACA,UACA,QACA,UACA,QACA,YACA,SACA,MACA,QACA,QACA,QACA,SACA,SACA,OACA,QACA,SACA,QACA,MACA,UACA,OACA,SACA,SACA,WACA,OACA,UACA,QACA,MACA,SACA,QACA,WACA,UACA,QACA,SACA,QACA,SACA,WACA,OACA,QACA,QACA,OACA,SACA,UACA,QACA,YACA,OACA,QACA,OACA,OACA,OACA,SACA,QACA,UACA,UACA,OACA,OACA,OACA,QACA,UACA,QACA,QACA,QACA,WACA,QACA,SACA,QACA,OACA,cACA,WACA,QACA,OACA,OACA,SACA,QACA,SACA,SACA,SACA,OACA,QACA,QACA,QACA,QACA,OACA,WACA,UACA,OACA,YACA,OACA,OACA,QACA,QACA,SACA,QACA,aACA,SACA,OACA,OACA,MACA,QACA,OACA,QACA,iBACA,SACA,MACA,MACA,QACA,QACA,QACA,UACA,SACA,OACA,YACA,WACA,OACA,OACA,WACF,EAEMC,GAAM,CACV,YACA,OACA,WACA,WACA,cACA,WACA,aACA,YACA,eACA,WACA,SACA,SACA,YACA,SACA,SACA,QACA,YACA,UACA,aACA,WACA,SACA,WACA,SACA,eACA,OACA,cACA,aACA,QACA,WACA,YACA,YACA,OACA,UACA,WACA,QACA,YACA,QACA,MACA,aACA,UACA,YACA,QACA,SACA,UACA,WACA,UACA,UACA,QACA,YACA,WACA,SACA,UACA,UACA,UACA,MACA,eACA,cACA,MACA,SACA,OACA,WACA,WACA,UACA,UACA,cACA,WACA,WACA,YACA,aACA,UACA,YACA,aACA,YACA,aACA,UACA,QACA,UACA,QACA,UACA,UACA,MACA,OACA,QACA,OACA,SACA,QACA,YACA,UACA,UACA,aACA,SACA,OACA,YACA,MACA,cACA,gBACA,aACA,SACA,QACA,kBACA,QACA,QACA,UACA,QACA,QACA,WACA,QACA,OACA,WACA,QACA,UACA,OACA,OACA,SACA,QACA,OACA,SACA,YACA,QACA,QACA,YACA,QACA,SACA,YACA,QACA,SACA,SACA,QACA,UACA,SACA,QACA,QACA,UACA,aACA,QACA,WACA,OACA,UACA,UACA,cACA,OACA,SACA,SACA,UACA,WACA,UACA,WACA,SACA,WACA,YACA,aACA,WACA,QACA,WACA,SACA,QACA,SACA,SACA,WACA,UACA,QACA,QACA,YACA,SACA,QACA,SACA,SACA,WACA,SACA,YACA,SACA,OACA,WACA,YACA,WACA,cACA,SACA,gBACA,YACA,WACA,UACA,cACA,WACA,YACA,WACA,WACA,YACA,cACA,WACA,UACA,eACA,SACA,OACA,cACA,cACA,QACA,UACA,SACA,aACA,YACA,SACA,QACA,SACA,WACA,SACA,WACA,QACA,WACA,UACA,UACA,QACA,WACA,SACA,aACA,WACA,aACA,QACA,QACA,OACA,cACA,UACA,OACA,YACA,SACA,SACA,UACA,OACA,WACA,OACA,SACA,YACA,OACA,UACA,SACA,UACA,WACA,OACA,cACA,YACA,UACA,YACA,WACA,aACA,UACA,aACA,YACA,aACA,YACA,YACA,QACA,SACA,aACA,YACA,cACA,WACA,WACA,aACA,UACA,YACA,YACA,UACA,WACA,MACA,UACA,YACA,SACA,aACA,WACA,aACA,aACA,WACA,SACA,UACA,YACA,SACA,QACA,YACA,YACA,SACA,UACA,WACA,YACA,QACA,QACA,SACA,SACA,YACA,OACA,SACA,WACA,SACA,SACA,MACA,OACA,OACA,UACA,OACA,QACA,UACA,QACA,OACA,aACA,WACA,SACA,WACA,YACA,UACA,SACA,UACA,WACA,UACA,aACA,aACA,cACA,cACA,UACA,YACA,QACA,YACA,aACA,YACA,cACA,WACA,UACA,SACA,UACA,QACA,aACA,YACA,WACA,UACA,WACA,OACA,YACA,cACA,QACA,OACA,UACA,YACA,YACA,YACA,YACA,UACA,WACA,SACA,YACA,cACA,SACA,aACA,cACA,cACA,cACA,WACA,UACA,QACA,OACA,WACA,OACA,QACA,WACA,SACA,QACA,YACA,MACA,UACA,YACA,UACA,OACA,MACA,QACA,WACA,YACA,WACA,UACA,WACA,SACA,SACA,SACA,WACA,MACA,SACA,SACA,OACA,WACA,OACA,QACA,YACA,UACA,QACA,QACA,aACA,SACA,OACA,SACA,WACA,aACA,SACA,WACA,UACA,SACA,QACA,YACA,UACA,OACA,YACA,UACA,WACA,SACA,SACA,WACA,aACA,YACA,WACA,QACA,QACA,SACA,OACA,SACA,QACA,WACA,WACA,aACA,cACA,SACA,SACA,SACA,YACA,QACA,SACA,SACA,SACA,WACA,OACA,WACA,aACA,QACA,QACA,QACA,aACA,UACA,UACA,WACA,SACA,UACA,QACA,QACA,WACA,SACA,SACA,YACA,UACA,QACA,WACA,UACA,aACA,aACA,SACA,WACA,SACA,OACA,SACA,OACA,eACA,WACA,WACA,WACA,QACA,YACA,WACA,WACA,QACA,OACA,QACA,SACA,QACA,aACA,OACA,QACA,WACA,WACA,QACA,YACA,UACA,WACA,UACA,WACA,QACA,SACA,WACA,SACA,SACA,WACA,QACA,QACA,OACA,WACA,WACA,QACA,QACA,iBACA,OACA,eACA,UACA,WACA,aACA,QACA,QACA,UACA,WACA,UACA,YACA,SACA,WACA,QACA,QACA,UACA,WACA,SACA,UACA,OACA,aACA,YACA,SACA,SACA,SACA,SACA,YACA,UACA,UACA,WACA,aACA,MACA,OACA,SACA,cACA,UACA,YACA,SACA,UACA,QACA,OACA,MACA,QACA,aACA,YACA,OACA,UACA,WACA,WACA,MACA,UACA,YACA,eACA,aACA,cACA,YACA,cACA,aACA,aACA,YACA,UACA,cACA,aACA,YACA,YACA,gBACA,SACA,WACA,YACA,aACA,cACA,iBACA,aACA,aACA,SACA,SACA,eACA,eACA,aACA,kBACA,aACA,YACA,gBACA,WACA,WACA,YACA,aACA,WACA,WACA,WACA,WACA,WACA,YACA,gBACA,YACA,cACA,gBACA,cACA,SACA,cACA,cACA,WACA,gBACA,WACA,WACA,gBACA,aACA,QACA,QACA,SACA,aACA,SACA,UACA,UACA,QACA,QACA,SACA,SACA,SACA,WACA,YACA,QACA,QACA,SACA,QACA,WACA,gBACA,OACA,MACA,OACA,cACA,SACA,SACA,SACA,SACA,gBACA,UACA,QACA,QACA,SACA,OACA,QACA,QACA,OACA,UACA,OACA,SACA,SACA,OACA,UACA,OACA,QACA,OACA,QACA,aACA,QACA,eACA,UACA,SACA,UACA,OACA,UACA,SACA,QACA,SACA,SACA,OACA,SACA,QACA,YACA,OACA,SACA,OACA,YACA,QACA,WACA,OACA,OACA,UACA,SACA,SACA,MACA,QACA,QACA,YACA,WACA,QACA,WACA,YACA,MACA,UACA,cACA,WACA,QACA,OACA,UACA,UACA,YACA,YACA,UACA,SACA,SACA,QACA,OACA,SACA,QACA,UACA,WACA,SACA,OACA,SACA,UACA,YACA,WACA,QACA,QACA,WACA,OACA,QACA,WACA,YACA,QACA,QACA,YACA,UACA,YACA,QACA,QACA,SACA,SACA,QACA,YACA,UACA,aACA,QACA,YACA,WACA,aACA,cACA,QACA,UACA,eACA,UACA,QACA,QACA,QACA,QACA,aACA,QACA,SACA,QACA,UACA,UACA,WACA,OACA,OACA,YACA,QACA,WACA,YACA,aACA,cACA,UACA,MACA,OACA,OACA,QACA,SACA,QACA,YACA,QACA,UACA,SACA,UACA,QACA,aACA,QACA,UACA,OACA,aACA,QACA,WACA,QACA,SACA,OACA,SACA,UACA,aACA,MACA,UACA,UACA,YACA,WACA,MACA,gBACA,OACA,OACA,UACA,aACA,UACA,SACA,UACA,UACA,SACA,SACA,WACA,WACA,QACA,MACA,WACA,WACA,aACA,aACA,cACA,OACA,aACA,UACA,YACA,aACA,YACA,OACA,SACA,WACA,UACA,UACA,aACA,OACA,SACA,WACA,UACA,UACA,WACA,WACA,QACA,WACA,YACA,QACA,cACA,QACA,QACA,WACA,WACA,OACA,UACA,QACA,YACA,UACA,UACA,WACA,UACA,WACA,QACA,QACA,WACA,SACA,YACA,UACA,YACA,SACA,OACA,UACA,SACA,OACA,WACA,WACA,UACA,WACA,YACA,YACA,WACA,UACA,cACA,SACA,WACA,WACA,SACA,UACA,UACA,QACA,WACA,UACA,QACA,WACA,aACA,aACA,UACA,SACA,QACA,UACA,WACA,UACA,OACA,OACA,SACA,QACA,SACA,UACA,WACA,SACA,YACA,cACA,YACA,SACA,YACA,eACA,QACA,eACA,QACA,iBACA,SACA,WACA,YACA,UACA,SACA,QACA,OACA,OACA,MACA,SACA,WACA,cACA,QACA,OACA,YACA,aACA,MACA,aACA,QACA,UACA,WACA,WACA,aACA,aACA,SACA,YACA,WACA,aACA,cACA,YACA,YACA,YACA,OACA,QACA,QACA,SACA,OACA,UACA,SACA,OACA,WACA,SACA,QACA,QACA,QACA,QACA,UACA,UACA,QACA,OACA,QACA,QACA,QACA,MACA,OACA,QACA,OACA,QACA,OACA,YACA,WACA,YACA,QACA,SACA,SACA,QACA,UACA,YACA,aACA,WACA,WACA,UACA,SACA,YACA,cACA,SACA,eACA,eACA,UACA,cACA,WACA,SACA,UACA,aACA,UACA,SACA,SACA,UACA,QACA,UACA,WACA,YACA,QACA,aACA,QACA,UACA,WACA,SACA,QACA,aACA,QACA,SACA,MACA,OACA,SACA,QACA,QACA,SACA,UACA,SACA,aACA,SACA,SACA,WACA,WACA,SACA,SACA,SACA,OACA,QACA,WACA,OACA,SACA,QACA,QACA,SACA,SACA,OACA,SACA,WACA,SACA,YACA,SACA,WACA,OACA,QACA,QACA,SACA,OACA,YACA,gBACA,OACA,YACA,UACA,QACA,OACA,UACA,YACA,SACA,WACA,cACA,SACA,QACA,SACA,WACA,WACA,WACA,WACA,UACA,OACA,SACA,UACA,WACA,SACA,QACA,UACA,QACA,WACA,UACA,QACA,SACA,QACA,SACA,QACA,cACA,SACA,SACA,WACA,UACA,QACA,SACA,WACA,WACA,UACA,SACA,WACA,WACA,aACA,SACA,SACA,UACA,UACA,aACA,cACA,SACA,WACA,SACA,SACA,QACA,QACA,SACA,cACA,WACA,aACA,cACA,YACA,aACA,SACA,SACA,QACA,aACA,QACA,cACA,OACA,YACA,OACA,MACA,WACA,OACA,QACA,WACA,OACA,UACA,UACA,WACA,SACA,QACA,QACA,WACA,WACA,QACA,WACA,OACA,QACA,QACA,OACA,QACA,UACA,OACA,WACA,SACA,QACA,aACA,aACA,UACA,aACA,OACA,QACA,SACA,SACA,OACA,QACA,OACA,QACA,QACA,YACA,YACA,aACA,SACA,UACA,aACA,aACA,SACA,WACA,OACA,UACA,WACA,OACA,WACA,cACA,SACA,WACA,QACA,YACA,OACA,OACA,WACA,eACA,UACA,gBACA,WACA,cACA,cACA,YACA,SACA,aACA,QACA,WACA,cACA,UACA,YACA,UACA,cACA,SACA,SACA,UACA,UACA,WACA,UACA,UACA,YACA,aACA,cACA,SACA,SACA,YACA,YACA,WACA,SACA,SACA,WACA,UACA,SACA,SACA,UACA,YACA,WACA,YACA,YACA,YACA,SACA,UACA,QACA,QACA,SACA,OACA,SACA,UACA,WACA,QACA,SACA,QACA,OACA,QACA,WACA,QACA,WACA,OACA,UACA,YACA,WACA,aACA,UACA,UACA,aACA,WACA,WACA,aACA,SACA,UACA,UACA,WACA,UACA,QACA,YACA,QACA,aACA,MACA,UACA,OACA,cACA,SACA,OACA,WACA,WACA,cACA,SACA,OACA,UACA,OACA,QACA,SACA,OACA,SACA,QACA,UACA,QACA,UACA,kBACA,eACA,gBACA,WACA,YACA,WACA,aACA,YACA,MACA,QACA,YACA,YACA,YACA,QACA,QACA,WACA,SACA,OACA,YACA,SACA,OACA,UACA,SACA,UACA,QACA,SACA,OACA,OACA,QACA,SACA,SACA,YACA,SACA,QACA,QACA,UACA,OACA,UACA,YACA,QACA,QACA,YACA,aACA,SACA,WACA,WACA,WACA,QACA,MACA,UACA,SACA,SACA,YACA,QACA,WACA,QACA,OACA,UACA,QACA,QACF,EAEO,SAASC,IAAuD,CACrE,IAAMC,EAAI,KAAK,MAAM,KAAK,OAAO,EAAIH,GAAK,MAAM,EAC1CI,EAAI,KAAK,MAAM,KAAK,OAAO,EAAIH,GAAI,MAAM,EAC/C,MAAO,CACL,MAAOA,GAAIG,CAAC,EACZ,OAAQJ,GAAKG,CAAC,CAChB,CACF,CAEO,SAASE,IAA4B,CAC1C,OAAOC,GAAYC,GAAe,EAAE,CAAC,CACvC,CHrzFA,IAAMC,GAAkB,IAExBC,GAAiB,UAAYD,GACtB,SAASC,GAAiB,CAC/B,wBAAAC,EACA,YAAAC,CACF,EAGU,CACR,GAAM,CAAE,KAAAC,CAAK,EAAIC,GAAsB,EACjC,CAAE,OAAAC,CAAO,EAAIC,GAAsB,EACzC,OAAKD,EAAO,oBAMVE,EAACC,GAAA,CACC,wBAAyBP,EACzB,YAAaC,EACf,EAPEK,EAAC,SAAGJ,EAAK,4DAA6D,CAS5E,CAGO,IAAMM,GAAiB,yBAO9BD,GAAiB,UAAYT,GAC7B,SAASS,GAAiB,CACxB,wBAAAP,EACA,YAAAC,CACF,EAGU,CACR,GAAM,CAACQ,EAAUC,CAAW,EAAIC,GAA6B,EACvD,CAACC,EAAMC,CAAO,EAAIF,GAA6B,EAC/C,CAACG,EAAUC,CAAW,EAAIJ,GAA6B,EAGvD,CAACK,EAAgBC,CAAiB,EAAIN,GAA6B,EACnE,CAACO,EAAcC,CAAmB,EAAIC,GAA2B,EACjEC,E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CF,EACA,4CAA6C,CAC3C,EACF,EACA,yFAA0F,CACxF,EACF,EACA,+BAAgC,CAC9B,+LACF,EACA,qBAAsB,CACpB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qEAAsE,CACpE,EACF,EACA,kEAAmE,CACjE,EACF,EACA,KAAQ,CACN,EACF,EACA,0BAA2B,CACzB,0LACF,EACA,0BAA2B,CACzB,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,KAAQ,CACN,EACF,EACA,OAAU,CACR,EACF,EACA,qBAAsB,CACpB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,oEAAqE,CACnE,EACF,EACA,4BAA6B,CAC3B,2GACF,EACA,mBAAoB,CAClB,EACF,EACA,uCAAwC,CACtC,uIACF,EACA,wKAAyK,CACvK,EACF,EACA,qEAAsE,CACpE,yNACF,EACA,yEAA0E,CACxE,EACF,EACA,4EAA6E,CAC3E,EACF,EACA,iCAAoC,CAClC,EACF,EACA,oCAAuC,CACrC,EACF,EACA,gBAAiB,CACf,EACF,EACA,oBAAqB,CACnB,EACF,EACA,kDAAmD,CACjD,EACF,EACA,OAAU,CACR,EACF,EACA,SAAY,CACV,EACF,EACA,6BAA8B,CAC5B,0LACF,EACA,8DAA+D,CAC7D,4TACF,EACA,MAAS,CACP,4CACF,EACA,sBAAuB,CACrB,kIACF,EACA,oIAAqI,CACnI,EACF,EACA,2BAA4B,CAC1B,2EACF,EACA,4CAA6C,CAC3C,sRACF,EACA,0BAA2B,CACzB,gHACF,EACA,iCAAkC,CAChC,iKACF,EACA,gDAAiD,CAC/C,EACF,EACA,yBAA0B,CACxB,0QACF,EACA,gCAAiC,CAC/B,6KACF,EACA,QAAW,CACT,kDACF,EACA,4BAA6B,CAC3B,8KACF,EACA,wBAAyB,CACvB,yGACF,EACA,qDAAsD,CACpD,EACF,EACA,qDAAsD,CACpD,qTACF,EACA,iBAAkB,CAChB,wIACF,EACA,kBAAmB,CACjB,kIACF,EACA,yCAA0C,CACxC,uIACF,EACA,oBAAqB,CACnB,qJACF,EACA,8EAA+E,CAC7E,qbACF,EACA,8CAA+C,CAC7C,8NACF,EACA,6CAA8C,CAC5C,iKACF,EACA,qCAAsC,CACpC,8LACF,EACA,oDAAqD,CACnD,EACF,EACA,qFAAsF,CACpF,2iBACF,EACA,sDAAuD,CACrD,sRACF,EACA,kBAAmB,CACjB,wIACF,EACA,QAAW,CACT,6FACF,EACA,kBAAmB,CACjB,2EACF,EACA,QAAW,CACT,sCACF,EACA,IAAO,CACL,4CACF,EACA,aAAc,CACZ,yDACF,EACA,aAAc,CACZ,EACF,EACA,mFAAoF,CAClF,EACF,EACA,oBAAqB,CACnB,0LACF,EACA,oFAAqF,CACnF,oXACF,EACA,mBAAoB,CAClB,qHACF,EACA,SAAY,CACV,EACF,EACA,YAAa,CACX,EACF,EACA,eAAgB,CACd,kDACF,EACA,OAAU,CACR,0BACF,EACA,aAAc,CACZ,mGACF,EACA,eAAgB,CACd,uFACF,EACA,aAAc,CACZ,yDACF,EACA,yBAA0B,CACxB,2JACF,EACA,YAAa,CACX,wDACF,EACA,8BAA+B,CAC7B,sHACF,EACA,mBAAoB,CAClB,oIACF,EACA,gDAAiD,CAC/C,uKACF,EACA,0EAA2E,CACzE,qTACF,EACA,mDAAoD,CAClD,yNACF,EACA,0DAA2D,CACzD,EACF,EACA,gDAAmD,CACjD,gOACF,EACA,oEAAqE,CACnE,qVACF,EACA,oDAAqD,CACnD,wPACF,EACA,2CAA8C,CAC5C,wMACF,EACA,sEAAuE,CACrE,EACF,EACA,8CAA+C,CAC7C,gNACF,EACA,yBAA0B,CACxB,+GACF,EACA,6BAA8B,CAC5B,gKACF,EACA,eAAgB,CACd,qHACF,EACA,yFAA0F,CACxF,EACF,EACA,UAAW,CACT,iFACF,EACA,6EAA8E,CAC5E,EACF,EACA,UAAa,CACX,wDACF,EACA,gCAAiC,CAC/B,8GACF,EACA,SAAY,CACV,6FACF,EACA,kCAAmC,CACjC,8GACF,EACA,QAAW,CACT,oEACF,EACA,qCAAsC,CACpC,mLACF,EACA,qBAAsB,CACpB,8FACF,EACA,aAAc,CACZ,YACF,EACA,oDAAqD,CACnD,sSACF,EACA,0FAA2F,CACzF,0TACF,EACA,mEAAoE,CAClE,oMACF,EACA,iDAAkD,CAChD,EACF,EACA,KAAQ,CACN,EACF,EACA,KAAQ,CACN,mGACF,EACA,2CAA8C,CAC5C,yIACF,EACA,wCAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,0JACF,EACA,mCAAsC,CACpC,yIACF,EACA,qEAAwE,CACtE,4SACF,EACA,sCAAyC,CACvC,2EACF,EACA,gFAAmF,CACjF,gXACF,EACA,sCAAyC,CACvC,EACF,EACA,yCAA0C,CACxC,+OACF,EACA,gCAAiC,CAC/B,iKACF,EACA,gCAAiC,CAC/B,qHACF,EACA,+BAAgC,CAC9B,2MACF,EACA,kCAAmC,CACjC,EACF,EACA,kBAAmB,CACjB,EACF,EACA,4BAA6B,CAC3B,+NACF,EACA,0DAA2D,CACzD,8MACF,EACA,sBAAuB,CACrB,EACF,EACA,mBAAoB,CAClB,yIACF,EACA,mBAAoB,CAClB,6FACF,EACA,+CAAgD,CAC9C,uGACF,EACA,6BAA8B,CAC5B,gHACF,EACA,uBAAwB,CACtB,wIACF,EACA,8CAA+C,CAC7C,sVACF,EACA,iDAAkD,CAChD,ySACF,EACA,qEAAsE,CACpE,8UACF,EACA,mDAAoD,CAClD,uYACF,EACA,kCAAmC,CACjC,oKACF,EACA,oCAAqC,CACnC,0QACF,EACA,0DAA2D,CACzD,gRACF,EACA,2CAA4C,CAC1C,kNACF,EACA,0DAA2D,CACzD,oTACF,EACA,yDAA0D,CACxD,kSACF,EACA,2CAA4C,CAC1C,8NACF,EACA,oEAAqE,CACnE,icACF,EACA,gEAAiE,CAC/D,uGACF,EACA,gEAAiE,CAC/D,uGACF,EACA,uBAAwB,CACtB,gKACF,EACA,iBAAkB,CAChB,wFACF,EACA,kCAAmC,CACjC,wNACF,EACA,SAAY,CACV,sCACF,EACA,yLAA0L,CACxL,EACF,EACA,kBAAmB,CACjB,6FACF,EACA,gBAAiB,CACf,qEACF,EACA,YAAa,CACX,EACF,EACA,SAAY,CACV,8DACF,EACA,iCAAkC,CAChC,2PACF,EACA,OAAU,CACR,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,iEAAkE,CAChE,EACF,EACA,+BAAkC,CAChC,wKACF,EACA,iBAAkB,CAChB,0JACF,EACA,kBAAmB,CACjB,wKACF,EACA,SAAY,CACV,6FACF,EACA,eAAkB,CAChB,gFACF,EACA,0BAA2B,CACzB,wIACF,EACA,OAAU,CACR,EACF,EACA,SAAU,CACR,sCACF,EACA,uBAAwB,CACtB,EACF,EACA,uBAAwB,CACtB,oIACF,EACA,0DAA2D,CACzD,EACF,EACA,KAAQ,CACN,0BACF,EACA,YAAe,CACb,0EACF,EACA,KAAQ,CACN,oEACF,EACA,SAAY,CACV,kDACF,EACA,gBAAiB,CACf,mGACF,EACA,GAAM,CACJ,cACF,EACA,KAAQ,CACN,oBACF,EACA,aAAc,CACZ,iFACF,EACA,KAAQ,CACN,0BACF,EACA,qBAAsB,CACpB,+LACF,EACA,QAAW,CACT,EACF,EACA,mBAAoB,CAClB,+LACF,EACA,oEAAqE,CACnE,iWACF,EACA,wFAAyF,CACvF,saACF,EACA,+BAAgC,CAC9B,yLACF,EACA,+BAAgC,CAC9B,iHACF,EACA,sEAAuE,CACrE,EACF,EACA,qEAAsE,CACpE,EACF,EACA,cAAe,CACb,EACF,EACA,6CAA8C,CAC5C,yLACF,EACA,oFAAgF,CAC9E,+XACF,EACA,uBAAwB,CACtB,+LACF,EACA,mCAAoC,CAClC,+LACF,EACA,wBAAyB,CACvB,gKACF,EACA,4CAA6C,CAC3C,gPACF,EACA,kCAAmC,CACjC,gPACF,EACA,mDAAoD,CAClD,gPACF,EACA,wCAAyC,CACvC,gPACF,EACA,6CAA8C,CAC5C,gPACF,EACA,qDAAsD,CACpD,gPACF,EACA,qCAAsC,CACpC,EACF,EACA,SAAY,CACV,8DACF,EACA,0BAA2B,CACzB,uIACF,EACA,mDAAoD,CAClD,uRACF,EACA,2FAAgG,CAC9F,EACF,EACA,2EAA4E,CAC1E,+XACF,EACA,2BAA4B,CAC1B,uKACF,EACA,sBAAuB,CACrB,+LACF,EACA,6FAA8F,CAC5F,8dACF,EACA,wDAAyD,CACvD,sRACF,EACA,uBAAwB,CACtB,oJACF,EACA,4IAA6I,CAC3I,6iBACF,EACA,yBAA0B,CACxB,6HACF,EACA,sDAAuD,CACrD,iPACF,EACA,8JAA+J,CAC7J,gwBACF,EACA,eAAgB,CACd,qEACF,EACA,SAAY,CACV,2EACF,EACA,oDAAqD,CACnD,kOACF,EACA,6CAA8C,CAC5C,6PACF,EACA,oBAAqB,CACnB,+LACF,EACA,0DAA2D,CACzD,+OACF,EACA,qBAAsB,CACpB,wGACF,EACA,uDAAwD,CACtD,+NACF,EACA,0BAA2B,CACzB,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,SAAY,CACV,8DACF,EACA,wBAAyB,CACvB,wIACF,EACA,2FAA4F,CAC1F,giBACF,EACA,0BAA2B,CACzB,gIACF,EACA,8DAA+D,CAC7D,+TACF,EACA,YAAa,CACX,qEACF,EACA,aAAc,CACZ,uFACF,EACA,oBAAqB,CACnB,8DACF,EACA,sEAAuE,CACrE,yXACF,EACA,0BAA2B,CACzB,2JACF,EACA,qEAAsE,CACpE,sbACF,EACA,iBAAkB,CAChB,kIACF,EACA,sLAAuL,CACrL,ugCACF,EACA,mFAAoF,CAClF,6aACF,EACA,kFAAmF,CACjF,EACF,EACA,iCAAkC,CAChC,qPACF,EACA,YAAe,CACb,0EACF,EACA,yBAA0B,CACxB,mLACF,EACA,QAAW,CACT,4CACF,EACA,gBAAiB,CACf,kDACF,EACA,2DAA4D,CAC1D,yNACF,EACA,qEAAsE,CACpE,EACF,EACA,mCAAoC,CAClC,iKACF,EACA,0BAA2B,CACzB,2EACF,EACA,+BAAgC,CAC9B,2EACF,EACA,2BAA4B,CAC1B,2EACF,EACA,KAAQ,CACN,gCACF,EACA,YAAe,CACb,oGACF,EACA,OAAU,CACR,+GACF,EACA,OAAQ,CACN,EACF,EACA,OAAQ,CACN,EACF,EACA,mBAAoB,CAClB,iFACF,EACA,QAAW,CACT,sCACF,EACA,OAAU,CACR,kDACF,EACA,YAAe,CACb,2EACF,EACA,SAAY,CACV,iFACF,EACA,WAAc,CACZ,2EACF,EACA,kCAAmC,CACjC,kSACF,EACA,wBAAyB,CACvB,wIACF,EACA,yBAA0B,CACxB,2EACF,EACA,oBAAqB,CACnB,wKACF,EACA,yBAA0B,CACxB,2EACF,EACA,iBAAkB,CAChB,6FACF,EACA,gBAAiB,CACf,+GACF,EACA,aAAc,CACZ,EACF,EACA,mGAAoG,CAClG,EACF,EACA,iBAAkB,CAChB,kIACF,EACA,4DAA6D,CAC3D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,UAAa,CACX,2EACF,EACA,mBAAoB,CAClB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,oBAAqB,CACnB,kIACF,EACA,oBAAqB,CACnB,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,OAAU,CACR,4CACF,EACA,QAAW,CACT,kDACF,EACA,cAAe,CACb,EACF,EACA,iBAAkB,CAChB,EACF,EACA,+DAAgE,CAC9D,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,2EACF,EACA,qBAAsB,CACpB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,cAAe,CACb,yDACF,EACA,gBAAiB,CACf,EACF,EACA,KAAQ,CACN,EACF,EACA,mFAAoF,CAClF,EACF,EACA,GAAM,CACJ,EACF,EACA,gFAAiF,CAC/E,EACF,EACA,QAAW,CACT,EACF,EACA,sDAAuD,CACrD,EACF,EACA,mDAAsD,CACpD,EACF,EACA,SAAY,CACV,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,wDAA2D,CACzD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,mDAAoD,CAClD,EACF,EACA,uIAAwI,CACtI,EACF,EACA,+BAAgC,CAC9B,2EACF,EACA,aAAgB,CACd,sJACF,EACA,UAAa,CACX,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,iKACF,EACA,+BAAgC,CAC9B,2EACF,EACA,YAAa,CACX,EACF,EACA,kBAAmB,CACjB,iKACF,EACA,8CAA+C,CAC7C,oGACF,EACA,wBAAyB,CACvB,2EACF,EACA,SAAY,CACV,4CACF,EACA,KAAQ,CACN,EACF,EACA,MAAS,CACP,6FACF,EACA,yCAA0C,CACxC,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,oDAAqD,CACnD,kNACF,EACA,6BAA8B,CAC5B,iJACF,EACA,QAAW,CACT,EACF,EACA,0BAA2B,CACzB,EACF,EACA,QAAW,CACT,4CACF,EACA,WAAY,CACV,EACF,EACA,yCAA0C,CACxC,EACF,EACA,MAAS,CACP,EACF,EACA,OAAU,CACR,oBACF,EACA,OAAU,CACR,kDACF,EACA,IAAO,CACL,EACF,EACA,uBAAwB,CACtB,2EACF,EACA,iCAAkC,CAChC,EACF,EACA,+BAAgC,CAC9B,2EACF,EACA,iCAAkC,CAChC,2EACF,EACA,sDAAuD,CACrD,iPACF,EACA,4BAA6B,CAC3B,2EACF,EACA,OAAU,CACR,kDACF,EACA,6BAA8B,CAC5B,oJACF,EACA,uBAAwB,CACtB,sKACF,EACA,kDAAmD,CACjD,6PACF,EACA,oBAAqB,CACnB,yGACF,EACA,8HAA+H,CAC7H,icACF,EACA,wBAAyB,CACvB,mIACF,EACA,kFAAmF,CACjF,0dACF,EACA,0EAA2E,CACzE,yjBACF,EACA,wGAAyG,CACvG,qhBACF,EACA,oEAAqE,CACnE,8WACF,EACA,sBAAuB,CACrB,gHACF,EACA,iJAAkJ,CAChJ,iqBACF,EACA,wBAAyB,CACvB,qJACF,EACA,kCAAmC,CACjC,yJACF,EACA,6HAA8H,CAC5H,EACF,EACA,kBAAmB,CACjB,4HACF,EACA,QAAW,CACT,kDACF,EACA,cAAe,CACb,uFACF,EACA,eAAgB,CACd,6FACF,EACA,2BAA4B,CAC1B,2MACF,EACA,uBAAwB,CACtB,mGACF,EACA,sBAAuB,CACrB,kHACF,EACA,0CAA2C,CACzC,+NACF,EACA,gCAAiC,CAC/B,yJACF,EACA,6BAA8B,CAC5B,0LACF,EACA,mBAAoB,CAClB,2JACF,EACA,+DAAgE,CAC9D,ySACF,EACA,kGAAmG,CACjG,EACF,EACA,MAAS,CACP,OACF,EACA,0DAA2D,CACzD,gNACF,EACA,MAAS,CACP,4CACF,EACA,sCAAuC,CACrC,gNACF,EACA,cAAe,CACb,4FACF,EACA,qDAAsD,CACpD,sVACF,EACA,YAAa,CACX,0FACF,EACA,2DAA4D,CAC1D,0UACF,EACA,kBAAmB,CACjB,sMACF,EACA,kFAAmF,CACjF,4VACF,EACA,WAAY,CACV,mGACF,EACA,0CAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,yKACF,EACA,yDAA0D,CACxD,yQACF,EACA,0DAA2D,CACzD,yKACF,EACA,iBAAkB,CAChB,wIACF,EACA,kBAAmB,CACjB,6FACF,EACA,6BAA8B,CAC5B,sJACF,EACA,kFAAmF,CACjF,ihBACF,EACA,kFAAmF,CACjF,0gBACF,EACA,uFAAwF,CACtF,ikBACF,EACA,8BAA+B,CAC7B,wQACF,EACA,iBAAoB,CAClB,mDACF,EACA,QAAW,CACT,kDACF,EACA,8BAA+B,CAC7B,iJACF,EACA,iBAAkB,CAChB,6FACF,EACA,uBAAwB,CACtB,gKACF,EACA,wRAA6R,CAC3R,EACF,EACA,eAAgB,CACd,0JACF,EACA,mCAAoC,CAClC,sKACF,EACA,KAAQ,CACN,EACF,EACA,qCAAsC,CACpC,EACF,EACA,eAAgB,CACd,0JACF,EACA,0CAA2C,CACzC,EACF,EACA,8CAA+C,CAC7C,+TACF,EACA,QAAW,CACT,EACF,EACA,eAAgB,CACd,6FACF,EACA,gDAAiD,CAC/C,qNACF,EACA,mBAAoB,CAClB,qJACF,EACA,kGAAmG,CACjG,EACF,EACA,kCAAmC,CACjC,0GACF,EACA,kBAAmB,CACjB,iFACF,EACA,mBAAoB,CAClB,iFACF,EACA,uEAAwE,CACtE,oRACF,EACA,iGAAkG,CAChG,wkBACF,EACA,uEAAwE,CACtE,0WACF,EACA,oDAAqD,CACnD,EACF,EACA,2BAA4B,CAC1B,iFACF,EACA,kBAAmB,CACjB,iFACF,EACA,mBAAoB,CAClB,uFACF,EACA,sCAAuC,CACrC,yKACF,EACA,eAAgB,CACd,qEACF,EACA,gBAAiB,CACf,qGACF,EACA,2BAA4B,CAC1B,+IACF,EACA,OAAU,CACR,4CACF,EACA,iBAAkB,CAChB,wIACF,EACA,QAAW,CACT,oBACF,EACA,QAAW,CACT,kDACF,EACA,kBAAmB,CACjB,iFACF,EACA,wCAAyC,CACvC,EACF,EACA,mCAAoC,CAClC,EACF,EACA,2BAA4B,CAC1B,sJACF,EACA,yCAA0C,CACxC,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,YAAa,CACX,iFACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,uFACF,EACA,YAAa,CACX,qEACF,EACA,YAAa,CACX,iFACF,EACA,mCAAoC,CAClC,0JACF,EACA,mEAAoE,CAClE,EACF,EACA,mEAAoE,CAClE,sbACF,EACA,MAAS,CACP,uFACF,EACA,mDAAoD,CAClD,EACF,EACA,OAAU,CACR,4CACF,EACA,wDAAyD,CACvD,gPACF,EACA,wBAAyB,CACvB,uLACF,EACA,SAAY,CACV,EACF,EACA,eAAgB,CACd,2EACF,EACA,eAAgB,CACd,iFACF,EACA,iBAAkB,CAChB,wIACF,EACA,wCAA2C,CACzC,EACF,EACA,gDAAiD,CAC/C,qVACF,EACA,yDAA0D,CACxD,wNACF,EACA,oCAAqC,CACnC,wPACF,EACA,8BAA+B,CAC7B,sPACF,EACA,gCAAiC,CAC/B,2LACF,EACA,qDAAsD,CACpD,2dACF,EACA,wBAAyB,CACvB,2JACF,EACA,yCAA0C,CACxC,kSACF,EACA,mBAAoB,CAClB,gHACF,EACA,sBAAuB,CACrB,uLACF,EACA,gCAAiC,CAC/B,kSACF,EACA,sBAAuB,CACrB,gKACF,EACA,sBAAuB,CACrB,kIACF,EACA,qBAAsB,CACpB,kIACF,EACA,uBAAwB,CACtB,wIACF,EACA,sBAAuB,CACrB,4HACF,EACA,uBAAwB,CACtB,oJACF,EACA,kCAAmC,CACjC,wNACF,EACA,sBAAuB,CACrB,uHACF,EACA,SAAY,CACV,oEACF,EACA,sBAAuB,CACrB,iFACF,EACA,qBAAsB,CACpB,iIACF,EACA,gDAAiD,CAC/C,mRACF,EACA,yCAA0C,CACxC,EACF,EACA,2BAA4B,CAC1B,sMACF,EACA,wHAAyH,CACvH,+mBACF,EACA,qBAAsB,CACpB,+FACF,EACA,iBAAkB,CAChB,wIACF,EACA,kBAAmB,CACjB,wIACF,EACA,8CAA+C,CAC7C,0QACF,EACA,8BAA+B,CAC7B,uJACF,EACA,oCAAqC,CACnC,qQACF,EACA,4DAA6D,CAC3D,iVACF,EACA,kBAAmB,CACjB,yDACF,EACA,sCAAuC,CACrC,kNACF,EACA,0BAA6B,CAC3B,0GACF,EACA,aAAgB,CACd,gFACF,EACA,qDAAsD,CACpD,+MACF,EACA,gCAAiC,CAC/B,yQACF,EACA,iDAAkD,CAChD,6SACF,EACA,iBAAkB,CAChB,sHACF,EACA,QAAW,CACT,8DACF,EACA,YAAe,CACb,8DACF,EACA,0CAA2C,CACzC,0QACF,EACA,iHAAkH,CAChH,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,0GACF,CACF,CACF,EACA,OAAU,WACV,aAAgB,uGAChB,KAAQ,KACR,aAAgB,EAClB,EAEAA,GAAQ,GAAQ,CACd,YAAe,CACb,SAAY,CACV,GAAI,CACF,OAAU,WACV,aAAgB,uGAChB,KAAQ,IACV,EACA,uDAAwD,CACtD,8PACF,EACA,uCAAwC,CACtC,2LACF,EACA,wCAAyC,CACvC,4LACF,EACA,8BAA+B,CAC7B,gHACF,EACA,8CAA+C,CAC7C,wQACF,EACA,2DAA4D,CAC1D,EACF,EACA,SAAY,CACV,oEACF,EACA,wBAAyB,CACvB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,yFAA0F,CACxF,EACF,EACA,+BAAgC,CAC9B,uKACF,EACA,qBAAsB,CACpB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qEAAsE,CACpE,EACF,EACA,kEAAmE,CACjE,EACF,EACA,KAAQ,CACN,EACF,EACA,0BAA2B,CACzB,4HACF,EACA,0BAA2B,CACzB,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,KAAQ,CACN,EACF,EACA,OAAU,CACR,EACF,EACA,qBAAsB,CACpB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,oEAAqE,CACnE,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,mBAAoB,CAClB,EACF,EACA,uCAAwC,CACtC,6IACF,EACA,wKAAyK,CACvK,EACF,EACA,qEAAsE,CACpE,wPACF,EACA,yEAA0E,CACxE,EACF,EACA,4EAA6E,CAC3E,EACF,EACA,iCAAoC,CAClC,EACF,EACA,oCAAuC,CACrC,EACF,EACA,gBAAiB,CACf,EACF,EACA,oBAAqB,CACnB,EACF,EACA,kDAAmD,CACjD,EACF,EACA,OAAU,CACR,sCACF,EACA,SAAY,CACV,EACF,EACA,6BAA8B,CAC5B,+IACF,EACA,8DAA+D,CAC7D,4RACF,EACA,MAAS,CACP,4CACF,EACA,sBAAuB,CACrB,uFACF,EACA,oIAAqI,CACnI,EACF,EACA,2BAA4B,CAC1B,2EACF,EACA,4CAA6C,CAC3C,0TACF,EACA,0BAA2B,CACzB,6HACF,EACA,iCAAkC,CAChC,wIACF,EACA,gDAAiD,CAC/C,EACF,EACA,yBAA0B,CACxB,2LACF,EACA,gCAAiC,CAC/B,8IACF,EACA,QAAW,CACT,4FACF,EACA,4BAA6B,CAC3B,mKACF,EACA,wBAAyB,CACvB,6KACF,EACA,qDAAsD,CACpD,EACF,EACA,qDAAsD,CACpD,2QACF,EACA,iBAAkB,CAChB,4HACF,EACA,kBAAmB,CACjB,uFACF,EACA,yCAA0C,CACxC,6IACF,EACA,oBAAqB,CACnB,yIACF,EACA,8EAA+E,CAC7E,oeACF,EACA,8CAA+C,CAC7C,iNACF,EACA,6CAA8C,CAC5C,iKACF,EACA,qCAAsC,CACpC,qKACF,EACA,oDAAqD,CACnD,EACF,EACA,qFAAsF,CACpF,kjBACF,EACA,sDAAuD,CACrD,0TACF,EACA,kBAAmB,CACjB,4HACF,EACA,QAAW,CACT,4CACF,EACA,kBAAmB,CACjB,2EACF,EACA,QAAW,CACT,sCACF,EACA,IAAO,CACL,kDACF,EACA,aAAc,CACZ,uCACF,EACA,aAAc,CACZ,EACF,EACA,mFAAoF,CAClF,EACF,EACA,oBAAqB,CACnB,+IACF,EACA,oFAAqF,CACnF,yWACF,EACA,mBAAoB,CAClB,6FACF,EACA,SAAY,CACV,EACF,EACA,YAAa,CACX,6DACF,EACA,eAAgB,CACd,uDACF,EACA,OAAU,CACR,gCACF,EACA,aAAc,CACZ,uFACF,EACA,eAAgB,CACd,uFACF,EACA,aAAc,CACZ,+DACF,EACA,yBAA0B,CACxB,2JACF,EACA,YAAa,CACX,0EACF,EACA,8BAA+B,CAC7B,oGACF,EACA,mBAAoB,CAClB,2GACF,EACA,gDAAiD,CAC/C,2JACF,EACA,0EAA2E,CACzE,wXACF,EACA,mDAAoD,CAClD,wPACF,EACA,0DAA2D,CACzD,EACF,EACA,gDAAmD,CACjD,+HACF,EACA,oEAAqE,CACnE,2VACF,EACA,oDAAqD,CACnD,4RACF,EACA,2CAA8C,CAC5C,uJACF,EACA,sEAAuE,CACrE,EACF,EACA,8CAA+C,CAC7C,sNACF,EACA,yBAA0B,CACxB,4CACF,EACA,6BAA8B,CAC5B,0JACF,EACA,eAAgB,CACd,uFACF,EACA,yFAA0F,CACxF,EACF,EACA,UAAW,CACT,2EACF,EACA,6EAA8E,CAC5E,EACF,EACA,UAAa,CACX,8DACF,EACA,gCAAiC,CAC/B,kGACF,EACA,SAAY,CACV,6FACF,EACA,kCAAmC,CACjC,kGACF,EACA,QAAW,CACT,4CACF,EACA,qCAAsC,CACpC,+NACF,EACA,qBAAsB,CACpB,oGACF,EACA,aAAc,CACZ,YACF,EACA,oDAAqD,CACnD,iVACF,EACA,0FAA2F,CACzF,wSACF,EACA,mEAAoE,CAClE,oMACF,EACA,iDAAkD,CAChD,EACF,EACA,KAAQ,CACN,EACF,EACA,KAAQ,CACN,+GACF,EACA,2CAA8C,CAC5C,kIACF,EACA,wCAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,6FACF,EACA,mCAAsC,CACpC,kIACF,EACA,qEAAwE,CACtE,0SACF,EACA,sCAAyC,CACvC,mLACF,EACA,gFAAmF,CACjF,mRACF,EACA,sCAAyC,CACvC,EACF,EACA,yCAA0C,CACxC,EACF,EACA,gCAAiC,CAC/B,iKACF,EACA,gCAAiC,CAC/B,6FACF,EACA,+BAAgC,CAC9B,iNACF,EACA,kCAAmC,CACjC,EACF,EACA,kBAAmB,CACjB,EACF,EACA,4BAA6B,CAC3B,wNACF,EACA,0DAA2D,CACzD,8RACF,EACA,sBAAuB,CACrB,EACF,EACA,mBAAoB,CAClB,gKACF,EACA,mBAAoB,CAClB,yGACF,EACA,+CAAgD,CAC9C,sGACF,EACA,6BAA8B,CAC5B,0GACF,EACA,uBAAwB,CACtB,4HACF,EACA,8CAA+C,CAC7C,gWACF,EACA,iDAAkD,CAChD,0QACF,EACA,qEAAsE,CACpE,4VACF,EACA,mDAAoD,CAClD,oZACF,EACA,kCAAmC,CACjC,6MACF,EACA,oCAAqC,CACnC,2LACF,EACA,0DAA2D,CACzD,0QACF,EACA,2CAA4C,CAC1C,wNACF,EACA,0DAA2D,CACzD,gUACF,EACA,yDAA0D,CACxD,EACF,EACA,2CAA4C,CAC1C,iNACF,EACA,oEAAqE,CACnE,yaACF,EACA,gEAAiE,CAC/D,sGACF,EACA,gEAAiE,CAC/D,sGACF,EACA,uBAAwB,CACtB,mGACF,EACA,iBAAkB,CAChB,6FACF,EACA,kCAAmC,CACjC,qJACF,EACA,SAAY,CACV,sCACF,EACA,yLAA0L,CACxL,EACF,EACA,kBAAmB,CACjB,6FACF,EACA,gBAAiB,CACf,qEACF,EACA,YAAa,CACX,EACF,EACA,SAAY,CACV,oEACF,EACA,iCAAkC,CAChC,+OACF,EACA,OAAU,CACR,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,iEAAkE,CAChE,EACF,EACA,+BAAkC,CAChC,yKACF,EACA,iBAAkB,CAChB,6FACF,EACA,kBAAmB,CACjB,EACF,EACA,SAAY,CACV,6FACF,EACA,eAAkB,CAChB,kDACF,EACA,0BAA2B,CACzB,kFACF,EACA,OAAU,CACR,EACF,EACA,SAAU,CACR,gCACF,EACA,uBAAwB,CACtB,EACF,EACA,uBAAwB,CACtB,2GACF,EACA,0DAA2D,CACzD,EACF,EACA,KAAQ,CACN,0BACF,EACA,YAAe,CACb,8DACF,EACA,KAAQ,CACN,8DACF,EACA,SAAY,CACV,kDACF,EACA,gBAAiB,CACf,2HACF,EACA,GAAM,CACJ,QACF,EACA,KAAQ,CACN,cACF,EACA,aAAc,CACZ,uFACF,EACA,KAAQ,CACN,gCACF,EACA,qBAAsB,CACpB,0JACF,EACA,QAAW,CACT,EACF,EACA,mBAAoB,CAClB,0JACF,EACA,oEAAqE,CACnE,uTACF,EACA,wFAAyF,CACvF,oeACF,EACA,+BAAgC,CAC9B,uNACF,EACA,+BAAgC,CAC9B,2GACF,EACA,sEAAuE,CACrE,EACF,EACA,qEAAsE,CACpE,EACF,EACA,cAAe,CACb,EACF,EACA,6CAA8C,CAC5C,mLACF,EACA,oFAAgF,CAC9E,uWACF,EACA,uBAAwB,CACtB,0JACF,EACA,mCAAoC,CAClC,0JACF,EACA,wBAAyB,CACvB,0JACF,EACA,4CAA6C,CAC3C,8IACF,EACA,kCAAmC,CACjC,8IACF,EACA,mDAAoD,CAClD,8IACF,EACA,wCAAyC,CACvC,8IACF,EACA,6CAA8C,CAC5C,8IACF,EACA,qDAAsD,CACpD,8IACF,EACA,qCAAsC,CACpC,EACF,EACA,SAAY,CACV,wDACF,EACA,0BAA2B,CACzB,6IACF,EACA,mDAAoD,CAClD,mSACF,EACA,2FAAgG,CAC9F,EACF,EACA,2EAA4E,CAC1E,uWACF,EACA,2BAA4B,CAC1B,2JACF,EACA,sBAAuB,CACrB,0JACF,EACA,6FAA8F,CAC5F,gbACF,EACA,wDAAyD,CACvD,gOACF,EACA,uBAAwB,CACtB,mGACF,EACA,4IAA6I,CAC3I,ugBACF,EACA,yBAA0B,CACxB,0GACF,EACA,sDAAuD,CACrD,qOACF,EACA,8JAA+J,CAC7J,wxBACF,EACA,eAAgB,CACd,2EACF,EACA,SAAY,CACV,iFACF,EACA,oDAAqD,CACnD,oPACF,EACA,6CAA8C,CAC5C,wQACF,EACA,oBAAqB,CACnB,0JACF,EACA,0DAA2D,CACzD,0MACF,EACA,qBAAsB,CACpB,gDACF,EACA,uDAAwD,CACtD,gOACF,EACA,0BAA2B,CACzB,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,SAAY,CACV,8DACF,EACA,wBAAyB,CACvB,wIACF,EACA,2FAA4F,CAC1F,+eACF,EACA,0BAA2B,CACzB,oGACF,EACA,8DAA+D,CAC7D,uSACF,EACA,YAAa,CACX,2EACF,EACA,aAAc,CACZ,6FACF,EACA,oBAAqB,CACnB,+DACF,EACA,sEAAuE,CACrE,oaACF,EACA,0BAA2B,CACzB,yIACF,EACA,qEAAsE,CACpE,4YACF,EACA,iBAAkB,CAChB,sEACF,EACA,sLAAuL,CACrL,4hCACF,EACA,mFAAoF,CAClF,mcACF,EACA,kFAAmF,CACjF,EACF,EACA,iCAAkC,CAChC,oNACF,EACA,YAAe,CACb,wDACF,EACA,yBAA0B,CACxB,6KACF,EACA,QAAW,CACT,6FACF,EACA,gBAAiB,CACf,mGACF,EACA,2DAA4D,CAC1D,wPACF,EACA,qEAAsE,CACpE,EACF,EACA,mCAAoC,CAClC,wIACF,EACA,0BAA2B,CACzB,2EACF,EACA,+BAAgC,CAC9B,2EACF,EACA,2BAA4B,CAC1B,2EACF,EACA,KAAQ,CACN,kDACF,EACA,YAAe,CACb,4HACF,EACA,OAAU,CACR,kDACF,EACA,OAAQ,CACN,EACF,EACA,OAAQ,CACN,EACF,EACA,mBAAoB,CAClB,uFACF,EACA,QAAW,CACT,oEACF,EACA,OAAU,CACR,4CACF,EACA,YAAe,CACb,iFACF,EACA,SAAY,CACV,4CACF,EACA,WAAc,CACZ,2EACF,EACA,kCAAmC,CACjC,EACF,EACA,wBAAyB,CACvB,4HACF,EACA,yBAA0B,CACxB,2EACF,EACA,oBAAqB,CACnB,yKACF,EACA,yBAA0B,CACxB,2EACF,EACA,iBAAkB,CAChB,4CACF,EACA,gBAAiB,CACf,kDACF,EACA,aAAc,CACZ,EACF,EACA,mGAAoG,CAClG,EACF,EACA,iBAAkB,CAChB,8IACF,EACA,4DAA6D,CAC3D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,UAAa,CACX,2EACF,EACA,mBAAoB,CAClB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,oBAAqB,CACnB,uFACF,EACA,oBAAqB,CACnB,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,OAAU,CACR,kDACF,EACA,QAAW,CACT,4FACF,EACA,cAAe,CACb,EACF,EACA,iBAAkB,CAChB,EACF,EACA,+DAAgE,CAC9D,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,2EACF,EACA,qBAAsB,CACpB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,cAAe,CACb,uCACF,EACA,gBAAiB,CACf,EACF,EACA,KAAQ,CACN,EACF,EACA,mFAAoF,CAClF,EACF,EACA,GAAM,CACJ,EACF,EACA,gFAAiF,CAC/E,EACF,EACA,QAAW,CACT,EACF,EACA,sDAAuD,CACrD,EACF,EACA,mDAAsD,CACpD,EACF,EACA,SAAY,CACV,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,wDAA2D,CACzD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,mDAAoD,CAClD,EACF,EACA,uIAAwI,CACtI,EACF,EACA,+BAAgC,CAC9B,2EACF,EACA,aAAgB,CACd,qJACF,EACA,UAAa,CACX,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,wIACF,EACA,+BAAgC,CAC9B,2EACF,EACA,YAAa,CACX,EACF,EACA,kBAAmB,CACjB,wIACF,EACA,8CAA+C,CAC7C,8FACF,EACA,wBAAyB,CACvB,2EACF,EACA,SAAY,CACV,gCACF,EACA,KAAQ,CACN,EACF,EACA,MAAS,CACP,6FACF,EACA,yCAA0C,CACxC,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,oDAAqD,CACnD,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,QAAW,CACT,EACF,EACA,0BAA2B,CACzB,EACF,EACA,QAAW,CACT,0BACF,EACA,WAAY,CACV,EACF,EACA,yCAA0C,CACxC,EACF,EACA,MAAS,CACP,EACF,EACA,OAAU,CACR,kDACF,EACA,OAAU,CACR,4CACF,EACA,IAAO,CACL,EACF,EACA,uBAAwB,CACtB,2EACF,EACA,iCAAkC,CAChC,EACF,EACA,+BAAgC,CAC9B,2EACF,EACA,iCAAkC,CAChC,2EACF,EACA,sDAAuD,CACrD,sMACF,EACA,4BAA6B,CAC3B,2EACF,EACA,OAAU,CACR,4CACF,EACA,6BAA8B,CAC5B,wIACF,EACA,uBAAwB,CACtB,oJACF,EACA,kDAAmD,CACjD,wQACF,EACA,oBAAqB,CACnB,mGACF,EACA,8HAA+H,CAC7H,+bACF,EACA,wBAAyB,CACvB,8FACF,EACA,kFAAmF,CACjF,2YACF,EACA,0EAA2E,CACzE,8dACF,EACA,wGAAyG,CACvG,8dACF,EACA,oEAAqE,CACnE,+RACF,EACA,sBAAuB,CACrB,EACF,EACA,iJAAkJ,CAChJ,EACF,EACA,wBAAyB,CACvB,EACF,EACA,kCAAmC,CACjC,+HACF,EACA,6HAA8H,CAC5H,EACF,EACA,kBAAmB,CACjB,+GACF,EACA,QAAW,CACT,4CACF,EACA,cAAe,CACb,+DACF,EACA,eAAgB,CACd,qEACF,EACA,2BAA4B,CAC1B,qHACF,EACA,uBAAwB,CACtB,2HACF,EACA,sBAAuB,CACrB,4GACF,EACA,0CAA2C,CACzC,0PACF,EACA,gCAAiC,CAC/B,qKACF,EACA,6BAA8B,CAC5B,4HACF,EACA,mBAAoB,CAClB,yIACF,EACA,+DAAgE,CAC9D,+PACF,EACA,kGAAmG,CACjG,EACF,EACA,MAAS,CACP,OACF,EACA,0DAA2D,CACzD,sNACF,EACA,MAAS,CACP,4CACF,EACA,sCAAuC,CACrC,sNACF,EACA,cAAe,CACb,8DACF,EACA,qDAAsD,CACpD,iYACF,EACA,YAAa,CACX,4DACF,EACA,2DAA4D,CAC1D,gVACF,EACA,kBAAmB,CACjB,2GACF,EACA,kFAAmF,CACjF,4VACF,EACA,WAAY,CACV,yJACF,EACA,0CAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,iMACF,EACA,yDAA0D,CACxD,4RACF,EACA,0DAA2D,CACzD,iMACF,EACA,iBAAkB,CAChB,4HACF,EACA,kBAAmB,CACjB,2EACF,EACA,6BAA8B,CAC5B,qJACF,EACA,kFAAmF,CACjF,idACF,EACA,kFAAmF,CACjF,2aACF,EACA,uFAAwF,CACtF,kiBACF,EACA,8BAA+B,CAC7B,mLACF,EACA,iBAAoB,CAClB,iCACF,EACA,QAAW,CACT,4CACF,EACA,8BAA+B,CAC7B,EACF,EACA,iBAAkB,CAChB,qHACF,EACA,uBAAwB,CACtB,mGACF,EACA,wRAA6R,CAC3R,EACF,EACA,eAAgB,CACd,iFACF,EACA,mCAAoC,CAClC,oJACF,EACA,KAAQ,CACN,EACF,EACA,qCAAsC,CACpC,EACF,EACA,eAAgB,CACd,6FACF,EACA,0CAA2C,CACzC,EACF,EACA,8CAA+C,CAC7C,sPACF,EACA,QAAW,CACT,EACF,EACA,eAAgB,CACd,6FACF,EACA,gDAAiD,CAC/C,0GACF,EACA,mBAAoB,CAClB,yIACF,EACA,kGAAmG,CACjG,EACF,EACA,kCAAmC,CACjC,0GACF,EACA,kBAAmB,CACjB,uFACF,EACA,mBAAoB,CAClB,iFACF,EACA,uEAAwE,CACtE,EACF,EACA,iGAAkG,CAChG,EACF,EACA,uEAAwE,CACtE,EACF,EACA,oDAAqD,CACnD,EACF,EACA,2BAA4B,CAC1B,uFACF,EACA,kBAAmB,CACjB,uFACF,EACA,mBAAoB,CAClB,iFACF,EACA,sCAAuC,CACrC,EACF,EACA,eAAgB,CACd,qEACF,EACA,gBAAiB,CACf,qGACF,EACA,2BAA4B,CAC1B,mIACF,EACA,OAAU,CACR,kDACF,EACA,iBAAkB,CAChB,4HACF,EACA,QAAW,CACT,kDACF,EACA,QAAW,CACT,8DACF,EACA,kBAAmB,CACjB,uFACF,EACA,wCAAyC,CACvC,EACF,EACA,mCAAoC,CAClC,EACF,EACA,2BAA4B,CAC1B,qJACF,EACA,yCAA0C,CACxC,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,YAAa,CACX,2EACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,uFACF,EACA,YAAa,CACX,2EACF,EACA,YAAa,CACX,+DACF,EACA,mCAAoC,CAClC,uKACF,EACA,mEAAoE,CAClE,EACF,EACA,mEAAoE,CAClE,4YACF,EACA,MAAS,CACP,4CACF,EACA,mDAAoD,CAClD,EACF,EACA,OAAU,CACR,4CACF,EACA,wDAAyD,CACvD,8IACF,EACA,wBAAyB,CACvB,+JACF,EACA,SAAY,CACV,EACF,EACA,eAAgB,CACd,iFACF,EACA,eAAgB,CACd,2EACF,EACA,iBAAkB,CAChB,4HACF,EACA,wCAA2C,CACzC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yDAA0D,CACxD,EACF,EACA,oCAAqC,CACnC,EACF,EACA,8BAA+B,CAC7B,2LACF,EACA,gCAAiC,CAC/B,EACF,EACA,qDAAsD,CACpD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,yCAA0C,CACxC,EACF,EACA,mBAAoB,CAClB,8FACF,EACA,sBAAuB,CACrB,+JACF,EACA,gCAAiC,CAC/B,EACF,EACA,sBAAuB,CACrB,oJACF,EACA,sBAAuB,CACrB,wIACF,EACA,qBAAsB,CACpB,wIACF,EACA,uBAAwB,CACtB,8IACF,EACA,sBAAuB,CACrB,wIACF,EACA,uBAAwB,CACtB,oJACF,EACA,kCAAmC,CACjC,oOACF,EACA,sBAAuB,CACrB,uHACF,EACA,SAAY,CACV,wDACF,EACA,sBAAuB,CACrB,sEACF,EACA,qBAAsB,CACpB,qHACF,EACA,gDAAiD,CAC/C,oSACF,EACA,yCAA0C,CACxC,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,wHAAyH,CACvH,EACF,EACA,qBAAsB,CACpB,0GACF,EACA,iBAAkB,CAChB,4HACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,oCAAqC,CACnC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,kBAAmB,CACjB,uCACF,EACA,sCAAuC,CACrC,EACF,EACA,0BAA6B,CAC3B,wFACF,EACA,aAAgB,CACd,kDACF,EACA,qDAAsD,CACpD,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,iDAAkD,CAChD,EACF,EACA,iBAAkB,CAChB,mJACF,EACA,QAAW,CACT,0EACF,EACA,YAAe,CACb,wDACF,EACA,0CAA2C,CACzC,0QACF,EACA,iHAAkH,CAChH,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,0GACF,CACF,CACF,EACA,OAAU,WACV,aAAgB,uGAChB,KAAQ,KACR,aAAgB,EAClB,EAEAA,GAAQ,GAAQ,CACd,YAAe,CACb,SAAY,CACV,GAAI,CACF,OAAU,WACV,aAAgB,6BAChB,KAAQ,IACV,EACA,uDAAwD,CACtD,EACF,EACA,uCAAwC,CACtC,EACF,EACA,wCAAyC,CACvC,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,SAAY,CACV,EACF,EACA,wBAAyB,CACvB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,yFAA0F,CACxF,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,qBAAsB,CACpB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qEAAsE,CACpE,EACF,EACA,kEAAmE,CACjE,EACF,EACA,KAAQ,CACN,EACF,EACA,0BAA2B,CACzB,qDACF,EACA,0BAA2B,CACzB,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,KAAQ,CACN,EACF,EACA,OAAU,CACR,EACF,EACA,qBAAsB,CACpB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,oEAAqE,CACnE,EACF,EACA,4BAA6B,CAC3B,0BACF,EACA,mBAAoB,CAClB,EACF,EACA,uCAAwC,CACtC,EACF,EACA,wKAAyK,CACvK,EACF,EACA,qEAAsE,CACpE,sCACF,EACA,yEAA0E,CACxE,EACF,EACA,4EAA6E,CAC3E,EACF,EACA,iCAAoC,CAClC,EACF,EACA,oCAAuC,CACrC,EACF,EACA,gBAAiB,CACf,EACF,EACA,oBAAqB,CACnB,EACF,EACA,kDAAmD,CACjD,EACF,EACA,OAAU,CACR,EACF,EACA,SAAY,CACV,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,8DAA+D,CAC7D,EACF,EACA,MAAS,CACP,EACF,EACA,sBAAuB,CACrB,EACF,EACA,oIAAqI,CACnI,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,0BAA2B,CACzB,qCACF,EACA,iCAAkC,CAChC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yBAA0B,CACxB,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,QAAW,CACT,EACF,EACA,4BAA6B,CAC3B,mBACF,EACA,wBAAyB,CACvB,EACF,EACA,qDAAsD,CACpD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,iBAAkB,CAChB,qBACF,EACA,kBAAmB,CACjB,EACF,EACA,yCAA0C,CACxC,EACF,EACA,oBAAqB,CACnB,EACF,EACA,8EAA+E,CAC7E,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,qCAAsC,CACpC,EACF,EACA,oDAAqD,CACnD,EACF,EACA,qFAAsF,CACpF,EACF,EACA,sDAAuD,CACrD,EACF,EACA,kBAAmB,CACjB,qBACF,EACA,QAAW,CACT,EACF,EACA,kBAAmB,CACjB,EACF,EACA,QAAW,CACT,EACF,EACA,IAAO,CACL,EACF,EACA,aAAc,CACZ,UACF,EACA,aAAc,CACZ,EACF,EACA,mFAAoF,CAClF,EACF,EACA,oBAAqB,CACnB,qBACF,EACA,oFAAqF,CACnF,EACF,EACA,mBAAoB,CAClB,qDACF,EACA,SAAY,CACV,EACF,EACA,YAAa,CACX,EACF,EACA,eAAgB,CACd,EACF,EACA,OAAU,CACR,SACF,EACA,aAAc,CACZ,EACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,EACF,EACA,yBAA0B,CACxB,EACF,EACA,YAAa,CACX,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,mBAAoB,CAClB,6BACF,EACA,gDAAiD,CAC/C,0DACF,EACA,0EAA2E,CACzE,EACF,EACA,mDAAoD,CAClD,sCACF,EACA,0DAA2D,CACzD,EACF,EACA,gDAAmD,CACjD,mCACF,EACA,oEAAqE,CACnE,EACF,EACA,oDAAqD,CACnD,EACF,EACA,2CAA8C,CAC5C,mCACF,EACA,sEAAuE,CACrE,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,yBAA0B,CACxB,UACF,EACA,6BAA8B,CAC5B,sCACF,EACA,eAAgB,CACd,EACF,EACA,yFAA0F,CACxF,EACF,EACA,UAAW,CACT,EACF,EACA,6EAA8E,CAC5E,EACF,EACA,UAAa,CACX,EACF,EACA,gCAAiC,CAC/B,4BACF,EACA,SAAY,CACV,EACF,EACA,kCAAmC,CACjC,EACF,EACA,QAAW,CACT,UACF,EACA,qCAAsC,CACpC,EACF,EACA,qBAAsB,CACpB,qBACF,EACA,aAAc,CACZ,EACF,EACA,oDAAqD,CACnD,EACF,EACA,0FAA2F,CACzF,EACF,EACA,mEAAoE,CAClE,EACF,EACA,iDAAkD,CAChD,EACF,EACA,KAAQ,CACN,EACF,EACA,KAAQ,CACN,EACF,EACA,2CAA8C,CAC5C,EACF,EACA,wCAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,SACF,EACA,mCAAsC,CACpC,EACF,EACA,qEAAwE,CACtE,EACF,EACA,sCAAyC,CACvC,qCACF,EACA,gFAAmF,CACjF,EACF,EACA,sCAAyC,CACvC,EACF,EACA,yCAA0C,CACxC,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,gCAAiC,CAC/B,qDACF,EACA,+BAAgC,CAC9B,qCACF,EACA,kCAAmC,CACjC,EACF,EACA,kBAAmB,CACjB,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,0DAA2D,CACzD,EACF,EACA,sBAAuB,CACrB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,+CAAgD,CAC9C,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,uBAAwB,CACtB,eACF,EACA,8CAA+C,CAC7C,EACF,EACA,iDAAkD,CAChD,EACF,EACA,qEAAsE,CACpE,EACF,EACA,mDAAoD,CAClD,EACF,EACA,kCAAmC,CACjC,EACF,EACA,oCAAqC,CACnC,EACF,EACA,0DAA2D,CACzD,EACF,EACA,2CAA4C,CAC1C,EACF,EACA,0DAA2D,CACzD,EACF,EACA,yDAA0D,CACxD,EACF,EACA,2CAA4C,CAC1C,EACF,EACA,oEAAqE,CACnE,EACF,EACA,gEAAiE,CAC/D,EACF,EACA,gEAAiE,CAC/D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kCAAmC,CACjC,EACF,EACA,SAAY,CACV,EACF,EACA,yLAA0L,CACxL,EACF,EACA,kBAAmB,CACjB,EACF,EACA,gBAAiB,CACf,EACF,EACA,YAAa,CACX,EACF,EACA,SAAY,CACV,YACF,EACA,iCAAkC,CAChC,EACF,EACA,OAAU,CACR,EACF,EACA,MAAS,CACP,QACF,EACA,sCAAuC,CACrC,EACF,EACA,iEAAkE,CAChE,EACF,EACA,+BAAkC,CAChC,uBACF,EACA,iBAAkB,CAChB,SACF,EACA,kBAAmB,CACjB,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,EACF,EACA,0BAA2B,CACzB,uBACF,EACA,OAAU,CACR,EACF,EACA,SAAU,CACR,EACF,EACA,uBAAwB,CACtB,EACF,EACA,uBAAwB,CACtB,6BACF,EACA,0DAA2D,CACzD,EACF,EACA,KAAQ,CACN,MACF,EACA,YAAe,CACb,gBACF,EACA,KAAQ,CACN,EACF,EACA,SAAY,CACV,EACF,EACA,gBAAiB,CACf,EACF,EACA,GAAM,CACJ,EACF,EACA,KAAQ,CACN,EACF,EACA,aAAc,CACZ,EACF,EACA,KAAQ,CACN,EACF,EACA,qBAAsB,CACpB,oBACF,EACA,QAAW,CACT,EACF,EACA,mBAAoB,CAClB,oBACF,EACA,oEAAqE,CACnE,EACF,EACA,wFAAyF,CACvF,EACF,EACA,+BAAgC,CAC9B,uCACF,EACA,+BAAgC,CAC9B,sCACF,EACA,sEAAuE,CACrE,EACF,EACA,qEAAsE,CACpE,EACF,EACA,cAAe,CACb,EACF,EACA,6CAA8C,CAC5C,sCACF,EACA,oFAAgF,CAC9E,EACF,EACA,uBAAwB,CACtB,oBACF,EACA,mCAAoC,CAClC,oBACF,EACA,wBAAyB,CACvB,UACF,EACA,4CAA6C,CAC3C,EACF,EACA,kCAAmC,CACjC,EACF,EACA,mDAAoD,CAClD,EACF,EACA,wCAAyC,CACvC,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,qDAAsD,CACpD,EACF,EACA,qCAAsC,CACpC,EACF,EACA,SAAY,CACV,EACF,EACA,0BAA2B,CACzB,EACF,EACA,mDAAoD,CAClD,mCACF,EACA,2FAAgG,CAC9F,EACF,EACA,2EAA4E,CAC1E,EACF,EACA,2BAA4B,CAC1B,UACF,EACA,sBAAuB,CACrB,oBACF,EACA,6FAA8F,CAC5F,EACF,EACA,wDAAyD,CACvD,EACF,EACA,uBAAwB,CACtB,qCACF,EACA,4IAA6I,CAC3I,EACF,EACA,yBAA0B,CACxB,EACF,EACA,sDAAuD,CACrD,EACF,EACA,8JAA+J,CAC7J,EACF,EACA,eAAgB,CACd,EACF,EACA,SAAY,CACV,WACF,EACA,oDAAqD,CACnD,EACF,EACA,6CAA8C,CAC5C,wBACF,EACA,oBAAqB,CACnB,oBACF,EACA,0DAA2D,CACzD,EACF,EACA,qBAAsB,CACpB,oBACF,EACA,uDAAwD,CACtD,EACF,EACA,0BAA2B,CACzB,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,SAAY,CACV,EACF,EACA,wBAAyB,CACvB,EACF,EACA,2FAA4F,CAC1F,EACF,EACA,0BAA2B,CACzB,uCACF,EACA,8DAA+D,CAC7D,EACF,EACA,YAAa,CACX,EACF,EACA,aAAc,CACZ,EACF,EACA,oBAAqB,CACnB,uCACF,EACA,sEAAuE,CACrE,EACF,EACA,0BAA2B,CACzB,qDACF,EACA,qEAAsE,CACpE,EACF,EACA,iBAAkB,CAChB,EACF,EACA,sLAAuL,CACrL,EACF,EACA,mFAAoF,CAClF,EACF,EACA,kFAAmF,CACjF,EACF,EACA,iCAAkC,CAChC,eACF,EACA,YAAe,CACb,EACF,EACA,yBAA0B,CACxB,qCACF,EACA,QAAW,CACT,EACF,EACA,gBAAiB,CACf,EACF,EACA,2DAA4D,CAC1D,sCACF,EACA,qEAAsE,CACpE,EACF,EACA,mCAAoC,CAClC,EACF,EACA,0BAA2B,CACzB,QACF,EACA,+BAAgC,CAC9B,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,KAAQ,CACN,EACF,EACA,YAAe,CACb,EACF,EACA,OAAU,CACR,EACF,EACA,OAAQ,CACN,EACF,EACA,OAAQ,CACN,EACF,EACA,mBAAoB,CAClB,EACF,EACA,QAAW,CACT,EACF,EACA,OAAU,CACR,EACF,EACA,YAAe,CACb,aACF,EACA,SAAY,CACV,mBACF,EACA,WAAc,CACZ,QACF,EACA,kCAAmC,CACjC,EACF,EACA,wBAAyB,CACvB,qBACF,EACA,yBAA0B,CACxB,QACF,EACA,oBAAqB,CACnB,uBACF,EACA,yBAA0B,CACxB,EACF,EACA,iBAAkB,CAChB,qBACF,EACA,gBAAiB,CACf,EACF,EACA,aAAc,CACZ,EACF,EACA,mGAAoG,CAClG,EACF,EACA,iBAAkB,CAChB,qCACF,EACA,4DAA6D,CAC3D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,UAAa,CACX,EACF,EACA,mBAAoB,CAClB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,OAAU,CACR,EACF,EACA,QAAW,CACT,EACF,EACA,cAAe,CACb,EACF,EACA,iBAAkB,CAChB,EACF,EACA,+DAAgE,CAC9D,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qBAAsB,CACpB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,cAAe,CACb,UACF,EACA,gBAAiB,CACf,EACF,EACA,KAAQ,CACN,EACF,EACA,mFAAoF,CAClF,EACF,EACA,GAAM,CACJ,EACF,EACA,gFAAiF,CAC/E,EACF,EACA,QAAW,CACT,EACF,EACA,sDAAuD,CACrD,EACF,EACA,mDAAsD,CACpD,EACF,EACA,SAAY,CACV,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,wDAA2D,CACzD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,mDAAoD,CAClD,EACF,EACA,uIAAwI,CACtI,EACF,EACA,+BAAgC,CAC9B,QACF,EACA,aAAgB,CACd,EACF,EACA,UAAa,CACX,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,EACF,EACA,+BAAgC,CAC9B,QACF,EACA,YAAa,CACX,EACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,qCACF,EACA,wBAAyB,CACvB,QACF,EACA,SAAY,CACV,SACF,EACA,KAAQ,CACN,EACF,EACA,MAAS,CACP,EACF,EACA,yCAA0C,CACxC,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,oDAAqD,CACnD,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,QAAW,CACT,EACF,EACA,0BAA2B,CACzB,EACF,EACA,QAAW,CACT,OACF,EACA,WAAY,CACV,EACF,EACA,yCAA0C,CACxC,EACF,EACA,MAAS,CACP,EACF,EACA,OAAU,CACR,EACF,EACA,OAAU,CACR,EACF,EACA,IAAO,CACL,iBACF,EACA,uBAAwB,CACtB,QACF,EACA,iCAAkC,CAChC,EACF,EACA,+BAAgC,CAC9B,QACF,EACA,iCAAkC,CAChC,EACF,EACA,sDAAuD,CACrD,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,OAAU,CACR,EACF,EACA,6BAA8B,CAC5B,4BACF,EACA,uBAAwB,CACtB,oBACF,EACA,kDAAmD,CACjD,wBACF,EACA,oBAAqB,CACnB,EACF,EACA,8HAA+H,CAC7H,EACF,EACA,wBAAyB,CACvB,EACF,EACA,kFAAmF,CACjF,EACF,EACA,0EAA2E,CACzE,EACF,EACA,wGAAyG,CACvG,EACF,EACA,oEAAqE,CACnE,EACF,EACA,sBAAuB,CACrB,EACF,EACA,iJAAkJ,CAChJ,EACF,EACA,wBAAyB,CACvB,EACF,EACA,kCAAmC,CACjC,qCACF,EACA,6HAA8H,CAC5H,EACF,EACA,kBAAmB,CACjB,qBACF,EACA,QAAW,CACT,EACF,EACA,cAAe,CACb,EACF,EACA,eAAgB,CACd,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,uBAAwB,CACtB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,6BAA8B,CAC5B,+CACF,EACA,mBAAoB,CAClB,eACF,EACA,+DAAgE,CAC9D,EACF,EACA,kGAAmG,CACjG,EACF,EACA,MAAS,CACP,EACF,EACA,0DAA2D,CACzD,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,cAAe,CACb,EACF,EACA,qDAAsD,CACpD,EACF,EACA,YAAa,CACX,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,kBAAmB,CACjB,kBACF,EACA,kFAAmF,CACjF,EACF,EACA,WAAY,CACV,EACF,EACA,0CAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,EACF,EACA,yDAA0D,CACxD,EACF,EACA,0DAA2D,CACzD,EACF,EACA,iBAAkB,CAChB,kBACF,EACA,kBAAmB,CACjB,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,kFAAmF,CACjF,EACF,EACA,kFAAmF,CACjF,EACF,EACA,uFAAwF,CACtF,EACF,EACA,8BAA+B,CAC7B,oCACF,EACA,iBAAoB,CAClB,EACF,EACA,QAAW,CACT,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,iBAAkB,CAChB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,wRAA6R,CAC3R,EACF,EACA,eAAgB,CACd,SACF,EACA,mCAAoC,CAClC,oBACF,EACA,KAAQ,CACN,EACF,EACA,qCAAsC,CACpC,EACF,EACA,eAAgB,CACd,SACF,EACA,0CAA2C,CACzC,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,QAAW,CACT,iBACF,EACA,eAAgB,CACd,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,mBAAoB,CAClB,mCACF,EACA,kGAAmG,CACjG,EACF,EACA,kCAAmC,CACjC,EACF,EACA,kBAAmB,CACjB,oCACF,EACA,mBAAoB,CAClB,EACF,EACA,uEAAwE,CACtE,EACF,EACA,iGAAkG,CAChG,EACF,EACA,uEAAwE,CACtE,EACF,EACA,oDAAqD,CACnD,EACF,EACA,2BAA4B,CAC1B,oCACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,eAAgB,CACd,EACF,EACA,gBAAiB,CACf,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,OAAU,CACR,EACF,EACA,iBAAkB,CAChB,EACF,EACA,QAAW,CACT,EACF,EACA,QAAW,CACT,EACF,EACA,kBAAmB,CACjB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,mCAAoC,CAClC,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,yCAA0C,CACxC,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,YAAa,CACX,EACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,EACF,EACA,YAAa,CACX,EACF,EACA,YAAa,CACX,EACF,EACA,mCAAoC,CAClC,EACF,EACA,mEAAoE,CAClE,EACF,EACA,mEAAoE,CAClE,EACF,EACA,MAAS,CACP,EACF,EACA,mDAAoD,CAClD,EACF,EACA,OAAU,CACR,EACF,EACA,wDAAyD,CACvD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,SAAY,CACV,EACF,EACA,eAAgB,CACd,EACF,EACA,eAAgB,CACd,EACF,EACA,iBAAkB,CAChB,UACF,EACA,wCAA2C,CACzC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yDAA0D,CACxD,EACF,EACA,oCAAqC,CACnC,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,qDAAsD,CACpD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,yCAA0C,CACxC,EACF,EACA,mBAAoB,CAClB,qDACF,EACA,sBAAuB,CACrB,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,sBAAuB,CACrB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,kCAAmC,CACjC,EACF,EACA,sBAAuB,CACrB,EACF,EACA,SAAY,CACV,EACF,EACA,sBAAuB,CACrB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yCAA0C,CACxC,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,wHAAyH,CACvH,EACF,EACA,qBAAsB,CACpB,EACF,EACA,iBAAkB,CAChB,UACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,oCAAqC,CACnC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,kBAAmB,CACjB,UACF,EACA,sCAAuC,CACrC,EACF,EACA,0BAA6B,CAC3B,EACF,EACA,aAAgB,CACd,EACF,EACA,qDAAsD,CACpD,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,iDAAkD,CAChD,EACF,EACA,iBAAkB,CAChB,EACF,EACA,QAAW,CACT,EACF,EACA,YAAe,CACb,qDACF,EACA,0CAA2C,CACzC,sCACF,EACA,iHAAkH,CAChH,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,EACF,CACF,CACF,EACA,OAAU,WACV,aAAgB,6BAChB,KAAQ,KACR,aAAgB,EAClB,EAEAA,GAAQ,GAAQ,CACd,YAAe,CACb,SAAY,CACV,GAAI,CACF,OAAU,WACV,aAAgB,wFAChB,KAAQ,IACV,EACA,uDAAwD,CACtD,EACF,EACA,uCAAwC,CACtC,EACF,EACA,wCAAyC,CACvC,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,SAAY,CACV,EACF,EACA,wBAAyB,CACvB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,yFAA0F,CACxF,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,qBAAsB,CACpB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qEAAsE,CACpE,EACF,EACA,kEAAmE,CACjE,EACF,EACA,KAAQ,CACN,EACF,EACA,0BAA2B,CACzB,EACF,EACA,0BAA2B,CACzB,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,KAAQ,CACN,EACF,EACA,OAAU,CACR,EACF,EACA,qBAAsB,CACpB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,oEAAqE,CACnE,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,mBAAoB,CAClB,EACF,EACA,uCAAwC,CACtC,EACF,EACA,wKAAyK,CACvK,EACF,EACA,qEAAsE,CACpE,EACF,EACA,yEAA0E,CACxE,EACF,EACA,4EAA6E,CAC3E,EACF,EACA,iCAAoC,CAClC,EACF,EACA,oCAAuC,CACrC,EACF,EACA,gBAAiB,CACf,EACF,EACA,oBAAqB,CACnB,EACF,EACA,kDAAmD,CACjD,EACF,EACA,OAAU,CACR,EACF,EACA,SAAY,CACV,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,8DAA+D,CAC7D,EACF,EACA,MAAS,CACP,EACF,EACA,sBAAuB,CACrB,EACF,EACA,oIAAqI,CACnI,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,0BAA2B,CACzB,EACF,EACA,iCAAkC,CAChC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yBAA0B,CACxB,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,QAAW,CACT,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,wBAAyB,CACvB,EACF,EACA,qDAAsD,CACpD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kBAAmB,CACjB,EACF,EACA,yCAA0C,CACxC,EACF,EACA,oBAAqB,CACnB,EACF,EACA,8EAA+E,CAC7E,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,qCAAsC,CACpC,EACF,EACA,oDAAqD,CACnD,EACF,EACA,qFAAsF,CACpF,EACF,EACA,sDAAuD,CACrD,EACF,EACA,kBAAmB,CACjB,EACF,EACA,QAAW,CACT,EACF,EACA,kBAAmB,CACjB,EACF,EACA,QAAW,CACT,EACF,EACA,IAAO,CACL,EACF,EACA,aAAc,CACZ,EACF,EACA,aAAc,CACZ,EACF,EACA,mFAAoF,CAClF,EACF,EACA,oBAAqB,CACnB,EACF,EACA,oFAAqF,CACnF,EACF,EACA,mBAAoB,CAClB,EACF,EACA,SAAY,CACV,EACF,EACA,YAAa,CACX,EACF,EACA,eAAgB,CACd,EACF,EACA,OAAU,CACR,EACF,EACA,aAAc,CACZ,EACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,EACF,EACA,yBAA0B,CACxB,EACF,EACA,YAAa,CACX,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,mBAAoB,CAClB,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,0EAA2E,CACzE,EACF,EACA,mDAAoD,CAClD,EACF,EACA,0DAA2D,CACzD,EACF,EACA,gDAAmD,CACjD,EACF,EACA,oEAAqE,CACnE,EACF,EACA,oDAAqD,CACnD,EACF,EACA,2CAA8C,CAC5C,EACF,EACA,sEAAuE,CACrE,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,yBAA0B,CACxB,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,eAAgB,CACd,EACF,EACA,yFAA0F,CACxF,EACF,EACA,UAAW,CACT,EACF,EACA,6EAA8E,CAC5E,EACF,EACA,UAAa,CACX,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,SAAY,CACV,EACF,EACA,kCAAmC,CACjC,EACF,EACA,QAAW,CACT,EACF,EACA,qCAAsC,CACpC,EACF,EACA,qBAAsB,CACpB,EACF,EACA,aAAc,CACZ,EACF,EACA,oDAAqD,CACnD,EACF,EACA,0FAA2F,CACzF,EACF,EACA,mEAAoE,CAClE,EACF,EACA,iDAAkD,CAChD,EACF,EACA,KAAQ,CACN,EACF,EACA,KAAQ,CACN,EACF,EACA,2CAA8C,CAC5C,EACF,EACA,wCAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,EACF,EACA,mCAAsC,CACpC,EACF,EACA,qEAAwE,CACtE,EACF,EACA,sCAAyC,CACvC,EACF,EACA,gFAAmF,CACjF,EACF,EACA,sCAAyC,CACvC,EACF,EACA,yCAA0C,CACxC,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,kCAAmC,CACjC,EACF,EACA,kBAAmB,CACjB,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,0DAA2D,CACzD,EACF,EACA,sBAAuB,CACrB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,+CAAgD,CAC9C,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,uBAAwB,CACtB,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,iDAAkD,CAChD,EACF,EACA,qEAAsE,CACpE,EACF,EACA,mDAAoD,CAClD,EACF,EACA,kCAAmC,CACjC,EACF,EACA,oCAAqC,CACnC,EACF,EACA,0DAA2D,CACzD,EACF,EACA,2CAA4C,CAC1C,EACF,EACA,0DAA2D,CACzD,EACF,EACA,yDAA0D,CACxD,EACF,EACA,2CAA4C,CAC1C,EACF,EACA,oEAAqE,CACnE,EACF,EACA,gEAAiE,CAC/D,EACF,EACA,gEAAiE,CAC/D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kCAAmC,CACjC,EACF,EACA,SAAY,CACV,EACF,EACA,yLAA0L,CACxL,EACF,EACA,kBAAmB,CACjB,EACF,EACA,gBAAiB,CACf,EACF,EACA,YAAa,CACX,EACF,EACA,SAAY,CACV,EACF,EACA,iCAAkC,CAChC,EACF,EACA,OAAU,CACR,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,iEAAkE,CAChE,EACF,EACA,+BAAkC,CAChC,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kBAAmB,CACjB,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,EACF,EACA,0BAA2B,CACzB,EACF,EACA,OAAU,CACR,EACF,EACA,SAAU,CACR,EACF,EACA,uBAAwB,CACtB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,0DAA2D,CACzD,EACF,EACA,KAAQ,CACN,EACF,EACA,YAAe,CACb,EACF,EACA,KAAQ,CACN,EACF,EACA,SAAY,CACV,EACF,EACA,gBAAiB,CACf,EACF,EACA,GAAM,CACJ,EACF,EACA,KAAQ,CACN,EACF,EACA,aAAc,CACZ,EACF,EACA,KAAQ,CACN,EACF,EACA,qBAAsB,CACpB,EACF,EACA,QAAW,CACT,EACF,EACA,mBAAoB,CAClB,EACF,EACA,oEAAqE,CACnE,EACF,EACA,wFAAyF,CACvF,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,sEAAuE,CACrE,EACF,EACA,qEAAsE,CACpE,EACF,EACA,cAAe,CACb,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,oFAAgF,CAC9E,EACF,EACA,uBAAwB,CACtB,EACF,EACA,mCAAoC,CAClC,EACF,EACA,wBAAyB,CACvB,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,kCAAmC,CACjC,EACF,EACA,mDAAoD,CAClD,EACF,EACA,wCAAyC,CACvC,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,qDAAsD,CACpD,EACF,EACA,qCAAsC,CACpC,EACF,EACA,SAAY,CACV,EACF,EACA,0BAA2B,CACzB,EACF,EACA,mDAAoD,CAClD,EACF,EACA,2FAAgG,CAC9F,EACF,EACA,2EAA4E,CAC1E,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,sBAAuB,CACrB,EACF,EACA,6FAA8F,CAC5F,EACF,EACA,wDAAyD,CACvD,EACF,EACA,uBAAwB,CACtB,EACF,EACA,4IAA6I,CAC3I,EACF,EACA,yBAA0B,CACxB,EACF,EACA,sDAAuD,CACrD,EACF,EACA,8JAA+J,CAC7J,EACF,EACA,eAAgB,CACd,EACF,EACA,SAAY,CACV,EACF,EACA,oDAAqD,CACnD,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,oBAAqB,CACnB,EACF,EACA,0DAA2D,CACzD,EACF,EACA,qBAAsB,CACpB,EACF,EACA,uDAAwD,CACtD,EACF,EACA,0BAA2B,CACzB,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,SAAY,CACV,EACF,EACA,wBAAyB,CACvB,EACF,EACA,2FAA4F,CAC1F,EACF,EACA,0BAA2B,CACzB,EACF,EACA,8DAA+D,CAC7D,EACF,EACA,YAAa,CACX,EACF,EACA,aAAc,CACZ,EACF,EACA,oBAAqB,CACnB,EACF,EACA,sEAAuE,CACrE,EACF,EACA,0BAA2B,CACzB,EACF,EACA,qEAAsE,CACpE,EACF,EACA,iBAAkB,CAChB,EACF,EACA,sLAAuL,CACrL,EACF,EACA,mFAAoF,CAClF,EACF,EACA,kFAAmF,CACjF,EACF,EACA,iCAAkC,CAChC,EACF,EACA,YAAe,CACb,EACF,EACA,yBAA0B,CACxB,EACF,EACA,QAAW,CACT,EACF,EACA,gBAAiB,CACf,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,qEAAsE,CACpE,EACF,EACA,mCAAoC,CAClC,EACF,EACA,0BAA2B,CACzB,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,KAAQ,CACN,EACF,EACA,YAAe,CACb,EACF,EACA,OAAU,CACR,EACF,EACA,OAAQ,CACN,EACF,EACA,OAAQ,CACN,EACF,EACA,mBAAoB,CAClB,EACF,EACA,QAAW,CACT,EACF,EACA,OAAU,CACR,EACF,EACA,YAAe,CACb,EACF,EACA,SAAY,CACV,EACF,EACA,WAAc,CACZ,EACF,EACA,kCAAmC,CACjC,EACF,EACA,wBAAyB,CACvB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,iBAAkB,CAChB,EACF,EACA,gBAAiB,CACf,EACF,EACA,aAAc,CACZ,EACF,EACA,mGAAoG,CAClG,EACF,EACA,iBAAkB,CAChB,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,UAAa,CACX,EACF,EACA,mBAAoB,CAClB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,OAAU,CACR,EACF,EACA,QAAW,CACT,EACF,EACA,cAAe,CACb,EACF,EACA,iBAAkB,CAChB,EACF,EACA,+DAAgE,CAC9D,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qBAAsB,CACpB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,cAAe,CACb,EACF,EACA,gBAAiB,CACf,EACF,EACA,KAAQ,CACN,EACF,EACA,mFAAoF,CAClF,EACF,EACA,GAAM,CACJ,EACF,EACA,gFAAiF,CAC/E,EACF,EACA,QAAW,CACT,EACF,EACA,sDAAuD,CACrD,EACF,EACA,mDAAsD,CACpD,EACF,EACA,SAAY,CACV,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,wDAA2D,CACzD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,mDAAoD,CAClD,EACF,EACA,uIAAwI,CACtI,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,aAAgB,CACd,EACF,EACA,UAAa,CACX,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,YAAa,CACX,EACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,wBAAyB,CACvB,EACF,EACA,SAAY,CACV,EACF,EACA,KAAQ,CACN,EACF,EACA,MAAS,CACP,EACF,EACA,yCAA0C,CACxC,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,oDAAqD,CACnD,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,QAAW,CACT,EACF,EACA,0BAA2B,CACzB,EACF,EACA,QAAW,CACT,EACF,EACA,WAAY,CACV,EACF,EACA,yCAA0C,CACxC,EACF,EACA,MAAS,CACP,EACF,EACA,OAAU,CACR,EACF,EACA,OAAU,CACR,EACF,EACA,IAAO,CACL,EACF,EACA,uBAAwB,CACtB,EACF,EACA,iCAAkC,CAChC,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,iCAAkC,CAChC,EACF,EACA,sDAAuD,CACrD,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,OAAU,CACR,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,uBAAwB,CACtB,EACF,EACA,kDAAmD,CACjD,EACF,EACA,oBAAqB,CACnB,EACF,EACA,8HAA+H,CAC7H,EACF,EACA,wBAAyB,CACvB,EACF,EACA,kFAAmF,CACjF,EACF,EACA,0EAA2E,CACzE,EACF,EACA,wGAAyG,CACvG,EACF,EACA,oEAAqE,CACnE,EACF,EACA,sBAAuB,CACrB,EACF,EACA,iJAAkJ,CAChJ,EACF,EACA,wBAAyB,CACvB,EACF,EACA,kCAAmC,CACjC,EACF,EACA,6HAA8H,CAC5H,EACF,EACA,kBAAmB,CACjB,EACF,EACA,QAAW,CACT,EACF,EACA,cAAe,CACb,EACF,EACA,eAAgB,CACd,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,uBAAwB,CACtB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,mBAAoB,CAClB,EACF,EACA,+DAAgE,CAC9D,EACF,EACA,kGAAmG,CACjG,EACF,EACA,MAAS,CACP,EACF,EACA,0DAA2D,CACzD,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,cAAe,CACb,EACF,EACA,qDAAsD,CACpD,EACF,EACA,YAAa,CACX,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,kBAAmB,CACjB,EACF,EACA,kFAAmF,CACjF,EACF,EACA,WAAY,CACV,EACF,EACA,0CAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,EACF,EACA,yDAA0D,CACxD,EACF,EACA,0DAA2D,CACzD,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kBAAmB,CACjB,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,kFAAmF,CACjF,EACF,EACA,kFAAmF,CACjF,EACF,EACA,uFAAwF,CACtF,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,iBAAoB,CAClB,EACF,EACA,QAAW,CACT,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,iBAAkB,CAChB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,wRAA6R,CAC3R,EACF,EACA,eAAgB,CACd,EACF,EACA,mCAAoC,CAClC,EACF,EACA,KAAQ,CACN,EACF,EACA,qCAAsC,CACpC,EACF,EACA,eAAgB,CACd,EACF,EACA,0CAA2C,CACzC,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,QAAW,CACT,EACF,EACA,eAAgB,CACd,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,mBAAoB,CAClB,EACF,EACA,kGAAmG,CACjG,EACF,EACA,kCAAmC,CACjC,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,uEAAwE,CACtE,EACF,EACA,iGAAkG,CAChG,EACF,EACA,uEAAwE,CACtE,EACF,EACA,oDAAqD,CACnD,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,eAAgB,CACd,EACF,EACA,gBAAiB,CACf,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,OAAU,CACR,EACF,EACA,iBAAkB,CAChB,EACF,EACA,QAAW,CACT,EACF,EACA,QAAW,CACT,EACF,EACA,kBAAmB,CACjB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,mCAAoC,CAClC,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,yCAA0C,CACxC,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,YAAa,CACX,EACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,EACF,EACA,YAAa,CACX,EACF,EACA,YAAa,CACX,EACF,EACA,mCAAoC,CAClC,EACF,EACA,mEAAoE,CAClE,EACF,EACA,mEAAoE,CAClE,EACF,EACA,MAAS,CACP,EACF,EACA,mDAAoD,CAClD,EACF,EACA,OAAU,CACR,EACF,EACA,wDAAyD,CACvD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,SAAY,CACV,EACF,EACA,eAAgB,CACd,EACF,EACA,eAAgB,CACd,EACF,EACA,iBAAkB,CAChB,EACF,EACA,wCAA2C,CACzC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yDAA0D,CACxD,EACF,EACA,oCAAqC,CACnC,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,qDAAsD,CACpD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,yCAA0C,CACxC,EACF,EACA,mBAAoB,CAClB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,sBAAuB,CACrB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,kCAAmC,CACjC,EACF,EACA,sBAAuB,CACrB,EACF,EACA,SAAY,CACV,EACF,EACA,sBAAuB,CACrB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yCAA0C,CACxC,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,wHAAyH,CACvH,EACF,EACA,qBAAsB,CACpB,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,oCAAqC,CACnC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,kBAAmB,CACjB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,0BAA6B,CAC3B,EACF,EACA,aAAgB,CACd,EACF,EACA,qDAAsD,CACpD,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,iDAAkD,CAChD,EACF,EACA,iBAAkB,CAChB,EACF,EACA,QAAW,CACT,EACF,EACA,YAAe,CACb,EACF,EACA,0CAA2C,CACzC,EACF,EACA,iHAAkH,CAChH,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,EACF,CACF,CACF,EACA,OAAU,WACV,aAAgB,wFAChB,KAAQ,KACR,aAAgB,CAClB,EAEAA,GAAQ,GAAQ,CACd,YAAe,CACb,SAAY,CACV,GAAI,CACF,OAAU,WACV,aAAgB,4BAChB,KAAQ,IACV,EACA,uDAAwD,CACtD,oEACF,EACA,uCAAwC,CACtC,4CACF,EACA,wCAAyC,CACvC,8CACF,EACA,8BAA+B,CAC7B,oDACF,EACA,8CAA+C,CAC7C,4EACF,EACA,2DAA4D,CAC1D,gFACF,EACA,SAAY,CACV,aACF,EACA,wBAAyB,CACvB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,yFAA0F,CACxF,EACF,EACA,+BAAgC,CAC9B,yCACF,EACA,qBAAsB,CACpB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qEAAsE,CACpE,EACF,EACA,kEAAmE,CACjE,EACF,EACA,KAAQ,CACN,EACF,EACA,0BAA2B,CACzB,6BACF,EACA,0BAA2B,CACzB,wBACF,EACA,+FAAgG,CAC9F,EACF,EACA,KAAQ,CACN,EACF,EACA,OAAU,CACR,EACF,EACA,qBAAsB,CACpB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,oEAAqE,CACnE,EACF,EACA,4BAA6B,CAC3B,qCACF,EACA,mBAAoB,CAClB,EACF,EACA,uCAAwC,CACtC,8BACF,EACA,wKAAyK,CACvK,2NACF,EACA,qEAAsE,CACpE,yDACF,EACA,yEAA0E,CACxE,EACF,EACA,4EAA6E,CAC3E,EACF,EACA,iCAAoC,CAClC,EACF,EACA,oCAAuC,CACrC,EACF,EACA,gBAAiB,CACf,EACF,EACA,oBAAqB,CACnB,EACF,EACA,kDAAmD,CACjD,EACF,EACA,OAAU,CACR,SACF,EACA,SAAY,CACV,EACF,EACA,6BAA8B,CAC5B,wCACF,EACA,8DAA+D,CAC7D,oFACF,EACA,MAAS,CACP,QACF,EACA,sBAAuB,CACrB,oCACF,EACA,oIAAqI,CACnI,0JACF,EACA,2BAA4B,CAC1B,oBACF,EACA,4CAA6C,CAC3C,wDACF,EACA,0BAA2B,CACzB,gCACF,EACA,iCAAkC,CAChC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yBAA0B,CACxB,8DACF,EACA,gCAAiC,CAC/B,uDACF,EACA,QAAW,CACT,UACF,EACA,4BAA6B,CAC3B,0CACF,EACA,wBAAyB,CACvB,8BACF,EACA,qDAAsD,CACpD,iDACF,EACA,qDAAsD,CACpD,+DACF,EACA,iBAAkB,CAChB,oBACF,EACA,kBAAmB,CACjB,yBACF,EACA,yCAA0C,CACxC,8BACF,EACA,oBAAqB,CACnB,sBACF,EACA,8EAA+E,CAC7E,oGACF,EACA,8CAA+C,CAC7C,wEACF,EACA,6CAA8C,CAC5C,8CACF,EACA,qCAAsC,CACpC,6CACF,EACA,oDAAqD,CACnD,6DACF,EACA,qFAAsF,CACpF,0GACF,EACA,sDAAuD,CACrD,wDACF,EACA,kBAAmB,CACjB,oBACF,EACA,QAAW,CACT,SACF,EACA,kBAAmB,CACjB,oBACF,EACA,QAAW,CACT,OACF,EACA,IAAO,CACL,OACF,EACA,aAAc,CACZ,uBACF,EACA,aAAc,CACZ,uDACF,EACA,mFAAoF,CAClF,+FACF,EACA,oBAAqB,CACnB,wCACF,EACA,oFAAqF,CACnF,0GACF,EACA,mBAAoB,CAClB,8BACF,EACA,SAAY,CACV,QACF,EACA,YAAa,CACX,cACF,EACA,eAAgB,CACd,eACF,EACA,OAAU,CACR,SACF,EACA,aAAc,CACZ,yBACF,EACA,eAAgB,CACd,eACF,EACA,aAAc,CACZ,iBACF,EACA,yBAA0B,CACxB,gCACF,EACA,YAAa,CACX,YACF,EACA,8BAA+B,CAC7B,0BACF,EACA,mBAAoB,CAClB,uDACF,EACA,gDAAiD,CAC/C,oEACF,EACA,0EAA2E,CACzE,0GACF,EACA,mDAAoD,CAClD,yDACF,EACA,0DAA2D,CACzD,iFACF,EACA,gDAAmD,CACjD,8DACF,EACA,oEAAqE,CACnE,+EACF,EACA,oDAAqD,CACnD,sDACF,EACA,2CAA8C,CAC5C,6CACF,EACA,sEAAuE,CACrE,qFACF,EACA,8CAA+C,CAC7C,iFACF,EACA,yBAA0B,CACxB,gCACF,EACA,6BAA8B,CAC5B,mCACF,EACA,eAAgB,CACd,6BACF,EACA,yFAA0F,CACxF,8FACF,EACA,UAAW,CACT,SACF,EACA,6EAA8E,CAC5E,2GACF,EACA,UAAa,CACX,cACF,EACA,gCAAiC,CAC/B,uCACF,EACA,SAAY,CACV,mBACF,EACA,kCAAmC,CACjC,gCACF,EACA,QAAW,CACT,iBACF,EACA,qCAAsC,CACpC,4CACF,EACA,qBAAsB,CACpB,4BACF,EACA,aAAc,CACZ,kBACF,EACA,oDAAqD,CACnD,oEACF,EACA,0FAA2F,CACzF,yGACF,EACA,mEAAoE,CAClE,iFACF,EACA,iDAAkD,CAChD,0DACF,EACA,KAAQ,CACN,SACF,EACA,KAAQ,CACN,SACF,EACA,2CAA8C,CAC5C,yDACF,EACA,wCAA2C,CACzC,mDACF,EACA,0BAA2B,CACzB,+BACF,EACA,mCAAsC,CACpC,8CACF,EACA,qEAAwE,CACtE,iFACF,EACA,sCAAyC,CACvC,4CACF,EACA,gFAAmF,CACjF,4GACF,EACA,sCAAyC,CACvC,yCACF,EACA,yCAA0C,CACxC,mEACF,EACA,gCAAiC,CAC/B,8BACF,EACA,gCAAiC,CAC/B,iDACF,EACA,+BAAgC,CAC9B,qCACF,EACA,kCAAmC,CACjC,+BACF,EACA,kBAAmB,CACjB,EACF,EACA,4BAA6B,CAC3B,iDACF,EACA,0DAA2D,CACzD,wEACF,EACA,sBAAuB,CACrB,cACF,EACA,mBAAoB,CAClB,sBACF,EACA,mBAAoB,CAClB,uBACF,EACA,+CAAgD,CAC9C,wDACF,EACA,6BAA8B,CAC5B,wCACF,EACA,uBAAwB,CACtB,oBACF,EACA,8CAA+C,CAC7C,wEACF,EACA,iDAAkD,CAChD,yDACF,EACA,qEAAsE,CACpE,+EACF,EACA,mDAAoD,CAClD,+EACF,EACA,kCAAmC,CACjC,8DACF,EACA,oCAAqC,CACnC,8DACF,EACA,0DAA2D,CACzD,wEACF,EACA,2CAA4C,CAC1C,uDACF,EACA,0DAA2D,CACzD,4EACF,EACA,yDAA0D,CACxD,wEACF,EACA,2CAA4C,CAC1C,wEACF,EACA,oEAAqE,CACnE,mGACF,EACA,gEAAiE,CAC/D,wDACF,EACA,gEAAiE,CAC/D,wDACF,EACA,uBAAwB,CACtB,gBACF,EACA,iBAAkB,CAChB,iCACF,EACA,kCAAmC,CACjC,EACF,EACA,SAAY,CACV,cACF,EACA,yLAA0L,CACxL,gPACF,EACA,kBAAmB,CACjB,+BACF,EACA,gBAAiB,CACf,sBACF,EACA,YAAa,CACX,aACF,EACA,SAAY,CACV,aACF,EACA,iCAAkC,CAChC,iDACF,EACA,OAAU,CACR,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,iEAAkE,CAChE,EACF,EACA,+BAAkC,CAChC,qDACF,EACA,iBAAkB,CAChB,uBACF,EACA,kBAAmB,CACjB,6BACF,EACA,SAAY,CACV,mBACF,EACA,eAAkB,CAChB,EACF,EACA,0BAA2B,CACzB,wBACF,EACA,OAAU,CACR,EACF,EACA,SAAU,CACR,cACF,EACA,uBAAwB,CACtB,6BACF,EACA,uBAAwB,CACtB,uDACF,EACA,0DAA2D,CACzD,yEACF,EACA,KAAQ,CACN,MACF,EACA,YAAe,CACb,cACF,EACA,KAAQ,CACN,WACF,EACA,SAAY,CACV,SACF,EACA,gBAAiB,CACf,mBACF,EACA,GAAM,CACJ,MACF,EACA,KAAQ,CACN,IACF,EACA,aAAc,CACZ,kBACF,EACA,KAAQ,CACN,UACF,EACA,qBAAsB,CACpB,sBACF,EACA,QAAW,CACT,EACF,EACA,mBAAoB,CAClB,sBACF,EACA,oEAAqE,CACnE,qFACF,EACA,wFAAyF,CACvF,+GACF,EACA,+BAAgC,CAC9B,mDACF,EACA,+BAAgC,CAC9B,iCACF,EACA,sEAAuE,CACrE,mFACF,EACA,qEAAsE,CACpE,mFACF,EACA,cAAe,CACb,EACF,EACA,6CAA8C,CAC5C,oCACF,EACA,oFAAgF,CAC9E,6GACF,EACA,uBAAwB,CACtB,sBACF,EACA,mCAAoC,CAClC,qCACF,EACA,wBAAyB,CACvB,wBACF,EACA,4CAA6C,CAC3C,4DACF,EACA,kCAAmC,CACjC,4CACF,EACA,mDAAoD,CAClD,8EACF,EACA,wCAAyC,CACvC,8DACF,EACA,6CAA8C,CAC5C,0DACF,EACA,qDAAsD,CACpD,8EACF,EACA,qCAAsC,CACpC,qDACF,EACA,SAAY,CACV,WACF,EACA,0BAA2B,CACzB,8BACF,EACA,mDAAoD,CAClD,4EACF,EACA,2FAAgG,CAC9F,EACF,EACA,2EAA4E,CAC1E,6GACF,EACA,2BAA4B,CAC1B,qCACF,EACA,sBAAuB,CACrB,sBACF,EACA,6FAA8F,CAC5F,uIACF,EACA,wDAAyD,CACvD,wEACF,EACA,uBAAwB,CACtB,qBACF,EACA,4IAA6I,CAC3I,6KACF,EACA,yBAA0B,CACxB,gCACF,EACA,sDAAuD,CACrD,iEACF,EACA,8JAA+J,CAC7J,wLACF,EACA,eAAgB,CACd,gBACF,EACA,SAAY,CACV,SACF,EACA,oDAAqD,CACnD,0DACF,EACA,6CAA8C,CAC5C,0DACF,EACA,oBAAqB,CACnB,sBACF,EACA,0DAA2D,CACzD,+DACF,EACA,qBAAsB,CACpB,4BACF,EACA,uDAAwD,CACtD,wEACF,EACA,0BAA2B,CACzB,6BACF,EACA,8BAA+B,CAC7B,qCACF,EACA,SAAY,CACV,WACF,EACA,wBAAyB,CACvB,mCACF,EACA,2FAA4F,CAC1F,4GACF,EACA,0BAA2B,CACzB,0CACF,EACA,8DAA+D,CAC7D,wEACF,EACA,YAAa,CACX,YACF,EACA,aAAc,CACZ,qBACF,EACA,oBAAqB,CACnB,4BACF,EACA,sEAAuE,CACrE,kGACF,EACA,0BAA2B,CACzB,8BACF,EACA,qEAAsE,CACpE,8FACF,EACA,iBAAkB,CAChB,sBACF,EACA,sLAAuL,CACrL,8OACF,EACA,mFAAoF,CAClF,iGACF,EACA,kFAAmF,CACjF,EACF,EACA,iCAAkC,CAChC,oCACF,EACA,YAAe,CACb,mBACF,EACA,yBAA0B,CACxB,0CACF,EACA,QAAW,CACT,WACF,EACA,gBAAiB,CACf,iBACF,EACA,2DAA4D,CAC1D,yDACF,EACA,qEAAsE,CACpE,EACF,EACA,mCAAoC,CAClC,EACF,EACA,0BAA2B,CACzB,oBACF,EACA,+BAAgC,CAC9B,oBACF,EACA,2BAA4B,CAC1B,oBACF,EACA,KAAQ,CACN,KACF,EACA,YAAe,CACb,uCACF,EACA,OAAU,CACR,EACF,EACA,OAAQ,CACN,EACF,EACA,OAAQ,CACN,EACF,EACA,mBAAoB,CAClB,6BACF,EACA,QAAW,CACT,YACF,EACA,OAAU,CACR,WACF,EACA,YAAe,CACb,cACF,EACA,SAAY,CACV,UACF,EACA,WAAc,CACZ,YACF,EACA,kCAAmC,CACjC,EACF,EACA,wBAAyB,CACvB,oBACF,EACA,yBAA0B,CACxB,oBACF,EACA,oBAAqB,CACnB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,iBAAkB,CAChB,EACF,EACA,gBAAiB,CACf,EACF,EACA,aAAc,CACZ,EACF,EACA,mGAAoG,CAClG,EACF,EACA,iBAAkB,CAChB,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,UAAa,CACX,EACF,EACA,mBAAoB,CAClB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,OAAU,CACR,cACF,EACA,QAAW,CACT,EACF,EACA,cAAe,CACb,EACF,EACA,iBAAkB,CAChB,EACF,EACA,+DAAgE,CAC9D,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qBAAsB,CACpB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,cAAe,CACb,uBACF,EACA,gBAAiB,CACf,EACF,EACA,KAAQ,CACN,EACF,EACA,mFAAoF,CAClF,EACF,EACA,GAAM,CACJ,EACF,EACA,gFAAiF,CAC/E,EACF,EACA,QAAW,CACT,EACF,EACA,sDAAuD,CACrD,EACF,EACA,mDAAsD,CACpD,EACF,EACA,SAAY,CACV,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,wDAA2D,CACzD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,mDAAoD,CAClD,EACF,EACA,uIAAwI,CACtI,0JACF,EACA,+BAAgC,CAC9B,oBACF,EACA,aAAgB,CACd,qCACF,EACA,UAAa,CACX,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,EACF,EACA,+BAAgC,CAC9B,oBACF,EACA,YAAa,CACX,EACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,4CACF,EACA,wBAAyB,CACvB,oBACF,EACA,SAAY,CACV,SACF,EACA,KAAQ,CACN,EACF,EACA,MAAS,CACP,mBACF,EACA,yCAA0C,CACxC,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,oDAAqD,CACnD,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,QAAW,CACT,EACF,EACA,0BAA2B,CACzB,EACF,EACA,QAAW,CACT,QACF,EACA,WAAY,CACV,EACF,EACA,yCAA0C,CACxC,EACF,EACA,MAAS,CACP,EACF,EACA,OAAU,CACR,SACF,EACA,OAAU,CACR,SACF,EACA,IAAO,CACL,SACF,EACA,uBAAwB,CACtB,oBACF,EACA,iCAAkC,CAChC,EACF,EACA,+BAAgC,CAC9B,oBACF,EACA,iCAAkC,CAChC,oBACF,EACA,sDAAuD,CACrD,6DACF,EACA,4BAA6B,CAC3B,oBACF,EACA,OAAU,CACR,EACF,EACA,6BAA8B,CAC5B,iCACF,EACA,uBAAwB,CACtB,gCACF,EACA,kDAAmD,CACjD,0DACF,EACA,oBAAqB,CACnB,4BACF,EACA,8HAA+H,CAC7H,qKACF,EACA,wBAAyB,CACvB,+CACF,EACA,kFAAmF,CACjF,6GACF,EACA,0EAA2E,CACzE,qHACF,EACA,wGAAyG,CACvG,uJACF,EACA,oEAAqE,CACnE,mHACF,EACA,sBAAuB,CACrB,6BACF,EACA,iJAAkJ,CAChJ,4KACF,EACA,wBAAyB,CACvB,mCACF,EACA,kCAAmC,CACjC,mCACF,EACA,6HAA8H,CAC5H,8JACF,EACA,kBAAmB,CACjB,wBACF,EACA,QAAW,CACT,aACF,EACA,cAAe,CACb,gBACF,EACA,eAAgB,CACd,iBACF,EACA,2BAA4B,CAC1B,kCACF,EACA,uBAAwB,CACtB,mBACF,EACA,sBAAuB,CACrB,sBACF,EACA,0CAA2C,CACzC,mEACF,EACA,gCAAiC,CAC/B,+CACF,EACA,6BAA8B,CAC5B,4BACF,EACA,mBAAoB,CAClB,gBACF,EACA,+DAAgE,CAC9D,8EACF,EACA,kGAAmG,CACjG,4GACF,EACA,MAAS,CACP,cACF,EACA,0DAA2D,CACzD,iFACF,EACA,MAAS,CACP,iBACF,EACA,sCAAuC,CACrC,iFACF,EACA,cAAe,CACb,cACF,EACA,qDAAsD,CACpD,EACF,EACA,YAAa,CACX,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,kBAAmB,CACjB,uBACF,EACA,kFAAmF,CACjF,wFACF,EACA,WAAY,CACV,qBACF,EACA,0CAA2C,CACzC,8DACF,EACA,0BAA2B,CACzB,gCACF,EACA,yDAA0D,CACxD,uDACF,EACA,0DAA2D,CACzD,4EACF,EACA,iBAAkB,CAChB,oBACF,EACA,kBAAmB,CACjB,sBACF,EACA,6BAA8B,CAC5B,kDACF,EACA,kFAAmF,CACjF,mGACF,EACA,kFAAmF,CACjF,2GACF,EACA,uFAAwF,CACtF,4GACF,EACA,8BAA+B,CAC7B,4CACF,EACA,iBAAoB,CAClB,eACF,EACA,QAAW,CACT,aACF,EACA,8BAA+B,CAC7B,2CACF,EACA,iBAAkB,CAChB,yBACF,EACA,uBAAwB,CACtB,mCACF,EACA,wRAA6R,CAC3R,wUACF,EACA,eAAgB,CACd,gBACF,EACA,mCAAoC,CAClC,qDACF,EACA,KAAQ,CACN,MACF,EACA,qCAAsC,CACpC,oDACF,EACA,eAAgB,CACd,uBACF,EACA,0CAA2C,CACzC,kDACF,EACA,8CAA+C,CAC7C,oDACF,EACA,QAAW,CACT,SACF,EACA,eAAgB,CACd,wBACF,EACA,gDAAiD,CAC/C,kDACF,EACA,mBAAoB,CAClB,6BACF,EACA,kGAAmG,CACjG,oHACF,EACA,kCAAmC,CACjC,mDACF,EACA,kBAAmB,CACjB,0BACF,EACA,mBAAoB,CAClB,yBACF,EACA,uEAAwE,CACtE,6FACF,EACA,iGAAkG,CAChG,uGACF,EACA,uEAAwE,CACtE,0FACF,EACA,oDAAqD,CACnD,EACF,EACA,2BAA4B,CAC1B,0BACF,EACA,kBAAmB,CACjB,0BACF,EACA,mBAAoB,CAClB,qBACF,EACA,sCAAuC,CACrC,+CACF,EACA,eAAgB,CACd,sBACF,EACA,gBAAiB,CACf,2BACF,EACA,2BAA4B,CAC1B,2BACF,EACA,OAAU,CACR,UACF,EACA,iBAAkB,CAChB,oBACF,EACA,QAAW,CACT,SACF,EACA,QAAW,CACT,SACF,EACA,kBAAmB,CACjB,yBACF,EACA,wCAAyC,CACvC,2DACF,EACA,mCAAoC,CAClC,oDACF,EACA,2BAA4B,CAC1B,qCACF,EACA,yCAA0C,CACxC,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,YAAa,CACX,EACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,EACF,EACA,YAAa,CACX,EACF,EACA,YAAa,CACX,EACF,EACA,mCAAoC,CAClC,EACF,EACA,mEAAoE,CAClE,EACF,EACA,mEAAoE,CAClE,EACF,EACA,MAAS,CACP,EACF,EACA,mDAAoD,CAClD,EACF,EACA,OAAU,CACR,EACF,EACA,wDAAyD,CACvD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,SAAY,CACV,EACF,EACA,eAAgB,CACd,EACF,EACA,eAAgB,CACd,EACF,EACA,iBAAkB,CAChB,oBACF,EACA,wCAA2C,CACzC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yDAA0D,CACxD,EACF,EACA,oCAAqC,CACnC,EACF,EACA,8BAA+B,CAC7B,8DACF,EACA,gCAAiC,CAC/B,EACF,EACA,qDAAsD,CACpD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,yCAA0C,CACxC,EACF,EACA,mBAAoB,CAClB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,sBAAuB,CACrB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,kCAAmC,CACjC,EACF,EACA,sBAAuB,CACrB,EACF,EACA,SAAY,CACV,EACF,EACA,sBAAuB,CACrB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yCAA0C,CACxC,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,wHAAyH,CACvH,EACF,EACA,qBAAsB,CACpB,EACF,EACA,iBAAkB,CAChB,oBACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,oCAAqC,CACnC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,kBAAmB,CACjB,uBACF,EACA,sCAAuC,CACrC,EACF,EACA,0BAA6B,CAC3B,EACF,EACA,aAAgB,CACd,EACF,EACA,qDAAsD,CACpD,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,iDAAkD,CAChD,EACF,EACA,iBAAkB,CAChB,EACF,EACA,QAAW,CACT,EACF,EACA,YAAe,CACb,WACF,EACA,0CAA2C,CACzC,yDACF,EACA,iHAAkH,CAChH,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,EACF,CACF,CACF,EACA,OAAU,WACV,aAAgB,4BAChB,KAAQ,KACR,aAAgB,EAClB,EAEAA,GAAQ,GAAQ,CACd,YAAe,CACb,SAAY,CACV,GAAI,CACF,OAAU,WACV,aAAgB,6BAChB,KAAQ,OACV,EACA,uDAAwD,CACtD,8DACF,EACA,uCAAwC,CACtC,mDACF,EACA,wCAAyC,CACvC,mDACF,EACA,8BAA+B,CAC7B,6CACF,EACA,8CAA+C,CAC7C,gEACF,EACA,2DAA4D,CAC1D,qEACF,EACA,SAAY,CACV,WACF,EACA,wBAAyB,CACvB,wBACF,EACA,qBAAsB,CACpB,yBACF,EACA,4CAA6C,CAC3C,qDACF,EACA,yFAA0F,CACxF,gHACF,EACA,+BAAgC,CAC9B,2CACF,EACA,qBAAsB,CACpB,sBACF,EACA,sCAAuC,CACrC,6CACF,EACA,qEAAsE,CACpE,0FACF,EACA,kEAAmE,CACjE,0FACF,EACA,KAAQ,CACN,WACF,EACA,0BAA2B,CACzB,gCACF,EACA,0BAA2B,CACzB,qBACF,EACA,+FAAgG,CAC9F,iGACF,EACA,KAAQ,CACN,QACF,EACA,OAAU,CACR,WACF,EACA,qBAAsB,CACpB,wBACF,EACA,wCAAyC,CACvC,oDACF,EACA,4DAA6D,CAC3D,4EACF,EACA,2DAA4D,CAC1D,yDACF,EACA,oEAAqE,CACnE,kEACF,EACA,4BAA6B,CAC3B,qCACF,EACA,mBAAoB,CAClB,wBACF,EACA,uCAAwC,CACtC,uDACF,EACA,wKAAyK,CACvK,yLACF,EACA,qEAAsE,CACpE,0EACF,EACA,yEAA0E,CACxE,oFACF,EACA,4EAA6E,CAC3E,oFACF,EACA,iCAAoC,CAClC,yCACF,EACA,oCAAuC,CACrC,oCACF,EACA,gBAAiB,CACf,oBACF,EACA,oBAAqB,CACnB,oBACF,EACA,kDAAmD,CACjD,oEACF,EACA,OAAU,CACR,UACF,EACA,SAAY,CACV,WACF,EACA,6BAA8B,CAC5B,6BACF,EACA,8DAA+D,CAC7D,iEACF,EACA,MAAS,CACP,QACF,EACA,sBAAuB,CACrB,iCACF,EACA,oIAAqI,CACnI,4JACF,EACA,2BAA4B,CAC1B,iCACF,EACA,4CAA6C,CAC3C,yCACF,EACA,0BAA2B,CACzB,kCACF,EACA,iCAAkC,CAChC,2CACF,EACA,gDAAiD,CAC/C,uDACF,EACA,yBAA0B,CACxB,sCACF,EACA,gCAAiC,CAC/B,gCACF,EACA,QAAW,CACT,aACF,EACA,4BAA6B,CAC3B,yBACF,EACA,wBAAyB,CACvB,2BACF,EACA,qDAAsD,CACpD,2CACF,EACA,qDAAsD,CACpD,sDACF,EACA,iBAAkB,CAChB,eACF,EACA,kBAAmB,CACjB,eACF,EACA,yCAA0C,CACxC,iDACF,EACA,oBAAqB,CACnB,sBACF,EACA,8EAA+E,CAC7E,gHACF,EACA,8CAA+C,CAC7C,2DACF,EACA,6CAA8C,CAC5C,uCACF,EACA,qCAAsC,CACpC,8CACF,EACA,oDAAqD,CACnD,sDACF,EACA,qFAAsF,CACpF,8GACF,EACA,sDAAuD,CACrD,6CACF,EACA,kBAAmB,CACjB,eACF,EACA,QAAW,CACT,QACF,EACA,kBAAmB,CACjB,uBACF,EACA,QAAW,CACT,OACF,EACA,IAAO,CACL,aACF,EACA,aAAc,CACZ,iBACF,EACA,aAAc,CACZ,cACF,EACA,mFAAoF,CAClF,6FACF,EACA,oBAAqB,CACnB,gCACF,EACA,oFAAqF,CACnF,wFACF,EACA,mBAAoB,CAClB,4BACF,EACA,SAAY,CACV,QACF,EACA,YAAa,CACX,aACF,EACA,eAAgB,CACd,cACF,EACA,OAAU,CACR,OACF,EACA,aAAc,CACZ,aACF,EACA,eAAgB,CACd,gBACF,EACA,aAAc,CACZ,yBACF,EACA,yBAA0B,CACxB,kBACF,EACA,YAAa,CACX,cACF,EACA,8BAA+B,CAC7B,8BACF,EACA,mBAAoB,CAClB,yBACF,EACA,gDAAiD,CAC/C,4DACF,EACA,0EAA2E,CACzE,0FACF,EACA,mDAAoD,CAClD,kEACF,EACA,0DAA2D,CACzD,8EACF,EACA,gDAAmD,CACjD,gDACF,EACA,oEAAqE,CACnE,mEACF,EACA,oDAAqD,CACnD,iDACF,EACA,2CAA8C,CAC5C,4CACF,EACA,sEAAuE,CACrE,kFACF,EACA,8CAA+C,CAC7C,iDACF,EACA,yBAA0B,CACxB,wCACF,EACA,6BAA8B,CAC5B,mDACF,EACA,eAAgB,CACd,sBACF,EACA,yFAA0F,CACxF,0EACF,EACA,UAAW,CACT,cACF,EACA,6EAA8E,CAC5E,6FACF,EACA,UAAa,CACX,cACF,EACA,gCAAiC,CAC/B,kCACF,EACA,SAAY,CACV,mBACF,EACA,kCAAmC,CACjC,oCACF,EACA,QAAW,CACT,QACF,EACA,qCAAsC,CACpC,kDACF,EACA,qBAAsB,CACpB,oBACF,EACA,aAAc,CACZ,YACF,EACA,oDAAqD,CACnD,wDACF,EACA,0FAA2F,CACzF,gHACF,EACA,mEAAoE,CAClE,yEACF,EACA,iDAAkD,CAChD,4DACF,EACA,KAAQ,CACN,OACF,EACA,KAAQ,CACN,QACF,EACA,2CAA8C,CAC5C,0CACF,EACA,wCAA2C,CACzC,iDACF,EACA,0BAA2B,CACzB,8BACF,EACA,mCAAsC,CACpC,kCACF,EACA,qEAAwE,CACtE,mEACF,EACA,sCAAyC,CACvC,0CACF,EACA,gFAAmF,CACjF,yFACF,EACA,sCAAyC,CACvC,wCACF,EACA,yCAA0C,CACxC,0CACF,EACA,gCAAiC,CAC/B,2BACF,EACA,gCAAiC,CAC/B,6CACF,EACA,+BAAgC,CAC9B,0CACF,EACA,kCAAmC,CACjC,+BACF,EACA,kBAAmB,CACjB,gCACF,EACA,4BAA6B,CAC3B,mDACF,EACA,0DAA2D,CACzD,qEACF,EACA,sBAAuB,CACrB,iBACF,EACA,mBAAoB,CAClB,4BACF,EACA,mBAAoB,CAClB,wBACF,EACA,+CAAgD,CAC9C,oDACF,EACA,6BAA8B,CAC5B,iCACF,EACA,uBAAwB,CACtB,wBACF,EACA,8CAA+C,CAC7C,kFACF,EACA,iDAAkD,CAChD,6CACF,EACA,qEAAsE,CACpE,kGACF,EACA,mDAAoD,CAClD,iEACF,EACA,kCAAmC,CACjC,0CACF,EACA,oCAAqC,CACnC,qCACF,EACA,0DAA2D,CACzD,uEACF,EACA,2CAA4C,CAC1C,oDACF,EACA,0DAA2D,CACzD,+DACF,EACA,yDAA0D,CACxD,+DACF,EACA,2CAA4C,CAC1C,8CACF,EACA,oEAAqE,CACnE,mFACF,EACA,gEAAiE,CAC/D,wEACF,EACA,gEAAiE,CAC/D,8EACF,EACA,uBAAwB,CACtB,oBACF,EACA,iBAAkB,CAChB,mBACF,EACA,kCAAmC,CACjC,uCACF,EACA,SAAY,CACV,eACF,EACA,yLAA0L,CACxL,2NACF,EACA,kBAAmB,CACjB,uBACF,EACA,gBAAiB,CACf,qBACF,EACA,YAAa,CACX,iBACF,EACA,SAAY,CACV,aACF,EACA,iCAAkC,CAChC,qCACF,EACA,OAAU,CACR,EACF,EACA,MAAS,CACP,mBACF,EACA,sCAAuC,CACrC,qDACF,EACA,iEAAkE,CAChE,2FACF,EACA,+BAAkC,CAChC,sCACF,EACA,iBAAkB,CAChB,sBACF,EACA,kBAAmB,CACjB,wBACF,EACA,SAAY,CACV,SACF,EACA,eAAkB,CAChB,mBACF,EACA,0BAA2B,CACzB,4BACF,EACA,OAAU,CACR,4BACF,EACA,SAAU,CACR,UACF,EACA,uBAAwB,CACtB,4BACF,EACA,uBAAwB,CACtB,8BACF,EACA,0DAA2D,CACzD,8DACF,EACA,KAAQ,CACN,OACF,EACA,YAAe,CACb,aACF,EACA,KAAQ,CACN,SACF,EACA,SAAY,CACV,UACF,EACA,gBAAiB,CACf,mBACF,EACA,GAAM,CACJ,OACF,EACA,KAAQ,CACN,OACF,EACA,aAAc,CACZ,mBACF,EACA,KAAQ,CACN,WACF,EACA,qBAAsB,CACpB,+BACF,EACA,QAAW,CACT,EACF,EACA,mBAAoB,CAClB,+BACF,EACA,oEAAqE,CACnE,qEACF,EACA,wFAAyF,CACvF,4GACF,EACA,+BAAgC,CAC9B,uCACF,EACA,+BAAgC,CAC9B,oCACF,EACA,sEAAuE,CACrE,mFACF,EACA,qEAAsE,CACpE,uEACF,EACA,cAAe,CACb,mBACF,EACA,6CAA8C,CAC5C,iDACF,EACA,oFAAgF,CAC9E,uFACF,EACA,uBAAwB,CACtB,6BACF,EACA,mCAAoC,CAClC,8CACF,EACA,wBAAyB,CACvB,oCACF,EACA,4CAA6C,CAC3C,wDACF,EACA,kCAAmC,CACjC,2CACF,EACA,mDAAoD,CAClD,6DACF,EACA,wCAAyC,CACvC,iDACF,EACA,6CAA8C,CAC5C,2DACF,EACA,qDAAsD,CACpD,6DACF,EACA,qCAAsC,CACpC,qCACF,EACA,SAAY,CACV,eACF,EACA,0BAA2B,CACzB,8BACF,EACA,mDAAoD,CAClD,yDACF,EACA,2FAAgG,CAC9F,+GACF,EACA,2EAA4E,CAC1E,gFACF,EACA,2BAA4B,CAC1B,wCACF,EACA,sBAAuB,CACrB,+BACF,EACA,6FAA8F,CAC5F,sHACF,EACA,wDAAyD,CACvD,yDACF,EACA,uBAAwB,CACtB,0BACF,EACA,4IAA6I,CAC3I,6IACF,EACA,yBAA0B,CACxB,qBACF,EACA,sDAAuD,CACrD,+DACF,EACA,8JAA+J,CAC7J,oKACF,EACA,eAAgB,CACd,mBACF,EACA,SAAY,CACV,SACF,EACA,oDAAqD,CACnD,oDACF,EACA,6CAA8C,CAC5C,oEACF,EACA,oBAAqB,CACnB,6BACF,EACA,0DAA2D,CACzD,kEACF,EACA,qBAAsB,CACpB,4BACF,EACA,uDAAwD,CACtD,wDACF,EACA,0BAA2B,CACzB,yBACF,EACA,8BAA+B,CAC7B,6BACF,EACA,SAAY,CACV,WACF,EACA,wBAAyB,CACvB,2BACF,EACA,2FAA4F,CAC1F,sGACF,EACA,0BAA2B,CACzB,kCACF,EACA,8DAA+D,CAC7D,qEACF,EACA,YAAa,CACX,gBACF,EACA,aAAc,CACZ,eACF,EACA,oBAAqB,CACnB,uBACF,EACA,sEAAuE,CACrE,+EACF,EACA,0BAA2B,CACzB,wBACF,EACA,qEAAsE,CACpE,sFACF,EACA,iBAAkB,CAChB,6BACF,EACA,sLAAuL,CACrL,qNACF,EACA,mFAAoF,CAClF,wFACF,EACA,kFAAmF,CACjF,2FACF,EACA,iCAAkC,CAChC,qCACF,EACA,YAAe,CACb,cACF,EACA,yBAA0B,CACxB,0CACF,EACA,QAAW,CACT,cACF,EACA,gBAAiB,CACf,oBACF,EACA,2DAA4D,CAC1D,qFACF,EACA,qEAAsE,CACpE,+FACF,EACA,mCAAoC,CAClC,mDACF,EACA,0BAA2B,CACzB,iCACF,EACA,+BAAgC,CAC9B,sCACF,EACA,2BAA4B,CAC1B,qCACF,EACA,KAAQ,CACN,QACF,EACA,YAAe,CACb,gBACF,EACA,OAAU,CACR,SACF,EACA,OAAQ,CACN,SACF,EACA,OAAQ,CACN,cACF,EACA,mBAAoB,CAClB,8BACF,EACA,QAAW,CACT,UACF,EACA,OAAU,CACR,UACF,EACA,YAAe,CACb,cACF,EACA,SAAY,CACV,SACF,EACA,WAAc,CACZ,eACF,EACA,kCAAmC,CACjC,yDACF,EACA,wBAAyB,CACvB,uBACF,EACA,yBAA0B,CACxB,kCACF,EACA,oBAAqB,CACnB,0BACF,EACA,yBAA0B,CACxB,wCACF,EACA,iBAAkB,CAChB,mBACF,EACA,gBAAiB,CACf,oBACF,EACA,aAAc,CACZ,mBACF,EACA,mGAAoG,CAClG,mFACF,EACA,iBAAkB,CAChB,eACF,EACA,4DAA6D,CAC3D,kEACF,EACA,uBAAwB,CACtB,uBACF,EACA,UAAa,CACX,YACF,EACA,mBAAoB,CAClB,sCACF,EACA,yBAA0B,CACxB,2BACF,EACA,oBAAqB,CACnB,qCACF,EACA,oBAAqB,CACnB,6BACF,EACA,+EAAgF,CAC9E,mFACF,EACA,OAAU,CACR,YACF,EACA,QAAW,CACT,aACF,EACA,cAAe,CACb,sBACF,EACA,iBAAkB,CAChB,iBACF,EACA,+DAAgE,CAC9D,wEACF,EACA,MAAS,CACP,MACF,EACA,sCAAuC,CACrC,qCACF,EACA,qBAAsB,CACpB,0BACF,EACA,0CAA2C,CACzC,sCACF,EACA,cAAe,CACb,6BACF,EACA,gBAAiB,CACf,kBACF,EACA,KAAQ,CACN,YACF,EACA,mFAAoF,CAClF,sFACF,EACA,GAAM,CACJ,cACF,EACA,gFAAiF,CAC/E,uFACF,EACA,QAAW,CACT,mBACF,EACA,sDAAuD,CACrD,4DACF,EACA,mDAAsD,CACpD,8DACF,EACA,SAAY,CACV,UACF,EACA,qDAAsD,CACpD,wDACF,EACA,+FAAgG,CAC9F,8FACF,EACA,wDAA2D,CACzD,0DACF,EACA,2DAA8D,CAC5D,iEACF,EACA,sDAAyD,CACvD,4DACF,EACA,qDAAsD,CACpD,wDACF,EACA,2DAA8D,CAC5D,iEACF,EACA,qDAAsD,CACpD,wDACF,EACA,+FAAgG,CAC9F,8FACF,EACA,sDAAyD,CACvD,4DACF,EACA,qDAAsD,CACpD,wDACF,EACA,mDAAoD,CAClD,gDACF,EACA,uIAAwI,CACtI,kKACF,EACA,+BAAgC,CAC9B,gCACF,EACA,aAAgB,CACd,eACF,EACA,UAAa,CACX,WACF,EACA,SAAY,CACV,eACF,EACA,eAAkB,CAChB,iBACF,EACA,+BAAgC,CAC9B,sCACF,EACA,YAAa,CACX,eACF,EACA,kBAAmB,CACjB,iBACF,EACA,8CAA+C,CAC7C,kDACF,EACA,wBAAyB,CACvB,gCACF,EACA,SAAY,CACV,SACF,EACA,KAAQ,CACN,QACF,EACA,MAAS,CACP,UACF,EACA,yCAA0C,CACxC,wDACF,EACA,+EAAgF,CAC9E,wEACF,EACA,oDAAqD,CACnD,yDACF,EACA,6BAA8B,CAC5B,gCACF,EACA,QAAW,CACT,SACF,EACA,0BAA2B,CACzB,yBACF,EACA,QAAW,CACT,QACF,EACA,WAAY,CACV,aACF,EACA,yCAA0C,CACxC,wDACF,EACA,MAAS,CACP,OACF,EACA,OAAU,CACR,WACF,EACA,OAAU,CACR,UACF,EACA,IAAO,CACL,SACF,EACA,uBAAwB,CACtB,oCACF,EACA,iCAAkC,CAChC,kCACF,EACA,+BAAgC,CAC9B,sCACF,EACA,iCAAkC,CAChC,wCACF,EACA,sDAAuD,CACrD,0DACF,EACA,4BAA6B,CAC3B,sCACF,EACA,OAAU,CACR,OACF,EACA,6BAA8B,CAC5B,kCACF,EACA,uBAAwB,CACtB,qCACF,EACA,kDAAmD,CACjD,oEACF,EACA,oBAAqB,CACnB,wBACF,EACA,8HAA+H,CAC7H,oIACF,EACA,wBAAyB,CACvB,yBACF,EACA,kFAAmF,CACjF,sGACF,EACA,0EAA2E,CACzE,2FACF,EACA,wGAAyG,CACvG,wHACF,EACA,oEAAqE,CACnE,uFACF,EACA,sBAAuB,CACrB,4BACF,EACA,iJAAkJ,CAChJ,kKACF,EACA,wBAAyB,CACvB,uBACF,EACA,kCAAmC,CACjC,yCACF,EACA,6HAA8H,CAC5H,gJACF,EACA,kBAAmB,CACjB,oBACF,EACA,QAAW,CACT,QACF,EACA,cAAe,CACb,iBACF,EACA,eAAgB,CACd,kBACF,EACA,2BAA4B,CAC1B,4BACF,EACA,uBAAwB,CACtB,8BACF,EACA,sBAAuB,CACrB,qBACF,EACA,0CAA2C,CACzC,4DACF,EACA,gCAAiC,CAC/B,oCACF,EACA,6BAA8B,CAC5B,iCACF,EACA,mBAAoB,CAClB,gBACF,EACA,+DAAgE,CAC9D,0EACF,EACA,kGAAmG,CACjG,oGACF,EACA,MAAS,CACP,uBACF,EACA,0DAA2D,CACzD,wEACF,EACA,MAAS,CACP,aACF,EACA,sCAAuC,CACrC,8CACF,EACA,cAAe,CACb,8BACF,EACA,qDAAsD,CACpD,+EACF,EACA,YAAa,CACX,YACF,EACA,2DAA4D,CAC1D,kFACF,EACA,kBAAmB,CACjB,kBACF,EACA,kFAAmF,CACjF,kFACF,EACA,WAAY,CACV,iBACF,EACA,0CAA2C,CACzC,qDACF,EACA,0BAA2B,CACzB,gCACF,EACA,yDAA0D,CACxD,8DACF,EACA,0DAA2D,CACzD,gEACF,EACA,iBAAkB,CAChB,mBACF,EACA,kBAAmB,CACjB,oBACF,EACA,6BAA8B,CAC5B,wCACF,EACA,kFAAmF,CACjF,2FACF,EACA,kFAAmF,CACjF,iGACF,EACA,uFAAwF,CACtF,qGACF,EACA,8BAA+B,CAC7B,yCACF,EACA,iBAAoB,CAClB,eACF,EACA,QAAW,CACT,WACF,EACA,8BAA+B,CAC7B,8BACF,EACA,iBAAkB,CAChB,eACF,EACA,uBAAwB,CACtB,6BACF,EACA,wRAA6R,CAC3R,iSACF,EACA,eAAgB,CACd,gBACF,EACA,mCAAoC,CAClC,kDACF,EACA,KAAQ,CACN,MACF,EACA,qCAAsC,CACpC,6CACF,EACA,eAAgB,CACd,qBACF,EACA,0CAA2C,CACzC,+CACF,EACA,8CAA+C,CAC7C,uDACF,EACA,QAAW,CACT,cACF,EACA,eAAgB,CACd,oBACF,EACA,gDAAiD,CAC/C,kDACF,EACA,mBAAoB,CAClB,oCACF,EACA,kGAAmG,CACjG,oHACF,EACA,kCAAmC,CACjC,uCACF,EACA,kBAAmB,CACjB,0BACF,EACA,mBAAoB,CAClB,wBACF,EACA,uEAAwE,CACtE,2FACF,EACA,iGAAkG,CAChG,gHACF,EACA,uEAAwE,CACtE,uEACF,EACA,oDAAqD,CACnD,qDACF,EACA,2BAA4B,CAC1B,wCACF,EACA,kBAAmB,CACjB,0BACF,EACA,mBAAoB,CAClB,sBACF,EACA,sCAAuC,CACrC,wCACF,EACA,eAAgB,CACd,qBACF,EACA,gBAAiB,CACf,oBACF,EACA,2BAA4B,CAC1B,kCACF,EACA,OAAU,CACR,SACF,EACA,iBAAkB,CAChB,cACF,EACA,QAAW,CACT,UACF,EACA,QAAW,CACT,aACF,EACA,kBAAmB,CACjB,uBACF,EACA,wCAAyC,CACvC,kDACF,EACA,mCAAoC,CAClC,8CACF,EACA,2BAA4B,CAC1B,kCACF,EACA,yCAA0C,CACxC,oDACF,EACA,4BAA6B,CAC3B,qCACF,EACA,YAAa,CACX,gBACF,EACA,eAAgB,CACd,iBACF,EACA,aAAc,CACZ,eACF,EACA,YAAa,CACX,kBACF,EACA,YAAa,CACX,kBACF,EACA,mCAAoC,CAClC,yCACF,EACA,mEAAoE,CAClE,kEACF,EACA,mEAAoE,CAClE,kEACF,EACA,MAAS,CACP,qBACF,EACA,mDAAoD,CAClD,mDACF,EACA,OAAU,CACR,mBACF,EACA,wDAAyD,CACvD,oDACF,EACA,wBAAyB,CACvB,kCACF,EACA,SAAY,CACV,UACF,EACA,eAAgB,CACd,iBACF,EACA,eAAgB,CACd,eACF,EACA,iBAAkB,CAChB,cACF,EACA,wCAA2C,CACzC,4CACF,EACA,gDAAiD,CAC/C,yFACF,EACA,yDAA0D,CACxD,+DACF,EACA,oCAAqC,CACnC,qDACF,EACA,8BAA+B,CAC7B,mCACF,EACA,gCAAiC,CAC/B,yDACF,EACA,qDAAsD,CACpD,4EACF,EACA,wBAAyB,CACvB,4BACF,EACA,yCAA0C,CACxC,wDACF,EACA,mBAAoB,CAClB,uBACF,EACA,sBAAuB,CACrB,2BACF,EACA,gCAAiC,CAC/B,uDACF,EACA,sBAAuB,CACrB,qCACF,EACA,sBAAuB,CACrB,6BACF,EACA,qBAAsB,CACpB,2BACF,EACA,uBAAwB,CACtB,4BACF,EACA,sBAAuB,CACrB,0BACF,EACA,uBAAwB,CACtB,6BACF,EACA,kCAAmC,CACjC,2CACF,EACA,sBAAuB,CACrB,4BACF,EACA,SAAY,CACV,WACF,EACA,sBAAuB,CACrB,qBACF,EACA,qBAAsB,CACpB,qBACF,EACA,gDAAiD,CAC/C,gEACF,EACA,yCAA0C,CACxC,gCACF,EACA,2BAA4B,CAC1B,gCACF,EACA,wHAAyH,CACvH,qHACF,EACA,qBAAsB,CACpB,uBACF,EACA,iBAAkB,CAChB,iBACF,EACA,kBAAmB,CACjB,kBACF,EACA,8CAA+C,CAC7C,2DACF,EACA,8BAA+B,CAC7B,yCACF,EACA,oCAAqC,CACnC,sDACF,EACA,4DAA6D,CAC3D,6DACF,EACA,kBAAmB,CACjB,kBACF,EACA,sCAAuC,CACrC,iCACF,EACA,0BAA6B,CAC3B,6BACF,EACA,aAAgB,CACd,iBACF,EACA,qDAAsD,CACpD,0DACF,EACA,gCAAiC,CAC/B,uCACF,EACA,iDAAkD,CAChD,4DACF,EACA,iBAAkB,CAChB,oBACF,EACA,QAAW,CACT,UACF,EACA,YAAe,CACb,aACF,EACA,0CAA2C,CACzC,kDACF,EACA,iHAAkH,CAChH,iIACF,EACA,kBAAmB,CACjB,qBACF,EACA,mBAAoB,CAClB,gBACF,CACF,CACF,EACA,OAAU,WACV,aAAgB,6BAChB,KAAQ,QACR,aAAgB,EAClB,EAEAA,GAAQ,GAAQ,CACd,YAAe,CACb,SAAY,CACV,GAAI,CACF,OAAU,WACV,aAAgB,6BAChB,KAAQ,IACV,EACA,uDAAwD,CACtD,wDACF,EACA,uCAAwC,CACtC,wDACF,EACA,wCAAyC,CACvC,4DACF,EACA,8BAA+B,CAC7B,6CACF,EACA,8CAA+C,CAC7C,8DACF,EACA,2DAA4D,CAC1D,yEACF,EACA,SAAY,CACV,cACF,EACA,wBAAyB,CACvB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,yFAA0F,CACxF,EACF,EACA,+BAAgC,CAC9B,4BACF,EACA,qBAAsB,CACpB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qEAAsE,CACpE,EACF,EACA,kEAAmE,CACjE,EACF,EACA,KAAQ,CACN,EACF,EACA,0BAA2B,CACzB,uBACF,EACA,0BAA2B,CACzB,6BACF,EACA,+FAAgG,CAC9F,4NACF,EACA,KAAQ,CACN,WACF,EACA,OAAU,CACR,WACF,EACA,qBAAsB,CACpB,EACF,EACA,wCAAyC,CACvC,gEACF,EACA,4DAA6D,CAC3D,wEACF,EACA,2DAA4D,CAC1D,mFACF,EACA,oEAAqE,CACnE,wGACF,EACA,4BAA6B,CAC3B,6CACF,EACA,mBAAoB,CAClB,EACF,EACA,uCAAwC,CACtC,gCACF,EACA,wKAAyK,CACvK,8NACF,EACA,qEAAsE,CACpE,8EACF,EACA,yEAA0E,CACxE,EACF,EACA,4EAA6E,CAC3E,EACF,EACA,iCAAoC,CAClC,EACF,EACA,oCAAuC,CACrC,EACF,EACA,gBAAiB,CACf,wDACF,EACA,oBAAqB,CACnB,8BACF,EACA,kDAAmD,CACjD,0FACF,EACA,OAAU,CACR,WACF,EACA,SAAY,CACV,cACF,EACA,6BAA8B,CAC5B,yDACF,EACA,8DAA+D,CAC7D,yEACF,EACA,MAAS,CACP,cACF,EACA,sBAAuB,CACrB,0CACF,EACA,oIAAqI,CACnI,gMACF,EACA,2BAA4B,CAC1B,sCACF,EACA,4CAA6C,CAC3C,sEACF,EACA,0BAA2B,CACzB,2BACF,EACA,iCAAkC,CAChC,+BACF,EACA,gDAAiD,CAC/C,EACF,EACA,yBAA0B,CACxB,sCACF,EACA,gCAAiC,CAC/B,wEACF,EACA,QAAW,CACT,aACF,EACA,4BAA6B,CAC3B,iDACF,EACA,wBAAyB,CACvB,+BACF,EACA,qDAAsD,CACpD,6EACF,EACA,qDAAsD,CACpD,qDACF,EACA,iBAAkB,CAChB,eACF,EACA,kBAAmB,CACjB,+BACF,EACA,yCAA0C,CACxC,sGACF,EACA,oBAAqB,CACnB,sBACF,EACA,8EAA+E,CAC7E,wHACF,EACA,8CAA+C,CAC7C,iDACF,EACA,6CAA8C,CAC5C,0DACF,EACA,qCAAsC,CACpC,0CACF,EACA,oDAAqD,CACnD,sDACF,EACA,qFAAsF,CACpF,6IACF,EACA,sDAAuD,CACrD,sEACF,EACA,kBAAmB,CACjB,eACF,EACA,QAAW,CACT,sBACF,EACA,kBAAmB,CACjB,iBACF,EACA,QAAW,CACT,QACF,EACA,IAAO,CACL,WACF,EACA,aAAc,CACZ,eACF,EACA,aAAc,CACZ,8FACF,EACA,mFAAoF,CAClF,8IACF,EACA,oBAAqB,CACnB,yDACF,EACA,oFAAqF,CACnF,+FACF,EACA,mBAAoB,CAClB,oCACF,EACA,SAAY,CACV,YACF,EACA,YAAa,CACX,oBACF,EACA,eAAgB,CACd,eACF,EACA,OAAU,CACR,QACF,EACA,aAAc,CACZ,qBACF,EACA,eAAgB,CACd,wBACF,EACA,aAAc,CACZ,2BACF,EACA,yBAA0B,CACxB,4BACF,EACA,YAAa,CACX,iBACF,EACA,8BAA+B,CAC7B,sBACF,EACA,mBAAoB,CAClB,yCACF,EACA,gDAAiD,CAC/C,2DACF,EACA,0EAA2E,CACzE,iFACF,EACA,mDAAoD,CAClD,8EACF,EACA,0DAA2D,CACzD,sFACF,EACA,gDAAmD,CACjD,oDACF,EACA,oEAAqE,CACnE,8DACF,EACA,oDAAqD,CACnD,mDACF,EACA,2CAA8C,CAC5C,iDACF,EACA,sEAAuE,CACrE,yFACF,EACA,8CAA+C,CAC7C,2EACF,EACA,yBAA0B,CACxB,mCACF,EACA,6BAA8B,CAC5B,oCACF,EACA,eAAgB,CACd,0BACF,EACA,yFAA0F,CACxF,6GACF,EACA,UAAW,CACT,SACF,EACA,6EAA8E,CAC5E,sJACF,EACA,UAAa,CACX,mBACF,EACA,gCAAiC,CAC/B,2BACF,EACA,SAAY,CACV,kBACF,EACA,kCAAmC,CACjC,6BACF,EACA,QAAW,CACT,iBACF,EACA,qCAAsC,CACpC,gEACF,EACA,qBAAsB,CACpB,4BACF,EACA,aAAc,CACZ,YACF,EACA,oDAAqD,CACnD,0DACF,EACA,0FAA2F,CACzF,sGACF,EACA,mEAAoE,CAClE,mFACF,EACA,iDAAkD,CAChD,gEACF,EACA,KAAQ,CACN,QACF,EACA,KAAQ,CACN,eACF,EACA,2CAA8C,CAC5C,gDACF,EACA,wCAA2C,CACzC,sEACF,EACA,0BAA2B,CACzB,wCACF,EACA,mCAAsC,CACpC,sCACF,EACA,qEAAwE,CACtE,gEACF,EACA,sCAAyC,CACvC,gCACF,EACA,gFAAmF,CACjF,gFACF,EACA,sCAAyC,CACvC,+CACF,EACA,yCAA0C,CACxC,0DACF,EACA,gCAAiC,CAC/B,oCACF,EACA,gCAAiC,CAC/B,yEACF,EACA,+BAAgC,CAC9B,mCACF,EACA,kCAAmC,CACjC,kCACF,EACA,kBAAmB,CACjB,EACF,EACA,4BAA6B,CAC3B,uCACF,EACA,0DAA2D,CACzD,2DACF,EACA,sBAAuB,CACrB,sBACF,EACA,mBAAoB,CAClB,sBACF,EACA,mBAAoB,CAClB,oBACF,EACA,+CAAgD,CAC9C,kDACF,EACA,6BAA8B,CAC5B,4CACF,EACA,uBAAwB,CACtB,eACF,EACA,8CAA+C,CAC7C,8EACF,EACA,iDAAkD,CAChD,uDACF,EACA,qEAAsE,CACpE,0GACF,EACA,mDAAoD,CAClD,4EACF,EACA,kCAAmC,CACjC,gDACF,EACA,oCAAqC,CACnC,sCACF,EACA,0DAA2D,CACzD,8FACF,EACA,2CAA4C,CAC1C,wEACF,EACA,0DAA2D,CACzD,kEACF,EACA,yDAA0D,CACxD,8EACF,EACA,2CAA4C,CAC1C,iDACF,EACA,oEAAqE,CACnE,gFACF,EACA,gEAAiE,CAC/D,kDACF,EACA,gEAAiE,CAC/D,kDACF,EACA,uBAAwB,CACtB,oBACF,EACA,iBAAkB,CAChB,yBACF,EACA,kCAAmC,CACjC,EACF,EACA,SAAY,CACV,UACF,EACA,yLAA0L,CACxL,4NACF,EACA,kBAAmB,CACjB,sBACF,EACA,gBAAiB,CACf,gBACF,EACA,YAAa,CACX,uBACF,EACA,SAAY,CACV,cACF,EACA,iCAAkC,CAChC,kDACF,EACA,OAAU,CACR,UACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,iEAAkE,CAChE,EACF,EACA,+BAAkC,CAChC,oCACF,EACA,iBAAkB,CAChB,YACF,EACA,kBAAmB,CACjB,gCACF,EACA,SAAY,CACV,YACF,EACA,eAAkB,CAChB,mBACF,EACA,0BAA2B,CACzB,qBACF,EACA,OAAU,CACR,EACF,EACA,SAAU,CACR,UACF,EACA,uBAAwB,CACtB,0BACF,EACA,uBAAwB,CACtB,yCACF,EACA,0DAA2D,CACzD,0EACF,EACA,KAAQ,CACN,OACF,EACA,YAAe,CACb,YACF,EACA,KAAQ,CACN,UACF,EACA,SAAY,CACV,WACF,EACA,gBAAiB,CACf,oBACF,EACA,GAAM,CACJ,IACF,EACA,KAAQ,CACN,KACF,EACA,aAAc,CACZ,aACF,EACA,KAAQ,CACN,kBACF,EACA,qBAAsB,CACpB,6BACF,EACA,QAAW,CACT,EACF,EACA,mBAAoB,CAClB,6BACF,EACA,oEAAqE,CACnE,oFACF,EACA,wFAAyF,CACvF,+GACF,EACA,+BAAgC,CAC9B,kCACF,EACA,+BAAgC,CAC9B,2CACF,EACA,sEAAuE,CACrE,uEACF,EACA,qEAAsE,CACpE,sEACF,EACA,cAAe,CACb,EACF,EACA,6CAA8C,CAC5C,8BACF,EACA,oFAAgF,CAC9E,2GACF,EACA,uBAAwB,CACtB,6BACF,EACA,mCAAoC,CAClC,qCACF,EACA,wBAAyB,CACvB,gCACF,EACA,4CAA6C,CAC3C,qCACF,EACA,kCAAmC,CACjC,0BACF,EACA,mDAAoD,CAClD,+DACF,EACA,wCAAyC,CACvC,8BACF,EACA,6CAA8C,CAC5C,mCACF,EACA,qDAAsD,CACpD,+DACF,EACA,qCAAsC,CACpC,6CACF,EACA,SAAY,CACV,gBACF,EACA,0BAA2B,CACzB,gCACF,EACA,mDAAoD,CAClD,6DACF,EACA,2FAAgG,CAC9F,EACF,EACA,2EAA4E,CAC1E,2GACF,EACA,2BAA4B,CAC1B,mCACF,EACA,sBAAuB,CACrB,6BACF,EACA,6FAA8F,CAC5F,qIACF,EACA,wDAAyD,CACvD,oEACF,EACA,uBAAwB,CACtB,uBACF,EACA,4IAA6I,CAC3I,2IACF,EACA,yBAA0B,CACxB,mCACF,EACA,sDAAuD,CACrD,uEACF,EACA,8JAA+J,CAC7J,sNACF,EACA,eAAgB,CACd,kBACF,EACA,SAAY,CACV,SACF,EACA,oDAAqD,CACnD,6EACF,EACA,6CAA8C,CAC5C,uDACF,EACA,oBAAqB,CACnB,6BACF,EACA,0DAA2D,CACzD,oEACF,EACA,qBAAsB,CACpB,kBACF,EACA,uDAAwD,CACtD,mEACF,EACA,0BAA2B,CACzB,uCACF,EACA,8BAA+B,CAC7B,mCACF,EACA,SAAY,CACV,QACF,EACA,wBAAyB,CACvB,iCACF,EACA,2FAA4F,CAC1F,+JACF,EACA,0BAA2B,CACzB,wCACF,EACA,8DAA+D,CAC7D,gEACF,EACA,YAAa,CACX,aACF,EACA,aAAc,CACZ,aACF,EACA,oBAAqB,CACnB,6CACF,EACA,sEAAuE,CACrE,uGACF,EACA,0BAA2B,CACzB,0BACF,EACA,qEAAsE,CACpE,4EACF,EACA,iBAAkB,CAChB,4BACF,EACA,sLAAuL,CACrL,0MACF,EACA,mFAAoF,CAClF,qIACF,EACA,kFAAmF,CACjF,EACF,EACA,iCAAkC,CAChC,kEACF,EACA,YAAe,CACb,gBACF,EACA,yBAA0B,CACxB,kCACF,EACA,QAAW,CACT,YACF,EACA,gBAAiB,CACf,2BACF,EACA,2DAA4D,CAC1D,8EACF,EACA,qEAAsE,CACpE,EACF,EACA,mCAAoC,CAClC,+BACF,EACA,0BAA2B,CACzB,iBACF,EACA,+BAAgC,CAC9B,iBACF,EACA,2BAA4B,CAC1B,iBACF,EACA,KAAQ,CACN,MACF,EACA,YAAe,CACb,cACF,EACA,OAAU,CACR,sBACF,EACA,OAAQ,CACN,EACF,EACA,OAAQ,CACN,EACF,EACA,mBAAoB,CAClB,uCACF,EACA,QAAW,CACT,gBACF,EACA,OAAU,CACR,YACF,EACA,YAAe,CACb,cACF,EACA,SAAY,CACV,wBACF,EACA,WAAc,CACZ,+BACF,EACA,kCAAmC,CACjC,wDACF,EACA,wBAAyB,CACvB,eACF,EACA,yBAA0B,CACxB,iBACF,EACA,oBAAqB,CACnB,2BACF,EACA,yBAA0B,CACxB,+BACF,EACA,iBAAkB,CAChB,yBACF,EACA,gBAAiB,CACf,mCACF,EACA,aAAc,CACZ,+BACF,EACA,mGAAoG,CAClG,mJACF,EACA,iBAAkB,CAChB,oCACF,EACA,4DAA6D,CAC3D,yFACF,EACA,uBAAwB,CACtB,sBACF,EACA,UAAa,CACX,aACF,EACA,mBAAoB,CAClB,uCACF,EACA,yBAA0B,CACxB,wBACF,EACA,oBAAqB,CACnB,uCACF,EACA,oBAAqB,CACnB,2BACF,EACA,+EAAgF,CAC9E,gHACF,EACA,OAAU,CACR,eACF,EACA,QAAW,CACT,aACF,EACA,cAAe,CACb,EACF,EACA,iBAAkB,CAChB,kBACF,EACA,+DAAgE,CAC9D,0DACF,EACA,MAAS,CACP,eACF,EACA,sCAAuC,CACrC,oDACF,EACA,qBAAsB,CACpB,sCACF,EACA,0CAA2C,CACzC,oCACF,EACA,cAAe,CACb,kBACF,EACA,gBAAiB,CACf,iBACF,EACA,KAAQ,CACN,MACF,EACA,mFAAoF,CAClF,mGACF,EACA,GAAM,CACJ,WACF,EACA,gFAAiF,CAC/E,sGACF,EACA,QAAW,CACT,gBACF,EACA,sDAAuD,CACrD,8DACF,EACA,mDAAsD,CACpD,EACF,EACA,SAAY,CACV,WACF,EACA,qDAAsD,CACpD,qDACF,EACA,+FAAgG,CAC9F,qIACF,EACA,wDAA2D,CACzD,iEACF,EACA,2DAA8D,CAC5D,yEACF,EACA,sDAAyD,CACvD,sEACF,EACA,qDAAsD,CACpD,qDACF,EACA,2DAA8D,CAC5D,yEACF,EACA,qDAAsD,CACpD,qDACF,EACA,+FAAgG,CAC9F,iIACF,EACA,sDAAyD,CACvD,sEACF,EACA,qDAAsD,CACpD,qDACF,EACA,mDAAoD,CAClD,gDACF,EACA,uIAAwI,CACtI,gMACF,EACA,+BAAgC,CAC9B,iBACF,EACA,aAAgB,CACd,wBACF,EACA,UAAa,CACX,UACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,EACF,EACA,+BAAgC,CAC9B,iBACF,EACA,YAAa,CACX,EACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,2CACF,EACA,wBAAyB,CACvB,iBACF,EACA,SAAY,CACV,QACF,EACA,KAAQ,CACN,EACF,EACA,MAAS,CACP,YACF,EACA,yCAA0C,CACxC,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,oDAAqD,CACnD,gDACF,EACA,6BAA8B,CAC5B,2EACF,EACA,QAAW,CACT,EACF,EACA,0BAA2B,CACzB,EACF,EACA,QAAW,CACT,OACF,EACA,WAAY,CACV,EACF,EACA,yCAA0C,CACxC,EACF,EACA,MAAS,CACP,EACF,EACA,OAAU,CACR,UACF,EACA,OAAU,CACR,WACF,EACA,IAAO,CACL,eACF,EACA,uBAAwB,CACtB,iBACF,EACA,iCAAkC,CAChC,EACF,EACA,+BAAgC,CAC9B,iBACF,EACA,iCAAkC,CAChC,iBACF,EACA,sDAAuD,CACrD,qEACF,EACA,4BAA6B,CAC3B,iBACF,EACA,OAAU,CACR,SACF,EACA,6BAA8B,CAC5B,+CACF,EACA,uBAAwB,CACtB,wCACF,EACA,kDAAmD,CACjD,uDACF,EACA,oBAAqB,CACnB,qBACF,EACA,8HAA+H,CAC7H,yJACF,EACA,wBAAyB,CACvB,4BACF,EACA,kFAAmF,CACjF,8GACF,EACA,0EAA2E,CACzE,sFACF,EACA,wGAAyG,CACvG,wHACF,EACA,oEAAqE,CACnE,wEACF,EACA,sBAAuB,CACrB,wBACF,EACA,iJAAkJ,CAChJ,kKACF,EACA,wBAAyB,CACvB,sBACF,EACA,kCAAmC,CACjC,iDACF,EACA,6HAA8H,CAC5H,gMACF,EACA,kBAAmB,CACjB,qBACF,EACA,QAAW,CACT,SACF,EACA,cAAe,CACb,4BACF,EACA,eAAgB,CACd,6BACF,EACA,2BAA4B,CAC1B,0BACF,EACA,uBAAwB,CACtB,oBACF,EACA,sBAAuB,CACrB,kCACF,EACA,0CAA2C,CACzC,4CACF,EACA,gCAAiC,CAC/B,gCACF,EACA,6BAA8B,CAC5B,wBACF,EACA,mBAAoB,CAClB,gBACF,EACA,+DAAgE,CAC9D,wEACF,EACA,kGAAmG,CACjG,uGACF,EACA,MAAS,CACP,QACF,EACA,0DAA2D,CACzD,2EACF,EACA,MAAS,CACP,SACF,EACA,sCAAuC,CACrC,2EACF,EACA,cAAe,CACb,qBACF,EACA,qDAAsD,CACpD,EACF,EACA,YAAa,CACX,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,kBAAmB,CACjB,kBACF,EACA,kFAAmF,CACjF,iFACF,EACA,WAAY,CACV,wBACF,EACA,0CAA2C,CACzC,+DACF,EACA,0BAA2B,CACzB,uCACF,EACA,yDAA0D,CACxD,yEACF,EACA,0DAA2D,CACzD,4DACF,EACA,iBAAkB,CAChB,eACF,EACA,kBAAmB,CACjB,8BACF,EACA,6BAA8B,CAC5B,mDACF,EACA,kFAAmF,CACjF,oIACF,EACA,kFAAmF,CACjF,gHACF,EACA,uFAAwF,CACtF,0HACF,EACA,8BAA+B,CAC7B,sCACF,EACA,iBAAoB,CAClB,cACF,EACA,QAAW,CACT,UACF,EACA,8BAA+B,CAC7B,yCACF,EACA,iBAAkB,CAChB,mBACF,EACA,uBAAwB,CACtB,wBACF,EACA,wRAA6R,CAC3R,gVACF,EACA,eAAgB,CACd,WACF,EACA,mCAAoC,CAClC,iDACF,EACA,KAAQ,CACN,MACF,EACA,qCAAsC,CACpC,wCACF,EACA,eAAgB,CACd,kBACF,EACA,0CAA2C,CACzC,mDACF,EACA,8CAA+C,CAC7C,iDACF,EACA,QAAW,CACT,SACF,EACA,eAAgB,CACd,wBACF,EACA,gDAAiD,CAC/C,2CACF,EACA,mBAAoB,CAClB,+BACF,EACA,kGAAmG,CACjG,8GACF,EACA,kCAAmC,CACjC,qDACF,EACA,kBAAmB,CACjB,mBACF,EACA,mBAAoB,CAClB,sBACF,EACA,uEAAwE,CACtE,gHACF,EACA,iGAAkG,CAChG,sIACF,EACA,uEAAwE,CACtE,2GACF,EACA,oDAAqD,CACnD,EACF,EACA,2BAA4B,CAC1B,mBACF,EACA,kBAAmB,CACjB,mBACF,EACA,mBAAoB,CAClB,mCACF,EACA,sCAAuC,CACrC,8CACF,EACA,eAAgB,CACd,gBACF,EACA,gBAAiB,CACf,gCACF,EACA,2BAA4B,CAC1B,gDACF,EACA,OAAU,CACR,WACF,EACA,iBAAkB,CAChB,eACF,EACA,QAAW,CACT,UACF,EACA,QAAW,CACT,WACF,EACA,kBAAmB,CACjB,oBACF,EACA,wCAAyC,CACvC,wDACF,EACA,mCAAoC,CAClC,kCACF,EACA,2BAA4B,CAC1B,oCACF,EACA,yCAA0C,CACxC,yDACF,EACA,4BAA6B,CAC3B,eACF,EACA,YAAa,CACX,mBACF,EACA,eAAgB,CACd,WACF,EACA,aAAc,CACZ,mBACF,EACA,YAAa,CACX,cACF,EACA,YAAa,CACX,kBACF,EACA,mCAAoC,CAClC,iCACF,EACA,mEAAoE,CAClE,uEACF,EACA,mEAAoE,CAClE,uEACF,EACA,MAAS,CACP,qBACF,EACA,mDAAoD,CAClD,sGACF,EACA,OAAU,CACR,sBACF,EACA,wDAAyD,CACvD,yGACF,EACA,wBAAyB,CACvB,uCACF,EACA,SAAY,CACV,WACF,EACA,eAAgB,CACd,eACF,EACA,eAAgB,CACd,aACF,EACA,iBAAkB,CAChB,eACF,EACA,wCAA2C,CACzC,mDACF,EACA,gDAAiD,CAC/C,yFACF,EACA,yDAA0D,CACxD,mEACF,EACA,oCAAqC,CACnC,wCACF,EACA,8BAA+B,CAC7B,qCACF,EACA,gCAAiC,CAC/B,sDACF,EACA,qDAAsD,CACpD,8FACF,EACA,wBAAyB,CACvB,4CACF,EACA,yCAA0C,CACxC,kDACF,EACA,mBAAoB,CAClB,aACF,EACA,sBAAuB,CACrB,uCACF,EACA,gCAAiC,CAC/B,wDACF,EACA,sBAAuB,CACrB,6BACF,EACA,sBAAuB,CACrB,4BACF,EACA,qBAAsB,CACpB,0BACF,EACA,uBAAwB,CACtB,2BACF,EACA,sBAAuB,CACrB,2BACF,EACA,uBAAwB,CACtB,gCACF,EACA,kCAAmC,CACjC,8CACF,EACA,sBAAuB,CACrB,8BACF,EACA,SAAY,CACV,eACF,EACA,sBAAuB,CACrB,4BACF,EACA,qBAAsB,CACpB,wBACF,EACA,gDAAiD,CAC/C,yDACF,EACA,yCAA0C,CACxC,EACF,EACA,2BAA4B,CAC1B,kDACF,EACA,wHAAyH,CACvH,2MACF,EACA,qBAAsB,CACpB,kCACF,EACA,iBAAkB,CAChB,eACF,EACA,kBAAmB,CACjB,6BACF,EACA,8CAA+C,CAC7C,uEACF,EACA,8BAA+B,CAC7B,sCACF,EACA,oCAAqC,CACnC,qEACF,EACA,4DAA6D,CAC3D,iFACF,EACA,kBAAmB,CACjB,4BACF,EACA,sCAAuC,CACrC,gDACF,EACA,0BAA6B,CAC3B,mCACF,EACA,aAAgB,CACd,mBACF,EACA,qDAAsD,CACpD,kDACF,EACA,gCAAiC,CAC/B,0CACF,EACA,iDAAkD,CAChD,0FACF,EACA,iBAAkB,CAChB,oBACF,EACA,QAAW,CACT,UACF,EACA,YAAe,CACb,gBACF,EACA,0CAA2C,CACzC,uEACF,EACA,iHAAkH,CAChH,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,sBACF,CACF,CACF,EACA,OAAU,WACV,aAAgB,6BAChB,KAAQ,KACR,aAAgB,EAClB,EAEAA,GAAQ,GAAQ,CACd,YAAe,CACb,SAAY,CACV,GAAI,CACF,OAAU,WACV,aAAgB,6BAChB,KAAQ,IACV,EACA,uDAAwD,CACtD,EACF,EACA,uCAAwC,CACtC,EACF,EACA,wCAAyC,CACvC,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,SAAY,CACV,EACF,EACA,wBAAyB,CACvB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,yFAA0F,CACxF,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,qBAAsB,CACpB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qEAAsE,CACpE,EACF,EACA,kEAAmE,CACjE,EACF,EACA,KAAQ,CACN,EACF,EACA,0BAA2B,CACzB,EACF,EACA,0BAA2B,CACzB,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,KAAQ,CACN,EACF,EACA,OAAU,CACR,EACF,EACA,qBAAsB,CACpB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,oEAAqE,CACnE,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,mBAAoB,CAClB,EACF,EACA,uCAAwC,CACtC,EACF,EACA,wKAAyK,CACvK,EACF,EACA,qEAAsE,CACpE,EACF,EACA,yEAA0E,CACxE,EACF,EACA,4EAA6E,CAC3E,EACF,EACA,iCAAoC,CAClC,EACF,EACA,oCAAuC,CACrC,EACF,EACA,gBAAiB,CACf,EACF,EACA,oBAAqB,CACnB,EACF,EACA,kDAAmD,CACjD,EACF,EACA,OAAU,CACR,EACF,EACA,SAAY,CACV,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,8DAA+D,CAC7D,EACF,EACA,MAAS,CACP,EACF,EACA,sBAAuB,CACrB,EACF,EACA,oIAAqI,CACnI,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,0BAA2B,CACzB,EACF,EACA,iCAAkC,CAChC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yBAA0B,CACxB,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,QAAW,CACT,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,wBAAyB,CACvB,EACF,EACA,qDAAsD,CACpD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kBAAmB,CACjB,EACF,EACA,yCAA0C,CACxC,EACF,EACA,oBAAqB,CACnB,EACF,EACA,8EAA+E,CAC7E,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,qCAAsC,CACpC,EACF,EACA,oDAAqD,CACnD,EACF,EACA,qFAAsF,CACpF,EACF,EACA,sDAAuD,CACrD,EACF,EACA,kBAAmB,CACjB,EACF,EACA,QAAW,CACT,EACF,EACA,kBAAmB,CACjB,EACF,EACA,QAAW,CACT,EACF,EACA,IAAO,CACL,EACF,EACA,aAAc,CACZ,EACF,EACA,aAAc,CACZ,EACF,EACA,mFAAoF,CAClF,EACF,EACA,oBAAqB,CACnB,EACF,EACA,oFAAqF,CACnF,EACF,EACA,mBAAoB,CAClB,EACF,EACA,SAAY,CACV,EACF,EACA,YAAa,CACX,EACF,EACA,eAAgB,CACd,EACF,EACA,OAAU,CACR,EACF,EACA,aAAc,CACZ,EACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,EACF,EACA,yBAA0B,CACxB,EACF,EACA,YAAa,CACX,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,mBAAoB,CAClB,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,0EAA2E,CACzE,EACF,EACA,mDAAoD,CAClD,EACF,EACA,0DAA2D,CACzD,EACF,EACA,gDAAmD,CACjD,EACF,EACA,oEAAqE,CACnE,EACF,EACA,oDAAqD,CACnD,EACF,EACA,2CAA8C,CAC5C,EACF,EACA,sEAAuE,CACrE,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,yBAA0B,CACxB,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,eAAgB,CACd,EACF,EACA,yFAA0F,CACxF,EACF,EACA,UAAW,CACT,EACF,EACA,6EAA8E,CAC5E,EACF,EACA,UAAa,CACX,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,SAAY,CACV,EACF,EACA,kCAAmC,CACjC,EACF,EACA,QAAW,CACT,EACF,EACA,qCAAsC,CACpC,EACF,EACA,qBAAsB,CACpB,EACF,EACA,aAAc,CACZ,EACF,EACA,oDAAqD,CACnD,EACF,EACA,0FAA2F,CACzF,EACF,EACA,mEAAoE,CAClE,EACF,EACA,iDAAkD,CAChD,EACF,EACA,KAAQ,CACN,EACF,EACA,KAAQ,CACN,EACF,EACA,2CAA8C,CAC5C,EACF,EACA,wCAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,EACF,EACA,mCAAsC,CACpC,EACF,EACA,qEAAwE,CACtE,EACF,EACA,sCAAyC,CACvC,EACF,EACA,gFAAmF,CACjF,EACF,EACA,sCAAyC,CACvC,EACF,EACA,yCAA0C,CACxC,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,+BAAgC,CAC9B,mCACF,EACA,kCAAmC,CACjC,+BACF,EACA,kBAAmB,CACjB,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,0DAA2D,CACzD,EACF,EACA,sBAAuB,CACrB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,+CAAgD,CAC9C,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,uBAAwB,CACtB,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,iDAAkD,CAChD,EACF,EACA,qEAAsE,CACpE,EACF,EACA,mDAAoD,CAClD,EACF,EACA,kCAAmC,CACjC,EACF,EACA,oCAAqC,CACnC,EACF,EACA,0DAA2D,CACzD,EACF,EACA,2CAA4C,CAC1C,EACF,EACA,0DAA2D,CACzD,EACF,EACA,yDAA0D,CACxD,EACF,EACA,2CAA4C,CAC1C,EACF,EACA,oEAAqE,CACnE,EACF,EACA,gEAAiE,CAC/D,EACF,EACA,gEAAiE,CAC/D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kCAAmC,CACjC,EACF,EACA,SAAY,CACV,EACF,EACA,yLAA0L,CACxL,EACF,EACA,kBAAmB,CACjB,EACF,EACA,gBAAiB,CACf,EACF,EACA,YAAa,CACX,EACF,EACA,SAAY,CACV,EACF,EACA,iCAAkC,CAChC,EACF,EACA,OAAU,CACR,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,iEAAkE,CAChE,EACF,EACA,+BAAkC,CAChC,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kBAAmB,CACjB,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,EACF,EACA,0BAA2B,CACzB,EACF,EACA,OAAU,CACR,EACF,EACA,SAAU,CACR,EACF,EACA,uBAAwB,CACtB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,0DAA2D,CACzD,EACF,EACA,KAAQ,CACN,EACF,EACA,YAAe,CACb,EACF,EACA,KAAQ,CACN,EACF,EACA,SAAY,CACV,EACF,EACA,gBAAiB,CACf,EACF,EACA,GAAM,CACJ,EACF,EACA,KAAQ,CACN,EACF,EACA,aAAc,CACZ,EACF,EACA,KAAQ,CACN,EACF,EACA,qBAAsB,CACpB,EACF,EACA,QAAW,CACT,EACF,EACA,mBAAoB,CAClB,EACF,EACA,oEAAqE,CACnE,EACF,EACA,wFAAyF,CACvF,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,sEAAuE,CACrE,EACF,EACA,qEAAsE,CACpE,EACF,EACA,cAAe,CACb,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,oFAAgF,CAC9E,EACF,EACA,uBAAwB,CACtB,EACF,EACA,mCAAoC,CAClC,EACF,EACA,wBAAyB,CACvB,EACF,EACA,4CAA6C,CAC3C,EACF,EACA,kCAAmC,CACjC,EACF,EACA,mDAAoD,CAClD,EACF,EACA,wCAAyC,CACvC,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,qDAAsD,CACpD,EACF,EACA,qCAAsC,CACpC,EACF,EACA,SAAY,CACV,EACF,EACA,0BAA2B,CACzB,EACF,EACA,mDAAoD,CAClD,EACF,EACA,2FAAgG,CAC9F,EACF,EACA,2EAA4E,CAC1E,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,sBAAuB,CACrB,EACF,EACA,6FAA8F,CAC5F,EACF,EACA,wDAAyD,CACvD,EACF,EACA,uBAAwB,CACtB,EACF,EACA,4IAA6I,CAC3I,EACF,EACA,yBAA0B,CACxB,EACF,EACA,sDAAuD,CACrD,EACF,EACA,8JAA+J,CAC7J,EACF,EACA,eAAgB,CACd,EACF,EACA,SAAY,CACV,EACF,EACA,oDAAqD,CACnD,EACF,EACA,6CAA8C,CAC5C,EACF,EACA,oBAAqB,CACnB,EACF,EACA,0DAA2D,CACzD,EACF,EACA,qBAAsB,CACpB,EACF,EACA,uDAAwD,CACtD,EACF,EACA,0BAA2B,CACzB,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,SAAY,CACV,EACF,EACA,wBAAyB,CACvB,EACF,EACA,2FAA4F,CAC1F,EACF,EACA,0BAA2B,CACzB,EACF,EACA,8DAA+D,CAC7D,EACF,EACA,YAAa,CACX,EACF,EACA,aAAc,CACZ,EACF,EACA,oBAAqB,CACnB,EACF,EACA,sEAAuE,CACrE,EACF,EACA,0BAA2B,CACzB,EACF,EACA,qEAAsE,CACpE,EACF,EACA,iBAAkB,CAChB,EACF,EACA,sLAAuL,CACrL,EACF,EACA,mFAAoF,CAClF,EACF,EACA,kFAAmF,CACjF,EACF,EACA,iCAAkC,CAChC,EACF,EACA,YAAe,CACb,EACF,EACA,yBAA0B,CACxB,mCACF,EACA,QAAW,CACT,EACF,EACA,gBAAiB,CACf,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,qEAAsE,CACpE,EACF,EACA,mCAAoC,CAClC,EACF,EACA,0BAA2B,CACzB,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,KAAQ,CACN,EACF,EACA,YAAe,CACb,yCACF,EACA,OAAU,CACR,EACF,EACA,OAAQ,CACN,EACF,EACA,OAAQ,CACN,EACF,EACA,mBAAoB,CAClB,EACF,EACA,QAAW,CACT,EACF,EACA,OAAU,CACR,EACF,EACA,YAAe,CACb,EACF,EACA,SAAY,CACV,EACF,EACA,WAAc,CACZ,EACF,EACA,kCAAmC,CACjC,EACF,EACA,wBAAyB,CACvB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,iBAAkB,CAChB,EACF,EACA,gBAAiB,CACf,EACF,EACA,aAAc,CACZ,EACF,EACA,mGAAoG,CAClG,EACF,EACA,iBAAkB,CAChB,EACF,EACA,4DAA6D,CAC3D,EACF,EACA,uBAAwB,CACtB,EACF,EACA,UAAa,CACX,EACF,EACA,mBAAoB,CAClB,EACF,EACA,yBAA0B,CACxB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,oBAAqB,CACnB,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,OAAU,CACR,EACF,EACA,QAAW,CACT,EACF,EACA,cAAe,CACb,EACF,EACA,iBAAkB,CAChB,EACF,EACA,+DAAgE,CAC9D,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,qBAAsB,CACpB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,cAAe,CACb,EACF,EACA,gBAAiB,CACf,EACF,EACA,KAAQ,CACN,EACF,EACA,mFAAoF,CAClF,EACF,EACA,GAAM,CACJ,EACF,EACA,gFAAiF,CAC/E,EACF,EACA,QAAW,CACT,EACF,EACA,sDAAuD,CACrD,EACF,EACA,mDAAsD,CACpD,EACF,EACA,SAAY,CACV,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,wDAA2D,CACzD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,2DAA8D,CAC5D,EACF,EACA,qDAAsD,CACpD,EACF,EACA,+FAAgG,CAC9F,EACF,EACA,sDAAyD,CACvD,EACF,EACA,qDAAsD,CACpD,EACF,EACA,mDAAoD,CAClD,EACF,EACA,uIAAwI,CACtI,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,aAAgB,CACd,EACF,EACA,UAAa,CACX,EACF,EACA,SAAY,CACV,EACF,EACA,eAAkB,CAChB,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,YAAa,CACX,EACF,EACA,kBAAmB,CACjB,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,wBAAyB,CACvB,EACF,EACA,SAAY,CACV,EACF,EACA,KAAQ,CACN,EACF,EACA,MAAS,CACP,EACF,EACA,yCAA0C,CACxC,EACF,EACA,+EAAgF,CAC9E,EACF,EACA,oDAAqD,CACnD,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,QAAW,CACT,EACF,EACA,0BAA2B,CACzB,EACF,EACA,QAAW,CACT,EACF,EACA,WAAY,CACV,EACF,EACA,yCAA0C,CACxC,EACF,EACA,MAAS,CACP,EACF,EACA,OAAU,CACR,EACF,EACA,OAAU,CACR,EACF,EACA,IAAO,CACL,EACF,EACA,uBAAwB,CACtB,EACF,EACA,iCAAkC,CAChC,EACF,EACA,+BAAgC,CAC9B,EACF,EACA,iCAAkC,CAChC,EACF,EACA,sDAAuD,CACrD,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,OAAU,CACR,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,uBAAwB,CACtB,EACF,EACA,kDAAmD,CACjD,EACF,EACA,oBAAqB,CACnB,EACF,EACA,8HAA+H,CAC7H,EACF,EACA,wBAAyB,CACvB,EACF,EACA,kFAAmF,CACjF,EACF,EACA,0EAA2E,CACzE,EACF,EACA,wGAAyG,CACvG,EACF,EACA,oEAAqE,CACnE,EACF,EACA,sBAAuB,CACrB,EACF,EACA,iJAAkJ,CAChJ,EACF,EACA,wBAAyB,CACvB,EACF,EACA,kCAAmC,CACjC,EACF,EACA,6HAA8H,CAC5H,EACF,EACA,kBAAmB,CACjB,EACF,EACA,QAAW,CACT,EACF,EACA,cAAe,CACb,EACF,EACA,eAAgB,CACd,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,uBAAwB,CACtB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,0CAA2C,CACzC,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,mBAAoB,CAClB,EACF,EACA,+DAAgE,CAC9D,EACF,EACA,kGAAmG,CACjG,EACF,EACA,MAAS,CACP,EACF,EACA,0DAA2D,CACzD,EACF,EACA,MAAS,CACP,EACF,EACA,sCAAuC,CACrC,EACF,EACA,cAAe,CACb,EACF,EACA,qDAAsD,CACpD,EACF,EACA,YAAa,CACX,EACF,EACA,2DAA4D,CAC1D,EACF,EACA,kBAAmB,CACjB,EACF,EACA,kFAAmF,CACjF,EACF,EACA,WAAY,CACV,EACF,EACA,0CAA2C,CACzC,EACF,EACA,0BAA2B,CACzB,EACF,EACA,yDAA0D,CACxD,EACF,EACA,0DAA2D,CACzD,EACF,EACA,iBAAkB,CAChB,EACF,EACA,kBAAmB,CACjB,EACF,EACA,6BAA8B,CAC5B,EACF,EACA,kFAAmF,CACjF,EACF,EACA,kFAAmF,CACjF,EACF,EACA,uFAAwF,CACtF,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,iBAAoB,CAClB,EACF,EACA,QAAW,CACT,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,iBAAkB,CAChB,EACF,EACA,uBAAwB,CACtB,EACF,EACA,wRAA6R,CAC3R,EACF,EACA,eAAgB,CACd,EACF,EACA,mCAAoC,CAClC,EACF,EACA,KAAQ,CACN,EACF,EACA,qCAAsC,CACpC,EACF,EACA,eAAgB,CACd,EACF,EACA,0CAA2C,CACzC,EACF,EACA,8CAA+C,CAC7C,EACF,EACA,QAAW,CACT,EACF,EACA,eAAgB,CACd,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,mBAAoB,CAClB,EACF,EACA,kGAAmG,CACjG,EACF,EACA,kCAAmC,CACjC,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,uEAAwE,CACtE,EACF,EACA,iGAAkG,CAChG,EACF,EACA,uEAAwE,CACtE,EACF,EACA,oDAAqD,CACnD,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,kBAAmB,CACjB,EACF,EACA,mBAAoB,CAClB,EACF,EACA,sCAAuC,CACrC,EACF,EACA,eAAgB,CACd,EACF,EACA,gBAAiB,CACf,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,OAAU,CACR,EACF,EACA,iBAAkB,CAChB,EACF,EACA,QAAW,CACT,EACF,EACA,QAAW,CACT,EACF,EACA,kBAAmB,CACjB,EACF,EACA,wCAAyC,CACvC,EACF,EACA,mCAAoC,CAClC,EACF,EACA,2BAA4B,CAC1B,EACF,EACA,yCAA0C,CACxC,EACF,EACA,4BAA6B,CAC3B,EACF,EACA,YAAa,CACX,EACF,EACA,eAAgB,CACd,EACF,EACA,aAAc,CACZ,EACF,EACA,YAAa,CACX,EACF,EACA,YAAa,CACX,EACF,EACA,mCAAoC,CAClC,EACF,EACA,mEAAoE,CAClE,EACF,EACA,mEAAoE,CAClE,EACF,EACA,MAAS,CACP,EACF,EACA,mDAAoD,CAClD,EACF,EACA,OAAU,CACR,EACF,EACA,wDAAyD,CACvD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,SAAY,CACV,EACF,EACA,eAAgB,CACd,EACF,EACA,eAAgB,CACd,EACF,EACA,iBAAkB,CAChB,EACF,EACA,wCAA2C,CACzC,EACF,EACA,gDAAiD,CAC/C,EACF,EACA,yDAA0D,CACxD,EACF,EACA,oCAAqC,CACnC,EACF,EACA,8BAA+B,CAC7B,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,qDAAsD,CACpD,EACF,EACA,wBAAyB,CACvB,EACF,EACA,yCAA0C,CACxC,EACF,EACA,mBAAoB,CAClB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,gCAAiC,CAC/B,EACF,EACA,sBAAuB,CACrB,EACF,EACA,sBAAuB,CACrB,EACF,EACA,qBAAsB,CACpB,EACF,EACA,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", "names": ["require_BigInteger", "__commonJSMin", "exports", "module", "bigInt", "undefined", "BASE", "LOG_BASE", "MAX_INT", "MAX_INT_ARR", "smallToArray", "DEFAULT_ALPHABET", "supportsNativeBigInt", "Integer", "v", "radix", "alphabet", "caseSensitive", "parseValue", "parseBase", "BigInteger", "value", "sign", "SmallInteger", "NativeBigInt", "isPrecise", "n", "arrayToSmall", "arr", "trim", "length", "compareAbs", "i", "createArray", "x", "truncate", "add", "a", "b", "l_a", "l_b", "r", "carry", "base", "sum", "addAny", "addSmall", "l", "subtract", "a_l", "b_l", "borrow", "difference", "subtractAny", "subtractSmall", "small", "multiplyLong", "product", "a_i", "b_j", "j", "multiplySmall", "shiftLeft", "multiplyKaratsuba", "y", "d", "c", "ac", "bd", "abcd", "useKaratsuba", "l1", "l2", "abs", "multiplySmallAndArray", "square", "a_j", "divMod1", "result", "divisorMostSignificantDigit", "lambda", "remainder", "divisor", "quotientDigit", "shift", "q", "divModSmall", "divMod2", "part", "guess", "xlen", "highx", "highy", "check", "quotient", "divModAny", "self", "comparison", "qSign", "mod", "mSign", "_0", "_1", "_2", "exp", "isBasicPrime", "millerRabinTest", "nPrev", "t", "next", "strict", "isPrime", "bits", "logN", "iterations", "rng", "newT", "newR", "lastT", "lastR", "powersOfTwo", "powers2Length", "highestPower2", "shift_isSmall", "remQuo", "bitwise", "fn", "xSign", "ySign", "xRem", "yRem", "xDigit", "yDigit", "xDivMod", "yDivMod", "LOBMASK_I", "LOBMASK_BI", "roughLOB", "integerLogarithm", "tmp", "p", "e", "max", "min", "gcd", "lcm", "randBetween", "usedRNG", "low", "high", "range", "digits", "toBase", "restricted", "top", "digit", "text", "absBase", "alphabetValues", "isNegative", "start", "parseBaseFromArray", "val", "pow", "stringify", "neg", "out", "left", "divmod", "toBaseString", "str", "zeros", "parseStringValue", "split", "decimalPlace", "isValid", "parseNumberValue", "require_jed", "__commonJSMin", "exports", "module", "root", "undef", "ArrayProto", "ObjProto", "slice", "hasOwnProp", "nativeForEach", "breaker", "_", "obj", "iterator", "context", "i", "l", "key", "source", "prop", "Jed", "options", "getPluralFormFunc", "plural_form_string", "Chain", "i18n", "domain", "num", "pkey", "sArr", "x", "skey", "val", "singular_key", "plural_key", "fallback", "locale_data", "dict", "defaultConf", "pluralForms", "val_list", "res", "val_idx", "sprintf", "get_type", "variable", "str_repeat", "input", "multiplier", "output", "str_format", "parse_tree", "argv", "cursor", "tree_length", "node_type", "arg", "k", "match", "pad", "pad_character", "pad_length", "fmt", "_fmt", "arg_names", "field_list", "replacement_field", "field_match", "vsprintf", "plural_forms", "n", "args", "plural_str", "imply", "ast", "nplurals_re", "plural_re", "nplurals_matches", "plural_matches", "parser", "yytext", "yyleng", "yylineno", "yy", "yystate", "$$", "_$", "$0", "str", "hash", "self", "stack", "vstack", "lstack", "table", "recovering", "TERROR", "EOF", "yyloc", "popStack", "lex", "token", "symbol", "preErrorSymbol", "state", "action", "a", "r", "yyval", "p", "len", "newState", "expected", "errStr", "lexer", "ch", "lines", "past", "next", "pre", "c", "col", "rules", "condition", "yy_", "$avoiding_name_collisions", "YY_START", "YYSTATE", "assign", "obj", "props", "i", "removeNode", "node", "parentNode", "removeChild", "createElement", "type", "children", "key", "ref", "normalizedProps", "arguments", "length", "slice", "call", "defaultProps", "createVNode", "original", "vnode", "__k", "__", "__b", "__e", "__d", "__c", "__h", "constructor", "__v", "vnodeId", "options", "createRef", "current", "Fragment", "Component", "context", "this", "getDomSibling", "childIndex", "indexOf", "sibling", "updateParentDomPointers", "child", "base", "enqueueRender", "c", "rerenderQueue", "push", "process", "prevDebounce", "debounceRendering", "setTimeout", "queue", "__r", "sort", "a", "b", "some", "component", "commitQueue", "oldVNode", "oldDom", "parentDom", "__P", "diff", "ownerSVGElement", "commitRoot", "diffChildren", "renderResult", "newParentVNode", "oldParentVNode", "globalContext", "isSvg", "excessDomChildren", "isHydrating", "j", "childVNode", "newDom", "firstChildDom", "refs", "oldChildren", "EMPTY_ARR", "oldChildrenLength", "Array", "isArray", "EMPTY_OBJ", "reorderChildren", "placeChild", "unmount", "applyRef", "tmp", "toChildArray", "out", "nextDom", "sibDom", "outer", "appendChild", "nextSibling", "insertBefore", "diffProps", "dom", "newProps", "oldProps", "hydrate", "setProperty", "setStyle", "style", "value", "IS_NON_DIMENSIONAL", "test", "name", "oldValue", "useCapture", "o", "cssText", "replace", "toLowerCase", "l", "addEventListener", "eventProxyCapture", "eventProxy", "removeEventListener", "e", "removeAttribute", "setAttribute", "event", "newVNode", "isNew", "oldState", "snapshot", "clearProcessingException", "provider", "componentContext", "renderHook", "count", "newType", "contextType", "__E", "prototype", "render", "doRender", "sub", "state", "_sb", "__s", "getDerivedStateFromProps", "componentWillMount", "componentDidMount", "componentWillReceiveProps", "shouldComponentUpdate", "forEach", "componentWillUpdate", "componentDidUpdate", "getChildContext", "getSnapshotBeforeUpdate", "diffElementNodes", "diffed", "root", "cb", "oldHtml", "newHtml", "nodeType", "localName", "document", "createTextNode", "createElementNS", "is", "data", "childNodes", "dangerouslySetInnerHTML", "attributes", "__html", "innerHTML", "checked", "parentVNode", "skipRemove", "r", "componentWillUnmount", "replaceNode", "firstChild", "cloneElement", "createContext", "defaultValue", "contextId", "Consumer", "contextValue", "Provider", "subs", "ctx", "_props", "old", "splice", "isValidElement", "error", "errorInfo", "ctor", "handled", "getDerivedStateFromError", "setState", "componentDidCatch", "update", "callback", "s", "forceUpdate", "getHookState", "index", "type", "options", "__h", "currentComponent", "currentHook", "hooks", "__H", "__", "length", "push", "__V", "EMPTY", "useState", "initialState", "useReducer", "invokeOrReturn", "reducer", "init", "hookState", "currentIndex", "_reducer", "__c", "action", "currentValue", "__N", "nextValue", "setState", "_hasScuFromHooks", "prevScu", "shouldComponentUpdate", "p", "s", "c", "stateHooks", "filter", "x", "every", "call", "this", "shouldUpdate", "forEach", "hookItem", "props", "useEffect", "callback", "args", "state", "__s", "argsChanged", "_pendingArgs", "useLayoutEffect", "useRef", "initialValue", "useMemo", "current", "useImperativeHandle", "ref", "createHandle", "concat", "factory", "useCallback", "useContext", "context", "provider", "sub", "value", "useDebugValue", "formatter", "useErrorBoundary", "cb", "errState", "componentDidCatch", "err", "errorInfo", "undefined", "useId", "root", "__v", "__m", "mask", "flushAfterPaintEffects", "component", "afterPaintEffects", "shift", "invokeCleanup", "invokeEffect", "e", "__e", "afterNextFrame", "raf", "done", "clearTimeout", "timeout", "HAS_RAF", "cancelAnimationFrame", "setTimeout", "requestAnimationFrame", "hook", "comp", "cleanup", "oldArgs", "newArgs", "some", "arg", "f", "previousComponent", "prevRaf", "oldBeforeDiff", "oldBeforeRender", "oldAfterDiff", "oldCommit", "oldBeforeUnmount", "diffed", "unmount", "__b", "vnode", "commitQueue", "hasErrored", "assign", "obj", "props", "i", "shallowDiffers", "a", "b", "is", "x", "y", "PureComponent", "p", "this", "memo", "c", "comparer", "shouldUpdate", "nextProps", "ref", "updateRef", "call", "current", "Memoed", "shouldComponentUpdate", "createElement", "displayName", "name", "prototype", "isReactComponent", "forwardRef", "fn", "Forwarded", "clone", "$$typeof", "REACT_FORWARD_SYMBOL", "render", "__f", "detachedClone", "vnode", "detachedParent", "parentDom", "__c", "forEach", "effect", "__H", "__P", "__k", "map", "child", "removeOriginal", "originalParent", "__v", "__e", "insertBefore", "__d", "Suspense", "__u", "_suspenders", "suspended", "component", "__", "__a", "lazy", "loader", "prom", "error", "Lazy", "then", "exports", "default", "e", "SuspenseList", "_next", "_map", "ContextProvider", "getChildContext", "context", "children", "Portal", "_this", "container", "_container", "componentWillUnmount", "_temp", "nodeType", "parentNode", "childNodes", "appendChild", "push", "before", "removeChild", "splice", "indexOf", "createPortal", "el", "containerInfo", "parent", "callback", "textContent", "preactRender", "hydrate", "preactHydrate", "empty", "isPropagationStopped", "cancelBubble", "isDefaultPrevented", "defaultPrevented", "createFactory", "type", "bind", "isValidElement", "element", "REACT_ELEMENT_TYPE", "cloneElement", "preactCloneElement", "apply", "arguments", "unmountComponentAtNode", "findDOMNode", "base", "Fragment", "startTransition", "cb", "useDeferredValue", "val", "useTransition", "useLayoutEffect", "useSyncExternalStore", "subscribe", "getSnapshot", "value", "_useState", "useState", "_instance", "_getSnapshot", "forceUpdate", "useEffect", "oldDiffHook", "mapFn", "Children", "oldCatchError", "oldUnmount", "resolve", "CAMEL_PROPS", "IS_DOM", "onChangeInputType", "oldEventHook", "currentComponent", "classNameDescriptor", "oldVNodeHook", "oldBeforeRender", "__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED", "version", "unstable_batchedUpdates", "flushSync", "StrictMode", "useInsertionEffect", "index", "Component", "isPureReactComponent", "state", "options", "__b", "Symbol", "for", "toChildArray", "count", "length", "only", "normalized", "toArray", "newVNode", "oldVNode", "errorInfo", "unmount", "__R", "__h", "promise", "suspendingVNode", "suspendingComponent", "resolved", "onResolved", "onSuspensionComplete", "suspendedVNode", "setState", "pop", "wasHydrating", "document", "detachedComponent", "__O", "fallback", "list", "node", "delete", "revealOrder", "size", "delegated", "get", "unsuspend", "wrappedUnsuspend", "Map", "reverse", "set", "componentDidUpdate", "componentDidMount", "test", "key", "Object", "defineProperty", "configurable", "v", "writable", "event", "persist", "nativeEvent", "class", "normalizedProps", "nonCustomElement", "toLowerCase", "replace", "multiple", "Array", "isArray", "selected", "defaultValue", "className", "enumerable", "__r", "ReactCurrentDispatcher", "readContext", "__n", "arg", "useId", "useReducer", "useRef", "useImperativeHandle", "useMemo", "useCallback", "useContext", "useDebugValue", "createContext", "createRef", "require_use_sync_external_store_shim_production_min", "__commonJSMin", "exports", "e", "h", "a", "b", "k", "l", "m", "n", "p", "q", "d", "f", "c", "g", "r", "t", "u", "require_shim", "__commonJSMin", "exports", "module", "require_qrcode", "__commonJSMin", "exports", "module", "qrcode", "typeNumber", "errorCorrectionLevel", "PAD0", "PAD1", "_typeNumber", "_errorCorrectionLevel", "QRErrorCorrectionLevel", "_modules", "_moduleCount", "_dataCache", "_dataList", "_this", "makeImpl", "test", "maskPattern", "moduleCount", "modules", "row", "col", "setupPositionProbePattern", "setupPositionAdjustPattern", "setupTimingPattern", "setupTypeInfo", "setupTypeNumber", "createData", "mapData", "r", "c", "getBestMaskPattern", "minLostPoint", "pattern", "i", "lostPoint", "QRUtil", "pos", "j", "bits", "mod", "data", "inc", "bitIndex", "byteIndex", "maskFunc", "dark", "mask", "createBytes", "buffer", "rsBlocks", "offset", "maxDcCount", "maxEcCount", "dcdata", "ecdata", "dcCount", "ecCount", "rsPoly", "rawPoly", "qrPolynomial", "modPoly", "modIndex", "totalCodeCount", "index", "dataList", "QRRSBlock", "qrBitBuffer", "totalDataCount", "mode", "newData", "qrNumber", "qrAlphaNum", "qr8BitByte", "qrKanji", "cellSize", "margin", "qrHtml", "alt", "title", "opts", "size", "mc", "mr", "qrSvg", "rect", "escapeXml", "min", "max", "createDataURL", "x", "y", "img", "s", "escaped", "_createHalfASCII", "r1", "r2", "p", "blocks", "blocksLastLineNoMargin", "ascii", "white", "black", "line", "context", "length", "bytes", "unicodeData", "numChars", "unicodeMap", "bin", "base64DecodeInputStream", "read", "b", "count", "b0", "b1", "b2", "b3", "k", "v", "unknownChar", "QRMode", "QRMaskPattern", "PATTERN_POSITION_TABLE", "G15", "G18", "G15_MASK", "getBCHDigit", "digit", "d", "errorCorrectLength", "a", "QRMath", "type", "sameCount", "darkCount", "ratio", "EXP_TABLE", "LOG_TABLE", "n", "num", "shift", "_num", "e", "RS_BLOCK_TABLE", "qrRSBlock", "totalCount", "dataCount", "getRsBlockTable", "rsBlock", "list", "_buffer", "_length", "bufIndex", "bit", "_mode", "_data", "strToNum", "chatToNum", "getCode", "_bytes", "stringToBytes", "code", "byteArrayOutputStream", "off", "len", "base64EncodeOutputStream", "_buflen", "_base64", "writeEncoded", "encode", "padlen", "str", "_str", "_pos", "decode", "gifImage", "width", "height", "_width", "_height", "pixel", "out", "lzwMinCodeSize", "raster", "getLZWRaster", "bitOutputStream", "_out", "_bitLength", "_bitBuffer", "clearCode", "endCode", "bitLength", "table", "lzwTable", "byteOut", "bitOut", "dataIndex", "_map", "_size", "key", "getPixel", "gif", "base64", "toUTF8Array", "utf8", "charcode", "factory", "gf", "init", "r", "i", "randombytes", "x", "n", "_9", "gf0", "gf1", "_121665", "D", "D2", "X", "Y", "I", "ts64", "h", "l", "vn", "xi", "y", "yi", "d", "crypto_verify_32", "x", "xi", "y", "yi", "vn", "sigma", "set25519", "r", "a", "i", "car25519", "o", "v", "c", "sel25519", "p", "q", "b", "t", "pack25519", "n", "j", "m", "gf", "neq25519", "d", "crypto_verify_32", "par25519", "unpack25519", "A", "Z", "M", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10", "t11", "t12", "t13", "t14", "t15", "t16", "t17", "t18", "t19", "t20", "t21", "t22", "t23", "t24", "t25", "t26", "t27", "t28", "t29", "t30", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15", "S", "inv25519", "pow2523", "K", "crypto_hashblocks_hl", "hh", "hl", "m", "wh", "wl", "bh0", "bh1", "bh2", "bh3", "bh4", "bh5", "bh6", "bh7", "bl0", "bl1", "bl2", "bl3", "bl4", "bl5", "bl6", "bl7", "th", "tl", "i", "j", "h", "l", "a", "b", "c", "d", "ah0", "ah1", "ah2", "ah3", "ah4", "ah5", "ah6", "ah7", "al0", "al1", "al2", "al3", "al4", "al5", "al6", "al7", "pos", "crypto_hash", "out", "n", "x", "ts64", "HashState", "data", "add", "p", "q", "gf", "e", "f", "g", "t", "Z", "M", "A", "D2", "cswap", "sel25519", "pack", "r", "tx", "ty", "zi", "inv25519", "pack25519", "par25519", "scalarmult", "s", "set25519", "gf0", "gf1", "scalarbase", "X", "Y", "crypto_sign_keypair", "pk", "sk", "seeded", "randombytes", "L", "modL", "carry", "k", "reduce", "crypto_sign", "sm", "smlen", "unpackpos", "unpackneg", "scalar0", "scalar1", "scalarNeg1", "crypto_core_ed25519_scalar_sub", "chk", "num", "den", "den2", "den4", "den6", "unpack25519", "S", "D", "pow2523", "neq25519", "I", "crypto_scalarmult_ed25519_base_noclamp", "crypto_scalarmult_ed25519_noclamp", "ql", "crypto_sign_open", "m", "sm", "n", "pk", "i", "mlen", "t", "h", "p", "gf", "q", "unpackneg", "crypto_hash", "reduce", "scalarmult", "scalarbase", "add", "pack", "crypto_verify_32", "crypto_sign_BYTES", "crypto_sign_PUBLICKEYBYTES", "crypto_sign_SECRETKEYBYTES", "crypto_sign_SEEDBYTES", "crypto_hash_BYTES", "checkArrayTypes", "args", "i", "randomBytes", "n", "b", "randombytes", "sign", "msg", "secretKey", "checkArrayTypes", "crypto_sign_SECRETKEYBYTES", "signedMsg", "crypto_sign_BYTES", "crypto_sign", "sign_detached", "msg", "secretKey", "signedMsg", "sign", "sig", "crypto_sign_BYTES", "i", "crypto_sign_keyPair_fromSeed", "seed", "checkArrayTypes", "crypto_sign_SEEDBYTES", "pk", "crypto_sign_PUBLICKEYBYTES", "sk", "crypto_sign_SECRETKEYBYTES", "i", "crypto_sign_keypair", "hash", "msg", "checkArrayTypes", "h", "crypto_hash_BYTES", "crypto_hash", "setPRNG", "fn", "randombytes", "crypto_core_ed25519_scalar_reduce", "x", "len", "z", "i", "o", "modL", "crypto_core_ed25519_scalar_sub", "y", "crypto_edx25519_private_key_create", "seed", "randombytes", "crypto_edx25519_private_key_create_from_seed", "pk", "hash", "crypto_edx25519_get_public", "priv", "crypto_scalarmult_ed25519_base_noclamp", "crypto_edx25519_sign_detached", "m", "skx", "pkx", "h", "r", "j", "p", "gf", "sm", "crypto_hash", "reduce", "scalarbase", "pack", "crypto_edx25519_sign_detached_verify", "msg", "sig", "publicKey", "checkArrayTypes", "crypto_sign_BYTES", "crypto_sign_PUBLICKEYBYTES", "crypto_sign_open", "nullRandom", "c", "loadBrowserPrng", "cr", "QUOTA", "setPRNG", "x", "i", "v", "regexPunycode", "regexNonASCII", "regexSeparators", "errors", "baseMinusTMin", "floor", "stringFromCharCode", "error", "type", "map", "array", "fn", "result", "length", "mapDomain", "string", "parts", "labels", "encoded", "ucs2decode", "output", "counter", "value", "extra", "ucs2encode", "basicToDigit", "codePoint", "digitToBasic", "digit", "flag", "adapt", "delta", "numPoints", "firstTime", "k", "decode", "input", "inputLength", "i", "n", "bias", "basic", "j", "index", "oldi", "w", "t", "baseMinusT", "out", "encode", "inputArg", "currentValue", "basicLength", "handledCPCount", "m", "handledCPCountPlusOne", "q", "qMinusT", "toUnicode", "toASCII", "punycode", "utf8Encoder", "utf8Decoder", "utf8Encode", "string", "utf8DecodeWithoutBOM", "bytes", "parseUrlencoded", "input", "sequences", "strictlySplitByteSequence", "p", "output", "name", "value", "indexOfEqual", "replaceByteInByteSequence", "nameString", "percentDecodeBytes", "valueString", "parseUrlencodedString", "serializeUrlencoded", "tuples", "encodingOverride", "encoding", "i", "tuple", "utf8PercentEncodeString", "isURLEncodedPercentEncode", "buf", "cp", "list", "last", "from", "to", "char", "percentEncode", "c", "hex", "outputIndex", "byte", "isASCIIHex", "bytePoint", "percentDecodeString", "isC0ControlPercentEncode", "extraFragmentPercentEncodeSet", "isFragmentPercentEncode", "extraQueryPercentEncodeSet", "isQueryPercentEncode", "isSpecialQueryPercentEncode", "extraPathPercentEncodeSet", "isPathPercentEncode", "extraUserinfoPercentEncodeSet", "isUserinfoPercentEncode", "extraComponentPercentEncodeSet", "isComponentPercentEncode", "extraURLEncodedPercentEncodeSet", "utf8PercentEncodeCodePointInternal", "codePoint", "percentEncodePredicate", "utf8PercentEncodeCodePoint", "spaceAsPlus", "isASCIIDigit", "isASCIIAlpha", "isASCIIAlphanumeric", "URLSearchParamsImpl", "init", "doNotStripQMark", "pair", "query", "x", "callbackfn", "thisArg", "found", "a", "b", "specialSchemes", "failure", "countSymbols", "str", "at", "idx", "isSingleDot", "buffer", "isDoubleDot", "isWindowsDriveLetterCodePoints", "cp1", "cp2", "isWindowsDriveLetterString", "isNormalizedWindowsDriveLetterString", "containsForbiddenHostCodePoint", "containsForbiddenDomainCodePoint", "isSpecialScheme", "scheme", "isSpecial", "url", "isNotSpecial", "defaultPort", "parseIPv4Number", "R", "regex", "parseIPv4", "parts", "numbers", "part", "n", "ipv4", "counter", "serializeIPv4", "address", "parseIPv6", "inputArg", "pieceIndex", "compress", "pointer", "length", "numbersSeen", "ipv4Piece", "number", "swaps", "temp", "serializeIPv6", "findLongestZeroSequence", "ignore0", "parseHost", "isNotSpecialArg", "parseOpaqueHost", "domain", "asciiDomain", "domainToASCII", "endsInANumber", "arr", "maxIdx", "maxLen", "currStart", "currLen", "serializeHost", "host", "beStrict", "result", "punycode", "trimControlChars", "trimTabAndNewline", "shortenPath", "path", "isNormalizedWindowsDriveLetter", "includesCredentials", "cannotHaveAUsernamePasswordPort", "hasAnOpaquePath", "URLStateMachine", "base", "stateOverride", "res", "cStr", "ret", "len", "encodedCodePoints", "port", "startsWithWindowsDriveLetter", "queryPercentEncodePredicate", "fileOtherwiseCodePoints", "serializeURL", "excludeFragment", "serializePath", "serializeOrigin", "segment", "serializeURLOrigin", "parseURL", "basicURLParse", "options", "usm", "setTheUsername", "username", "setThePassword", "password", "serializeInteger", "integer", "NativeURL", "URLImpl", "parsedBase", "parsedURL", "v", "blob", "useOwnUrlImp", "_URL", "URLImpl", "URL", "_URLSearchParams", "URLSearchParamsImpl", "URLSearchParams", "canonicalizeBaseUrl", "url", "x", "URL", "canonicalJson", "obj", "e", "keys", "key", "s", "i", "strcmp", "s1", "s2", "j2s", "isNode", "LogLevel", "globalLogLevel", "byTagLogLevel", "nativeLogging", "name", "msg", "cause", "getGlobalLogLevel", "setGlobalLogLevelFromString", "logLevelStr", "getLevelForString", "getLevelForString", "logLevelStr", "LogLevel", "isNode", "writeNativeLog", "message", "tag", "level", "args", "logFn", "m", "writeNodeLog", "msg", "e", "Logger", "globalLogLevel", "byTagLogLevel", "nativeLogging", "location", "logger", "Logger", "DecodingError", "_DecodingError", "message", "renderContext", "c", "p", "joinContext", "part", "ObjectCodecBuilder", "x", "codec", "other", "objectDisplayName", "propList", "allowExtra", "deprecatedPros", "obj", "prop", "propRawVal", "propVal", "UnionCodecBuilder", "discriminator", "baseCodec", "tagValue", "alternatives", "d", "alt", "altDecoded", "UnionCodecPreBuilder", "buildCodecForObject", "buildCodecForUnion", "codecForMap", "innerCodec", "map", "i", "codecForList", "arr", "codecForNumber", "codecForBoolean", "codecForString", "codecForStringURL", "shouldEndWithSlash", "x", "c", "DecodingError", "renderContext", "url", "e", "codecForAny", "x", "c", "codecForConstString", "s", "DecodingError", "renderContext", "codecForConstNumber", "n", "x", "c", "DecodingError", "renderContext", "codecOptional", "innerCodec", "codecOptionalDefault", "def", "codecForEither", "alts", "x", "c", "alt", "logger", "j2s", "DecodingError", "renderContext", "NOOP", "CancellationToken", "_CancellationToken", "asyncOperation", "resolve", "reject", "unregister", "reason", "value", "err", "cb", "_isCancelled", "_canBeCancelled", "token", "cancel", "dispose", "ms", "originalCancel", "originalDispose", "timer", "disposeTimer", "tokens", "combined", "countdown", "handleNextTokenCancelled", "reasons", "unregistrations", "handleAnyTokenCancelled", "CancellationError", "TalerErrorCode", "opaque_AbsoluteTime", "TalerPreciseTimestamp", "now", "absNow", "AbsoluteTime", "round", "t", "fromSeconds", "s", "fromMilliseconds", "ms", "TalerProtocolDuration", "fromSpec", "d", "Duration", "forever", "TalerProtocolTimestamp", "isTimestamp", "x", "zero", "never", "isNever", "min", "t1", "t2", "max", "timeshift", "Duration", "toMilliseconds", "d", "getRemaining", "deadline", "now", "AbsoluteTime", "fromPrettyString", "s", "dMs", "currentNum", "parsingNum", "i", "cc", "cmp", "d1", "d2", "add", "max", "durationMax", "min", "durationMin", "multiply", "n", "durationMul", "toIntegerYears", "fromSpec", "spec", "d_ms", "SECONDS", "MINUTES", "HOURS", "DAYS", "MONTHS", "YEARS", "fromSpecOrUndefined", "toSpec", "ms", "Y_rest", "M_rest", "D_rest", "h_rest", "m_rest", "millis", "getForever", "isForever", "getZero", "fromTalerProtocolDuration", "toTalerProtocolDuration", "fromMilliseconds", "clamp", "args", "getStampMsNow", "getStampMsNever", "timeshift", "opaque_AbsoluteTime", "zero", "never", "t1", "t2", "difference", "isExpired", "t", "isNever", "fromProtocolTimestamp", "fromStampMs", "stampMs", "fromPreciseTimestamp", "offsetUs", "toStampMs", "at", "toPreciseTimestamp", "t_s", "off_us", "toProtocolTimestamp", "isBetween", "start", "end", "toIsoString", "addDuration", "remaining", "stampNow", "subtractDuraction", "stringify", "codecForAbsoluteTime", "x", "c", "renderContext", "t_ms", "opaque_AbsoluteTime", "codecForTimestamp", "t_s", "codecForPreciseTimestamp", "codecForDuration", "d_us", "makeErrorDetail", "code", "detail", "hint", "getDefaultTalerErrorHint", "when", "AbsoluteTime", "getDefaultTalerErrorHint", "code", "errName", "TalerErrorCode", "TalerError", "_TalerError", "d", "cause", "code", "detail", "hint", "getDefaultTalerErrorHint", "when", "AbsoluteTime", "c", "e", "errDetail", "getErrorDetailFromException", "getErrorDetailFromException", "TalerError", "CancellationToken", "makeErrorDetail", "TalerErrorCode", "excString", "assertUnreachable", "x", "textEncoder", "logger", "Logger", "DEFAULT_REQUEST_TIMEOUT_MS", "HeadersImpl", "name", "value", "normalizedName", "existing", "m", "v", "k", "readTalerErrorResponse", "httpResponse", "contentType", "mediaType", "TalerError", "TalerErrorCode", "errJson", "e", "j2s", "readSuccessResponseJsonOrErrorCode", "httpResponse", "codec", "readTalerErrorResponse", "respJson", "e", "TalerError", "TalerErrorCode", "parsedResponse", "readResponseJsonOrThrow", "throwUnexpectedRequestError", "httpResponse", "talerErrorResponse", "errorDetails", "logger", "j2s", "TalerError", "TalerErrorCode", "readSuccessResponseJsonOrThrow", "codec", "readSuccessResponseJsonOrErrorCode", "encodeBody", "body", "textEncoder", "getDefaultHeaders", "method", "headers", "LibtoolVersion", "compare", "me", "other", "meVer", "parseVersion", "otherVer", "compatible", "currentCmp", "parseVersionOrThrow", "v", "res", "currentStr", "revisionStr", "ageStr", "rest", "current", "revision", "age", "codecForURLString", "codecForString", "codecForCurrencyName", "codecForString", "codecForDecimalNumber", "codecForEddsaPublicKey", "codecForEddsaSignature", "codecForString", "codecForInternationalizedString", "codecForMap", "codecForCurrencySpecificiation", "buildCodecForObject", "codecForNumber", "codecOptional", "codecForList", "codecForAmountString", "codecForTalerCommonConfigResponse", "ExchangeProtocolVersion", "MerchantProtocolVersion", "codecForTokenInfo", "buildCodecForObject", "codecForTimestamp", "codecForString", "codecForBoolean", "codecOptional", "codecForNumber", "codecForTokenInfoList", "codecForList", "codecForAccessToken", "codecForTokenSuccessResponse", "codecForURN", "createRFC8959AccessTokenEncoded", "token", "opSuccessFromHttp", "resp", "codec", "readSuccessResponseJsonOrThrow", "opFixedSuccess", "body", "opEmptySuccess", "opKnownFailure", "case_", "opKnownFailureWithBody", "carefullyParseConfig", "expectedName", "clientVersion", "httpResponse", "minBody", "codecForTalerCommonConfigResponse", "TalerError", "TalerErrorCode", "LibtoolVersion", "opKnownAlternativeHttpFailure", "s", "readResponseJsonOrThrow", "opKnownHttpFailure", "_case", "detail", "readTalerErrorResponse", "opUnknownHttpFailure", "opKnownTalerFailure", "amountFractionalBase", "amountFractionalLength", "amountMaxValue", "FRAC_SEPARATOR", "CURRENCY_SEPARATOR", "Amount", "_Amount", "a", "Amounts", "currency", "n", "val", "saturated", "codecForAmountString", "x", "c", "DecodingError", "renderContext", "Amounts", "AmountParseError", "_Amounts", "amount", "currency", "amt", "Amount", "a1", "a2", "am1", "am2", "x1", "amountFractionalBase", "x2", "quotient", "remainderScaled", "amounts", "jsonAmounts", "first", "rest", "firstJ", "value", "amountMaxValue", "fraction", "xJ", "a", "aJ", "b", "bJ", "av", "af", "bv", "bf", "n", "r", "s", "c_idx", "CURRENCY_SEPARATOR", "opKnownFailure", "number", "d_idx", "FRAC_SEPARATOR", "integerStr", "fractStr", "amountFractionalLength", "opFixedSuccess", "res", "tail", "acc", "r2", "curr1", "curr2", "minFractional", "i", "check", "spec", "strValue", "pos", "originalPosition", "names", "FRAC_POS_NEW_POSITION", "unitIndex", "index", "normal", "small", "splitNormalAndSmall", "intPart", "fracPArt", "newValue", "decimal", "fracSeparatorIndex", "limit", "HttpLibImpl", "url", "opt", "createPlatformHttpLib", "args", "HttpLibImpl", "base64FromArrayBuffer", "arrayBuffer", "base64", "encodings", "bytes", "byteLength", "byteRemainder", "mainLength", "a", "b", "c", "chunk", "i", "import_big_integer", "K", "hashBlocks", "w", "v", "p", "pos", "len", "a", "b", "d", "e", "f", "g", "h", "u", "i", "j", "t1", "t2", "HashSha256", "data", "dataLength", "dataPos", "out", "bytesHashed", "left", "bitLenHi", "bitLenLo", "padLength", "from", "sha256", "data", "h", "HashSha256", "digest", "sha512", "data", "hash", "hmac", "digest", "blockSize", "key", "message", "k", "okp", "ikp", "i", "b1", "h0", "b2", "hmacSha512", "hmacSha256", "sha256", "TalerSignaturePurpose", "Result", "value", "error", "detail", "r", "alt", "CHARSET", "GENERATOR", "polymod", "values", "chk", "p", "top", "i", "hrpExpand", "hrp", "ret", "getEncodingConst", "enc", "BitcoinBech32", "assertUnreachable", "verifyChecksum", "data", "createChecksum", "mod", "Encodings", "encode", "combined", "BitcoinParseError", "decode", "bechString", "has_lower", "has_upper", "Result", "pos", "d", "convertbits", "data", "frombits", "tobits", "pad", "acc", "bits", "ret", "maxv", "p", "value", "BitcoinSewgit", "BitcoinSewgitParseError", "decode", "addr", "enc", "decResp", "BitcoinBech32", "dec", "Result", "res", "encode", "hrp", "version", "program", "opKnownFailure", "opFixedSuccess", "GenerateSegwitAddrError", "generateFakeSegwitAddress", "pub", "addr", "first_rnd", "second_rnd", "first_part", "second_part", "prefix", "Result", "addr1", "BitcoinSewgit", "addr2", "result", "ParseIbanError", "ccZero", "ccNine", "ccA", "ccZ", "appendDigit", "digits", "cc", "n", "mod97", "i", "modAccum", "parseIban", "ibanString", "Result", "ParseIbanError", "myIban", "countryCode", "ibanCountryInfoTable", "digits", "i", "cc", "appendDigit", "mod97", "ibanCountryInfoTable", "PAYTO_PREFIX", "PaytoType", "ReservePubParseError", "PaytoParseError", "Paytos", "supported_targets", "hash", "p", "hashTruncate32", "stringToBytes", "toNormalizedString", "toFullString", "url", "paramList", "createSearchParams", "parseReservePub", "reserve", "Result", "pub", "decodeCrock", "e", "parseHostPortPath2", "hostname", "path", "scheme", "withoutScheme", "h", "parseHostPortPath", "hostnameAndPath", "host", "parseEthereumAddress", "str", "parseTalerBankAccount", "account", "createUnsupported", "targetType", "params", "createIban", "iban", "bic", "createBitcoin", "address", "reservePub", "sgRes", "generateFakeSegwitAddress", "segwitAddrs", "encodeCrock", "createEthereum", "createTalerReserve", "exchange", "createCyclos", "createTalerReserveHttp", "createTalerBank", "asString", "fromString", "s", "opts", "acct", "search", "firstSlashPos", "targetPath", "URLSearchParams", "v", "k", "cs", "ibaRes", "parseIban", "btRes", "BitcoinBech32", "pubRes", "accountId", "assertUnreachable", "codecForPaytoHash", "x", "c", "DecodingError", "renderContext", "codecFullForPaytoString", "codecForPaytoString", "x", "c", "DecodingError", "renderContext", "PAYTO_PREFIX", "encodeRFC3986URIComponent", "str", "c", "rfc3986", "createSearchParams", "paramList", "key", "value", "DenominationPubKey", "cmp", "p1", "p2", "DenomKeyType", "strcmp", "codecForNgDenominations", "codecForAny", "DenomKeyType", "toIntTag", "t", "codecForRsaBlindedDenominationSignature", "buildCodecForObject", "codecForConstString", "codecForString", "codecForBlindedDenominationSignature", "buildCodecForUnion", "codecForExchangeWithdrawResponse", "buildCodecForObject", "codecForList", "codecForBlindedDenominationSignature", "codecForExchangeMeltResponse", "buildCodecForObject", "codecForEddsaPublicKey", "codecForEddsaSignature", "codecForNumber", "codecOptional", "codecForString", "codecForExchangeGetContractResponse", "buildCodecForObject", "codecForString", "codecForExchangeMergeSuccessResponse", "codecForAmountString", "codecForTimestamp", "codecForEddsaSignature", "codecForEddsaPublicKey", "codecForPurseCreateSuccessResponse", "codecForExchangeMergeConflictResponse", "codecOptional", "codecForExchangePurseStatus", "buildCodecForObject", "codecForAmountString", "codecOptional", "codecForTimestamp", "AmlSpaDialect", "LimitOperationType", "AmlState", "codecForAmlSpaDialect", "codecForEither", "codecForConstString", "codecForExchangeConfig", "buildCodecForObject", "codecForString", "codecOptional", "codecForURN", "codecForCurrencySpecificiation", "codecForList", "codecForExchangeKeysResponse", "codecForURLString", "codecForAny", "codecForBoolean", "codecForAmountString", "codecForAmlStatisticsResponse", "codecForEventCounter", "codecForNumber", "codecForLegitimizationMeasuresList", "codecForLegitimizationMeasureDetails", "codecForAvailableMeasureSummary", "buildCodecForObject", "codecForMap", "codecForKycCheckInformation", "codecForAmlProgramRequirement", "codecForMeasureInformation", "codecForList", "codecForKycRules", "codecForString", "codecOptional", "codecForInternationalizedString", "codecForAny", "codecForOperationType", "codecForBoolean", "codecForAmlDecisionsResponse", "codecForAmlDecision", "codecForAmlCustomerAccountSummary", "codecForPaytoHash", "codecForTimestamp", "codecFullForPaytoString", "codecForNumber", "codecForAmlDecisionsAccounts", "codecForAmlDecision", "buildCodecForObject", "codecForString", "codecOptional", "codecForNumber", "codecForBoolean", "codecForTimestamp", "codecForAccountProperties", "codecForLegitimizationRuleSet", "codecForList", "codecForKycRules", "codecForMap", "codecForMeasureInformation", "codecForOperationType", "codecForAmountString", "codecForDuration", "codecForAmlKycAttributes", "codecForKycAttributeCollectionEvent", "codecForAny", "codecForAmlWalletKycCheckResponse", "codecForLegitimizationNeededResponse", "codecForEddsaPublicKey", "codecForAccountKycStatus", "codecForAccessToken", "codecForAccountLimit", "codecForEither", "codecForConstString", "LimitOperationType", "codecForKycRequirementInformationId", "codecForString", "codecForKycFormId", "codecForKycRequirementInformation", "buildCodecForObject", "codecForEither", "codecForConstString", "codecOptional", "codecForAny", "codecForInternationalizedString", "codecForKycProcessClientInformation", "codecOptionalDefault", "codecForList", "codecForBoolean", "codecForExchangeTransferList", "codecForExchangeTransferListEntry", "codecForNumber", "codecForPaytoString", "codecForAmountString", "codecForTimestamp", "codecForKycProcessStartInformation", "codecForURLString", "TransactionHistoryType", "codecForPurseConflict", "buildCodecForUnion", "TalerErrorCode", "codecForDepositDoubleSpendError", "codecForPurseCreateConflict", "codecForPurseDepositConflict", "codecForPurseContractConflict", "codecForPurseConflictPartial", "getRandomBytes", "n", "randomBytes", "useNative", "tart", "encTable", "EncodingError", "_EncodingError", "getValue", "chr", "a", "dec", "encodeCrock", "data", "dataBytes", "sb", "size", "bitBuf", "numBits", "pos", "d", "v", "kdf", "outputLength", "ikm", "salt", "info", "prk", "hmacSha512", "N", "output", "i", "buf", "j", "chunk", "hmacSha256", "kdfKw", "args", "decodeCrock", "encoded", "bitpos", "bitbuf", "readPosition", "outLen", "out", "outPos", "eddsaGetPublic", "eddsaPriv", "tart", "crypto_sign_keyPair_fromSeed", "encoder", "stringToBytes", "s", "encoder", "typedArrayConcat", "chunks", "payloadLen", "c", "buf", "u8buf", "p", "hash", "d", "tart", "hashTruncate32", "logger", "Logger", "eddsaSign", "msg", "eddsaPriv", "tart", "pair", "crypto_sign_keyPair_fromSeed", "sign_detached", "bufferForUint32", "n", "arrBuf", "buf", "bufferForUint64", "dv", "WalletAccountMergeFlags", "SignaturePurposeBuilder", "purposeNum", "bytes", "payloadLen", "c", "buf", "u8buf", "p", "dvbuf", "buildSigPS", "bigintToNaclArr", "x", "size", "byteArr", "arr", "bigintFromNaclArr", "rev", "bigint", "Edx25519", "revL", "L", "keyCreateFromSeed", "seed", "crypto_edx25519_private_key_create_from_seed", "keyCreate", "crypto_edx25519_private_key_create", "getPublic", "priv", "crypto_edx25519_get_public", "sign", "msg", "key", "deriveFactor", "pub", "kdfKw", "stringToBytes", "privateKeyDerive", "privDec", "a", "factorEnc", "factorModL", "aPrime", "bPrime", "hash", "typedArrayConcat", "publicKeyDerive", "factorReduced", "crypto_core_ed25519_scalar_reduce", "crypto_scalarmult_ed25519_noclamp", "invariant", "cond", "AgeRestriction", "hashCommitment", "ac", "hc", "HashState", "decodeCrock", "encodeCrock", "countAgeGroups", "mask", "count", "m", "getAgeGroupsFromMask", "groups", "age", "getAgeGroupIndex", "i", "ageGroupSpecToMask", "ageGroupSpec", "restrictionCommit", "ageMask", "numPubs", "numPrivs", "pubs", "privs", "PublishedAgeRestrictionBaseKey", "restrictionCommitSeeded", "privSeed", "bufferForUint32", "deriveSeed", "commitCompare", "c1", "c2", "salt", "k1", "k2", "commitmentDerive", "commitmentProof", "newPrivs", "newPubs", "oldPub", "oldPriv", "commitmentAttest", "d", "TalerSignaturePurpose", "group", "crypto_edx25519_sign_detached", "commitmentVerify", "commitment", "sig", "crypto_edx25519_sign_detached_verify", "ContractFormatTag", "foreverNum", "timestampRoundedToBuffer", "ts", "b", "v", "numVal", "arr", "bigint", "offset", "i", "HpkeRole", "HpkeMode", "makeBearerTokenAuthHeader", "token", "authHeaders", "auth", "credentials", "base64FromArrayBuffer", "stringToBytes", "addPaginationParams", "url", "pagination", "order", "limit", "addLongPollingParam", "param", "nullEvictor", "logger", "Logger", "CreditDebitIndicator", "codecForCanonBaseUrl", "x", "c", "canon", "canonicalizeBaseUrl", "DecodingError", "renderContext", "ScopeType", "TransactionAmountMode", "codecForConvertAmountRequest", "buildCodecForObject", "codecForAmountString", "codecForPaytoString", "codecForEither", "codecForConstString", "BalanceFlag", "CoinStatus", "ConfirmPayResultType", "codecForTalerErrorDetail", "buildCodecForObject", "codecForNumber", "codecOptional", "codecForAbsoluteTime", "codecForString", "PreparePayResultType", "InsufficientBalanceHint", "TokenAvailabilityHint", "RefreshReason", "ExchangeTosStatus", "ExchangeEntryStatus", "ExchangeUpdateStatus", "ExchangeWalletKycStatus", "ChoiceSelectionDetailType", "RecoveryMergeStrategy", "codecForEmptyObject", "buildCodecForObject", "FlightRecordEvent", "MerchantContractVersion", "MerchantContractInputType", "MerchantContractOutputType", "MerchantContractTokenKind", "codecForLocation", "buildCodecForObject", "codecOptional", "codecForString", "codecForList", "codecForMerchantInfo", "codecForMerchantContractTermsCommon", "codecForInternationalizedString", "codecForDuration", "codecForTimestamp", "codecForExchange", "codecForProductSold", "codecForAny", "codecForNumber", "codecForMerchantContractTermsV0", "codecForConstNumber", "MerchantContractVersion", "codecForAmountString", "codecForMerchantContractTermsV1", "codecForMerchantContractChoice", "codecForMap", "codecForMerchantContractTokenFamily", "codecForMerchantContractTerms", "buildCodecForUnion", "codecForMerchantContractInput", "codecForMerchantContractOutput", "MerchantContractInputType", "codecForMerchantContractInputToken", "codecForConstString", "MerchantContractOutputType", "codecForMerchantContractOutputToken", "codecForMerchantContractOutputTaxReceipt", "codecForTokenIssuePublicKey", "codecForMerchantContractTokenDetails", "codecForBoolean", "codecForTokenIssueRsaPublicKey", "codecForTokenIssueCsPublicKey", "MerchantContractTokenKind", "codecForMerchantContractSubscriptionTokenDetails", "codecForMerchantContractDiscountTokenDetails", "RoundingInterval", "KycStatusLongPollingReason", "LoginTokenScope", "MerchantAuthMethod", "MerchantAccountKycStatus", "MerchantAccountKycStatusSimplified", "TemplateType", "TokenFamilyKind", "StatisticBucketRange", "OrderInputType", "OrderOutputType", "OrderVersion", "codecForExchangeStatusResponse", "buildCodecForObject", "codecForList", "codecForExchangeStatusDetail", "codecForCanonBaseUrl", "codecForTimestamp", "codecOptional", "codecForNumber", "codecForString", "codecForExchangeConfigInfo", "codecForEddsaPublicKey", "codecForTalerMerchantConfigResponse", "codecForConstString", "codecOptionalDefault", "codecForEither", "codecForMap", "codecForCurrencySpecificiation", "codecForBoolean", "TanChannel", "codecForDuration", "codecForRoundingInterval", "RoundingInterval", "codecForClaimResponse", "codecForAny", "codecForEddsaSignature", "codecForPaymentResponse", "codecForPaymentDeniedLegallyResponse", "codecForStatusPaid", "codecForAmountString", "codecForStatusGoto", "codecForURLString", "codecForStatusStatusUnpaid", "codecForTalerUriString", "codecForPaidRefundStatusResponse", "codecForMerchantAbortPayRefundSuccessStatus", "codecForConstNumber", "codecForMerchantAbortPayRefundFailureStatus", "codecForMerchantAbortPayRefundUndepositedStatus", "codecForMerchantAbortPayRefundStatus", "buildCodecForUnion", "codecForAbortResponse", "codecForWalletRefundResponse", "codecForMerchantCoinRefundStatus", "codecForMerchantCoinRefundSuccessStatus", "codecForMerchantCoinRefundFailureStatus", "codecForMerchantAuthMethod", "MerchantAuthMethod", "codecForQueryInstancesResponse", "codecForLocation", "codecForAccountKycRedirects", "codecForMerchantAccountKycRedirect", "codecForMerchantAccountKycStatus", "MerchantAccountKycStatus", "codecForPaytoString", "codecForAccessToken", "codecForAccountLimit", "codecForTokenScope", "LoginTokenScope", "codecForLoginTokenSuccessResponse", "codecForAccountAddResponse", "buildCodecForObject", "codecForString", "codecForAccountsSummaryResponse", "codecForList", "codecForBankAccountEntry", "codecForPaytoString", "codecOptional", "codecForBoolean", "codecForBankAccountDetail", "codecForURLString", "codecForCategoryListResponse", "codecForCategoryListEntry", "codecForNumber", "codecForInternationalizedString", "codecForCategoryProductList", "codecForProductSummary", "codecForInventorySummaryResponse", "codecForInventoryEntry", "codecForMerchantPosProductDetail", "codecForAmountString", "codecForTax", "codecForMerchantCategory", "codecForFullInventoryDetailsResponse", "codecForProductDetailResponse", "codecForLocation", "codecForTimestamp", "codecForPostOrderResponse", "codecForOutOfStockResponse", "codecForOrderHistory", "codecForOrderHistoryEntry", "codecForExchange", "buildCodecForObject", "codecForEddsaPublicKey", "codecForNumber", "codecForString", "codecOptional", "codecForAmountString", "codecForOrderChoice", "buildCodecForObject", "codecForAmountString", "codecOptional", "codecForString", "codecForInternationalizedString", "codecForList", "codecForOrderInput", "codecForOrderOutput", "buildCodecForUnion", "OrderInputType", "codecForOrderInputToken", "codecForConstString", "codecForNumber", "OrderOutputType", "codecForOrderOutputToken", "codecForOrderOutputTaxReceipt", "codecForPreciseTimestamp", "codecForStringURL", "codecForProductSold", "codecForTax", "codecForTimestamp", "codecForCheckPaymentPaidResponse", "codecForBoolean", "codecForMerchantContractTerms", "codecForTransactionWireReport", "codecForTransactionWireTransfer", "codecForRefundDetails", "codecForURLString", "codecForCheckPaymentUnpaidResponse", "codecForTalerUriString", "codecForCheckPaymentClaimedResponse", "codecForMerchantOrderPrivateStatusResponse", "codecForGetSessionStatusPaidResponse", "codecForRefundDetails", "buildCodecForObject", "codecForString", "codecForBoolean", "codecForTimestamp", "codecForAmountString", "codecForTransactionWireTransfer", "codecForURLString", "codecOptional", "codecForNumber", "codecForTransactionWireReport", "codecForEddsaPublicKey", "codecForMerchantRefundResponse", "codecForTalerUriString", "codecForTansferList", "codecForList", "codecForTransferDetails", "codecForExpectedTansferList", "codecForExpectedTransferEntry", "codecForExchangeTransferReconciliationDetails", "codecForExpectedTransferDetails", "codecForPaytoString", "codecForAny", "codecForOtpDeviceSummaryResponse", "codecForOtpDeviceEntry", "codecForOtpDeviceDetails", "codecForTemplateSummaryResponse", "codecForTemplateEntry", "codecForTemplateDetails", "codecForTemplateContractDetails", "codecForTemplateContractDetailsDefaults", "codecForTemplateContractPaivana", "codecForOrderChoice", "codecForDuration", "codecForConstString", "TemplateType", "codecForTemplateContractInventoryCart", "codecOptionalDefault", "codecForTemplateContractFixedOrder", "buildCodecForUnion", "codecForWalletTemplateDetails", "codecForWebhookSummaryResponse", "codecForWebhookEntry", "codecForWebhookDetails", "codecForTokenFamilyKind", "codecForEither", "TokenFamilyKind", "codecForTokenFamilyDetails", "codecForInternationalizedString", "codecForTokenFamiliesList", "codecForTokenFamilySummary", "codecForStatisticBucketRange", "StatisticBucketRange", "TanChannel", "codecForChallenge", "buildCodecForObject", "codecForString", "codecForEither", "codecForConstString", "codecForChallengeResponse", "codecForList", "codecForBoolean", "codecForChallengeRequestResponse", "codecOptional", "codecForTimestamp", "codecForReportAddedResponse", "buildCodecForObject", "codecForNumber", "codecForReportDetailResponse", "codecForString", "codecForDuration", "codecOptional", "codecForReportsSummaryResponse", "codecForList", "codecForReportEntry", "codecForGroupsSummaryResponse", "codecForGroupEntry", "codecForGroupAddedResponse", "codecForPotAddedResponse", "codecForPotsSummaryResponse", "codecForPotEntry", "codecForAmountString", "codecForPotDetailResponse", "logger", "Logger", "ContractTermsUtil", "forgetAllImpl", "anyJson", "path", "pred", "dup", "i", "x", "membValCanon", "stringToBytes", "canonicalJson", "scrub", "membSalt", "h", "kdf", "encodeCrock", "forgetAll", "saltForgettable", "k", "getRandomBytes", "nameRegex", "validateForgettable", "fga", "fk", "fgo", "fv", "decodeCrock", "validateNothingForgotten", "contractTerms", "validateParsed", "MerchantContractVersion", "regex", "slug", "family", "domains", "MerchantContractTokenKind", "assertUnreachable", "domain", "hashContractTerms", "cleaned", "canon", "bytes", "hash", "extractAmounts", "choiceIndex", "amountRaw", "maxFee", "getV0CompatChoiceIndex", "terms", "firstGood", "downgradeContractTerms", "fnutil", "all", "arr", "f", "x", "any", "HttpStatusCode", "codecForCashoutConversionResponse", "buildCodecForObject", "codecForAmountString", "codecForCashinConversionResponse", "codecForConversionRate", "codecForDecimalNumber", "codecForEither", "codecForConstString", "codecForConversionBankConfig", "codecForString", "codecForCurrencySpecificiation", "TalerBankConversionCacheEviction", "TalerBankConversionHttpClient", "_TalerBankConversionHttpClient", "baseUrl", "httpClient", "cacheEvictor", "createPlatformHttpLib", "nullEvictor", "version", "LibtoolVersion", "url", "resp", "HttpStatusCode", "carefullyParseConfig", "codecForConversionBankConfig", "opKnownHttpFailure", "opUnknownHttpFailure", "auth", "authHeaders", "opSuccessFromHttp", "codecForConversionRate", "conversion", "Amounts", "codecForCashinConversionResponse", "body", "details", "codecForTalerErrorDetail", "TalerErrorCode", "opKnownTalerFailure", "codecForCashoutConversionResponse", "opEmptySuccess", "types_taler_corebank_exports", "__export", "MonitorTimeframeParam", "codecForAccountData", "codecForAccountMinimalData", "codecForBankAccountCreateWithdrawalResponse", "codecForBankAccountTransactionInfo", "codecForBankAccountTransactionsResponse", "codecForCashoutInfo", "codecForCashoutPending", "codecForCashoutStatusResponse", "codecForCashouts", "codecForChallengeContactData", "codecForConversionRateClass", "codecForConversionRateClassResponse", "codecForConversionRateClasses", "codecForConversionRatesResponse", "codecForCoreBankConfig", "codecForCreateTransactionResponse", "codecForGlobalCashoutInfo", "codecForGlobalCashouts", "codecForIntegrationBankConfig", "codecForListBankAccountsResponse", "codecForMonitorNoConversion", "codecForMonitorResponse", "codecForMonitorWithCashout", "codecForPublicAccountsResponse", "codecForRegisterAccountResponse", "codecForWithdrawalPublicInfo", "codecForTalerUriString", "x", "c", "DecodingError", "renderContext", "parseTalerUri", "TALER_PREFIX", "TALER_HTTP_PREFIX", "TalerUriParseError", "TalerUris", "supported_targets", "createTalerPay", "merchantBaseUrl", "orderId", "sessionId", "opts", "TalerUriAction", "createTalerWithdraw", "bankIntegrationApiBaseUrl", "withdrawalOperationId", "createTalerRefund", "createTalerPayPull", "exchangeBaseUrl", "contractPriv", "createTalerPayPush", "createTalerPayTemplate", "templateId", "createTalerRestore", "walletRootPriv", "providers", "createTalerDevExperiment", "devExperimentId", "query", "createTalerWithdrawExchange", "createTalerAddExchange", "createTalerAddContact", "aliasType", "alias", "mailboxUri", "mailboxIdentity", "sourceBaseUrl", "createTalerWithdrawalTransferResult", "ref", "asHost", "s", "b", "URL", "getTalerParamList", "p", "result", "assertUnreachable", "getTalerPrefix", "getTalerPath", "d", "toString", "prefix", "path", "paramList", "url", "createSearchParams", "fromString", "isHttp", "prefixCheck", "Result", "scheme", "search", "firstSlashPos", "uriTypeUncased", "uriType", "targetPath", "params", "URLSearchParams", "v", "k", "cs", "merchant", "Paytos", "bank", "operationId", "externalConfirmation", "exchange", "walletPriv", "name", "withoutScheme", "thisScheme", "hostname", "host", "experimentId", "amountRes", "Amounts", "amount", "status", "mailboxBaseUri", "parseWithdrawUriWithError", "pi", "parseProtoInfoWithError", "q", "parts", "TalerErrorCode", "pathSegments", "withdrawId", "parseWithdrawUri", "r", "parseAddExchangeUriWithError", "parseAddContactUriWithError", "lastPart", "mailboxHostPort", "parseAddExchangeUri", "parseAddContactUri", "parseProtoInfo", "action", "pfxPlain", "pfxHttp", "parsers", "parsePayUri", "parsePayPullUri", "parsePayPushUri", "parsePayTemplateUri", "parseRestoreUri", "parseRefundUri", "parseDevExperimentUri", "parseWithdrawExchangeUri", "string", "https", "http", "actionStart", "actionEnd", "found", "stringifyTalerUri", "uri", "stringifyDevExperimentUri", "stringifyPayUri", "stringifyPayPullUri", "stringifyPayPushUri", "stringifyPayTemplateUri", "stringifyRestoreUri", "stringifyRefundUri", "stringifyWithdrawUri", "stringifyWithdrawExchange", "stringifyAddExchange", "stringifyAddContact", "claimToken", "noncePriv", "uriString", "hostAndSegments", "proto", "getUrlInfo", "list", "baseUri", "fulfillmentUrl", "getUrlInfo", "baseUrl", "params", "url", "URL", "proto", "path", "qp", "URLSearchParams", "withParams", "name", "value", "query", "encodeRFC3986URIComponent", "str", "c", "rfc3986", "createSearchParams", "paramList", "key", "MonitorTimeframeParam", "codecForIntegrationBankConfig", "buildCodecForObject", "codecForConstString", "codecForString", "codecForCurrencySpecificiation", "codecOptional", "codecForCoreBankConfig", "codecForEither", "codecForBoolean", "codecForAmountString", "codecForList", "TanChannel", "codecOptionalDefault", "codecForBalance", "codecForPublicAccount", "codecForPaytoString", "codecForNumber", "codecForPublicAccountsResponse", "codecForAccountMinimalData", "codecForConversionRate", "codecForListBankAccountsResponse", "codecForAccountData", "codecForChallengeContactData", "codecForConversionRateClassResponse", "codecForConversionRateClass", "codecForDecimalNumber", "codecForConversionRateClasses", "codecForWithdrawalPublicInfo", "codecForBankAccountTransactionsResponse", "codecForBankAccountTransactionInfo", "codecForTimestamp", "codecForCreateTransactionResponse", "codecForRegisterAccountResponse", "codecForBankAccountCreateWithdrawalResponse", "codecForTalerUriString", "codecForCashoutPending", "codecForCashouts", "codecForCashoutInfo", "codecForGlobalCashouts", "codecForGlobalCashoutInfo", "codecForCashoutStatusResponse", "codecForConversionRatesResponse", "codecForMonitorResponse", "buildCodecForUnion", "codecForMonitorNoConversion", "codecForMonitorWithCashout", "logger", "Logger", "TalerCoreBankCacheEviction", "TalerCoreBankHttpClient", "_TalerCoreBankHttpClient", "baseUrl", "httpClient", "cacheEvictor", "createPlatformHttpLib", "nullEvictor", "version", "LibtoolVersion", "username", "auth", "body", "params", "url", "headers", "authHeaders", "resp", "HttpStatusCode", "opSuccessFromHttp", "codecForTokenSuccessResponse", "opKnownAlternativeHttpFailure", "codecForChallengeResponse", "opKnownHttpFailure", "details", "readTalerErrorResponse", "TalerErrorCode", "opKnownTalerFailure", "opUnknownHttpFailure", "password", "user", "token", "makeBearerTokenAuthHeader", "opEmptySuccess", "pagination", "addPaginationParams", "codecForTokenInfoList", "opFixedSuccess", "carefullyParseConfig", "codecForCoreBankConfig", "codecForRegisterAccountResponse", "filter", "codecForPublicAccountsResponse", "codecForListBankAccountsResponse", "codecForAccountData", "addLongPollingParam", "codecForBankAccountTransactionsResponse", "txid", "codecForBankAccountTransactionInfo", "codecForCreateTransactionResponse", "codecForBankAccountCreateWithdrawalResponse", "wid", "codecForWithdrawalPublicInfo", "codecForCashoutPending", "cid", "codecForCashoutStatusResponse", "codecForCashouts", "codecForGlobalCashouts", "codecForConversionRateClassResponse", "codecForConversionRateClass", "codecForConversionRateClasses", "codecForChallengeRequestResponse", "MonitorTimeframeParam", "seconds", "AbsoluteTime", "codecForMonitorResponse", "classId", "codecForBankWithdrawalOperationStatus", "buildCodecForObject", "codecForEither", "codecForConstString", "codecOptional", "codecForCurrencyName", "codecForAmountString", "codecForPaytoString", "codecForURLString", "codecForList", "codecForString", "codecForBoolean", "codecForBankWithdrawalOperationPostResponse", "logger", "Logger", "TalerBankIntegrationHttpClient", "_TalerBankIntegrationHttpClient", "baseUrl", "httpClient", "createPlatformHttpLib", "version", "LibtoolVersion", "url", "resp", "HttpStatusCode", "carefullyParseConfig", "codecForIntegrationBankConfig", "opUnknownHttpFailure", "woid", "params", "addLongPollingParam", "opSuccessFromHttp", "codecForBankWithdrawalOperationStatus", "opKnownHttpFailure", "body", "codecForBankWithdrawalOperationPostResponse", "readTalerErrorResponse", "details", "codecForTalerErrorDetail", "TalerErrorCode", "opKnownTalerFailure", "opEmptySuccess", "codecForRevenueConfig", "buildCodecForObject", "codecForConstString", "codecForString", "codecOptional", "codecForRevenueIncomingHistory", "codecForPaytoString", "codecForList", "codecForRevenueIncomingBankTransaction", "codecForNumber", "codecForTimestamp", "codecForAmountString", "TalerRevenueHttpClient", "_TalerRevenueHttpClient", "baseUrl", "httpClient", "createPlatformHttpLib", "version", "LibtoolVersion", "auth", "url", "resp", "authHeaders", "HttpStatusCode", "carefullyParseConfig", "codecForRevenueConfig", "opKnownHttpFailure", "opUnknownHttpFailure", "params", "addPaginationParams", "addLongPollingParam", "opSuccessFromHttp", "codecForRevenueIncomingHistory", "opFixedSuccess", "codecForWireConfigResponse", "buildCodecForObject", "codecForString", "codecForConstString", "codecForBoolean", "codecForTransferResponse", "codecForNumber", "codecForTimestamp", "codecForIncomingHistory", "codecForPaytoString", "codecForList", "codecForIncomingBankTransaction", "buildCodecForUnion", "codecForIncomingReserveTransaction", "codecForIncomingKycAuthTransaction", "codecForIncomingWadTransaction", "codecForAmountString", "codecForEddsaPublicKey", "codecOptional", "codecForEddsaSignature", "codecForOutgoingHistory", "codecForOutgoingBankTransaction", "codecForAddIncomingResponse", "codecForBankWireTransferList", "codecForBankWireTransferListStatus", "codecForBankWireTransferListStatus", "buildCodecForObject", "codecForNumber", "codecForEither", "codecForConstString", "codecForAmountString", "codecForPaytoString", "codecForTimestamp", "TalerWireGatewayHttpClient", "_TalerWireGatewayHttpClient", "baseUrl", "options", "createPlatformHttpLib", "version", "LibtoolVersion", "url", "resp", "HttpStatusCode", "carefullyParseConfig", "codecForWireConfigResponse", "opKnownHttpFailure", "opUnknownHttpFailure", "req", "authHeaders", "opSuccessFromHttp", "codecForTransferResponse", "body", "readTalerErrorResponse", "details", "codecForTalerErrorDetail", "TalerErrorCode", "opKnownTalerFailure", "addPaginationParams", "codecForBankWireTransferList", "opFixedSuccess", "addLongPollingParam", "codecForIncomingHistory", "codecForOutgoingHistory", "codecForAddIncomingResponse", "codeForSubjectFormat", "codecForEither", "codecForConstString", "codecForPreparedTransferConfig", "buildCodecForObject", "codecForString", "codecOptional", "codecForList", "codecForTransferSubject", "buildCodecForUnion", "codecForSimpleSubject", "codecForUriSubject", "codecForSwissQrBillSubject", "buildCodecForObject", "codecForConstString", "codecForAmountString", "codecForString", "codecForStringURL", "codecForRegistrationResponse", "codecForList", "codecForTimestamp", "TalerPreparedTransferHttpClient", "_TalerPreparedTransferHttpClient", "baseUrl", "options", "createPlatformHttpLib", "version", "LibtoolVersion", "url", "resp", "HttpStatusCode", "carefullyParseConfig", "codecForPreparedTransferConfig", "opKnownHttpFailure", "opUnknownHttpFailure", "body", "opSuccessFromHttp", "codecForRegistrationResponse", "opEmptySuccess", "readTalerErrorResponse", "details", "codecForTalerErrorDetail", "TalerErrorCode", "opKnownTalerFailure", "codecForChallengerTermsOfServiceResponse", "buildCodecForObject", "codecForConstString", "codecForString", "codecOptional", "codecForMap", "codecForAny", "codecForEither", "codecForChallengeSetupResponse", "codecForChallengeStatus", "codecForBoolean", "codecForNumber", "codecForTimestamp", "codecForChallengeResponse", "buildCodecForUnion", "codecForChallengeRedirect", "codecForChallengeCreateResponse", "codecForChallengeInvalidPinResponse", "codecForChallengeSolveResponse", "codecForChallengerAuthResponse", "codecForChallengerInfoResponse", "ChallengerCacheEviction", "ChallengerHttpClient", "_ChallengerHttpClient", "baseUrl", "httpClient", "cacheEvictor", "createPlatformHttpLib", "nullEvictor", "version", "LibtoolVersion", "url", "resp", "HttpStatusCode", "carefullyParseConfig", "codecForChallengerTermsOfServiceResponse", "opKnownHttpFailure", "opUnknownHttpFailure", "clientId", "token", "body", "makeBearerTokenAuthHeader", "opSuccessFromHttp", "codecForChallengeSetupResponse", "nonce", "redirectUri", "state", "codecForChallengeStatus", "codecForChallengeResponse", "codecForChallengeSolveResponse", "opKnownAlternativeHttpFailure", "codecForChallengeInvalidPinResponse", "client_id", "redirect_uri", "client_secret", "code", "codecForChallengerAuthResponse", "codecForChallengerInfoResponse", "codecForDonauVersionResponse", "buildCodecForObject", "codecForString", "codecForConstString", "codecForDonationUnitKeyGroup", "codecForAny", "codecForDonauKeysResponse", "buildCodecForObject", "codecForString", "codecForList", "codecForIssuePrepareResponse", "buildCodecForUnion", "codecForDonauCharityResponse", "codecForNumber", "codecForDonauDonationStatementResponse", "codecForAmountString", "codecForEddsaPublicKey", "codecForEddsaSignature", "DonauHttpClient", "_DonauHttpClient", "baseUrl", "params", "createPlatformHttpLib", "version", "LibtoolVersion", "url", "resp", "HttpStatusCode", "opSuccessFromHttp", "codecForDonauKeysResponse", "opUnknownHttpFailure", "buffer", "uintar", "opFixedSuccess", "opKnownHttpFailure", "carefullyParseConfig", "codecForDonauVersionResponse", "body", "codecForIssuePrepareResponse", "opKnownFailure", "charityId", "codecForAny", "opEmptySuccess", "year", "hash", "codecForDonauDonationStatementResponse", "token", "makeBearerTokenAuthHeader", "id", "codecForDonauCharityResponse", "logger", "Logger", "TalerExchangeCacheEviction", "TalerExchangeHttpClient", "_TalerExchangeHttpClient", "baseUrl", "params", "createPlatformHttpLib", "nullEvictor", "CancellationToken", "LongpollQueue", "version", "LibtoolVersion", "url_or_path", "opts", "longpoll", "url", "timeoutMs", "resp", "HttpStatusCode", "buffer", "uintar", "opFixedSuccess", "opKnownHttpFailure", "opUnknownHttpFailure", "carefullyParseConfig", "codecForExchangeConfig", "opSuccessFromHttp", "codecForExchangeKeysResponse", "pursePub", "codecForExchangePurseStatus", "body", "codecForPurseCreateSuccessResponse", "opKnownAlternativeHttpFailure", "codecForPurseConflict", "purseSig", "opEmptySuccess", "codecForExchangeMergeSuccessResponse", "codecForLegitimizationNeededResponse", "codecForExchangeMergeConflictResponse", "codecForPurseConflictPartial", "details", "readTalerErrorResponse", "TalerErrorCode", "opKnownTalerFailure", "codecForExchangeGetContractResponse", "codecForAny", "codecForAmlWalletKycCheckResponse", "args", "paytoHash", "accountPub", "accountSig", "awaitAuth", "codecForAccountKycStatus", "opKnownFailureWithBody", "token", "known", "d", "codecForKycProcessClientInformation", "codecForEmptyObject", "etag", "addLongPollingParam", "etagRaw", "readSuccessResponseJsonOrThrow", "opKnownFailure", "requirement", "codecForKycProcessStartInformation", "provider", "state", "code", "auth", "encodeCrock", "signAmlQuery", "codecForAvailableMeasureSummary", "names", "filter", "codecForAmlStatisticsResponse", "name", "addPaginationParams", "codecForAmlDecisionsAccounts", "mime", "codecForAmlDecisionsResponse", "officer", "codecForLegitimizationMeasuresList", "account", "codecForAmlKycAttributes", "decision", "signAmlDecision", "Amounts", "codecForExchangeTransferList", "codecForExchangeWithdrawResponse", "codecForExchangeMeltResponse", "TalerMailboxInstanceHttpClient", "_TalerMailboxInstanceHttpClient", "baseUrl", "httpClient", "cancellationToken", "createPlatformHttpLib", "version", "LibtoolVersion", "url", "resp", "HttpStatusCode", "carefullyParseConfig", "codecForTalerMailboxConfigResponse", "opKnownHttpFailure", "opUnknownHttpFailure", "args", "hAddress", "body", "opEmptySuccess", "opKnownAlternativeHttpFailure", "codecForTalerMailboxRateLimitedResponse", "hMailbox", "uintar", "etag", "opFixedSuccess", "index", "mailboxConf", "count", "signature", "mailboxPubkeyString", "encodeCrock", "eddsaGetPublic", "decodeCrock", "opSuccessFromHttp", "codecForTalerMailboxMetadata", "codecForEmptyObject", "req", "TalerMerchantInstanceCacheEviction", "TalerMerchantManagementCacheEviction", "TalerMerchantInstanceHttpClient", "_TalerMerchantInstanceHttpClient", "baseUrl", "httpClient", "cacheEvictor", "cancellationToken", "createPlatformHttpLib", "nullEvictor", "version", "LibtoolVersion", "url", "resp", "HttpStatusCode", "carefullyParseConfig", "codecForTalerMerchantConfigResponse", "opKnownHttpFailure", "opUnknownHttpFailure", "opSuccessFromHttp", "codecForExchangeStatusResponse", "instance", "password", "body", "params", "headers", "authHeaders", "codecForLoginTokenSuccessResponse", "opKnownAlternativeHttpFailure", "codecForChallengeResponse", "token", "addPaginationParams", "makeBearerTokenAuthHeader", "codecForTokenInfoList", "opFixedSuccess", "serial", "opEmptySuccess", "args", "orderId", "codecForClaimResponse", "details", "codecForTalerErrorDetail", "TalerErrorCode", "opKnownTalerFailure", "codecForPaymentResponse", "codecForPaymentDeniedLegallyResponse", "codecForStatusPaid", "codecForStatusGoto", "codecForStatusStatusUnpaid", "sessionId", "fulfillmentUrl", "codecForGetSessionStatusPaidResponse", "codecForPaidRefundStatusResponse", "codecForAbortResponse", "codecForWalletRefundResponse", "codecForQueryInstancesResponse", "assertUnreachable", "etag", "f", "codecForAccountKycRedirects", "opKnownFailure", "opKnownFailureWithBody", "codecForAccountAddResponse", "wireAccount", "codecForAccountsSummaryResponse", "codecForBankAccountDetail", "codecForCategoryListResponse", "cId", "codecForCategoryProductList", "cid", "readTalerErrorResponse", "productId", "codecForInventorySummaryResponse", "codecForFullInventoryDetailsResponse", "codecForProductDetailResponse", "codecForPostOrderResponse", "codecForOutOfStockResponse", "AbsoluteTime", "time", "Duration", "codecForOrderHistory", "codecForMerchantOrderPrivateStatusResponse", "force", "codecForMerchantRefundResponse", "codecForTansferList", "codecForExpectedTansferList", "serial_wid", "codecForExpectedTransferDetails", "deviceId", "codecForOtpDeviceSummaryResponse", "codecForOtpDeviceDetails", "templateId", "codecForTemplateSummaryResponse", "codecForTemplateDetails", "codecForWalletTemplateDetails", "webhookId", "codecForWebhookSummaryResponse", "codecForWebhookDetails", "tokenSlug", "codecForTokenFamilyDetails", "codecForTokenFamiliesList", "codecForChallengeRequestResponse", "id", "codecForReportAddedResponse", "codecForReportsSummaryResponse", "codecForReportDetailResponse", "codecForPotAddedResponse", "codecForPotsSummaryResponse", "codecForPotDetailResponse", "codecForGroupAddedResponse", "codecForGroupsSummaryResponse", "jedLib", "logger", "Logger", "jed", "setupI18n", "lang", "strings", "toI18nString", "stringSeq", "s", "i", "singular", "values", "jed", "withContext", "ctx", "v", "translate", "translation", "replacePlaceholderWithValues", "Translate", "children", "debug", "c", "stringifyArray", "replacePlaceholderWithValues", "translation", "childArray", "tr", "placeholderChildren", "i", "x", "result", "childIdx", "stringifyArray", "children", "n", "c", "i18n", "singular", "withContext", "Translate", "translate", "openPromise", "resolve", "promiseReject", "promise", "res", "rej", "result", "saveLastError", "reason", "logger", "Logger", "PERMITS", "LongpollQueue", "url", "cancellationToken", "f", "hostname", "rid", "triggerNextLongpoll", "next", "doRunLongpoll", "numWaiting", "numConcurrent", "timeoutMs", "promcap", "openPromise", "NotificationType", "ObservabilityEventType", "logger", "Logger", "IntervalHandle", "h", "TimeoutHandle", "performanceNow", "performanceDelta", "start", "end", "SetTimeoutTimerAPI", "delayMs", "callback", "IntervalHandle", "TimeoutHandle", "timer", "seqId", "ObservableHttpClientLibrary", "impl", "oc", "id", "cancelator", "url", "opt", "CancellationToken", "AbsoluteTime", "ObservabilityEventType", "optsWithCancel", "start", "performanceNow", "res", "end", "event", "performanceDelta", "e", "getErrorDetailFromException", "PerformanceStatType", "PerformanceStat", "fromNotification", "evt", "ObservabilityEventType", "equals", "a", "b", "assertUnreachable", "MAX_PERFORMANCE_TABLE_SIZE", "PerformanceTable", "insertEvent", "tab", "stat", "insertOrIncrement", "sort", "rotate", "limit", "n", "limited", "k", "key", "index", "el", "existing", "type", "logger", "Logger", "MAX_PER_SECOND", "MAX_PER_MINUTE", "MAX_PER_HOUR", "OriginState", "AbsoluteTime", "now", "d", "RequestThrottler", "origin", "s", "requestUrl", "state", "ReserveTransactionType", "logger", "Logger", "TransactionMajorState", "TransactionMinorState", "TransactionAction", "TransactionType", "WithdrawalType", "DenomLossEventType", "PaymentStatus", "sampleWalletCoreTransactions", "TransactionType", "TransactionMajorState", "PaymentStatus", "RefreshReason", "codecForTalerMailboxConfigResponse", "buildCodecForObject", "codecForString", "codecForConstString", "codecForAmountString", "codecForNumber", "codecForDuration", "codecForTalerMailboxMetadata", "buildCodecForObject", "codecForEddsaPublicKey", "codecForConstString", "codecForString", "codecForTimestamp", "codecForTalerMailboxRateLimitedResponse", "codecForNumber", "codecForDuration", "TalerAmlProperties", "signAmlDecision", "priv", "decision", "builder", "buildSigPS", "TalerSignaturePurpose", "flags", "timestampRoundedToBuffer", "TalerProtocolTimestamp", "decodeCrock", "hash", "stringToBytes", "canonicalJson", "bufferForUint64", "sigBlob", "eddsaSign", "signAmlQuery", "key", "TOPS_AccountProperties", "TalerAmlProperties", "GLS_AccountProperties", "KnownForms", "TOPS_AmlEventsName", "GLS_AmlEventsName", "KnownForms", "topsEventNames", "TOPS_AmlEventsName", "EventReporting_TOPS_queries", "TOPS_AmlEventsName", "AbsoluteTime", "Duration", "loadBrowserPrng", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_compat_module", "init_preact_module", "init_preact_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_hooks_module", "init_hooks_module", "init_hooks_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "init_preact_module", "init_preact_module", "init_preact_module", "init_hooks_module", "init_hooks_module", "require_qrcode", "__commonJS", "exports", "module", "qrcode", "typeNumber", "errorCorrectionLevel", "PAD0", "PAD1", "_typeNumber", "_errorCorrectionLevel", "QRErrorCorrectionLevel", "_modules", "_moduleCount", "_dataCache", "_dataList", "_this", "makeImpl", "test", "maskPattern", "moduleCount", "modules", "row", "col", "setupPositionProbePattern", "setupPositionAdjustPattern", "setupTimingPattern", "setupTypeInfo", "setupTypeNumber", "createData", "mapData", "r", "c", "getBestMaskPattern", "minLostPoint", "pattern", "i", "lostPoint", "QRUtil", "pos", "j", "bits", "mod", "data", "inc", "bitIndex", "byteIndex", "maskFunc", "dark", "mask", "createBytes", "buffer", "rsBlocks", "offset", "maxDcCount", "maxEcCount", "dcdata", "ecdata", "dcCount", "ecCount", "rsPoly", "rawPoly", "qrPolynomial", "modPoly", "modIndex", "totalCodeCount", "index", "dataList", "QRRSBlock", "qrBitBuffer", "totalDataCount", "mode", "newData", "qrNumber", "qrAlphaNum", "qr8BitByte", "qrKanji", "cellSize", "margin", "qrHtml", "alt", "title", "opts", "size", "mc", "mr", "qrSvg", "rect", "escapeXml", "min", "max", "createDataURL", "x", "y", "img", "s", "escaped", "_createHalfASCII", "r1", "r2", "p", "blocks", "blocksLastLineNoMargin", "ascii", "white", "black", "line", "context", "length", "bytes", "unicodeData", "numChars", "unicodeMap", "bin", "base64DecodeInputStream", "read", "b", "count", "b0", "b1", "b2", "b3", "k", "v", "unknownChar", "QRMode", "QRMaskPattern", "PATTERN_POSITION_TABLE", "G15", "G18", "G15_MASK", "getBCHDigit", "digit", "d", "errorCorrectLength", "a", "QRMath", "type", "sameCount", "darkCount", "ratio", "EXP_TABLE", "LOG_TABLE", "n", "num", "shift", "_num", "e", "RS_BLOCK_TABLE", "qrRSBlock", "totalCount", "dataCount", "getRsBlockTable", "rsBlock", "list", "_buffer", "_length", "bufIndex", "bit", "_mode", "_data", "strToNum", "chatToNum", "getCode", "_bytes", "stringToBytes", "code", "byteArrayOutputStream", "off", "len", "base64EncodeOutputStream", "_buflen", "_base64", "writeEncoded", "encode", "padlen", "str", "_str", "_pos", "decode", "gifImage", "width", "height", "_width", "_height", "pixel", "out", "lzwMinCodeSize", "raster", "getLZWRaster", "bitOutputStream", "_out", "_bitLength", "_bitBuffer", "clearCode", "endCode", "bitLength", "table", "lzwTable", "byteOut", "bitOut", "dataIndex", "_map", "_size", "key", "getPixel", "gif", "base64", "toUTF8Array", "utf8", "charcode", "factory", "utils_exports", "__export", "compose", "composeRef", "doAutoFocus", "doAutoFocusWithScroll", "onComponentUnload", "preconnectAs", "recursive", "saveRef", "saveVNodeForInspection", "hook", "viewMap", "withHook", "stateHook", "ComposedComponent", "state", "subComponent", "h", "statusName", "viewComponent", "callback", "ref", "_", "ownerDocument", "preconnectsSet", "pre", "rel", "href", "crossOrigin", "instance", "fn", "element", "handler", "obj", "inspect", "componentName", "stateList", "value", "args", "contextId", "effectName", "children", "Attention", "onClose", "timeout", "Duration", "assertUnreachable", "CopyIcon", "CopiedIcon", "CopyButton", "clazz", "getContent", "copied", "setCopied", "copyText", "useEffect", "DebugInfo", "error", "i18n", "useTranslationContext", "showDebugInfo", "update", "useCommonPreferences", "ErrorLoading", "TalerErrorCode", "requestMethod", "requestUrl", "timeoutMs", "throttleStats", "httpStatusCode", "validationError", "errorResponse", "names", "getLangName", "LangSelector", "lang", "changeLanguage", "completeness", "supportedLang", "hidden", "setHidden", "useState", "bodyKeyPress", "event", "bodyOnClick", "lang_default", "Fragment", "l", "Loading", "Spinner", "Header", "profileURL", "notificationURL", "iconLinkURL", "sites", "onLogout", "open", "setOpen", "ns", "useNotifications", "taler_logo_white_default", "site", "name", "url", "Footer", "testingUrlKey", "VERSION", "GIT_HASH", "testingUrl", "versionText", "ButtonBetter", "children", "focus", "onClick", "disabled", "rest", "running", "setRunning", "useState", "h", "doAutoFocus", "e", "Wait", "Wait", "h", "Fragment", "ShowInputErrorLabel", "isDirty", "message", "LocalNotificationBanner", "notification", "i18n", "useTranslationContext", "showDebugInfo", "useCommonPreferences", "moreInfo", "setMoreInfo", "useState", "desc", "Attention", "d", "ToastBanner", "debug", "notifs", "useNotifications", "h", "Fragment", "show", "e", "AttentionByType", "msg", "Attention", "Duration", "GLOBAL_NOTIFICATION_TIMEOUT", "toInteger", "dirtyNumber", "number", "requiredArgs", "required", "args", "_typeof", "obj", "toDate", "argument", "argStr", "addDays", "dirtyDate", "dirtyAmount", "date", "amount", "addMonths", "dayOfMonth", "endOfDesiredMonth", "daysInMonth", "add", "duration", "years", "months", "weeks", "days", "hours", "minutes", "seconds", "dateWithMonths", "dateWithDays", "minutesToAdd", "secondsToAdd", "msToAdd", "finalDate", "addMilliseconds", "timestamp", "defaultOptions", "getDefaultOptions", "getTimezoneOffsetInMilliseconds", "date", "utcDate", "startOfDay", "dirtyDate", "requiredArgs", "toDate", "MILLISECONDS_IN_DAY", "differenceInCalendarDays", "dirtyDateLeft", "dirtyDateRight", "startOfDayLeft", "startOfDayRight", "timestampLeft", "timestampRight", "compareAsc", "dateLeft", "dateRight", "diff", "daysInYear", "maxTime", "millisecondsInMinute", "millisecondsInHour", "millisecondsInSecond", "minTime", "secondsInHour", "secondsInDay", "secondsInWeek", "secondsInYear", "secondsInMonth", "secondsInQuarter", "_typeof", "obj", "isDate", "value", "requiredArgs", "isValid", "dirtyDate", "date", "toDate", "differenceInCalendarMonths", "dirtyDateLeft", "dirtyDateRight", "dateLeft", "dateRight", "yearDiff", "monthDiff", "differenceInCalendarYears", "compareLocalAsc", "diff", "differenceInDays", "sign", "difference", "differenceInCalendarDays", "isLastDayNotFull", "result", "differenceInMilliseconds", "roundingMap", "defaultRoundingMethod", "getRoundingMethod", "method", "differenceInHours", "options", "millisecondsInHour", "differenceInMinutes", "millisecondsInMinute", "endOfDay", "endOfMonth", "month", "isLastDayOfMonth", "differenceInMonths", "compareAsc", "isLastMonthNotFull", "differenceInSeconds", "differenceInYears", "isLastYearNotFull", "subMilliseconds", "dirtyDate", "dirtyAmount", "requiredArgs", "amount", "toInteger", "addMilliseconds", "MILLISECONDS_IN_DAY", "getUTCDayOfYear", "date", "toDate", "timestamp", "startOfYearTimestamp", "difference", "startOfUTCISOWeek", "weekStartsOn", "day", "diff", "getUTCISOWeekYear", "year", "fourthOfJanuaryOfNextYear", "startOfNextYear", "fourthOfJanuaryOfThisYear", "startOfThisYear", "startOfUTCISOWeekYear", "fourthOfJanuary", "MILLISECONDS_IN_WEEK", "getUTCISOWeek", "startOfUTCWeek", "options", "_ref", "_ref2", "_ref3", "_options$weekStartsOn", "_options$locale", "_options$locale$optio", "_defaultOptions$local", "_defaultOptions$local2", "defaultOptions", "getDefaultOptions", "getUTCWeekYear", "_options$firstWeekCon", "firstWeekContainsDate", "firstWeekOfNextYear", "firstWeekOfThisYear", "startOfUTCWeekYear", "firstWeek", "getUTCWeek", "addLeadingZeros", "number", "targetLength", "sign", "output", "formatters", "token", "signedYear", "month", "dayPeriodEnumValue", "numberOfDigits", "milliseconds", "fractionalSeconds", "lightFormatters_default", "dayPeriodEnum", "localize", "era", "signedWeekYear", "weekYear", "twoDigitYear", "isoWeekYear", "quarter", "week", "isoWeek", "dayOfYear", "dayOfWeek", "localDayOfWeek", "isoDayOfWeek", "hours", "_localize", "originalDate", "timezoneOffset", "formatTimezoneWithOptionalMinutes", "formatTimezone", "formatTimezoneShort", "offset", "dirtyDelimiter", "absOffset", "minutes", "delimiter", "formatters_default", "dateLongFormatter", "pattern", "formatLong", "timeLongFormatter", "dateTimeLongFormatter", "matchResult", "datePattern", "timePattern", "dateTimeFormat", "longFormatters", "longFormatters_default", "protectedDayOfYearTokens", "protectedWeekYearTokens", "isProtectedDayOfYearToken", "isProtectedWeekYearToken", "throwProtectedError", "format", "input", "formatDistanceLocale", "formatDistance", "count", "result", "tokenValue", "formatDistance_default", "buildFormatLongFn", "args", "width", "dateFormats", "timeFormats", "dateTimeFormats", "formatLong_default", "formatRelativeLocale", "formatRelative", "_date", "_baseDate", "_options", "formatRelative_default", "buildLocalizeFn", "dirtyIndex", "context", "valuesArray", "defaultWidth", "_defaultWidth", "_width", "index", "eraValues", "quarterValues", "monthValues", "dayValues", "dayPeriodValues", "formattingDayPeriodValues", "ordinalNumber", "dirtyNumber", "rem100", "localize_default", "buildMatchFn", "string", "matchPattern", "matchedString", "parsePatterns", "key", "findIndex", "findKey", "value", "rest", "object", "predicate", "array", "buildMatchPatternFn", "parseResult", "matchOrdinalNumberPattern", "parseOrdinalNumberPattern", "matchEraPatterns", "parseEraPatterns", "matchQuarterPatterns", "parseQuarterPatterns", "matchMonthPatterns", "parseMonthPatterns", "matchDayPatterns", "parseDayPatterns", "matchDayPeriodPatterns", "parseDayPeriodPatterns", "match", "match_default", "locale", "en_US_default", "defaultLocale_default", "formattingTokensRegExp", "longFormattingTokensRegExp", "escapedStringRegExp", "doubleQuoteRegExp", "unescapedLatinCharacterRegExp", "dirtyFormatStr", "_ref4", "_options$locale2", "_options$locale2$opti", "_ref5", "_ref6", "_ref7", "_options$locale3", "_options$locale3$opti", "_defaultOptions$local3", "_defaultOptions$local4", "formatStr", "isValid", "getTimezoneOffsetInMilliseconds", "utcDate", "formatterOptions", "substring", "firstCharacter", "longFormatter", "cleanEscapedString", "formatter", "matched", "defaultFormat", "formatDuration", "duration", "options", "_ref", "_options$locale", "_options$format", "_options$zero", "_options$delimiter", "defaultOptions", "getDefaultOptions", "locale", "defaultLocale_default", "format", "zero", "delimiter", "result", "acc", "unit", "token", "m", "value", "formatISO", "date", "_options$representati", "requiredArgs", "originalDate", "toDate", "representation", "tzOffset", "dateDelimiter", "timeDelimiter", "day", "addLeadingZeros", "month", "year", "offset", "absoluteOffset", "hourOffset", "minuteOffset", "sign", "hour", "minute", "second", "separator", "time", "getMonth", "dirtyDate", "requiredArgs", "date", "toDate", "month", "getYear", "dirtyDate", "requiredArgs", "toDate", "intervalToDuration", "interval", "start", "end", "duration", "differenceInYears", "sign", "compareAsc", "remainingMonths", "add", "differenceInMonths", "remainingDays", "differenceInDays", "remainingHours", "differenceInHours", "remainingMinutes", "differenceInMinutes", "remainingSeconds", "differenceInSeconds", "_typeof", "obj", "_inherits", "subClass", "superClass", "_setPrototypeOf", "o", "p", "_createSuper", "Derived", "hasNativeReflectConstruct", "_isNativeReflectConstruct", "Super", "_getPrototypeOf", "result", "NewTarget", "_possibleConstructorReturn", "self", "call", "_assertThisInitialized", "_classCallCheck", "instance", "Constructor", "_defineProperties", "target", "props", "i", "descriptor", "_createClass", "protoProps", "staticProps", "_defineProperty", "key", "value", "Setter", "_classCallCheck", "_defineProperty", "_createClass", "_utcDate", "_options", "ValueSetter", "_Setter", "_inherits", "_super", "_createSuper", "value", "validateValue", "setValue", "priority", "subPriority", "_this", "utcDate", "options", "flags", "_classCallCheck", "instance", "Constructor", "_defineProperties", "target", "props", "i", "descriptor", "_createClass", "protoProps", "staticProps", "Parser", "dateString", "token", "match", "options", "result", "ValueSetter", "_utcDate", "_value", "_options", "_typeof", "obj", "_inherits", "subClass", "superClass", "_setPrototypeOf", "o", "p", "_createSuper", "Derived", "hasNativeReflectConstruct", "_isNativeReflectConstruct", "Super", "_getPrototypeOf", "NewTarget", "_possibleConstructorReturn", "self", "call", "_assertThisInitialized", "_defineProperty", "key", "value", "EraParser", "_Parser", "_super", "_this", "_len", "args", "_key", "date", "flags", "numericPatterns", "timezonePatterns", "mapValue", "parseFnResult", "mapFn", "parseNumericPattern", "pattern", "matchResult", "parseTimezonePattern", "sign", "hours", "minutes", "seconds", "millisecondsInHour", "millisecondsInMinute", "millisecondsInSecond", "parseAnyDigitsSigned", "parseNDigits", "n", "parseNDigitsSigned", "dayPeriodEnumToHours", "dayPeriod", "normalizeTwoDigitYear", "twoDigitYear", "currentYear", "isCommonEra", "absCurrentYear", "rangeEnd", "rangeEndCentury", "isPreviousCentury", "isLeapYearIndex", "year", "YearParser", "valueCallback", "_date", "normalizedTwoDigitYear", "LocalWeekYearParser", "getUTCWeekYear", "startOfUTCWeek", "ISOWeekYearParser", "_flags", "firstWeekOfYear", "startOfUTCISOWeek", "ExtendedYearParser", "QuarterParser", "StandAloneQuarterParser", "MonthParser", "StandAloneMonthParser", "setUTCWeek", "dirtyDate", "dirtyWeek", "requiredArgs", "toDate", "week", "toInteger", "diff", "getUTCWeek", "LocalWeekParser", "setUTCISOWeek", "dirtyISOWeek", "isoWeek", "getUTCISOWeek", "ISOWeekParser", "DAYS_IN_MONTH", "DAYS_IN_MONTH_LEAP_YEAR", "DateParser", "isLeapYear", "month", "DayOfYearParser", "setUTCDay", "dirtyDay", "_ref", "_ref2", "_ref3", "_options$weekStartsOn", "_options$locale", "_options$locale$optio", "_defaultOptions$local", "_defaultOptions$local2", "defaultOptions", "getDefaultOptions", "weekStartsOn", "day", "currentDay", "remainder", "dayIndex", "DayParser", "LocalDayParser", "wholeWeekDays", "StandAloneLocalDayParser", "setUTCISODay", "ISODayParser", "AMPMParser", "AMPMMidnightParser", "DayPeriodParser", "Hour1to12Parser", "isPM", "Hour0to23Parser", "Hour0To11Parser", "Hour1To24Parser", "MinuteParser", "SecondParser", "FractionOfSecondParser", "ISOTimezoneWithZParser", "ISOTimezoneParser", "TimestampSecondsParser", "TimestampMillisecondsParser", "parsers", "Time", "timestamp", "relative", "formatString", "i18n", "dateLocale", "useTranslationContext", "h", "Fragment", "now", "AbsoluteTime", "diff", "Duration", "d", "intervalToDuration", "duration", "formatDuration", "formatISO", "format", "RenderAmount", "value", "spec", "specMap", "negative", "withColor", "withSign", "hideSmall", "neg", "currentSpec", "currency", "normal", "small", "Amounts", "import_qrcode_generator", "__toESM", "require_qrcode", "utf8Encoder", "utf8Decoder", "base64encode", "str", "base64EncArr", "strToUTF8Arr", "uint6ToB64", "nUint6", "aBytes", "nMod3", "sB64Enc", "nLen", "nUint24", "nIdx", "sDOMStr", "nChr", "nStrLen", "nArrLen", "nMapIdx", "nChrIdx", "defaultRequestHandler", "baseUrl", "endpoint", "options", "requestHeaders", "base64encode", "requestMethod", "requestBody", "requestTimeout", "requestParams", "requestPreventCache", "requestPreventCors", "validURL", "validateURL", "error", "RequestError", "key", "value", "payload", "controller", "timeoutId", "response", "ex", "info", "headerMap", "buildRequestOk", "dataTxt", "buildRequestFailed", "d", "url", "hasToken", "status", "maybeOptions", "data", "errorCode", "errorHint", "message", "Context", "B", "useAsync", "callback", "deps", "data", "setData", "useState", "error", "setError", "useEffect", "unloaded", "resp", "TalerError", "useLongPolling", "initial", "shouldRetryFn", "retryFn", "deps", "opts", "minTime", "result", "setResult", "useState", "useEffect", "ct", "useRef", "tk", "CancellationToken", "diff", "r", "error", "delayMs", "ms", "resolve", "reject", "undefinedIfEmpty", "obj", "k", "memoryMap", "backend", "obs", "theMemoryMap", "handler", "key", "result", "value", "localStorageMap", "theLocalStorageMap", "handleStorageEvent", "ev", "exists", "v", "index", "total", "item", "cb", "isFirefox", "getAllContent", "updateContent", "obj", "onBrowserStorageUpdate", "browserStorageMap", "content", "k", "changes", "changedItems", "buildStorageKey", "name", "codec", "codecForString", "supportLocalStorage", "supportBrowserStorage", "storage", "useLocalStorage", "defaultValue", "current", "convert", "_", "setStoredValue", "useState", "AbsoluteTime", "useEffect", "setValue", "updated", "e", "MIN_LANG_COVERAGE_THRESHOLD", "getBrowserLang", "completeness", "match", "code", "l", "max", "langPreferenceKey", "useLang", "initial", "useChallengeHandler", "state", "setState", "reset", "onChallengeRequired", "challenge", "repeat", "onChallengeRequiredWithInitial", "useMemoryStorage", "storedValue", "prev", "newValue", "NOTIFICATION_KEY", "GLOBAL_NOTIFICATION_TIMEOUT", "Duration", "updateInStorage", "n", "h", "hash", "mem", "newState", "notify", "notif", "notifyError", "title", "description", "debug", "notifyException", "ex", "notifyInfo", "useNotifications", "setLastUpdate", "message", "idx", "hashCode", "str", "chr", "i", "msg", "useLocalNotificationBetter", "save", "i18n", "useTranslationContext", "safeFunctionHandler", "opName", "doAction", "args", "buildSafeHandler", "a", "thiz", "newArgs", "r", "converter", "init", "d", "resp", "successWithTitle", "error", "failWithTitle", "assertUnreachable", "logBugForDevelopers", "onUnexpected", "fail", "rest", "describeErrorResponse", "errorResponse", "TalerErrorCode", "notUndefined", "t", "translateTalerError", "cause", "hint", "TalerError", "sanitizeFunctionArguments", "formatDistanceLocale", "formatDistance", "token", "count", "options", "tokenValue", "formatDistance_default", "dateFormats", "timeFormats", "dateTimeFormats", "formatLong", "buildFormatLongFn", "formatLong_default", "formatRelativeLocale", "formatRelative", "_date", "_baseDate", "_options", "formatRelative_default", "eraValues", "quarterValues", "monthValues", "formattingMonthValues", "dayValues", "dayPeriodValues", "formattingDayPeriodValues", "ordinalNumber", "dirtyNumber", "number", "localize", "buildLocalizeFn", "quarter", "localize_default", "matchOrdinalNumberPattern", "parseOrdinalNumberPattern", "matchEraPatterns", "parseEraPatterns", "matchQuarterPatterns", "parseQuarterPatterns", "matchMonthPatterns", "parseMonthPatterns", "matchDayPatterns", "parseDayPatterns", "matchDayPeriodPatterns", "parseDayPeriodPatterns", "buildMatchPatternFn", "buildMatchFn", "match_default", "locale", "de_default", "en_GB_default", "formatRelativeLocalePlural", "date", "es_default", "form", "unit", "feminineUnits", "suffix", "fr_default", "SUPPORTED_LANGS", "Context", "createContext", "TranslationProvider", "children", "forceLang", "source", "map", "lang", "changeLanguage", "setupI18n", "dateLocale", "useContext", "ActiviyTracker", "data", "observer", "func", "BankContext", "useBankCoreApiContext", "CONFIG_FAIL_TRY_AGAIN_MS", "BankApiProvider", "baseUrl", "frameOnError", "evictors", "checked", "setChecked", "getRemoteConfig", "VERSION", "lib", "cancelRequest", "onActivity", "buildBankApiClient", "keepRetrying", "testConfig", "config", "LibtoolVersion", "ErrorLoading", "url", "httpFetch", "BrowserFetchHttpLib", "tracker", "httpLib", "ObservableHttpClientLibrary", "bank", "TalerCoreBankHttpClient", "conversion", "TalerBankConversionHttpClient", "classId", "username", "ChallengerContext", "createContext", "MerchantContext", "createContext", "ExchangeContext", "createContext", "urlPattern", "pattern", "reverse", "url", "nullRountDef", "findMatch", "pagesMap", "pageList", "path", "params", "idx", "name", "found", "values", "key", "value", "Context", "createContext", "useNavigationContext", "useContext", "useCurrentLocation", "getPathAndParamsFromWindow", "initialPath", "initialParams", "PopStateEventType", "BrowserHashNavigationProvider", "children", "setState", "useState", "navigateTo", "useEffect", "eventListener", "h", "codecForPreferences", "buildCodecForObject", "codecOptionalDefault", "codecForBoolean", "COMMON_PREFERENCES_KEY", "buildStorageKey", "initial", "useCommonPreferences", "update", "useMemoryStorage", "updateField", "k", "v", "newValue", "createHeadMetaTag", "uri", "onNotFound", "meta", "stringifyTalerUri", "walletFound", "useTalerWalletIntegrationAPI", "TalerWalletIntegrationBrowserProvider", "THIS_MONTH", "getMonth", "THIS_YEAR", "getYear", "TODAY", "startOfDay", "noHandlerPropsAndNoContextForField", "field", "TooltipIcon", "h", "LabelWithTooltipMaybeRequired", "label", "required", "tooltip", "name", "Label", "WithTooltip", "RenderAddon", "disabled", "addon", "reverse", "InputWrapper", "children", "before", "after", "help", "error", "defaultToString", "v", "defaultFromString", "InputLine", "props", "placeholder", "converter", "type", "hidden", "input", "useRef", "value", "onChange", "noHandlerPropsAndNoContextForField", "fromString", "toString", "useEffect", "Fragment", "clazz", "showError", "composeRef", "saveRef", "e", "InputText", "props", "h", "InputLine", "InputToggle", "props", "label", "tooltip", "help", "required", "threeState", "disabled", "trueValue", "falseValue", "onlyTrueValue", "value", "onChange", "error", "noHandlerPropsAndNoContextForField", "dirty", "setDirty", "useState", "isOn", "h", "Fragment", "LabelWithTooltipMaybeRequired", "logger", "Logger", "compress", "alg", "buf", "cs", "writer", "retBuf", "BrowserFetchHttpLib", "args", "RequestThrottler", "requestUrl", "options", "requestMethod", "requestBody", "requestHeader", "requestTimeout", "Duration", "DEFAULT_REQUEST_TIMEOUT_MS", "requestCancel", "requestRedirect", "parsedUrl", "TalerError", "TalerErrorCode", "encodedBody", "encodeBody", "myBody", "requestHeadersMap", "getDefaultHeaders", "key", "value", "controller", "timeoutId", "reason", "response", "headerMap", "HeadersImpl", "text", "makeTextHandler", "json", "makeJsonHandler", "e", "firstTime", "respText", "error", "readTextHandler", "responseJson", "responseText", "message", "init_preact_module", "init_hooks_module", "init_compat_module", "import_shim", "init_compat_module", "SWRGlobalState", "EMPTY_CACHE", "INITIAL_CACHE", "noop", "UNDEFINED", "OBJECT", "isUndefined", "v", "isFunction", "mergeObjects", "a", "b", "STR_UNDEFINED", "isWindowDefined", "isDocumentDefined", "hasRequestAnimationFrame", "createCacheHelper", "cache", "key", "state", "info", "prev", "table", "counter", "stableHash", "arg", "type", "constructor", "isDate", "result", "index", "keys", "online", "isOnline", "onWindowEvent", "offWindowEvent", "isVisible", "visibilityState", "initFocus", "callback", "initReconnect", "onOnline", "onOffline", "preset", "defaultConfigOptions", "IS_REACT_LEGACY", "bn", "IS_SERVER", "rAF", "f", "useIsomorphicLayoutEffect", "h", "s", "navigatorConnection", "slowConnection", "serialize", "args", "__timestamp", "getTimestamp", "FOCUS_EVENT", "RECONNECT_EVENT", "MUTATE_EVENT", "constants", "internalMutate", "_key", "_data", "_opts", "options", "populateCache", "rollbackOnErrorOption", "optimisticData", "revalidate", "rollbackOnError", "error", "throwOnError", "keyFilter", "matchedKeys", "it", "keyIt", "mutateByKey", "_k", "get", "set", "EVENT_REVALIDATORS", "MUTATION", "FETCH", "revalidators", "startRevalidate", "data", "beforeMutationTs", "hasOptimisticData", "displayedData", "currentData", "committedData", "err", "res", "revalidateAllKeys", "initCache", "provider", "opts", "mutate", "unmount", "subscriptions", "subscribe", "subs", "setter", "value", "i", "initProvider", "releaseFocus", "releaseReconnect", "onErrorRetry", "_", "__", "config", "maxRetryCount", "currentRetryCount", "timeout", "compare", "newData", "defaultConfig", "mergeConfigs", "u1", "f1", "u2", "f2", "SWRConfigContext", "B", "SWRConfig", "props", "parentConfig", "q", "isFunctionalConfig", "F", "extendedConfig", "cacheContext", "p", "enableDevtools", "use", "setupDevTools", "normalize", "useSWRConfig", "middleware", "useSWRNext", "key_", "fetcher_", "config", "args", "key", "serialize", "PRELOAD", "SWRGlobalState", "cache", "req", "BUILT_IN_MIDDLEWARE", "use", "withArgs", "hook", "fallbackConfig", "useSWRConfig", "fn", "_config", "normalize", "mergeConfigs", "next", "i", "subscribeCallback", "key", "callbacks", "callback", "keyedRevalidators", "index", "setupDevTools", "WITH_DEDUPE", "useSWRHandler", "_key", "fetcher", "config", "cache", "compare", "suspense", "fallbackData", "revalidateOnMount", "revalidateIfStale", "refreshInterval", "refreshWhenHidden", "refreshWhenOffline", "keepPreviousData", "EVENT_REVALIDATORS", "MUTATION", "FETCH", "SWRGlobalState", "key", "fnArg", "serialize", "initialMountedRef", "_", "unmountedRef", "keyRef", "fetcherRef", "configRef", "getConfig", "isActive", "getCache", "setCache", "subscribeCache", "getInitialCache", "createCacheHelper", "stateDependencies", "fallback", "isUndefined", "isEqual", "prev", "current", "equal", "t", "returnedData", "getSnapshot", "F", "shouldStartRequest", "getSelectedCache", "state", "snapshot", "mergeObjects", "memorizedSnapshot", "memorizedInitialSnapshot", "newSnapshot", "cached", "T", "callback", "isInitialMount", "hasRevalidator", "cachedData", "data", "error", "laggyDataRef", "shouldDoInitialRevalidation", "defaultValidatingState", "isValidating", "isLoading", "revalidate", "revalidateOpts", "currentFetcher", "newData", "startAt", "loading", "opts", "shouldStartNewRequest", "callbackSafeguard", "IS_REACT_LEGACY", "finalState", "finishRequestAndUpdateState", "cleanupState", "requestInfo", "initialState", "getTimestamp", "UNDEFINED", "mutationInfo", "cacheData", "err", "currentConfig", "shouldRetryOnError", "isFunction", "boundMutate", "args", "internalMutate", "useIsomorphicLayoutEffect", "softRevalidate", "nextFocusRevalidatedAt", "unsubEvents", "subscribeCallback", "type", "constants", "now", "IS_SERVER", "rAF", "timer", "next", "interval", "execute", "x", "SWRConfig", "OBJECT", "defaultConfig", "useSWR", "withArgs", "useSWRHandler", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "undefinedIfEmpty", "obj", "k", "PAGINATED_LIST_SIZE", "PAGINATED_LIST_REQUEST", "COUNTRY_TABLE", "IBAN_REGEX", "validateIBAN", "account", "i18n", "A_code", "Z_code", "IBAN", "step2", "step3", "letter", "code", "calculate_iban_checksum", "str", "numberStr", "rest", "result", "USERNAME_REGEX", "validateTalerBank", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "SolveChallenge", "challenge", "onCancel", "onSolved", "username", "expiration", "i18n", "useTranslationContext", "tanCode", "setTanCode", "p", "api", "useBankCoreApiContext", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "showExpired", "setExpired", "AbsoluteTime", "errors", "undefinedIfEmpty", "h", "remain", "handler", "doVerification", "tan", "fail", "TalerErrorCode", "HttpStatusCode", "assertUnreachable", "LocalNotificationBanner", "c", "TanChannel", "e", "doAutoFocus", "ShowInputErrorLabel", "Time", "ButtonBetter", "SolveMFAChallenges", "currentChallenge", "description", "onCompleted", "solved", "setSolved", "selected", "setSelected", "retransmission", "setRetransmission", "total", "currentSolved", "challenge_id", "hasSolvedEnough", "sendMessage", "ch", "success", "complete", "selectChallenge", "opEmptySuccess", "time", "alreadySent", "noNeedToComplete", "doSelect", "doSend", "init_preact_module", "init_hooks_module", "init_hooks_module", "useSWR", "revalidateAccountDetails", "mutate", "key", "useAccountDetails", "account", "credentials", "useSessionState", "api", "useBankCoreApiContext", "fetcher", "username", "token", "data", "error", "useWithdrawalDetails", "wid", "api", "useBankCoreApiContext", "prev", "useAsync", "useLongPolling", "result", "TalerError", "status", "ct", "r", "revalidatePublicAccounts", "mutate", "key", "usePublicAccounts", "filterAccount", "initial", "offset", "setOffset", "p", "api", "useBankCoreApiContext", "fetcher", "account", "txid", "PAGINATED_LIST_REQUEST", "data", "error", "useSWR", "buildPaginatedResult", "d", "getId", "isLastPage", "isFirstPage", "result", "id", "revalidateTransactions", "useTransactions", "credentials", "useSessionState", "token", "username", "init_hooks_module", "useSWR", "revalidateConversionInfo", "mutate", "key", "useConversionInfo", "conversion", "config", "useBankCoreApiContext", "fetcher", "data", "error", "useConversionRateForUser", "username", "token", "conversionForUser", "buildEstimatorWithTheBackend", "estimation", "amount", "fee", "auth", "resp", "assertUnreachable", "credit", "Amounts", "debit", "beforeFee", "opFixedSuccess", "buildConversionEstimatorsWithTheBackend", "direction", "state", "useSessionState", "useCashinEstimator", "useCashoutEstimator", "useCashinEstimatorForClass", "classId", "conversionForClass", "useCashoutEstimatorForClass", "useCashoutEstimatorByUser", "username", "conversionForUser", "useBankCoreApiContext", "buildConversionEstimatorsWithTheBackend", "revalidateBusinessAccounts", "mutate", "key", "useBusinessAccounts", "credentials", "useSessionState", "token", "api", "offset", "setOffset", "p", "fetcher", "aid", "PAGINATED_LIST_REQUEST", "data", "error", "useSWR", "buildPaginatedResult", "d", "notUndefined", "c", "revalidateCashouts", "mutate", "key", "useCashouts", "account", "credentials", "useSessionState", "api", "config", "useBankCoreApiContext", "token", "fetcher", "username", "list", "cashouts", "c", "r", "notUndefined", "opFixedSuccess", "data", "error", "useSWR", "useCashoutDetails", "cashoutId", "credentials", "useSessionState", "creds", "api", "useBankCoreApiContext", "fetcher", "username", "token", "id", "data", "error", "useSWR", "useLastMonitorInfo", "currentMoment", "previousMoment", "timeframe", "api", "useBankCoreApiContext", "credentials", "useSessionState", "token", "fetcher", "current", "previous", "data", "error", "useSWR", "revalidateConversionRateClasses", "mutate", "key", "useConversionRateClasses", "offset", "setOffset", "p", "aid", "PAGINATED_LIST_REQUEST", "buildPaginatedResult", "d", "revalidateConversionRateClassDetails", "useConversionRateClassDetails", "classId", "username", "revalidateConversionRateClassUsers", "useConversionRateClassUsers", "RANDOM_STRING", "encodeCrock", "getRandomBytes", "CreateCashout", "accountName", "onCashout", "focus", "routeClose", "i18n", "useTranslationContext", "config", "useBankCoreApiContext", "h", "p", "Attention", "resultAccount", "useAccountDetails", "credentials", "useSessionState", "creds", "rateResp", "useConversionRateForUser", "conversionResp", "useConversionInfo", "TalerError", "ErrorLoading", "HttpStatusCode", "LoginForm", "assertUnreachable", "Loading", "CreateCashoutInternal", "accountData", "fiat_currency", "fiat_currency_specification", "regional_currency", "regional_currency_specification", "session", "rate", "calculateFromCredit", "calculateFromDebit", "useCashoutEstimatorByUser", "form", "setForm", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "mfa", "useChallengeHandler", "api", "regionalZero", "Amounts", "fiatZero", "account", "balanceLimit", "IntAmounts", "zeroCalc", "calculationResult", "setCalculation", "sellFee", "sellRate", "inputAmount", "higerThanMin", "notZero", "conversionCalculator", "isDebit", "input", "fee", "opFixedSuccess", "success", "fail", "TalerErrorCode", "calc", "balanceAfter", "updateForm", "newForm", "errors", "undefinedIfEmpty", "trimmedAmountStr", "subject", "cashout", "challengeIds", "notifyInfo", "retryCashout", "ids", "cashoutDisabled", "cashoutAccount", "Paytos", "cashoutAccountName", "cashoutLegalName", "SolveMFAChallenges", "LocalNotificationBanner", "RenderAmount", "e", "doAutoFocus", "ShowInputErrorLabel", "InputAmount", "value", "ButtonBetter", "_IntAmounts", "negative", "saturated", "d", "am", "amount", "PaytoWireTransferForm", "focus", "withAccount", "withSubject", "withAmount", "onSuccess", "routeCancel", "routeCashout", "limit", "balance", "inputType", "setInputType", "p", "isRawPayto", "credentials", "useSessionState", "api", "config", "url", "useBankCoreApiContext", "sendingToFixedAccount", "account", "setAccount", "subject", "setSubject", "amount", "setAmount", "rawPaytoInput", "rawPaytoInputSetter", "i18n", "useTranslationContext", "wireFee", "Amounts", "trimmedAmountStr", "limitWithFee", "IntAmounts", "parsedAmount", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "mfa", "useChallengeHandler", "paytoType", "errorsWire", "undefinedIfEmpty", "validateIBAN", "validateTalerBank", "validateSubject", "validateAmount", "foundPayto", "searchPaytoInHumanReadableText", "parsed", "Paytos", "errorsPayto", "validateRawPayto", "parsedURI", "sendingAmount", "res", "assertUnreachable", "sAmount", "send", "creds", "uri", "challengeIds", "success", "notifyInfo", "fail", "HttpStatusCode", "TalerErrorCode", "repeatSend", "ids", "h", "SolveMFAChallenges", "PaytoType", "amountStr", "payto", "e", "doAutoFocus", "ShowInputErrorLabel", "TextField", "v", "InputAmount", "d", "RenderAmount", "ButtonBetter", "LocalNotificationBanner", "element", "currency", "name", "value", "left", "placeholder", "onChange", "ref", "l", "sep_pos", "FRAC_SEPARATOR", "host", "type", "result", "text", "Wrapper", "withIcon", "children", "id", "label", "help", "disabled", "rightIcons", "required", "error", "PAYTO_START_REGEX", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "initial", "Context", "B", "useSettingsContext", "q", "SettingsProvider", "children", "value", "h", "codecForPreferences", "buildCodecForObject", "codecForBoolean", "codecOptionalDefault", "defaultPreferences", "BANK_PREFERENCES_KEY", "buildStorageKey", "usePreferences", "value", "update", "useLocalStorage", "updateField", "k", "v", "newValue", "getAllBooleanPreferences", "settings", "getLabelForPreferences", "i18n", "noun", "adj", "getRandomUsername", "n", "a", "getRandomPassword", "encodeCrock", "getRandomBytes", "TALER_SCREEN_ID", "RegistrationPage", "onRegistrationSuccesful", "routeCancel", "i18n", "useTranslationContext", "config", "useBankCoreApiContext", "h", "RegistrationForm", "USERNAME_REGEX", "username", "setUsername", "p", "name", "setName", "password", "setPassword", "repeatPassword", "setRepeatPassword", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "settings", "useSettingsContext", "pref", "usePreferences", "api", "errors", "undefinedIfEmpty", "reg", "register", "account", "success", "acc", "fail", "HttpStatusCode", "TalerErrorCode", "assertUnreachable", "registerRandom", "user", "getRandomUsername", "capitalizeFirstLetter", "LocalNotificationBanner", "e", "ShowInputErrorLabel", "ButtonBetter", "str", "TALER_SCREEN_ID", "SESSION_DURATION", "Duration", "LoginForm", "currentUser", "fixedUser", "routeRegister", "session", "useSessionState", "sessionUser", "username", "setUsername", "p", "password", "setPassword", "i18n", "useTranslationContext", "api", "useBankCoreApiContext", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "mfa", "useChallengeHandler", "config", "errors", "undefinedIfEmpty", "USERNAME_REGEX", "logout", "opEmptySuccess", "fail", "tokenRequest", "login", "challengeIds", "result", "createRFC8959AccessTokenEncoded", "AbsoluteTime", "HttpStatusCode", "TalerErrorCode", "assertUnreachable", "retryLogin", "ids", "h", "SolveMFAChallenges", "onlyThisUser", "LocalNotificationBanner", "Attention", "e", "doAutoFocus", "ShowInputErrorLabel", "ButtonBetter", "init_hooks_module", "codecForSessionStateLoggedIn", "buildCodecForObject", "codecForConstString", "codecForString", "codecOptionalDefault", "codecForAbsoluteTime", "AbsoluteTime", "codecForBoolean", "codecForSessionStateExpired", "codecForSessionStateLoggedOut", "codecForSessionState", "buildCodecForUnion", "defaultState", "SESSION_STATE_KEY", "buildStorageKey", "useSessionState", "state", "update", "useLocalStorage", "h", "nextState", "info", "cleanAllCache", "mutate", "useRefreshSessionBeforeExpires", "session", "bank", "useBankCoreApiContext", "refreshSession", "timeLeftBeforeExpiration", "Duration", "refreshWindow", "SESSION_DURATION", "remain", "timeoutId", "result", "createRFC8959AccessTokenEncoded", "useComponentState", "account", "tab", "routeChargeWallet", "routeCreateWireTransfer", "routePublicAccounts", "routeOperationDetails", "routeWireTransfer", "routeCashout", "onOperationCreated", "onClose", "routeClose", "result", "useAccountDetails", "TalerError", "HttpStatusCode", "assertUnreachable", "data", "balance", "Amounts", "debitThreshold", "payto", "Paytos", "PaytoType", "balanceIsDebit", "limit", "IntAmounts", "positiveBalance", "init_preact_module", "useComponentState", "account", "routeCreateWireTransfer", "result", "useTransactions", "TalerError", "transactions", "tx", "negative", "cp", "Paytos", "counterpart", "Result", "when", "AbsoluteTime", "amount", "Amounts", "subject", "x", "toInteger", "dirtyNumber", "number", "requiredArgs", "required", "args", "_typeof", "obj", "toDate", "argument", "requiredArgs", "argStr", "addDays", "dirtyDate", "dirtyAmount", "requiredArgs", "date", "toDate", "amount", "toInteger", "addMonths", "dirtyDate", "dirtyAmount", "requiredArgs", "date", "toDate", "amount", "toInteger", "dayOfMonth", "endOfDesiredMonth", "daysInMonth", "addMilliseconds", "dirtyDate", "dirtyAmount", "requiredArgs", "timestamp", "toDate", "amount", "toInteger", "defaultOptions", "getDefaultOptions", "getTimezoneOffsetInMilliseconds", "date", "utcDate", "_typeof", "obj", "isDate", "value", "requiredArgs", "isValid", "dirtyDate", "requiredArgs", "isDate", "date", "toDate", "subMilliseconds", "dirtyDate", "dirtyAmount", "requiredArgs", "amount", "toInteger", "addMilliseconds", "MILLISECONDS_IN_DAY", "getUTCDayOfYear", "dirtyDate", "requiredArgs", "date", "toDate", "timestamp", "startOfYearTimestamp", "difference", "startOfUTCISOWeek", "dirtyDate", "requiredArgs", "weekStartsOn", "date", "toDate", "day", "diff", "getUTCISOWeekYear", "dirtyDate", "requiredArgs", "date", "toDate", "year", "fourthOfJanuaryOfNextYear", "startOfNextYear", "startOfUTCISOWeek", "fourthOfJanuaryOfThisYear", "startOfThisYear", "startOfUTCISOWeekYear", "dirtyDate", "requiredArgs", "year", "getUTCISOWeekYear", "fourthOfJanuary", "date", "startOfUTCISOWeek", "MILLISECONDS_IN_WEEK", "getUTCISOWeek", "dirtyDate", "requiredArgs", "date", "toDate", "diff", "startOfUTCISOWeek", "startOfUTCISOWeekYear", "startOfUTCWeek", "dirtyDate", "options", "_ref", "_ref2", "_ref3", "_options$weekStartsOn", "_options$locale", "_options$locale$optio", "_defaultOptions$local", "_defaultOptions$local2", "requiredArgs", "defaultOptions", "getDefaultOptions", "weekStartsOn", "toInteger", "date", "toDate", "day", "diff", "getUTCWeekYear", "dirtyDate", "options", "_ref", "_ref2", "_ref3", "_options$firstWeekCon", "_options$locale", "_options$locale$optio", "_defaultOptions$local", "_defaultOptions$local2", "requiredArgs", "date", "toDate", "year", "defaultOptions", "getDefaultOptions", "firstWeekContainsDate", "toInteger", "firstWeekOfNextYear", "startOfNextYear", "startOfUTCWeek", "firstWeekOfThisYear", "startOfThisYear", "startOfUTCWeekYear", "dirtyDate", "options", "_ref", "_ref2", "_ref3", "_options$firstWeekCon", "_options$locale", "_options$locale$optio", "_defaultOptions$local", "_defaultOptions$local2", "requiredArgs", "defaultOptions", "getDefaultOptions", "firstWeekContainsDate", "toInteger", "year", "getUTCWeekYear", "firstWeek", "date", "startOfUTCWeek", "MILLISECONDS_IN_WEEK", "getUTCWeek", "dirtyDate", "options", "requiredArgs", "date", "toDate", "diff", "startOfUTCWeek", "startOfUTCWeekYear", "addLeadingZeros", "number", "targetLength", "sign", "output", "formatters", "date", "token", "signedYear", "year", "addLeadingZeros", "month", "dayPeriodEnumValue", "numberOfDigits", "milliseconds", "fractionalSeconds", "lightFormatters_default", "dayPeriodEnum", "formatters", "date", "token", "localize", "era", "signedYear", "year", "lightFormatters_default", "options", "signedWeekYear", "getUTCWeekYear", "weekYear", "twoDigitYear", "addLeadingZeros", "isoWeekYear", "getUTCISOWeekYear", "quarter", "month", "week", "getUTCWeek", "isoWeek", "getUTCISOWeek", "dayOfYear", "getUTCDayOfYear", "dayOfWeek", "localDayOfWeek", "isoDayOfWeek", "hours", "dayPeriodEnumValue", "_localize", "originalDate", "timezoneOffset", "formatTimezoneWithOptionalMinutes", "formatTimezone", "formatTimezoneShort", "timestamp", "offset", "dirtyDelimiter", "sign", "absOffset", "minutes", "delimiter", "formatters_default", "dateLongFormatter", "pattern", "formatLong", "timeLongFormatter", "dateTimeLongFormatter", "matchResult", "datePattern", "timePattern", "dateTimeFormat", "longFormatters", "longFormatters_default", "protectedDayOfYearTokens", "protectedWeekYearTokens", "isProtectedDayOfYearToken", "token", "isProtectedWeekYearToken", "throwProtectedError", "format", "input", "formatDistanceLocale", "formatDistance", "token", "count", "options", "result", "tokenValue", "formatDistance_default", "buildFormatLongFn", "args", "options", "width", "format", "dateFormats", "timeFormats", "dateTimeFormats", "formatLong", "buildFormatLongFn", "formatLong_default", "formatRelativeLocale", "formatRelative", "token", "_date", "_baseDate", "_options", "formatRelative_default", "buildLocalizeFn", "args", "dirtyIndex", "options", "context", "valuesArray", "defaultWidth", "width", "_defaultWidth", "_width", "index", "eraValues", "quarterValues", "monthValues", "dayValues", "dayPeriodValues", "formattingDayPeriodValues", "ordinalNumber", "dirtyNumber", "_options", "number", "rem100", "localize", "buildLocalizeFn", "quarter", "localize_default", "buildMatchFn", "args", "string", "options", "width", "matchPattern", "matchResult", "matchedString", "parsePatterns", "key", "findIndex", "pattern", "findKey", "value", "rest", "object", "predicate", "array", "buildMatchPatternFn", "args", "string", "options", "matchResult", "matchedString", "parseResult", "value", "rest", "matchOrdinalNumberPattern", "parseOrdinalNumberPattern", "matchEraPatterns", "parseEraPatterns", "matchQuarterPatterns", "parseQuarterPatterns", "matchMonthPatterns", "parseMonthPatterns", "matchDayPatterns", "parseDayPatterns", "matchDayPeriodPatterns", "parseDayPeriodPatterns", "match", "buildMatchPatternFn", "value", "buildMatchFn", "index", "match_default", "locale", "formatDistance_default", "formatLong_default", "formatRelative_default", "localize_default", "match_default", "en_US_default", "defaultLocale_default", "en_US_default", "formattingTokensRegExp", "longFormattingTokensRegExp", "escapedStringRegExp", "doubleQuoteRegExp", "unescapedLatinCharacterRegExp", "format", "dirtyDate", "dirtyFormatStr", "options", "_ref", "_options$locale", "_ref2", "_ref3", "_ref4", "_options$firstWeekCon", "_options$locale2", "_options$locale2$opti", "_defaultOptions$local", "_defaultOptions$local2", "_ref5", "_ref6", "_ref7", "_options$weekStartsOn", "_options$locale3", "_options$locale3$opti", "_defaultOptions$local3", "_defaultOptions$local4", "requiredArgs", "formatStr", "defaultOptions", "getDefaultOptions", "locale", "defaultLocale_default", "firstWeekContainsDate", "toInteger", "weekStartsOn", "originalDate", "toDate", "isValid", "timezoneOffset", "getTimezoneOffsetInMilliseconds", "utcDate", "subMilliseconds", "formatterOptions", "result", "substring", "firstCharacter", "longFormatter", "longFormatters_default", "cleanEscapedString", "formatter", "formatters_default", "isProtectedWeekYearToken", "throwProtectedError", "isProtectedDayOfYearToken", "input", "matched", "subDays", "dirtyDate", "dirtyAmount", "requiredArgs", "amount", "toInteger", "addDays", "subMonths", "dirtyDate", "dirtyAmount", "requiredArgs", "amount", "toInteger", "addMonths", "_typeof", "obj", "sub", "date", "duration", "requiredArgs", "years", "toInteger", "months", "weeks", "days", "hours", "minutes", "seconds", "dateWithoutMonths", "subMonths", "dateWithoutDays", "subDays", "minutestoSub", "secondstoSub", "mstoSub", "finalDate", "init_preact_module", "ReadyView", "transactions", "routeCreateWireTransfer", "onGoNext", "onGoStart", "i18n", "dateLocale", "useTranslationContext", "config", "useBankCoreApiContext", "h", "Attention", "txByDate", "prev", "cur", "format", "date", "txs", "idx", "p", "item", "Time", "RenderAmount", "viewMapping", "Loading", "ErrorLoading", "ReadyView", "Transactions", "utils_exports", "p", "useComponentState", "init_preact_module", "init_preact_module", "init_compat_module", "init_hooks_module", "codecForChallengeUpdatePassword", "buildCodecForObject", "codecForConstString", "codecForString", "codecForAppLocation", "codecForAbsoluteTime", "codecForAny", "codecForChallengeDeleteAccount", "codecForChallengeUpdateAccount", "codecForChallengeCreateTransaction", "codecForChallengeConfirmWithdrawal", "codecForChallengeCashout", "codecForLoginChallenge", "codecOptional", "codecForChallenge", "buildCodecForUnion", "codecForBankState", "defaultBankState", "BANK_STATE_KEY", "buildStorageKey", "useBankState", "value", "update", "useLocalStorage", "updateField", "k", "v", "newValue", "reset", "init_hooks_module", "useComponentState", "routeClose", "onAbort", "focus", "preference", "usePreferences", "settings", "useSettingsContext", "bankState", "updateBankState", "useBankState", "credentials", "useSessionState", "creds", "config", "bank", "useBankCoreApiContext", "failure", "setFailure", "p", "amount", "doSilentStart", "parsedAmount", "Amounts", "params", "resp", "withdrawalOperationId", "h", "parsedUri", "TalerUris", "uri", "result", "useWithdrawalDetails", "shouldCreateNewOperation", "TalerError", "HttpStatusCode", "assertUnreachable", "data", "account", "Paytos", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "import_qrcode_generator", "QR", "text", "divRef", "_", "h", "qr", "qrcode", "init_preact_module", "useComponentState", "opid", "credentials", "useSessionState", "creds", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "i18n", "useTranslationContext", "mfa", "useChallengeHandler", "config", "api", "useBankCoreApiContext", "wireFee", "Amounts", "confirm", "challengeIds", "mutate", "fail", "HttpStatusCode", "TalerErrorCode", "assertUnreachable", "repeat", "ids", "abort", "spec", "WithdrawalConfirmationQuestion", "details", "withdrawUri", "h", "SolveMFAChallenges", "p", "LocalNotificationBanner", "ShouldBeSameUser", "e", "PaytoType", "name", "RenderAmount", "ButtonBetter", "username", "children", "Attention", "LoginForm", "InvalidPaytoView", "payto", "h", "InvalidWithdrawalView", "uri", "InvalidReserveView", "reserve", "NeedConfirmationView", "onAbort", "account", "details", "operationId", "i18n", "useTranslationContext", "settings", "usePreferences", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "credentials", "useSessionState", "creds", "mfa", "useChallengeHandler", "config", "bank", "useBankCoreApiContext", "wireFee", "Amounts", "abort", "fail", "HttpStatusCode", "assertUnreachable", "confirm", "challengeIds", "notifyInfo", "TalerErrorCode", "repeatConfirm", "ids", "SolveMFAChallenges", "LocalNotificationBanner", "ShouldBeSameUser", "e", "PaytoType", "name", "p", "RenderAmount", "ButtonBetter", "FailedView", "error", "Attention", "AbortedView", "ConfirmedView", "routeClose", "updateSettings", "ReadyView", "focus", "walletInegrationApi", "useTalerWalletIntegrationAPI", "parsedUri", "TalerUris", "talerWithdrawUri", "QR", "viewMapping", "Loading", "FailedView", "InvalidPaytoView", "InvalidWithdrawalView", "InvalidReserveView", "NeedConfirmationView", "AbortedView", "ConfirmedView", "ErrorLoading", "ReadyView", "OperationState", "utils_exports", "p", "useComponentState", "RefAmount", "k", "InputAmount", "OldWithdrawalForm", "onOperationCreated", "limit", "balance", "routeCancel", "focus", "i18n", "useTranslationContext", "settings", "useSettingsContext", "preference", "usePreferences", "updateBankState", "useBankState", "api", "config", "useBankCoreApiContext", "credentials", "useSessionState", "creds", "amountStr", "setAmountStr", "p", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "trimmedAmountStr", "parsedAmount", "Amounts", "errors", "undefinedIfEmpty", "start", "amount", "success", "uri", "TalerUris", "TalerUriAction", "notifyError", "fail", "HttpStatusCode", "assertUnreachable", "h", "e", "LocalNotificationBanner", "v", "doAutoFocus", "ShowInputErrorLabel", "RenderAmount", "ButtonBetter", "WalletWithdrawForm", "onOperationAborted", "pref", "updatePref", "Attention", "OperationState", "PaymentOptions", "routeClose", "routeCashout", "routeChargeWallet", "routeWireTransfer", "tab", "limit", "balance", "onOperationCreated", "onClose", "routeOperationDetails", "i18n", "useTranslationContext", "h", "WalletWithdrawForm", "PaytoWireTransferForm", "InvalidIbanView", "error", "h", "IS_PUBLIC_ACCOUNT_ENABLED", "ShowDemoInfo", "routePublicAccounts", "i18n", "useTranslationContext", "settings", "useSettingsContext", "preferences", "updatePreferences", "usePreferences", "p", "Attention", "ReadyView", "tab", "account", "routeChargeWallet", "routeWireTransfer", "limit", "balance", "routeCashout", "routeCreateWireTransfer", "routeOperationDetails", "onClose", "routeClose", "onOperationCreated", "PaymentOptions", "Transactions", "viewMapping", "Loading", "LoginForm", "InvalidIbanView", "ErrorLoading", "ReadyView", "AccountPage", "utils_exports", "p", "useComponentState", "init_preact_module", "init_hooks_module", "TALER_SCREEN_ID", "GIT_HASH", "VERSION", "BankFrame", "children", "account", "routeAccountDetails", "routeNotifications", "i18n", "useTranslationContext", "session", "useSessionState", "settings", "useSettingsContext", "showDebugInfo", "update", "useCommonPreferences", "preferences", "updatePreferences", "usePreferences", "resetBankState", "useBankState", "d", "useBankCoreApiContext", "config", "authenticator", "error", "resetError", "P", "h", "logBugForDevelopers", "notifyException", "notifyError", "Header", "getAllBooleanPreferences", "set", "isOn", "getLabelForPreferences", "ToastBanner", "WelcomeAccount", "AccountBalance", "AppActivity", "Footer", "Wait", "clazz", "p", "lastEvent", "setLastEvent", "status", "setStatus", "onBackendActivity", "cancelRequest", "ev", "ObservabilityEventType", "assertUnreachable", "result", "useAccountDetails", "TalerError", "Loading", "RenderAmount", "Amounts", "init_preact_module", "init_hooks_module", "init_hooks_module", "constructFormHandler", "form", "updateForm", "errors", "prev", "fieldName", "currentValue", "currentError", "updater", "newValue", "group", "field", "useFormState", "defaultValue", "check", "p", "status", "init_preact_module", "ConversionClassList", "routeCreate", "routeShowDetails", "result", "useConversionRateClasses", "i18n", "useTranslationContext", "resultInfo", "useConversionInfo", "convInfo", "h", "p", "Loading", "TalerError", "ErrorLoading", "HttpStatusCode", "Attention", "assertUnreachable", "classes", "row", "idx", "DescribeConversion", "fee", "min", "ratio", "rounding", "feeSpec", "minSpec", "Amounts", "RenderAmount", "init_preact_module", "init_hooks_module", "init_preact_module", "ProfileNavigation", "current", "routeMyAccountCashout", "routeMyAccountDelete", "routeMyAccountDetails", "routeMyAccountPassword", "routeConversionConfig", "i18n", "useTranslationContext", "config", "useBankCoreApiContext", "credentials", "useSessionState", "isAdminUser", "nonAdminUser", "navigateTo", "useNavigationContext", "h", "e", "op", "assertUnreachable", "p", "useComponentState", "routeCancel", "routeConversionConfig", "routeMyAccountCashout", "routeMyAccountDelete", "routeMyAccountDetails", "routeMyAccountPassword", "i18n", "useTranslationContext", "credentials", "useSessionState", "creds", "h", "resp", "useConversionInfo", "Loading", "TalerError", "ErrorLoading", "HttpStatusCode", "Attention", "assertUnreachable", "info", "conversion", "useBankCoreApiContext", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "initalState", "form", "status", "useFormState", "createFormValidator", "calculateCashoutFromDebit", "useCashoutEstimator", "calculateCashinFromDebit", "useCashinEstimator", "calculationResult", "setCalc", "p", "in_amount", "Amounts", "in_fee", "out_fee", "calculate", "amount", "respCashin", "cashin", "respCashout", "cashout", "opFixedSuccess", "fail", "TalerErrorCode", "section", "setSection", "cashinCalc", "cashoutCalc", "update", "in_ratio", "out_ratio", "both_high", "both_low", "ProfileNavigation", "LocalNotificationBanner", "e", "ConversionForm", "DescribeConversion", "InputAmount", "ShowInputErrorLabel", "RenderAmount", "ButtonBetter", "ConversionConfig", "utils_exports", "regional", "fiat", "state", "cashin_min_amount", "cashin_tiny_amount", "cashin_fee", "cashout_min_amount", "cashout_tiny_amount", "cashout_fee", "am", "cashin_ratio", "cashout_ratio", "errors", "undefinedIfEmpty", "result", "id", "inputCurrency", "outputCurrency", "fee", "minimum", "ratio", "rounding", "tiny", "fallback_fee", "fallback_minimum", "fallback_ratio", "fallback_rounding", "fallback_tiny", "ConversionRateClassDetails", "routeCancel", "classId", "onClassDeleted", "i18n", "useTranslationContext", "detailsResult", "useConversionRateClassDetails", "conversionInfoResult", "useConversionInfo", "conversionInfo", "TalerError", "h", "Loading", "ErrorLoading", "HttpStatusCode", "Attention", "assertUnreachable", "Form", "credentials", "useSessionState", "creds", "lib", "config", "useBankCoreApiContext", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "section", "setSection", "p", "initalState", "form", "status", "useFormState", "createFormValidator", "deleteClass", "token", "fail", "input", "updateClass", "TalerErrorCode", "updateRequest", "updateDetails", "t", "id", "r", "updateCashin", "updateCashout", "default_rate", "final_cashin_ratio", "final_cashin_fee", "final_cashin_min", "final_cashin_rounding", "final_cashout_ratio", "final_cashout_fee", "final_cashout_min", "final_cashout_rounding", "in_ratio", "out_ratio", "both_high", "both_low", "LocalNotificationBanner", "e", "ConversionForm", "doAutoFocus", "ShowInputErrorLabel", "DescribeConversion", "AccountsOnConversionClass", "DeleteConversionClass", "TestConversionClass", "ButtonBetter", "regional", "fiat", "state", "cashin_min_amount", "Amounts", "cashin_fee", "cashout_min_amount", "cashout_fee", "cashin_ratio_f", "cashout_ratio_f", "cashin_ratio", "cashout_ratio", "errors", "undefinedIfEmpty", "result", "info", "calculateCashoutFromDebit", "useCashoutEstimatorForClass", "calculateCashinFromDebit", "useCashinEstimatorForClass", "amount", "setAmount", "error", "setError", "calculationResult", "setCalc", "in_amount", "in_fee", "out_fee", "calculate", "respCashin", "cashin", "respCashout", "cashout", "opFixedSuccess", "resp", "cashinCalc", "cashoutCalc", "InputAmount", "d", "RenderAmount", "userCount", "bank", "resultInfo", "convInfo", "filter", "setFilter", "userListResult", "useConversionRateClassUsers", "InputToggle", "v", "InputText", "item", "idx", "revalidateConversionRateClassUsers", "revalidateConversionRateClassDetails", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "ConversionRateClassForm", "onChange", "focus", "children", "i18n", "useTranslationContext", "credentials", "useSessionState", "form", "setForm", "p", "errors", "setErrors", "editableForm", "updateForm", "newForm", "undefinedIfEmpty", "result", "h", "e", "doAutoFocus", "ShowInputErrorLabel", "NewConversionRateClass", "routeCancel", "onCreated", "i18n", "useTranslationContext", "credentials", "useSessionState", "token", "api", "useBankCoreApiContext", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "submitData", "setSubmitData", "p", "create", "data", "success", "notifyInfo", "fail", "HttpStatusCode", "TalerErrorCode", "assertUnreachable", "h", "LocalNotificationBanner", "ConversionRateClassForm", "ButtonBetter", "init_preact_module", "init_hooks_module", "PublicHistoriesPage", "i18n", "useTranslationContext", "result", "usePublicAccounts", "firstAccount", "TalerError", "showAccount", "setShowAccount", "p", "h", "Loading", "accountList", "txs", "accountsBar", "account", "isSelected", "Transactions", "init_preact_module", "ShowNotifications", "ns", "useNotifications", "h", "n", "idx", "Time", "init_preact_module", "WireTransfer", "toAccount", "withSubject", "withAmount", "routeCancel", "onSuccess", "i18n", "useTranslationContext", "r", "useSessionState", "account", "result", "useAccountDetails", "h", "Loading", "TalerError", "p", "ErrorLoading", "LoginForm", "HttpStatusCode", "assertUnreachable", "data", "balanceAbs", "Amounts", "isBalanceNegative", "debitThreshold", "balance", "IntAmounts", "limit", "positiveBalance", "PaytoWireTransferForm", "notifyInfo", "init_preact_module", "init_preact_module", "init_preact_module", "init_hooks_module", "QrCodeSection", "withdrawUri", "onAborted", "i18n", "useTranslationContext", "walletInegrationApi", "useTalerWalletIntegrationAPI", "talerWithdrawUri", "TalerUris", "credentials", "useSessionState", "creds", "h", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "api", "useBankCoreApiContext", "abort", "fail", "HttpStatusCode", "assertUnreachable", "p", "LocalNotificationBanner", "ButtonBetter", "QR", "WithdrawalQRCode", "withdrawUri", "onOperationAborted", "routeClose", "origin", "i18n", "useTranslationContext", "result", "useWithdrawalDetails", "h", "Loading", "TalerError", "ErrorLoading", "HttpStatusCode", "OperationNotFound", "assertUnreachable", "data", "talerWithdrawUri", "TalerUris", "QrCodeSection", "notifyInfo", "account", "Paytos", "Attention", "WithdrawalConfirmationQuestion", "Amounts", "WithdrawalOperationPage", "operationId", "onOperationAborted", "routeClose", "origin", "api", "useBankCoreApiContext", "parsedUri", "TalerUris", "uri", "i18n", "useTranslationContext", "updateBankState", "useBankState", "h", "WithdrawalQRCode", "Attention", "init_preact_module", "useComponentState", "account", "routeCashoutDetails", "result", "useCashouts", "TalerError", "init_preact_module", "FailedView", "error", "i18n", "useTranslationContext", "HttpStatusCode", "h", "Attention", "assertUnreachable", "ReadyView", "cashouts", "routeCashoutDetails", "dateLocale", "txByDate", "prev", "cur", "format", "conversionResp", "useConversionInfo", "TalerError", "ErrorLoading", "Loading", "fiat_currency_specification", "regional_currency_specification", "date", "txs", "idx", "p", "item", "Time", "AbsoluteTime", "RenderAmount", "Amounts", "viewMapping", "Loading", "ErrorLoading", "FailedView", "ReadyView", "Cashouts", "utils_exports", "p", "useComponentState", "CashoutListForAccount", "account", "onCashout", "routeCashoutDetails", "routeMyAccountCashout", "routeMyAccountDelete", "routeMyAccountDetails", "routeConversionConfig", "routeMyAccountPassword", "routeClose", "i18n", "useTranslationContext", "credentials", "useSessionState", "accountIsTheCurrentUser", "h", "p", "ProfileNavigation", "CreateCashout", "Cashouts", "init_preact_module", "init_hooks_module", "init_preact_module", "init_hooks_module", "EMAIL_REGEX", "REGEX_JUST_NUMBERS_REGEX", "AccountForm", "template", "username", "purpose", "onChange", "focus", "children", "config", "url", "useBankCoreApiContext", "i18n", "useTranslationContext", "credentials", "useSessionState", "form", "setForm", "p", "errors", "setErrors", "paytoType", "cashoutPaytoType", "defaultValue", "Amounts", "getAccountId", "userIsAdmin", "editableUsername", "editableName", "isCashoutEnabled", "editableCashout", "editableThreshold", "editableAccount", "hasPhone", "hasEmail", "updateForm", "newForm", "trimmedDebitThresholdStr", "parsedDebitThreshold", "undefinedIfEmpty", "validateIBAN", "validateTalerBank", "cashout", "Paytos", "assertUnreachable", "cashoutURI", "internal", "internalURI", "threshold", "callback", "result", "getRandomPassword", "h", "e", "doAutoFocus", "ShowInputErrorLabel", "TextField", "CopyButton", "InputAmount", "type", "s", "PaytoType", "ShowAccountDetails", "account", "routeClose", "onUpdateSuccess", "routeMyAccountCashout", "routeMyAccountDelete", "routeMyAccountDetails", "routeMyAccountPassword", "routeConversionConfig", "i18n", "useTranslationContext", "credentials", "useSessionState", "sessionToken", "bank", "useBankCoreApiContext", "accountIsTheCurrentUser", "submitAccount", "setSubmitAccount", "p", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "mfa", "useChallengeHandler", "result", "useAccountDetails", "h", "Loading", "TalerError", "ErrorLoading", "LoginForm", "HttpStatusCode", "assertUnreachable", "update", "username", "token", "challengeIds", "success", "notifyInfo", "fail", "TalerErrorCode", "repeatUpdate", "ids", "baseURL", "revenueURL", "ac", "Paytos", "payto", "SolveMFAChallenges", "LocalNotificationBanner", "ProfileNavigation", "Attention", "AccountForm", "a", "ButtonBetter", "CopyButton", "init_preact_module", "init_hooks_module", "UpdateAccountPassword", "accountName", "routeClose", "onUpdateSuccess", "routeMyAccountCashout", "routeMyAccountDelete", "routeMyAccountDetails", "routeMyAccountPassword", "routeConversionConfig", "focus", "i18n", "useTranslationContext", "credentials", "useSessionState", "token", "api", "useBankCoreApiContext", "current", "setCurrent", "p", "password", "setPassword", "repeat", "setRepeat", "accountIsTheCurrentUser", "errors", "undefinedIfEmpty", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "mfa", "useChallengeHandler", "update", "request", "challengeIds", "success", "notifyInfo", "fail", "HttpStatusCode", "TalerErrorCode", "assertUnreachable", "repeatUpdate", "ids", "h", "SolveMFAChallenges", "LocalNotificationBanner", "ProfileNavigation", "e", "doAutoFocus", "ShowInputErrorLabel", "ButtonBetter", "init_preact_module", "init_hooks_module", "init_preact_module", "AccountList", "routeCreate", "routeRemoveAccount", "routeShowAccount", "routeUpdatePasswordAccount", "result", "useBusinessAccounts", "i18n", "useTranslationContext", "config", "useBankCoreApiContext", "h", "Loading", "TalerError", "ErrorLoading", "HttpStatusCode", "p", "assertUnreachable", "accounts", "item", "idx", "balance", "Amounts", "noBalance", "balanceIsDebit", "RenderAmount", "AdminHome", "routeCreateAccount", "routeRemoveAccount", "routeShowAccount", "routeUpdatePasswordAccount", "routeDownloadStats", "routeCreateWireTransfer", "routeCreateConversionRateClass", "routeShowConversionRateClass", "config", "useBankCoreApiContext", "h", "p", "Metrics", "WireTransfer", "Transactions", "AccountList", "ConversionClassList", "getDateForTimeframeStart", "date", "timeframe", "locale", "types_taler_corebank_exports", "format", "assertUnreachable", "getDateForTimeframeEnd", "end", "AbsoluteTime", "Duration", "getTimeframesForDate", "time", "sub", "i18n", "dateLocale", "useTranslationContext", "metricType", "setMetricType", "respInfo", "useConversionInfo", "params", "resp", "useLastMonitorInfo", "TalerError", "ErrorLoading", "HttpStatusCode", "Attention", "e", "MetricValueAmount", "MetricValueNumber", "current", "previous", "spec", "cmp", "Amounts", "cv", "currAmount", "prevAmount", "rate", "negative", "rateStr", "RenderAmount", "init_preact_module", "init_hooks_module", "CreateNewAccount", "routeCancel", "onCreateSuccess", "i18n", "useTranslationContext", "credentials", "useSessionState", "token", "api", "useBankCoreApiContext", "submitAccount", "setSubmitAccount", "p", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "create", "success", "account", "notifyInfo", "fail", "HttpStatusCode", "TalerErrorCode", "assertUnreachable", "h", "LocalNotificationBanner", "AccountForm", "a", "ButtonBetter", "Attention", "init_preact_module", "init_hooks_module", "DownloadStats", "routeCancel", "i18n", "useTranslationContext", "credentials", "useSessionState", "creds", "api", "useBankCoreApiContext", "options", "setOptions", "p", "lastStep", "setLastStep", "downloaded", "setDownloaded", "referenceDates", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "download", "token", "fetchAllStatus", "step", "total", "success", "fail", "h", "LocalNotificationBanner", "e", "ButtonBetter", "Attention", "references", "progress", "allMetrics", "types_taler_corebank_exports", "allFrames", "timeframe", "reference", "getTimeframesForDate", "allInfo", "prev", "frame", "index", "accumulatedMap", "previous", "current", "metricName", "table", "name", "data", "row", "dataToRow", "csv", "acc", "opFixedSuccess", "info", "init_preact_module", "init_hooks_module", "RemoveAccount", "account", "routeCancel", "onUpdateSuccess", "focus", "i18n", "useTranslationContext", "result", "useAccountDetails", "accountName", "setAccountName", "p", "state", "useSessionState", "token", "api", "useBankCoreApiContext", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "mfa", "useChallengeHandler", "h", "Loading", "TalerError", "ErrorLoading", "LoginForm", "HttpStatusCode", "assertUnreachable", "balance", "Amounts", "Attention", "errors", "undefinedIfEmpty", "deleteAccount", "auth", "challengeIds", "success", "notifyInfo", "fail", "TalerErrorCode", "retryDeleteAccount", "ids", "SolveMFAChallenges", "LocalNotificationBanner", "e", "doAutoFocus", "ShowInputErrorLabel", "ButtonBetter", "init_preact_module", "TALER_SCREEN_ID", "ShowCashoutDetails", "id", "routeClose", "i18n", "useTranslationContext", "cid", "result", "useCashoutDetails", "info", "useConversionInfo", "h", "Attention", "Loading", "TalerError", "ErrorLoading", "HttpStatusCode", "assertUnreachable", "fiat_currency_specification", "regional_currency_specification", "Time", "AbsoluteTime", "RenderAmount", "Amounts", "TALER_SCREEN_ID", "Routing", "session", "useSessionState", "useRefreshSessionBeforeExpires", "isUserAdministrator", "username", "h", "BankFrame", "privatePages", "PrivateRouting", "PublicRounting", "token", "expiration", "publicPages", "urlPattern", "wopid", "onLoggedUser", "i18n", "useTranslationContext", "location", "useCurrentLocation", "navigateTo", "useNavigationContext", "config", "lib", "useBankCoreApiContext", "notification", "safeFunctionHandler", "useLocalNotificationBetter", "mfa", "useChallengeHandler", "tokenRequest", "SESSION_DURATION", "login", "password", "challengeIds", "success", "createRFC8959AccessTokenEncoded", "AbsoluteTime", "fail", "HttpStatusCode", "TalerErrorCode", "assertUnreachable", "repeatLogin", "ids", "SolveMFAChallenges", "p", "LoginForm", "PublicHistoriesPage", "WithdrawalOperationPage", "LocalNotificationBanner", "RegistrationPage", "usr", "pwd", "cid", "account", "classId", "isAdmin", "DownloadStats", "CreateNewAccount", "ShowAccountDetails", "UpdateAccountPassword", "RemoveAccount", "CashoutListForAccount", "AdminHome", "AccountPage", "CreateCashout", "ShowCashoutDetails", "WireTransfer", "ConversionConfig", "NewConversionRateClass", "id", "ConversionRateClassDetails", "ShowNotifications", "strings", "defaultSettings", "buildDefaultBackendBaseURL", "codecForUISettings", "buildCodecForObject", "codecOptional", "codecForString", "codecForBoolean", "codecForNumber", "codecForMap", "removeUndefineField", "obj", "prev", "cur", "fetchSettings", "listener", "resp", "json", "result", "e", "currentLocation", "canonicalizeBaseUrl", "WITH_LOCAL_STORAGE_CACHE", "App", "settings", "setSettings", "p", "h", "fetchSettings", "Loading", "baseUrl", "getInitialBackendBaseURL", "SettingsProvider", "TranslationProvider", "strings", "SubApp", "setGlobalLogLevelFromString", "getGlobalLogLevel", "localStorageProvider", "map", "appCache", "backendFromSettings", "overrideUrl", "result", "canonicalizeBaseUrl", "evictBankSwrCache", "op", "TalerCoreBankCacheEviction", "revalidatePublicAccounts", "revalidateBusinessAccounts", "revalidateAccountDetails", "revalidateTransactions", "revalidateCashouts", "revalidateConversionInfo", "revalidateConversionRateClassDetails", "revalidateConversionRateClasses", "assertUnreachable", "evictConversionSwrCache", "TalerBankConversionCacheEviction", "BankApiProvider", "BankFrame", "SWRConfig", "TalerWalletIntegrationBrowserProvider", "BrowserHashNavigationProvider", "Routing", "init_preact_module", "getState", "node", "component", "element", "vnode", "h", "App", "P"] } libeufin-1.6.8/contrib/wallet-core/bank/index.css0000664000175000017500000015064315204341712022165 0ustar grothoffgrothoff*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}[type=text],[type=email],[type=url],[type=password],[type=number],[type=date],[type=datetime-local],[type=month],[type=search],[type=tel],[type=time],[type=week],[multiple],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow: 0 0 #0000}[type=text]:focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=month]:focus,[type=search]:focus,[type=tel]:focus,[type=time]:focus,[type=week]:focus,[multiple]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:initial;background-position:initial;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow: 0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 2px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.\!fixed{position:fixed!important}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.-inset-0\.5{inset:-.125rem}.-inset-1{inset:-.25rem}.-inset-2\.5{inset:-.625rem}.inset-0{inset:0}.inset-x-0{left:0;right:0}.inset-y-0{top:0;bottom:0}.-left-\[15px\]{left:-15px}.-top-\[21px\]{top:-21px}.bottom-0{bottom:0}.bottom-1\/2{bottom:50%}.bottom-4{bottom:1rem}.left-0{left:0}.left-1\/2{left:50%}.left-\[calc\(50\%-1px\)\]{left:calc(50% - 1px)}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.top-14{top:3.5rem}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.col-span-2{grid-column:span 2 / span 2}.col-span-6{grid-column:span 6 / span 6}.col-span-full{grid-column:1 / -1}.m-0{margin:0}.m-1{margin:.25rem}.m-1\.5{margin:.375rem}.m-2{margin:.5rem}.m-4{margin:1rem}.m-auto{margin:auto}.-mx-4{margin-left:-1rem;margin-right:-1rem}.-my-2{margin-top:-.5rem;margin-bottom:-.5rem}.mx-8{margin-left:2rem;margin-right:2rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-auto{margin-top:auto;margin-bottom:auto}.-ml-1{margin-left:-.25rem}.-ml-10{margin-left:-2.5rem}.-ml-px{margin-left:-1px}.-mr-px{margin-right:-1px}.-mt-1{margin-top:-.25rem}.-mt-2{margin-top:-.5rem}.-mt-32{margin-top:-8rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mr-auto{margin-right:auto}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.box-content{box-sizing:content-box}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.table-row{display:table-row}.flow-root{display:flow-root}.grid{display:grid}.contents{display:contents}.\!hidden{display:none!important}.hidden{display:none}.size-4{width:1rem;height:1rem}.size-6{width:1.5rem;height:1.5rem}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-2\/5{height:40%}.h-24{height:6rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-\[260px\]{height:260px}.h-\[32px\]{height:32px}.h-\[4px\]{height:4px}.h-\[56px\]{height:56px}.h-\[6px\]{height:6px}.h-full{height:100%}.max-h-60{max-height:15rem}.min-h-\[305px\]{min-height:305px}.min-h-full{min-height:100%}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-12{width:3rem}.w-28{width:7rem}.w-3{width:.75rem}.w-4{width:1rem}.w-4\/5{width:80%}.w-44{width:11rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-\[260px\]{width:260px}.w-\[2px\]{width:2px}.w-\[32px\]{width:32px}.w-\[4px\]{width:4px}.w-\[6px\]{width:6px}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.min-w-\[310px\]{min-width:310px}.min-w-fit{min-width:-moz-fit-content;min-width:fit-content}.min-w-full{min-width:100%}.max-w-2xl{max-width:42rem}.max-w-7xl{max-width:80rem}.max-w-\[325px\]{max-width:325px}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-xl{max-width:36rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-auto{flex:1 1 auto}.flex-none{flex:none}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.origin-\[center_bottom_0\]{transform-origin:center bottom 0}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-5{--tw-translate-x: 1.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-6{--tw-translate-x: 1.5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-0{--tw-rotate: 0deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-45{--tw-rotate: 45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.animate-\[show-up-clock_350ms_linear\]{animation:show-up-clock .35s linear}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.justify-evenly{justify-content:space-evenly}.gap-1{gap:.25rem}.gap-4{gap:1rem}.gap-px{gap:1px}.gap-x-0\.5{-moz-column-gap:.125rem;column-gap:.125rem}.gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.gap-x-8{-moz-column-gap:2rem;column-gap:2rem}.gap-y-2{row-gap:.5rem}.gap-y-3{row-gap:.75rem}.gap-y-4{row-gap:1rem}.gap-y-6{row-gap:1.5rem}.gap-y-7{row-gap:1.75rem}.gap-y-8{row-gap:2rem}.-space-y-px>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(-1px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(-1px * var(--tw-space-y-reverse))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.divide-x>:not([hidden])~:not([hidden]){--tw-divide-x-reverse: 0;border-right-width:calc(1px * var(--tw-divide-x-reverse));border-left-width:calc(1px * calc(1 - var(--tw-divide-x-reverse)))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(243 244 246 / var(--tw-divide-opacity, 1))}.divide-gray-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(229 231 235 / var(--tw-divide-opacity, 1))}.divide-gray-300>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(209 213 219 / var(--tw-divide-opacity, 1))}.self-center{align-self:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.whitespace-break-spaces{white-space:break-spaces}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-\[100\%\]{border-radius:100%}.rounded-\[50\%\]{border-radius:50%}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.rounded-b-lg{border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.rounded-l-lg{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}.rounded-l-md{border-top-left-radius:.375rem;border-bottom-left-radius:.375rem}.rounded-l-none{border-top-left-radius:0;border-bottom-left-radius:0}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-r-md{border-top-right-radius:.375rem;border-bottom-right-radius:.375rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.rounded-t-sm{border-top-left-radius:.125rem;border-top-right-radius:.125rem}.rounded-bl-md{border-bottom-left-radius:.375rem}.rounded-br-md{border-bottom-right-radius:.375rem}.rounded-tl-md{border-top-left-radius:.375rem}.rounded-tr-md{border-top-right-radius:.375rem}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-\[14px\]{border-width:14px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-r-0{border-right-width:0px}.border-r-2{border-right-width:2px}.border-t{border-top-width:1px}.border-t-2{border-top-width:2px}.border-solid{border-style:solid}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-\[\#3b71ca\]{--tw-border-opacity: 1;border-color:rgb(59 113 202 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-gray-800{--tw-border-opacity: 1;border-color:rgb(31 41 55 / var(--tw-border-opacity, 1))}.border-gray-900\/10{border-color:#1118271a}.border-gray-900\/25{border-color:#11182740}.border-indigo-200{--tw-border-opacity: 1;border-color:rgb(199 210 254 / var(--tw-border-opacity, 1))}.border-indigo-400{--tw-border-opacity: 1;border-color:rgb(129 140 248 / var(--tw-border-opacity, 1))}.border-indigo-600{--tw-border-opacity: 1;border-color:rgb(79 70 229 / var(--tw-border-opacity, 1))}.border-red-700{--tw-border-opacity: 1;border-color:rgb(185 28 28 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-opacity-25{--tw-border-opacity: .25}.bg-\[\#00000012\]{background-color:#00000012}.bg-\[\#3b71ca\]{--tw-bg-opacity: 1;background-color:rgb(59 113 202 / var(--tw-bg-opacity, 1))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.bg-indigo-50{--tw-bg-opacity: 1;background-color:rgb(238 242 255 / var(--tw-bg-opacity, 1))}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-yellow-100{--tw-bg-opacity: 1;background-color:rgb(254 249 195 / var(--tw-bg-opacity, 1))}.bg-opacity-75{--tw-bg-opacity: .75}.fill-yellow-500{fill:#eab308}.stroke-gray-700\/50{stroke:#37415180}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-12{padding:3rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-\[12px\]{padding-left:12px;padding-right:12px}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pb-32{padding-bottom:8rem}.pb-4{padding-bottom:1rem}.pl-1{padding-left:.25rem}.pl-10{padding-left:2.5rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pr-10{padding-right:2.5rem}.pr-12{padding-right:3rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pr-4{padding-right:1rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[0\.625rem\]{font-size:.625rem}.text-\[1\.1rem\]{font-size:1.1rem}.text-\[18px\]{font-size:18px}.text-\[3\.75rem\]{font-size:3.75rem}.text-base{font-size:1rem;line-height:1.5rem}.text-base\/7{font-size:1rem;line-height:1.75rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-sm\/6{font-size:.875rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-light{font-weight:300}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.leading-10{line-height:2.5rem}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-7{line-height:1.75rem}.leading-9{line-height:2.25rem}.leading-\[1\.2\]{line-height:1.2}.leading-none{line-height:1}.tracking-tight{letter-spacing:-.025em}.text-\[\#ffffff8a\]{color:#ffffff8a}.text-\[grey\]{--tw-text-opacity: 1;color:rgb(128 128 128 / var(--tw-text-opacity, 1))}.text-\[red\]{--tw-text-opacity: 1;color:rgb(255 0 0 / var(--tw-text-opacity, 1))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.text-indigo-200{--tw-text-opacity: 1;color:rgb(199 210 254 / var(--tw-text-opacity, 1))}.text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.text-indigo-700{--tw-text-opacity: 1;color:rgb(67 56 202 / var(--tw-text-opacity, 1))}.text-indigo-900{--tw-text-opacity: 1;color:rgb(49 46 129 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.text-red-900{--tw-text-opacity: 1;color:rgb(127 29 29 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-700{--tw-text-opacity: 1;color:rgb(161 98 7 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.opacity-0{opacity:0}.opacity-\[\.54\]{opacity:.54}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-inset{--tw-ring-inset: inset}.ring-black{--tw-ring-opacity: 1;--tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity, 1))}.ring-gray-200{--tw-ring-opacity: 1;--tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity, 1))}.ring-gray-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity, 1))}.ring-gray-600{--tw-ring-opacity: 1;--tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity, 1))}.ring-gray-900\/5{--tw-ring-color: rgb(17 24 39 / .05)}.ring-indigo-600{--tw-ring-opacity: 1;--tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1))}.ring-red-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(252 165 165 / var(--tw-ring-opacity, 1))}.ring-opacity-5{--tw-ring-opacity: .05}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.delay-1000{transition-delay:1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.selection\:bg-transparent *::-moz-selection{background-color:transparent}.selection\:bg-transparent *::selection{background-color:transparent}.selection\:bg-transparent::-moz-selection{background-color:transparent}.selection\:bg-transparent::selection{background-color:transparent}.placeholder\:text-gray-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.placeholder\:text-gray-400::placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.placeholder\:text-red-300::-moz-placeholder{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.placeholder\:text-red-300::placeholder{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.last\:border-none:last-child{border-style:none}.odd\:bg-white:nth-child(odd){--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.even\:bg-gray-100:nth-child(2n){--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.visited\:text-purple-600:visited{color:#9333ea}.focus-within\:z-10:focus-within{z-index:10}.focus-within\:outline-none:focus-within{outline:2px solid transparent;outline-offset:2px}.focus-within\:ring-2:focus-within{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-within\:ring-indigo-600:focus-within{--tw-ring-opacity: 1;--tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1))}.focus-within\:ring-offset-2:focus-within{--tw-ring-offset-width: 2px}.hover\:bg-\[\#00000026\]:hover{background-color:#00000026}.hover\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-300:hover{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-500\/20:hover{background-color:#6b728033}.hover\:bg-gray-700:hover{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.hover\:bg-green-500:hover{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.hover\:bg-indigo-500:hover{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity, 1))}.hover\:bg-indigo-600:hover{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.hover\:bg-red-500:hover{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.hover\:bg-opacity-75:hover{--tw-bg-opacity: .75}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.hover\:text-blue-900:hover{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity, 1))}.hover\:text-gray-400:hover{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.hover\:text-gray-500:hover{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.hover\:text-indigo-500:hover{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.hover\:text-indigo-600:hover{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.hover\:text-indigo-900:hover{--tw-text-opacity: 1;color:rgb(49 46 129 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:opacity-70:hover{opacity:.7}.hover\:outline-none:hover{outline:2px solid transparent;outline-offset:2px}.hover\:ring-indigo-500:hover{--tw-ring-opacity: 1;--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1))}.focus\:z-10:focus{z-index:10}.focus\:border-indigo-500:focus{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.focus\:bg-\[\#00000026\]:focus{background-color:#00000026}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-inset:focus{--tw-ring-inset: inset}.focus\:ring-indigo-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1))}.focus\:ring-indigo-600:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1))}.focus\:ring-red-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.focus\:ring-white:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity, 1))}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.focus\:ring-offset-indigo-600:focus{--tw-ring-offset-color: #4f46e5}.focus-visible\:outline:focus-visible{outline-style:solid}.focus-visible\:outline-2:focus-visible{outline-width:2px}.focus-visible\:outline-offset-0:focus-visible{outline-offset:0px}.focus-visible\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\:outline-blue-600:focus-visible{outline-color:#2563eb}.focus-visible\:outline-gray-600:focus-visible{outline-color:#4b5563}.focus-visible\:outline-green-600:focus-visible{outline-color:#16a34a}.focus-visible\:outline-indigo-600:focus-visible{outline-color:#4f46e5}.focus-visible\:outline-red-600:focus-visible{outline-color:#dc2626}.active\:ring-2:active{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.active\:ring-indigo-600:active{--tw-ring-opacity: 1;--tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1))}.active\:ring-offset-2:active{--tw-ring-offset-width: 2px}.disabled\:cursor-default:disabled{cursor:default}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-100:disabled{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.disabled\:bg-gray-200:disabled{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.disabled\:bg-gray-300:disabled{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.disabled\:bg-gray-50:disabled{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.disabled\:bg-gray-600:disabled{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.disabled\:text-gray-500:disabled{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:ring-gray-200:disabled{--tw-ring-opacity: 1;--tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity, 1))}.disabled\:hover\:bg-gray-600:hover:disabled{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.group[open] .group-open\:rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:flex{display:flex}.group:hover .group-hover\:border-indigo-600{--tw-border-opacity: 1;border-color:rgb(79 70 229 / var(--tw-border-opacity, 1))}.group:hover .group-hover\:stroke-gray-700\/75{stroke:#374151bf}.group:hover .group-hover\:text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.group.attention-danger .group-\[\.attention-danger\]\:bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.group.attention-danger .group-\[\.attention-danger\]\:bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.group.attention-info .group-\[\.attention-info\]\:bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.group.attention-info .group-\[\.attention-info\]\:bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.group.attention-low .group-\[\.attention-low\]\:bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.group.attention-low .group-\[\.attention-low\]\:bg-gray-600{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.group.attention-success .group-\[\.attention-success\]\:bg-green-50{--tw-bg-opacity: 1;background-color:rgb(240 253 244 / var(--tw-bg-opacity, 1))}.group.attention-success .group-\[\.attention-success\]\:bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.group.attention-warning .group-\[\.attention-warning\]\:bg-yellow-50{--tw-bg-opacity: 1;background-color:rgb(254 252 232 / var(--tw-bg-opacity, 1))}.group.attention-warning .group-\[\.attention-warning\]\:bg-yellow-600{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.group.attention-danger .group-\[\.attention-danger\]\:text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.group.attention-danger .group-\[\.attention-danger\]\:text-red-700{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.group.attention-danger .group-\[\.attention-danger\]\:text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.group.attention-info .group-\[\.attention-info\]\:text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.group.attention-info .group-\[\.attention-info\]\:text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.group.attention-info .group-\[\.attention-info\]\:text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.group.attention-success .group-\[\.attention-success\]\:text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.group.attention-success .group-\[\.attention-success\]\:text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.group.attention-success .group-\[\.attention-success\]\:text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.group.attention-warning .group-\[\.attention-warning\]\:text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.group.attention-warning .group-\[\.attention-warning\]\:text-yellow-700{--tw-text-opacity: 1;color:rgb(161 98 7 / var(--tw-text-opacity, 1))}.group.attention-warning .group-\[\.attention-warning\]\:text-yellow-800{--tw-text-opacity: 1;color:rgb(133 77 14 / var(--tw-text-opacity, 1))}.data-\[selection\=charge-wallet\]\:visible[data-selection=charge-wallet],.data-\[selection\=wire-transfer\]\:visible[data-selection=wire-transfer]{visibility:visible}.data-\[checked\=true\]\:z-10[data-checked=true]{z-index:10}.data-\[selected\=false\]\:hidden[data-selected=false]{display:none}.data-\[enabled\=false\]\:translate-x-0[data-enabled=false],.data-\[state\=off\]\:translate-x-0[data-state=off]{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=undefined\]\:translate-x-3[data-state=undefined]{--tw-translate-x: .75rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[status\=ok\]\:scale-y-0[data-status=ok]{--tw-scale-y: 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[disabled\=false\]\:cursor-pointer[data-disabled=false]{cursor:pointer}.data-\[disabled\=true\]\:cursor-not-allowed[data-disabled=true]{cursor:not-allowed}.data-\[fixed\=false\]\:cursor-pointer[data-fixed=false]{cursor:pointer}.data-\[left\=true\]\:rounded-l-md[data-left=true]{border-top-left-radius:.375rem;border-bottom-left-radius:.375rem}.data-\[right\=true\]\:rounded-r-md[data-right=true]{border-top-right-radius:.375rem;border-bottom-right-radius:.375rem}.data-\[timed\=true\]\:rounded-b-none[data-timed=true]{border-bottom-right-radius:0;border-bottom-left-radius:0}.data-\[checked\=true\]\:border-indigo-200[data-checked=true]{--tw-border-opacity: 1;border-color:rgb(199 210 254 / var(--tw-border-opacity, 1))}.data-\[enabled\=true\]\:border-indigo-600[data-enabled=true]{--tw-border-opacity: 1;border-color:rgb(79 70 229 / var(--tw-border-opacity, 1))}.data-\[checked\=true\]\:bg-indigo-50[data-checked=true]{--tw-bg-opacity: 1;background-color:rgb(238 242 255 / var(--tw-bg-opacity, 1))}.data-\[disabled\=true\]\:bg-gray-200[data-disabled=true]{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.data-\[disabled\=true\]\:bg-gray-50[data-disabled=true]{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.data-\[enabled\=false\]\:bg-gray-200[data-enabled=false]{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.data-\[month\=false\]\:bg-gray-100[data-month=false]{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.data-\[month\=true\]\:bg-white[data-month=true]{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.data-\[negative\=true\]\:bg-red-100[data-negative=true]{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.data-\[selected\=true\]\:\!bg-blue-400[data-selected=true]{--tw-bg-opacity: 1 !important;background-color:rgb(96 165 250 / var(--tw-bg-opacity, 1))!important}.data-\[selected\=true\]\:bg-\[\#3b71ca\][data-selected=true]{--tw-bg-opacity: 1;background-color:rgb(59 113 202 / var(--tw-bg-opacity, 1))}.data-\[selected\=true\]\:bg-indigo-500[data-selected=true]{--tw-bg-opacity: 1;background-color:rgb(99 102 241 / var(--tw-bg-opacity, 1))}.data-\[state\=off\]\:bg-gray-200[data-state=off],.data-\[state\=undefined\]\:bg-gray-200[data-state=undefined]{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.data-\[status\=deleted\]\:bg-gray-100[data-status=deleted]{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.data-\[status\=fail\]\:bg-red-200[data-status=fail]{--tw-bg-opacity: 1;background-color:rgb(254 202 202 / var(--tw-bg-opacity, 1))}.data-\[status\=ok\]\:bg-green-200[data-status=ok]{--tw-bg-opacity: 1;background-color:rgb(187 247 208 / var(--tw-bg-opacity, 1))}.data-\[today\=true\]\:bg-red-300[data-today=true]{--tw-bg-opacity: 1;background-color:rgb(252 165 165 / var(--tw-bg-opacity, 1))}.data-\[left\=true\]\:text-left[data-left=true]{text-align:left}.data-\[selected\=true\]\:font-normal[data-selected=true]{font-weight:400}.data-\[today\=true\]\:font-semibold[data-today=true]{font-weight:600}.data-\[checked\=true\]\:text-indigo-600[data-checked=true]{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.data-\[checked\=true\]\:text-indigo-900[data-checked=true]{--tw-text-opacity: 1;color:rgb(49 46 129 / var(--tw-text-opacity, 1))}.data-\[disabled\=true\]\:text-gray-500[data-disabled=true]{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.data-\[month\=true\]\:text-gray-900[data-month=true]{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.data-\[negative\=false\]\:text-green-600[data-negative=false]{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.data-\[negative\=true\]\:text-red-600[data-negative=true]{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.data-\[negative\=true\]\:text-red-700[data-negative=true]{--tw-text-opacity: 1;color:rgb(185 28 28 / var(--tw-text-opacity, 1))}.data-\[selected\=true\]\:text-gray-900[data-selected=true]{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.data-\[selected\=true\]\:text-white[data-selected=true]{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.data-\[enabled\=true\]\:ring-2[data-enabled=true],.data-\[selected\=true\]\:ring-2[data-selected=true]{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.data-\[enabled\=true\]\:ring-indigo-600[data-enabled=true]{--tw-ring-opacity: 1;--tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1))}.data-\[error\=true\]\:ring-red-500[data-error=true]{--tw-ring-opacity: 1;--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1))}.data-\[selected\=true\]\:ring-indigo-600[data-selected=true]{--tw-ring-opacity: 1;--tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1))}.data-\[month\=true\]\:hover\:bg-gray-200:hover[data-month=true]{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.data-\[selected\=true\]\:hover\:\!bg-blue-300:hover[data-selected=true]{--tw-bg-opacity: 1 !important;background-color:rgb(147 197 253 / var(--tw-bg-opacity, 1))!important}.data-\[today\=true\]\:hover\:bg-red-200:hover[data-today=true]{--tw-bg-opacity: 1;background-color:rgb(254 202 202 / var(--tw-bg-opacity, 1))}@media(min-width:640px){.sm\:col-span-2{grid-column:span 2 / span 2}.sm\:col-span-5{grid-column:span 5 / span 5}.sm\:col-span-6{grid-column:span 6 / span 6}.sm\:-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.sm\:mx-0{margin-left:0;margin-right:0}.sm\:mx-auto{margin-left:auto;margin-right:auto}.sm\:my-8{margin-top:2rem;margin-bottom:2rem}.sm\:ml-16{margin-left:4rem}.sm\:mt-0{margin-top:0}.sm\:mt-5{margin-top:1.25rem}.sm\:mt-6{margin-top:1.5rem}.sm\:block{display:block}.sm\:inline{display:inline}.sm\:flex{display:flex}.sm\:table-cell{display:table-cell}.sm\:grid{display:grid}.sm\:hidden{display:none}.sm\:w-96{width:24rem}.sm\:w-full{width:100%}.sm\:max-w-sm{max-width:24rem}.sm\:flex-auto{flex:1 1 auto}.sm\:flex-none{flex:none}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:flex-nowrap{flex-wrap:nowrap}.sm\:items-center{align-items:center}.sm\:justify-end{justify-content:flex-end}.sm\:justify-between{justify-content:space-between}.sm\:gap-4{gap:1rem}.sm\:gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.sm\:rounded-lg{border-radius:.5rem}.sm\:rounded-none{border-radius:0}.sm\:rounded-xl{border-radius:.75rem}.sm\:p-6{padding:1.5rem}.sm\:p-8{padding:2rem}.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:px-8{padding-left:2rem;padding-right:2rem}.sm\:pl-0{padding-left:0}.sm\:pl-3{padding-left:.75rem}.sm\:pr-0{padding-right:0}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}.sm\:leading-6{line-height:1.5rem}}@media(min-width:768px){.md\:col-span-2{grid-column:span 2 / span 2}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:divide-x>:not([hidden])~:not([hidden]){--tw-divide-x-reverse: 0;border-right-width:calc(1px * var(--tw-divide-x-reverse));border-left-width:calc(1px * calc(1 - var(--tw-divide-x-reverse)))}.md\:divide-y-0>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(0px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(0px * var(--tw-divide-y-reverse))}}@media(min-width:1024px){.lg\:-mx-8{margin-left:-2rem;margin-right:-2rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}}.rtl\:\!left-auto:where([dir=rtl],[dir=rtl] *){left:auto!important}.rtl\:\!origin-\[50\%_50\%_0\]:where([dir=rtl],[dir=rtl] *){transform-origin:50% 50% 0!important}@media(prefers-color-scheme:dark){.dark\:bg-zinc-500{--tw-bg-opacity: 1;background-color:rgb(113 113 122 / var(--tw-bg-opacity, 1))}.dark\:bg-zinc-600\/50{background-color:#52525b80}.dark\:bg-zinc-700{--tw-bg-opacity: 1;background-color:rgb(63 63 70 / var(--tw-bg-opacity, 1))}} /*# sourceMappingURL=index.css.map */ libeufin-1.6.8/contrib/wallet-core/bank/index.js0000664000175000017500000507367415204341712022026 0ustar grothoffgrothoffvar q1=Object.create;var ci=Object.defineProperty;var K1=Object.getOwnPropertyDescriptor;var Y1=Object.getOwnPropertyNames;var z1=Object.getPrototypeOf,$1=Object.prototype.hasOwnProperty;var _u=(e,t)=>()=>(e&&(t=e(e=0)),t);var lo=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Bp=(e,t)=>{for(var r in t)ci(e,r,{get:t[r],enumerable:!0})},Wp=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Y1(t))!$1.call(e,a)&&a!==r&&ci(e,a,{get:()=>t[a],enumerable:!(n=K1(t,a))||n.enumerable});return e};var ui=(e,t,r)=>(r=e!=null?q1(z1(e)):{},Wp(t||!e||!e.__esModule?ci(r,"default",{value:e,enumerable:!0}):r,e)),X1=e=>Wp(ci({},"__esModule",{value:!0}),e);var em=lo((g3,Hi)=>{var hr=(function(e){"use strict";var t=1e7,r=7,n=9007199254740992,a=R(n),o="0123456789abcdefghijklmnopqrstuvwxyz",s=typeof BigInt=="function";function c(N,P,z,Q){return typeof N>"u"?c[0]:typeof P<"u"?+P==10&&!z?Ye(N):oe(N,P,z,Q):Ye(N)}function u(N,P){this.value=N,this.sign=P,this.isSmall=!1}u.prototype=Object.create(c.prototype);function f(N){this.value=N,this.sign=N<0,this.isSmall=!0}f.prototype=Object.create(c.prototype);function d(N){this.value=N}d.prototype=Object.create(c.prototype);function w(N){return-n0?Math.floor(N):Math.ceil(N)}function C(N,P){var z=N.length,Q=P.length,ce=new Array(z),re=0,ye=t,_e,Te;for(Te=0;Te=ye?1:0,ce[Te]=_e-re*ye;for(;Te0&&ce.push(re),ce}function S(N,P){return N.length>=P.length?C(N,P):C(P,N)}function k(N,P){var z=N.length,Q=new Array(z),ce=t,re,ye;for(ye=0;ye0;)Q[ye++]=P%ce,P=Math.floor(P/ce);return Q}u.prototype.add=function(N){var P=Ye(N);if(this.sign!==P.sign)return this.subtract(P.negate());var z=this.value,Q=P.value;return P.isSmall?new u(k(z,Math.abs(Q)),this.sign):new u(S(z,Q),this.sign)},u.prototype.plus=u.prototype.add,f.prototype.add=function(N){var P=Ye(N),z=this.value;if(z<0!==P.sign)return this.subtract(P.negate());var Q=P.value;if(P.isSmall){if(w(z+Q))return new f(z+Q);Q=R(Math.abs(Q))}return new u(k(Q,Math.abs(z)),z<0)},f.prototype.plus=f.prototype.add,d.prototype.add=function(N){return new d(this.value+Ye(N).value)},d.prototype.plus=d.prototype.add;function v(N,P){var z=N.length,Q=P.length,ce=new Array(z),re=0,ye=t,_e,Te;for(_e=0;_e=0?Q=v(N,P):(Q=v(P,N),z=!z),Q=h(Q),typeof Q=="number"?(z&&(Q=-Q),new f(Q)):new u(Q,z)}function g(N,P,z){var Q=N.length,ce=new Array(Q),re=-P,ye=t,_e,Te;for(_e=0;_e=0)},f.prototype.minus=f.prototype.subtract,d.prototype.subtract=function(N){return new d(this.value-Ye(N).value)},d.prototype.minus=d.prototype.subtract,u.prototype.negate=function(){return new u(this.value,!this.sign)},f.prototype.negate=function(){var N=this.sign,P=new f(-this.value);return P.sign=!N,P},d.prototype.negate=function(){return new d(-this.value)},u.prototype.abs=function(){return new u(this.value,!1)},f.prototype.abs=function(){return new f(Math.abs(this.value))},d.prototype.abs=function(){return new d(this.value>=0?this.value:-this.value)};function O(N,P){var z=N.length,Q=P.length,ce=z+Q,re=T(ce),ye=t,_e,Te,et,Et,ot;for(et=0;et0;)Q[_e++]=re%ce,re=Math.floor(re/ce);return Q}function m(N,P){for(var z=[];P-- >0;)z.push(0);return z.concat(N)}function y(N,P){var z=Math.max(N.length,P.length);if(z<=30)return O(N,P);z=Math.ceil(z/2);var Q=N.slice(z),ce=N.slice(0,z),re=P.slice(z),ye=P.slice(0,z),_e=y(ce,ye),Te=y(Q,re),et=y(S(ce,Q),S(ye,re)),Et=S(S(_e,m(v(v(et,_e),Te),z)),m(Te,2*z));return p(Et),Et}function b(N,P){return-.012*N-.012*P+15e-6*N*P>0}u.prototype.multiply=function(N){var P=Ye(N),z=this.value,Q=P.value,ce=this.sign!==P.sign,re;if(P.isSmall){if(Q===0)return c[0];if(Q===1)return this;if(Q===-1)return this.negate();if(re=Math.abs(Q),re=0;ot--){for(Et=ce-1,Te[ot+Q]!==ye&&(Et=Math.floor((Te[ot+Q]*ce+Te[ot+Q-1])/ye)),Ot=0,Gr=0,mu=et.length,Ur=0;UrQ&&(et=(et+1)*ye),_e=Math.ceil(et/Et);do{if(ot=E(P,_e),pe(ot,re)<=0)break;_e--}while(_e);ce.push(_e),re=v(re,ot)}return ce.reverse(),[h(ce),h(re)]}function K(N,P){var z=N.length,Q=T(z),ce=t,re,ye,_e,Te;for(_e=0,re=z-1;re>=0;--re)Te=_e*ce+N[re],ye=A(Te/P),_e=Te-ye*P,Q[re]=ye|0;return[Q,_e|0]}function Z(N,P){var z,Q=Ye(P);if(s)return[new d(N.value/Q.value),new d(N.value%Q.value)];var ce=N.value,re=Q.value,ye;if(re===0)throw new Error("Cannot divide by zero");if(N.isSmall)return Q.isSmall?[new f(A(ce/re)),new f(ce%re)]:[c[0],N];if(Q.isSmall){if(re===1)return[N,c[0]];if(re==-1)return[N.negate(),c[0]];var _e=Math.abs(re);if(_eP.length?1:-1;for(var z=N.length-1;z>=0;z--)if(N[z]!==P[z])return N[z]>P[z]?1:-1;return 0}u.prototype.compareAbs=function(N){var P=Ye(N),z=this.value,Q=P.value;return P.isSmall?1:pe(z,Q)},f.prototype.compareAbs=function(N){var P=Ye(N),z=Math.abs(this.value),Q=P.value;return P.isSmall?(Q=Math.abs(Q),z===Q?0:z>Q?1:-1):-1},d.prototype.compareAbs=function(N){var P=this.value,z=Ye(N).value;return P=P>=0?P:-P,z=z>=0?z:-z,P===z?0:P>z?1:-1},u.prototype.compare=function(N){if(N===1/0)return-1;if(N===-1/0)return 1;var P=Ye(N),z=this.value,Q=P.value;return this.sign!==P.sign?P.sign?1:-1:P.isSmall?this.sign?-1:1:pe(z,Q)*(this.sign?-1:1)},u.prototype.compareTo=u.prototype.compare,f.prototype.compare=function(N){if(N===1/0)return-1;if(N===-1/0)return 1;var P=Ye(N),z=this.value,Q=P.value;return P.isSmall?z==Q?0:z>Q?1:-1:z<0!==P.sign?z<0?-1:1:z<0?1:-1},f.prototype.compareTo=f.prototype.compare,d.prototype.compare=function(N){if(N===1/0)return-1;if(N===-1/0)return 1;var P=this.value,z=Ye(N).value;return P===z?0:P>z?1:-1},d.prototype.compareTo=d.prototype.compare,u.prototype.equals=function(N){return this.compare(N)===0},d.prototype.eq=d.prototype.equals=f.prototype.eq=f.prototype.equals=u.prototype.eq=u.prototype.equals,u.prototype.notEquals=function(N){return this.compare(N)!==0},d.prototype.neq=d.prototype.notEquals=f.prototype.neq=f.prototype.notEquals=u.prototype.neq=u.prototype.notEquals,u.prototype.greater=function(N){return this.compare(N)>0},d.prototype.gt=d.prototype.greater=f.prototype.gt=f.prototype.greater=u.prototype.gt=u.prototype.greater,u.prototype.lesser=function(N){return this.compare(N)<0},d.prototype.lt=d.prototype.lesser=f.prototype.lt=f.prototype.lesser=u.prototype.lt=u.prototype.lesser,u.prototype.greaterOrEquals=function(N){return this.compare(N)>=0},d.prototype.geq=d.prototype.greaterOrEquals=f.prototype.geq=f.prototype.greaterOrEquals=u.prototype.geq=u.prototype.greaterOrEquals,u.prototype.lesserOrEquals=function(N){return this.compare(N)<=0},d.prototype.leq=d.prototype.lesserOrEquals=f.prototype.leq=f.prototype.lesserOrEquals=u.prototype.leq=u.prototype.lesserOrEquals,u.prototype.isEven=function(){return(this.value[0]&1)===0},f.prototype.isEven=function(){return(this.value&1)===0},d.prototype.isEven=function(){return(this.value&BigInt(1))===BigInt(0)},u.prototype.isOdd=function(){return(this.value[0]&1)===1},f.prototype.isOdd=function(){return(this.value&1)===1},d.prototype.isOdd=function(){return(this.value&BigInt(1))===BigInt(1)},u.prototype.isPositive=function(){return!this.sign},f.prototype.isPositive=function(){return this.value>0},d.prototype.isPositive=f.prototype.isPositive,u.prototype.isNegative=function(){return this.sign},f.prototype.isNegative=function(){return this.value<0},d.prototype.isNegative=f.prototype.isNegative,u.prototype.isUnit=function(){return!1},f.prototype.isUnit=function(){return Math.abs(this.value)===1},d.prototype.isUnit=function(){return this.abs().value===BigInt(1)},u.prototype.isZero=function(){return!1},f.prototype.isZero=function(){return this.value===0},d.prototype.isZero=function(){return this.value===BigInt(0)},u.prototype.isDivisibleBy=function(N){var P=Ye(N);return P.isZero()?!1:P.isUnit()?!0:P.compareAbs(2)===0?this.isEven():this.mod(P).isZero()},d.prototype.isDivisibleBy=f.prototype.isDivisibleBy=u.prototype.isDivisibleBy;function Ie(N){var P=N.abs();if(P.isUnit())return!1;if(P.equals(2)||P.equals(3)||P.equals(5))return!0;if(P.isEven()||P.isDivisibleBy(3)||P.isDivisibleBy(5))return!1;if(P.lesser(49))return!0}function be(N,P){for(var z=N.prev(),Q=z,ce=0,re,ye,_e,Te;Q.isEven();)Q=Q.divide(2),ce++;e:for(_e=0;_e-n?new f(N-1):new u(a,!0)},d.prototype.prev=function(){return new d(this.value-BigInt(1))};for(var xe=[1];2*xe[xe.length-1]<=t;)xe.push(2*xe[xe.length-1]);var Le=xe.length,Ue=xe[Le-1];function Ve(N){return Math.abs(N)<=t}u.prototype.shiftLeft=function(N){var P=Ye(N).toJSNumber();if(!Ve(P))throw new Error(String(P)+" is too large for shifting.");if(P<0)return this.shiftRight(-P);var z=this;if(z.isZero())return z;for(;P>=Le;)z=z.multiply(Ue),P-=Le-1;return z.multiply(xe[P])},d.prototype.shiftLeft=f.prototype.shiftLeft=u.prototype.shiftLeft,u.prototype.shiftRight=function(N){var P,z=Ye(N).toJSNumber();if(!Ve(z))throw new Error(String(z)+" is too large for shifting.");if(z<0)return this.shiftLeft(-z);for(var Q=this;z>=Le;){if(Q.isZero()||Q.isNegative()&&Q.isUnit())return Q;P=Z(Q,Ue),Q=P[1].isNegative()?P[0].prev():P[0],z-=Le-1}return P=Z(Q,xe[z]),P[1].isNegative()?P[0].prev():P[0]},d.prototype.shiftRight=f.prototype.shiftRight=u.prototype.shiftRight;function te(N,P,z){P=Ye(P);for(var Q=N.isNegative(),ce=P.isNegative(),re=Q?N.not():N,ye=ce?P.not():P,_e=0,Te=0,et=null,Et=null,ot=[];!re.isZero()||!ye.isZero();)et=Z(re,Ue),_e=et[1].toJSNumber(),Q&&(_e=Ue-1-_e),Et=Z(ye,Ue),Te=Et[1].toJSNumber(),ce&&(Te=Ue-1-Te),re=et[0],ye=Et[0],ot.push(z(_e,Te));for(var Ot=z(Q?1:0,ce?1:0)!==0?hr(-1):hr(0),Gr=ot.length-1;Gr>=0;Gr-=1)Ot=Ot.multiply(Ue).add(hr(ot[Gr]));return Ot}u.prototype.not=function(){return this.negate().prev()},d.prototype.not=f.prototype.not=u.prototype.not,u.prototype.and=function(N){return te(this,N,function(P,z){return P&z})},d.prototype.and=f.prototype.and=u.prototype.and,u.prototype.or=function(N){return te(this,N,function(P,z){return P|z})},d.prototype.or=f.prototype.or=u.prototype.or,u.prototype.xor=function(N){return te(this,N,function(P,z){return P^z})},d.prototype.xor=f.prototype.xor=u.prototype.xor;var ee=1<<30,$=(t&-t)*(t&-t)|ee;function H(N){var P=N.value,z=typeof P=="number"?P|ee:typeof P=="bigint"?P|BigInt(ee):P[0]+P[1]*t|$;return z&-z}function M(N,P){if(P.compareTo(N)<=0){var z=M(N,P.square(P)),Q=z.p,ce=z.e,re=Q.multiply(P);return re.compareTo(N)<=0?{p:re,e:ce*2+1}:{p:Q,e:ce*2}}return{p:hr(1),e:0}}u.prototype.bitLength=function(){var N=this;return N.compareTo(hr(0))<0&&(N=N.negate().subtract(hr(1))),N.compareTo(hr(0))===0?hr(0):hr(M(N,hr(2)).e).add(hr(1))},d.prototype.bitLength=f.prototype.bitLength=u.prototype.bitLength;function q(N,P){return N=Ye(N),P=Ye(P),N.greater(P)?N:P}function Y(N,P){return N=Ye(N),P=Ye(P),N.lesser(P)?N:P}function j(N,P){if(N=Ye(N).abs(),P=Ye(P).abs(),N.equals(P))return N;if(N.isZero())return P;if(P.isZero())return N;for(var z=c[1],Q,ce;N.isEven()&&P.isEven();)Q=Y(H(N),H(P)),N=N.divide(Q),P=P.divide(Q),z=z.multiply(Q);for(;N.isEven();)N=N.divide(H(N));do{for(;P.isEven();)P=P.divide(H(P));N.greater(P)&&(ce=P,P=N,N=ce),P=P.subtract(N)}while(!P.isZero());return z.isUnit()?N:N.multiply(z)}function ie(N,P){return N=Ye(N).abs(),P=Ye(P).abs(),N.divide(j(N,P)).multiply(P)}function we(N,P,z){N=Ye(N),P=Ye(P);var Q=z||Math.random,ce=Y(N,P),re=q(N,P),ye=re.subtract(ce).add(1);if(ye.isSmall)return ce.add(Math.floor(Q()*ye));for(var _e=qe(ye,t).value,Te=[],et=!0,Et=0;Et<_e.length;Et++){var ot=et?_e[Et]+(Et+1<_e.length?_e[Et+1]/t:0):t,Ot=A(Q()*ot);Te.push(Ot),Ot<_e[Et]&&(et=!1)}return ce.add(c.fromArray(Te,t,!1))}var oe=function(N,P,z,Q){z=z||o,N=String(N),Q||(N=N.toLowerCase(),z=z.toLowerCase());var ce=N.length,re,ye=Math.abs(P),_e={};for(re=0;re=ye){if(Te==="1"&&ye===1)continue;throw new Error(Te+" is not a valid digit in base "+P+".")}}P=Ye(P);var et=[],Et=N[0]==="-";for(re=Et?1:0;re"&&re=0;re--)Q=Q.add(N[re].times(ce)),ce=ce.times(P);return z?Q.negate():Q}function ct(N,P){return P=P||o,N"}function qe(N,P){if(P=hr(P),P.isZero()){if(N.isZero())return{value:[0],isNegative:!1};throw new Error("Cannot convert nonzero numbers to base 0.")}if(P.equals(-1)){if(N.isZero())return{value:[0],isNegative:!1};if(N.isNegative())return{value:[].concat.apply([],Array.apply(null,Array(-N.toJSNumber())).map(Array.prototype.valueOf,[1,0])),isNegative:!1};var z=Array.apply(null,Array(N.toJSNumber()-1)).map(Array.prototype.valueOf,[0,1]);return z.unshift([1]),{value:[].concat.apply([],z),isNegative:!1}}var Q=!1;if(N.isNegative()&&P.isPositive()&&(Q=!0,N=N.abs()),P.isUnit())return N.isZero()?{value:[0],isNegative:!1}:{value:Array.apply(null,Array(N.toJSNumber())).map(Number.prototype.valueOf,1),isNegative:Q};for(var ce=[],re=N,ye;re.isNegative()||re.compareAbs(P)>=0;){ye=re.divmod(P),re=ye.quotient;var _e=ye.remainder;_e.isNegative()&&(_e=P.minus(_e).abs(),re=re.next()),ce.push(_e.toJSNumber())}return ce.push(re.toJSNumber()),{value:ce.reverse(),isNegative:Q}}function zt(N,P,z){var Q=qe(N,P);return(Q.isNegative?"-":"")+Q.value.map(function(ce){return ct(ce,z)}).join("")}u.prototype.toArray=function(N){return qe(this,N)},f.prototype.toArray=function(N){return qe(this,N)},d.prototype.toArray=function(N){return qe(this,N)},u.prototype.toString=function(N,P){if(N===e&&(N=10),N!==10||P)return zt(this,N,P);for(var z=this.value,Q=z.length,ce=String(z[--Q]),re="0000000",ye;--Q>=0;)ye=String(z[Q]),ce+=re.slice(ye.length)+ye;var _e=this.sign?"-":"";return _e+ce},f.prototype.toString=function(N,P){return N===e&&(N=10),N!=10||P?zt(this,N,P):String(this.value)},d.prototype.toString=f.prototype.toString,d.prototype.toJSON=u.prototype.toJSON=f.prototype.toJSON=function(){return this.toString()},u.prototype.valueOf=function(){return parseInt(this.toString(),10)},u.prototype.toJSNumber=u.prototype.valueOf,f.prototype.valueOf=function(){return this.value},f.prototype.toJSNumber=f.prototype.valueOf,d.prototype.valueOf=d.prototype.toJSNumber=function(){return parseInt(this.toString(),10)};function ir(N){if(w(+N)){var P=+N;if(P===A(P))return s?new d(BigInt(P)):new f(P);throw new Error("Invalid integer: "+N)}var z=N[0]==="-";z&&(N=N.slice(1));var Q=N.split(/e/i);if(Q.length>2)throw new Error("Invalid integer: "+Q.join("e"));if(Q.length===2){var ce=Q[1];if(ce[0]==="+"&&(ce=ce.slice(1)),ce=+ce,ce!==A(ce)||!w(ce))throw new Error("Invalid integer: "+ce+" is not a valid exponent.");var re=Q[0],ye=re.indexOf(".");if(ye>=0&&(ce-=re.length-ye-1,re=re.slice(0,ye)+re.slice(ye+1)),ce<0)throw new Error("Cannot include negative exponent part for integers");re+=new Array(ce+1).join("0"),N=re}var _e=/^([0-9][0-9]*)$/.test(N);if(!_e)throw new Error("Invalid integer: "+N);if(s)return new d(BigInt(z?"-"+N:N));for(var Te=[],et=N.length,Et=r,ot=et-Et;et>0;)Te.push(+N.slice(ot,et)),ot-=Et,ot<0&&(ot=0),et-=Et;return p(Te),new u(Te,z)}function tn(N){if(s)return new d(BigInt(N));if(w(N)){if(N!==A(N))throw new Error(N+" is not an integer.");return new f(N)}return ir(N.toString())}function Ye(N){return typeof N=="number"?tn(N):typeof N=="string"?ir(N):typeof N=="bigint"?new d(N):N}for(var $t=0;$t<1e3;$t++)c[$t]=Ye($t),$t>0&&(c[-$t]=Ye(-$t));return c.one=c[1],c.zero=c[0],c.minusOne=c[-1],c.max=q,c.min=Y,c.gcd=j,c.lcm=ie,c.isInstance=function(N){return N instanceof u||N instanceof f||N instanceof d},c.randBetween=we,c.fromArray=function(N,P,z){return je(N.map(Ye),Ye(P||10),z)},c})();typeof Hi<"u"&&Hi.hasOwnProperty("exports")&&(Hi.exports=hr);typeof define=="function"&&define.amd&&define(function(){return hr})});var ty=lo((Mo,is)=>{(function(e,t){var r=Array.prototype,n=Object.prototype,a=r.slice,o=n.hasOwnProperty,s=r.forEach,c={},u={forEach:function(p,T,A){var C,S,k;if(p!==null){if(s&&p.forEach===s)p.forEach(T,A);else if(p.length===+p.length){for(C=0,S=p.length;Cm.length?(this.options.missing_key_callback&&this.options.missing_key_callback(v,p),y=[A,C],this.options.debug===!0&&console.log(y[d(E)(S)]),y[d()(S)]):(y=m[b],y||(y=[A,C],y[d()(S)]))}});var R=(function(){function p(C){return Object.prototype.toString.call(C).slice(8,-1).toLowerCase()}function T(C,S){for(var k=[];S>0;k[--S]=C);return k.join("")}var A=function(){return A.cache.hasOwnProperty(arguments[0])||(A.cache[arguments[0]]=A.parse(arguments[0])),A.format.call(null,A.cache[arguments[0]],arguments)};return A.format=function(C,S){var k=1,v=C.length,_="",g,O=[],E,m,y,b,x,D;for(E=0;E"u"||g===null)&&(g=""),y[8]){case"b":g=g.toString(2);break;case"c":g=String.fromCharCode(g);break;case"d":g=parseInt(g,10);break;case"e":g=y[7]?g.toExponential(y[7]):g.toExponential();break;case"f":g=y[7]?parseFloat(g).toFixed(y[7]):parseFloat(g);break;case"o":g=g.toString(8);break;case"s":g=(g=String(g))&&y[7]?g.substring(0,y[7]):g;break;case"u":g=Math.abs(g);break;case"x":g=g.toString(16);break;case"X":g=g.toString(16).toUpperCase();break}g=/[def]/.test(y[8])&&y[3]&&g>=0?"+"+g:g,x=y[4]?y[4]=="0"?"0":y[4].charAt(1):" ",D=y[6]-String(g).length,b=y[6]?T(x,D):"",O.push(y[5]?g+b:b+g)}return O.join("")},A.cache={},A.parse=function(C){for(var S=C,k=[],v=[],_=0;S;){if((k=/^[^\x25]+/.exec(S))!==null)v.push(k[0]);else if((k=/^\x25{2}/.exec(S))!==null)v.push("%");else if((k=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(S))!==null){if(k[2]){_|=1;var g=[],O=k[2],E=[];if((E=/^([a-z_][a-z_\d]*)/i.exec(O))!==null)for(g.push(E[1]);(O=O.substring(E[0].length))!=="";)if((E=/^\.([a-z_][a-z_\d]*)/i.exec(O))!==null)g.push(E[1]);else if((E=/^\[(\d+)\]/.exec(O))!==null)g.push(E[1]);else throw"[sprintf] huh?";else throw"[sprintf] huh?";k[2]=g}else _|=2;if(_===3)throw"[sprintf] mixing positional and named placeholders is not (yet) supported";v.push(k)}else throw"[sprintf] huh?";S=S.substring(k[0].length)}return v},A})(),h=function(p,T){return T.unshift(p),R.apply(null,T)};f.parse_plural=function(p,T){return p=p.replace(/n/g,T),f.parse_expression(p)},f.sprintf=function(p,T){return{}.toString.call(T)=="[object Array]"?h(p,[].slice.call(T)):R.apply(this,[].slice.call(arguments))},f.prototype.sprintf=function(){return f.sprintf.apply(this,arguments)},f.PF={},f.PF.parse=function(p){var T=f.PF.extractPluralExpr(p);return f.PF.parser.parse.call(f.PF.parser,T)},f.PF.compile=function(p){function T(C){return C===!0?1:C||0}var A=f.PF.parse(p);return function(C){return T(f.PF.interpreter(A)(C))}},f.PF.interpreter=function(p){return function(T){var A;switch(p.type){case"GROUP":return f.PF.interpreter(p.expr)(T);case"TERNARY":return f.PF.interpreter(p.expr)(T)?f.PF.interpreter(p.truthy)(T):f.PF.interpreter(p.falsey)(T);case"OR":return f.PF.interpreter(p.left)(T)||f.PF.interpreter(p.right)(T);case"AND":return f.PF.interpreter(p.left)(T)&&f.PF.interpreter(p.right)(T);case"LT":return f.PF.interpreter(p.left)(T)f.PF.interpreter(p.right)(T);case"LTE":return f.PF.interpreter(p.left)(T)<=f.PF.interpreter(p.right)(T);case"GTE":return f.PF.interpreter(p.left)(T)>=f.PF.interpreter(p.right)(T);case"EQ":return f.PF.interpreter(p.left)(T)==f.PF.interpreter(p.right)(T);case"NEQ":return f.PF.interpreter(p.left)(T)!=f.PF.interpreter(p.right)(T);case"MOD":return f.PF.interpreter(p.left)(T)%f.PF.interpreter(p.right)(T);case"VAR":return T;case"NUM":return p.val;default:throw new Error("Invalid Token found.")}}},f.PF.extractPluralExpr=function(p){p=p.replace(/^\s\s*/,"").replace(/\s\s*$/,""),/;\s*$/.test(p)||(p=p.concat(";"));var T=/nplurals\=(\d+);/,A=/plural\=(.*);/,C=p.match(T),S={},k;if(C.length>1)S.nplurals=C[1];else throw new Error("nplurals not found in plural_forms string: "+p);if(p=p.replace(T,""),k=p.match(A),!(k&&k.length>1))throw new Error("`plural` expression not found: "+p);return k[1]},f.PF.parser=(function(){var p={trace:function(){},yy:{},symbols_:{error:2,expressions:3,e:4,EOF:5,"?":6,":":7,"||":8,"&&":9,"<":10,"<=":11,">":12,">=":13,"!=":14,"==":15,"%":16,"(":17,")":18,n:19,NUMBER:20,$accept:0,$end:1},terminals_:{2:"error",5:"EOF",6:"?",7:":",8:"||",9:"&&",10:"<",11:"<=",12:">",13:">=",14:"!=",15:"==",16:"%",17:"(",18:")",19:"n",20:"NUMBER"},productions_:[0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]],performAction:function(C,S,k,v,_,g,O){var E=g.length-1;switch(_){case 1:return{type:"GROUP",expr:g[E-1]};case 2:this.$={type:"TERNARY",expr:g[E-4],truthy:g[E-2],falsey:g[E]};break;case 3:this.$={type:"OR",left:g[E-2],right:g[E]};break;case 4:this.$={type:"AND",left:g[E-2],right:g[E]};break;case 5:this.$={type:"LT",left:g[E-2],right:g[E]};break;case 6:this.$={type:"LTE",left:g[E-2],right:g[E]};break;case 7:this.$={type:"GT",left:g[E-2],right:g[E]};break;case 8:this.$={type:"GTE",left:g[E-2],right:g[E]};break;case 9:this.$={type:"NEQ",left:g[E-2],right:g[E]};break;case 10:this.$={type:"EQ",left:g[E-2],right:g[E]};break;case 11:this.$={type:"MOD",left:g[E-2],right:g[E]};break;case 12:this.$={type:"GROUP",expr:g[E-1]};break;case 13:this.$={type:"VAR"};break;case 14:this.$={type:"NUM",val:Number(C)};break}},table:[{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}],defaultActions:{6:[2,1]},parseError:function(C,S){throw new Error(C)},parse:function(C){var S=this,k=[0],v=[null],_=[],g=this.table,O="",E=0,m=0,y=0,b=2,x=1;this.lexer.setInput(C),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,typeof this.lexer.yylloc>"u"&&(this.lexer.yylloc={});var D=this.lexer.yylloc;_.push(D),typeof this.yy.parseError=="function"&&(this.parseError=this.yy.parseError);function F(H){k.length=k.length-2*H,v.length=v.length-H,_.length=_.length-H}function B(){var H;return H=S.lexer.lex()||1,typeof H!="number"&&(H=S.symbols_[H]||H),H}for(var K,Z,pe,Ie,be,xe,Le={},Ue,Ve,te,ee;;){if(pe=k[k.length-1],this.defaultActions[pe]?Ie=this.defaultActions[pe]:(K==null&&(K=B()),Ie=g[pe]&&g[pe][K]),typeof Ie>"u"||!Ie.length||!Ie[0]){if(!y){ee=[];for(Ue in g[pe])this.terminals_[Ue]&&Ue>2&&ee.push("'"+this.terminals_[Ue]+"'");var $="";this.lexer.showPosition?$="Parse error on line "+(E+1)+`: `+this.lexer.showPosition()+` Expecting `+ee.join(", ")+", got '"+this.terminals_[K]+"'":$="Parse error on line "+(E+1)+": Unexpected "+(K==1?"end of input":"'"+(this.terminals_[K]||K)+"'"),this.parseError($,{text:this.lexer.match,token:this.terminals_[K]||K,line:this.lexer.yylineno,loc:D,expected:ee})}if(y==3){if(K==x)throw new Error($||"Parsing halted.");m=this.lexer.yyleng,O=this.lexer.yytext,E=this.lexer.yylineno,D=this.lexer.yylloc,K=B()}for(;!(b.toString()in g[pe]);){if(pe==0)throw new Error($||"Parsing halted.");F(1),pe=k[k.length-1]}Z=K,K=b,pe=k[k.length-1],Ie=g[pe]&&g[pe][b],y=3}if(Ie[0]instanceof Array&&Ie.length>1)throw new Error("Parse Error: multiple actions possible at state: "+pe+", token: "+K);switch(Ie[0]){case 1:k.push(K),v.push(this.lexer.yytext),_.push(this.lexer.yylloc),k.push(Ie[1]),K=null,Z?(K=Z,Z=null):(m=this.lexer.yyleng,O=this.lexer.yytext,E=this.lexer.yylineno,D=this.lexer.yylloc,y>0&&y--);break;case 2:if(Ve=this.productions_[Ie[1]][1],Le.$=v[v.length-Ve],Le._$={first_line:_[_.length-(Ve||1)].first_line,last_line:_[_.length-1].last_line,first_column:_[_.length-(Ve||1)].first_column,last_column:_[_.length-1].last_column},xe=this.performAction.call(Le,O,m,E,this.yy,Ie[1],v,_),typeof xe<"u")return xe;Ve&&(k=k.slice(0,-1*Ve*2),v=v.slice(0,-1*Ve),_=_.slice(0,-1*Ve)),k.push(this.productions_[Ie[1]][0]),v.push(Le.$),_.push(Le._$),te=g[k[k.length-2]][k[k.length-1]],k.push(te);break;case 3:return!0}}return!0}},T=(function(){var A={EOF:1,parseError:function(S,k){if(this.yy.parseError)this.yy.parseError(S,k);else throw new Error(S)},setInput:function(C){return this._input=C,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this},input:function(){var C=this._input[0];this.yytext+=C,this.yyleng++,this.match+=C,this.matched+=C;var S=C.match(/\n/);return S&&this.yylineno++,this._input=this._input.slice(1),C},unput:function(C){return this._input=C+this._input,this},more:function(){return this._more=!0,this},pastInput:function(){var C=this.matched.substr(0,this.matched.length-this.match.length);return(C.length>20?"...":"")+C.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var C=this.match;return C.length<20&&(C+=this._input.substr(0,20-C.length)),(C.substr(0,20)+(C.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var C=this.pastInput(),S=new Array(C.length+1).join("-");return C+this.upcomingInput()+` `+S+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var C,S,k,v;this._more||(this.yytext="",this.match="");for(var _=this._currentRules(),g=0;g<_.length;g++)if(S=this._input.match(this.rules[_[g]]),S)return v=S[0].match(/\n.*/g),v&&(this.yylineno+=v.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:v?v[v.length-1].length-1:this.yylloc.last_column+S[0].length},this.yytext+=S[0],this.match+=S[0],this.matches=S,this.yyleng=this.yytext.length,this._more=!1,this._input=this._input.slice(S[0].length),this.matched+=S[0],C=this.performAction.call(this,this.yy,this,_[g],this.conditionStack[this.conditionStack.length-1]),C||void 0;if(this._input==="")return this.EOF;this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. `+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var S=this.next();return typeof S<"u"?S:this.lex()},begin:function(S){this.conditionStack.push(S)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(S){this.begin(S)}};return A.performAction=function(S,k,v,_){var g=_;switch(v){case 0:break;case 1:return 20;case 2:return 19;case 3:return 8;case 4:return 9;case 5:return 6;case 6:return 7;case 7:return 11;case 8:return 13;case 9:return 10;case 10:return 12;case 11:return 14;case 12:return 15;case 13:return 16;case 14:return 17;case 15:return 18;case 16:return 5;case 17:return"INVALID"}},A.rules=[/^\s+/,/^[0-9]+(\.[0-9]+)?\b/,/^n\b/,/^\|\|/,/^&&/,/^\?/,/^:/,/^<=/,/^>=/,/^/,/^!=/,/^==/,/^%/,/^\(/,/^\)/,/^$/,/^./],A.conditions={INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],inclusive:!0}},A})();return p.lexer=T,p})(),typeof Mo<"u"?(typeof is<"u"&&is.exports&&(Mo=is.exports=f),Mo.Jed=f):(typeof define=="function"&&define.amd&&define(function(){return f}),e.Jed=f)})(Mo)});function Dn(e,t){for(var r in t)e[r]=t[r];return e}function Ty(e){var t=e.parentNode;t&&t.removeChild(e)}function i(e,t,r){var n,a,o,s={};for(o in t)o=="key"?n=t[o]:o=="ref"?a=t[o]:s[o]=t[o];if(arguments.length>2&&(s.children=arguments.length>3?Ko.call(arguments,2):r),typeof e=="function"&&e.defaultProps!=null)for(o in e.defaultProps)s[o]===void 0&&(s[o]=e.defaultProps[o]);return Vo(e,s,n,a,null)}function Vo(e,t,r,n,a){var o={type:e,props:t,key:r,ref:n,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:a??++Ey};return a==null&&ze.vnode!=null&&ze.vnode(o),o}function gs(){return{current:null}}function ae(e){return e.children}function Yr(e,t){this.props=e,this.context=t}function qo(e,t){if(t==null)return e.__?qo(e.__,e.__.__k.indexOf(e)+1):null;for(var r;t0?Vo(h.type,h.props,h.key,h.ref?h.ref:null,h.__v):h)!=null){if(h.__=r,h.__b=r.__b+1,(R=C[d])===null||R&&h.key==R.key&&h.type===R.type)C[d]=void 0;else for(w=0;w2&&(s.children=arguments.length>3?Ko.call(arguments,2):r),Vo(e.type,s,n||e.key,a||e.ref,null)}function Kt(e,t){var r={__c:t="__cC"+wy++,__:e,Consumer:function(n,a){return n.children(a)},Provider:function(n){var a,o;return this.getChildContext||(a=[],(o={})[t]=this,this.getChildContext=function(){return o},this.shouldComponentUpdate=function(s){this.props.value!==s.value&&a.some(nd)},this.sub=function(s){a.push(s);var c=s.componentWillUnmount;s.componentWillUnmount=function(){a.splice(a.indexOf(s),1),c&&c.call(s)}}),n.children}};return r.Provider.__=r.Consumer.contextType=r}var Ko,ze,Ey,uR,Wo,_y,wy,ps,Ay,lR,Re=_u(()=>{ps={},Ay=[],lR=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;Ko=Ay.slice,ze={__e:function(e,t,r,n){for(var a,o,s;t=t.__;)if((a=t.__c)&&!a.__)try{if((o=a.constructor)&&o.getDerivedStateFromError!=null&&(a.setState(o.getDerivedStateFromError(e)),s=a.__d),a.componentDidCatch!=null&&(a.componentDidCatch(e,n||{}),s=a.__d),s)return a.__E=a}catch(c){e=c}throw e}},Ey=0,uR=function(e){return e!=null&&e.constructor===void 0},Yr.prototype.setState=function(e,t){var r;r=this.__s!=null&&this.__s!==this.state?this.__s:this.__s=Dn({},this.state),typeof e=="function"&&(e=e(Dn({},r),this.props)),e&&Dn(r,e),e!=null&&this.__v&&(t&&this._sb.push(t),nd(this))},Yr.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),nd(this))},Yr.prototype.render=ae,Wo=[],hs.__r=0,wy=0});function fa(e,t){ze.__h&&ze.__h(Wt,e,Wa||t),Wa=0;var r=Wt.__H||(Wt.__H={__:[],__h:[]});return e>=r.__.length&&r.__.push({__V:_s}),r.__[e]}function de(e){return Wa=1,bs(By,e)}function bs(e,t,r){var n=fa(qn++,2);if(n.t=e,!n.__c&&(n.__=[r?r(t):By(void 0,t),function(o){var s=n.__N?n.__N[0]:n.__[0],c=n.t(s,o);s!==c&&(n.__N=[c,n.__[1]],n.__c.setState({}))}],n.__c=Wt,!Wt.u)){Wt.u=!0;var a=Wt.shouldComponentUpdate;Wt.shouldComponentUpdate=function(o,s,c){if(!n.__c.__H)return!0;var u=n.__c.__H.__.filter(function(d){return d.__c});if(u.every(function(d){return!d.__N}))return!a||a.call(this,o,s,c);var f=!1;return u.forEach(function(d){if(d.__N){var w=d.__[0];d.__=d.__N,d.__N=void 0,w!==d.__[0]&&(f=!0)}}),!(!f&&n.__c.props===o)&&(!a||a.call(this,o,s,c))}}return n.__N||n.__}function Ge(e,t){var r=fa(qn++,3);!ze.__s&&ld(r.__H,t)&&(r.__=e,r.i=t,Wt.__H.__h.push(r))}function Kn(e,t){var r=fa(qn++,4);!ze.__s&&ld(r.__H,t)&&(r.__=e,r.i=t,Wt.__h.push(r))}function Yt(e){return Wa=5,en(function(){return{current:e}},[])}function cd(e,t,r){Wa=6,Kn(function(){return typeof e=="function"?(e(t()),function(){return e(null)}):e?(e.current=t(),function(){return e.current=null}):void 0},r==null?r:r.concat(e))}function en(e,t){var r=fa(qn++,7);return ld(r.__H,t)?(r.__V=e(),r.i=t,r.__h=e,r.__V):r.__}function Yn(e,t){return Wa=8,en(function(){return e},t)}function lr(e){var t=Wt.context[e.__c],r=fa(qn++,9);return r.c=e,t?(r.__==null&&(r.__=!0,t.sub(Wt)),t.props.value):e.__}function Yo(e,t){ze.useDebugValue&&ze.useDebugValue(t?t(e):e)}function vs(e){var t=fa(qn++,10),r=de();return t.__=e,Wt.componentDidCatch||(Wt.componentDidCatch=function(n,a){t.__&&t.__(n,a),r[1](n)}),[r[0],function(){r[1](void 0)}]}function ud(){var e=fa(qn++,11);if(!e.__){for(var t=Wt.__v;t!==null&&!t.__m&&t.__!==null;)t=t.__;var r=t.__m||(t.__m=[0,0]);e.__="P"+r[0]+"-"+r[1]++}return e.__}function hR(){for(var e;e=Gy.shift();)if(e.__P&&e.__H)try{e.__H.__h.forEach(ys),e.__H.__h.forEach(sd),e.__H.__h=[]}catch(t){e.__H.__h=[],ze.__e(t,e.__v)}}function mR(e){var t,r=function(){clearTimeout(n),Hy&&cancelAnimationFrame(t),setTimeout(e)},n=setTimeout(r,100);Hy&&(t=requestAnimationFrame(r))}function ys(e){var t=Wt,r=e.__c;typeof r=="function"&&(e.__c=void 0,r()),Wt=t}function sd(e){var t=Wt;e.__c=e.__(),Wt=t}function ld(e,t){return!e||e.length!==t.length||t.some(function(r,n){return r!==e[n]})}function By(e,t){return typeof t=="function"?t(e):t}var qn,Wt,id,Py,Wa,Gy,_s,Ly,Uy,My,ky,Fy,Hy,Be=_u(()=>{Re();Wa=0,Gy=[],_s=[],Ly=ze.__b,Uy=ze.__r,My=ze.diffed,ky=ze.__c,Fy=ze.unmount;ze.__b=function(e){Wt=null,Ly&&Ly(e)},ze.__r=function(e){Uy&&Uy(e),qn=0;var t=(Wt=e.__c).__H;t&&(id===Wt?(t.__h=[],Wt.__h=[],t.__.forEach(function(r){r.__N&&(r.__=r.__N),r.__V=_s,r.__N=r.i=void 0})):(t.__h.forEach(ys),t.__h.forEach(sd),t.__h=[])),id=Wt},ze.diffed=function(e){My&&My(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(Gy.push(t)!==1&&Py===ze.requestAnimationFrame||((Py=ze.requestAnimationFrame)||mR)(hR)),t.__H.__.forEach(function(r){r.i&&(r.__H=r.i),r.__V!==_s&&(r.__=r.__V),r.i=void 0,r.__V=_s})),id=Wt=null},ze.__c=function(e,t){t.some(function(r){try{r.__h.forEach(ys),r.__h=r.__h.filter(function(n){return!n.__||sd(n)})}catch(n){t.some(function(a){a.__h&&(a.__h=[])}),t=[],ze.__e(n,r.__v)}}),ky&&ky(e,t)},ze.unmount=function(e){Fy&&Fy(e);var t,r=e.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{ys(n)}catch(a){t=a}}),r.__H=void 0,t&&ze.__e(t,r.__v))};Hy=typeof requestAnimationFrame=="function"});var vb={};Bp(vb,{Children:()=>Zy,Component:()=>Yr,Fragment:()=>ae,PureComponent:()=>Es,StrictMode:()=>mb,Suspense:()=>zo,SuspenseList:()=>Va,__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED:()=>cb,cloneElement:()=>lb,createContext:()=>Kt,createElement:()=>i,createFactory:()=>ub,createPortal:()=>nb,createRef:()=>gs,default:()=>As,findDOMNode:()=>fb,flushSync:()=>hb,forwardRef:()=>ws,hydrate:()=>ib,isValidElement:()=>pd,lazy:()=>rb,memo:()=>Qy,render:()=>ob,startTransition:()=>hd,unmountComponentAtNode:()=>db,unstable_batchedUpdates:()=>pb,useCallback:()=>Yn,useContext:()=>lr,useDebugValue:()=>Yo,useDeferredValue:()=>gb,useEffect:()=>Ge,useErrorBoundary:()=>vs,useId:()=>ud,useImperativeHandle:()=>cd,useInsertionEffect:()=>yb,useLayoutEffect:()=>Kn,useMemo:()=>en,useReducer:()=>bs,useRef:()=>Yt,useState:()=>de,useSyncExternalStore:()=>bb,useTransition:()=>_b,version:()=>RR});function jy(e,t){for(var r in t)e[r]=t[r];return e}function fd(e,t){for(var r in e)if(r!=="__source"&&!(r in t))return!0;for(var n in t)if(n!=="__source"&&e[n]!==t[n])return!0;return!1}function dd(e,t){return e===t&&(e!==0||1/e==1/t)||e!=e&&t!=t}function Es(e){this.props=e}function Qy(e,t){function r(a){var o=this.props.ref,s=o==a.ref;return!s&&o&&(o.call?o(null):o.current=null),t?!t(this.props,a)||!s:fd(this.props,a)}function n(a){return this.shouldComponentUpdate=r,i(e,a)}return n.displayName="Memo("+(e.displayName||e.name)+")",n.prototype.isReactComponent=!0,n.__f=!0,n}function ws(e){function t(r){var n=jy({},r);return delete n.ref,e(n,r.ref||null)}return t.$$typeof=gR,t.render=t,t.prototype.isReactComponent=t.__f=!0,t.displayName="ForwardRef("+(e.displayName||e.name)+")",t}function Jy(e,t,r){return e&&(e.__c&&e.__c.__H&&(e.__c.__H.__.forEach(function(n){typeof n.__c=="function"&&n.__c()}),e.__c.__H=null),(e=jy({},e)).__c!=null&&(e.__c.__P===r&&(e.__c.__P=t),e.__c=null),e.__k=e.__k&&e.__k.map(function(n){return Jy(n,t,r)})),e}function eb(e,t,r){return e&&(e.__v=null,e.__k=e.__k&&e.__k.map(function(n){return eb(n,t,r)}),e.__c&&e.__c.__P===t&&(e.__e&&r.insertBefore(e.__e,e.__d),e.__c.__e=!0,e.__c.__P=r)),e}function zo(){this.__u=0,this.t=null,this.__b=null}function tb(e){var t=e.__.__c;return t&&t.__a&&t.__a(e)}function rb(e){var t,r,n;function a(o){if(t||(t=e()).then(function(s){r=s.default||s},function(s){n=s}),n)throw n;if(!r)throw t;return i(r,o)}return a.displayName="Lazy",a.__f=!0,a}function Va(){this.u=null,this.o=null}function yR(e){return this.getChildContext=function(){return e.context},e.children}function bR(e){var t=this,r=e.i;t.componentWillUnmount=function(){Pn(null,t.l),t.l=null,t.i=null},t.i&&t.i!==r&&t.componentWillUnmount(),e.__v?(t.l||(t.i=r,t.l={nodeType:1,parentNode:r,childNodes:[],appendChild:function(n){this.childNodes.push(n),t.i.appendChild(n)},insertBefore:function(n,a){this.childNodes.push(n),t.i.appendChild(n)},removeChild:function(n){this.childNodes.splice(this.childNodes.indexOf(n)>>>1,1),t.i.removeChild(n)}}),Pn(i(yR,{context:t.context},e.__v),t.l)):t.l&&t.componentWillUnmount()}function nb(e,t){var r=i(bR,{__v:e,i:t});return r.containerInfo=t,r}function ob(e,t,r){return t.__k==null&&(t.textContent=""),Pn(e,t),typeof r=="function"&&r(),e?e.__c:null}function ib(e,t,r){return od(e,t),typeof r=="function"&&r(),e?e.__c:null}function AR(){}function TR(){return this.cancelBubble}function NR(){return this.defaultPrevented}function ub(e){return i.bind(null,e)}function pd(e){return!!e&&e.$$typeof===ab}function lb(e){return pd(e)?Dy.apply(null,arguments):e}function db(e){return!!e.__k&&(Pn(null,e),!0)}function fb(e){return e&&(e.base||e.nodeType===1&&e)||null}function hd(e){e()}function gb(e){return e}function _b(){return[!1,hd]}function bb(e,t){var r=t(),n=de({h:{__:r,v:t}}),a=n[0].h,o=n[1];return Kn(function(){a.__=r,a.v=t,dd(a.__,t())||o({h:a})},[e,r,t]),Ge(function(){return dd(a.__,a.v())||o({h:a}),e(function(){dd(a.__,a.v())||o({h:a})})},[e]),r}var Wy,gR,Vy,Zy,_R,qy,Ky,ab,vR,ER,wR,Yy,sb,zy,$y,Xy,cb,RR,pb,hb,mb,yb,As,pa=_u(()=>{Re();Re();Be();Be();(Es.prototype=new Yr).isPureReactComponent=!0,Es.prototype.shouldComponentUpdate=function(e,t){return fd(this.props,e)||fd(this.state,t)};Wy=ze.__b;ze.__b=function(e){e.type&&e.type.__f&&e.ref&&(e.props.ref=e.ref,e.ref=null),Wy&&Wy(e)};gR=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.forward_ref")||3911;Vy=function(e,t){return e==null?null:_n(_n(e).map(t))},Zy={map:Vy,forEach:Vy,count:function(e){return e?_n(e).length:0},only:function(e){var t=_n(e);if(t.length!==1)throw"Children.only";return t[0]},toArray:_n},_R=ze.__e;ze.__e=function(e,t,r,n){if(e.then){for(var a,o=t;o=o.__;)if((a=o.__c)&&a.__c)return t.__e==null&&(t.__e=r.__e,t.__k=r.__k),a.__c(e,t)}_R(e,t,r,n)};qy=ze.unmount;ze.unmount=function(e){var t=e.__c;t&&t.__R&&t.__R(),t&&e.__h===!0&&(e.type=null),qy&&qy(e)},(zo.prototype=new Yr).__c=function(e,t){var r=t.__c,n=this;n.t==null&&(n.t=[]),n.t.push(r);var a=tb(n.__v),o=!1,s=function(){o||(o=!0,r.__R=null,a?a(c):c())};r.__R=s;var c=function(){if(!--n.__u){if(n.state.__a){var f=n.state.__a;n.__v.__k[0]=eb(f,f.__c.__P,f.__c.__O)}var d;for(n.setState({__a:n.__b=null});d=n.t.pop();)d.forceUpdate()}},u=t.__h===!0;n.__u++||u||n.setState({__a:n.__b=n.__v.__k[0]}),e.then(s,s)},zo.prototype.componentWillUnmount=function(){this.t=[]},zo.prototype.render=function(e,t){if(this.__b){if(this.__v.__k){var r=document.createElement("div"),n=this.__v.__k[0].__c;this.__v.__k[0]=Jy(this.__b,r,n.__O=n.__P)}this.__b=null}var a=t.__a&&i(ae,null,e.fallback);return a&&(a.__h=null),[i(ae,null,t.__a?null:e.children),a]};Ky=function(e,t,r){if(++r[1]===r[0]&&e.o.delete(t),e.props.revealOrder&&(e.props.revealOrder[0]!=="t"||!e.o.size))for(r=e.u;r;){for(;r.length>3;)r.pop()();if(r[1]{"use strict";var Za=(pa(),X1(vb));function FP(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var HP=typeof Object.is=="function"?Object.is:FP,GP=Za.useState,BP=Za.useEffect,WP=Za.useLayoutEffect,VP=Za.useDebugValue;function qP(e,t){var r=t(),n=GP({inst:{value:r,getSnapshot:t}}),a=n[0].inst,o=n[1];return WP(function(){a.value=r,a.getSnapshot=t,zf(a)&&o({inst:a})},[e,r,t]),BP(function(){return zf(a)&&o({inst:a}),e(function(){zf(a)&&o({inst:a})})},[e]),VP(r),r}function zf(e){var t=e.getSnapshot;e=e.value;try{var r=t();return!HP(e,r)}catch{return!0}}function KP(e,t){return t()}var YP=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?KP:qP;Lv.useSyncExternalStore=Za.useSyncExternalStore!==void 0?Za.useSyncExternalStore:YP});var kv=lo((nW,Mv)=>{"use strict";Mv.exports=Uv()});var t1=lo((JE,e1)=>{var ZE=(function(){var e=function(S,k){var v=236,_=17,g=S,O=r[k],E=null,m=0,y=null,b=[],x={},D=function(te,ee){m=g*4+17,E=(function($){for(var H=new Array($),M=0;M<$;M+=1){H[M]=new Array($);for(var q=0;q<$;q+=1)H[M][q]=null}return H})(m),F(0,0),F(m-7,0),F(0,m-7),Z(),K(),Ie(te,ee),g>=7&&pe(te),y==null&&(y=Le(g,O,b)),be(y,ee)},F=function(te,ee){for(var $=-1;$<=7;$+=1)if(!(te+$<=-1||m<=te+$))for(var H=-1;H<=7;H+=1)ee+H<=-1||m<=ee+H||(0<=$&&$<=6&&(H==0||H==6)||0<=H&&H<=6&&($==0||$==6)||2<=$&&$<=4&&2<=H&&H<=4?E[te+$][ee+H]=!0:E[te+$][ee+H]=!1)},B=function(){for(var te=0,ee=0,$=0;$<8;$+=1){D(!0,$);var H=a.getLostPoint(x);($==0||te>H)&&(te=H,ee=$)}return ee},K=function(){for(var te=8;te>$&1)==1;E[Math.floor($/3)][$%3+m-8-3]=H}for(var $=0;$<18;$+=1){var H=!te&&(ee>>$&1)==1;E[$%3+m-8-3][Math.floor($/3)]=H}},Ie=function(te,ee){for(var $=O<<3|ee,H=a.getBCHTypeInfo($),M=0;M<15;M+=1){var q=!te&&(H>>M&1)==1;M<6?E[M][8]=q:M<8?E[M+1][8]=q:E[m-15+M][8]=q}for(var M=0;M<15;M+=1){var q=!te&&(H>>M&1)==1;M<8?E[8][m-M-1]=q:M<9?E[8][15-M-1+1]=q:E[8][15-M-1]=q}E[m-8][8]=!te},be=function(te,ee){for(var $=-1,H=m-1,M=7,q=0,Y=a.getMaskFunction(ee),j=m-1;j>0;j-=2)for(j==6&&(j-=1);;){for(var ie=0;ie<2;ie+=1)if(E[H][j-ie]==null){var we=!1;q>>M&1)==1);var oe=Y(H,j-ie);oe&&(we=!we),E[H][j-ie]=we,M-=1,M==-1&&(q+=1,M=7)}if(H+=$,H<0||m<=H){H-=$,$=-$;break}}},xe=function(te,ee){for(var $=0,H=0,M=0,q=new Array(ee.length),Y=new Array(ee.length),j=0;j=0?qe.getAt(zt):0}}for(var ir=0,oe=0;oej*8)throw"code length overflow. ("+M.getLengthInBits()+">"+j*8+")";for(M.getLengthInBits()+4<=j*8&&M.put(0,4);M.getLengthInBits()%8!=0;)M.putBit(!1);for(;!(M.getLengthInBits()>=j*8||(M.put(v,8),M.getLengthInBits()>=j*8));)M.put(_,8);return xe(M,H)};x.addData=function(te,ee){ee=ee||"Byte";var $=null;switch(ee){case"Numeric":$=f(te);break;case"Alphanumeric":$=d(te);break;case"Byte":$=w(te);break;case"Kanji":$=R(te);break;default:throw"mode:"+ee}b.push($),y=null},x.isDark=function(te,ee){if(te<0||m<=te||ee<0||m<=ee)throw te+","+ee;return E[te][ee]},x.getModuleCount=function(){return m},x.make=function(){if(g<1){for(var te=1;te<40;te++){for(var ee=c.getRSBlocks(te,O),$=u(),H=0;H"u"?te*4:ee;var $="";$+='";for(var M=0;M';$+=""}return $+="",$+="
    ",$},x.createSvgTag=function(te,ee,$,H){var M={};typeof arguments[0]=="object"&&(M=arguments[0],te=M.cellSize,ee=M.margin,$=M.alt,H=M.title),te=te||2,ee=typeof ee>"u"?te*4:ee,$=typeof $=="string"?{text:$}:$||{},$.text=$.text||null,$.id=$.text?$.id||"qrcode-description":null,H=typeof H=="string"?{text:H}:H||{},H.text=H.text||null,H.id=H.text?H.id||"qrcode-title":null;var q=x.getModuleCount()*te+ee*2,Y,j,ie,we,oe="",je;for(je="l"+te+",0 0,"+te+" -"+te+",0 0,-"+te+"z ",oe+=''+Ue(H.text)+"":"",oe+=$.text?''+Ue($.text)+"":"",oe+='',oe+='"u"?te*4:ee;var $=x.getModuleCount()*te+ee*2,H=ee,M=$-ee;return C($,$,function(q,Y){if(H<=q&&q"u"?te*4:ee;var H=x.getModuleCount()*te+ee*2,M="";return M+="",M};var Ue=function(te){for(var ee="",$=0;$":ee+=">";break;case"&":ee+="&";break;case'"':ee+=""";break;default:ee+=H;break}}return ee},Ve=function(te){var ee=1;te=typeof te>"u"?ee*2:te;var $=x.getModuleCount()*ee+te*2,H=te,M=$-te,q,Y,j,ie,we,oe={"\u2588\u2588":"\u2588","\u2588 ":"\u2580"," \u2588":"\u2584"," ":" "},je={"\u2588\u2588":"\u2580","\u2588 ":"\u2580"," \u2588":" "," ":" "},ct="";for(q=0;q<$;q+=2){for(j=Math.floor((q-H)/ee),ie=Math.floor((q+1-H)/ee),Y=0;Y<$;Y+=1)we="\u2588",H<=Y&&Y=M?je[we]:oe[we];ct+=` `}return $%2&&te>0?ct.substring(0,ct.length-$-1)+Array($+1).join("\u2580"):ct.substring(0,ct.length-1)};return x.createASCII=function(te,ee){if(te=te||1,te<2)return Ve(ee);te-=1,ee=typeof ee>"u"?te*2:ee;var $=x.getModuleCount()*te+ee*2,H=ee,M=$-ee,q,Y,j,ie,we=Array(te+1).join("\u2588\u2588"),oe=Array(te+1).join(" "),je="",ct="";for(q=0;q<$;q+=1){for(j=Math.floor((q-H)/te),ct="",Y=0;Y<$;Y+=1)ie=1,H<=Y&&Y>>8),O.push(y&255)):O.push(_)}}return O}};var t={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8},r={L:1,M:0,Q:3,H:2},n={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},a=(function(){var S=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],k=1335,v=7973,_=21522,g={},O=function(E){for(var m=0;E!=0;)m+=1,E>>>=1;return m};return g.getBCHTypeInfo=function(E){for(var m=E<<10;O(m)-O(k)>=0;)m^=k<=0;)m^=v<5&&(y+=3+D-5)}for(var b=0;b=256;)g-=255;return S[g]},_})();function s(S,k){if(typeof S.length>"u")throw S.length+"/"+k;var v=(function(){for(var g=0;g"u")throw"bad rs block @ typeNumber:"+g+"/errorCorrectionLevel:"+O;for(var m=E.length/3,y=[],b=0;b>>7-_%8&1)==1},v.put=function(_,g){for(var O=0;O>>g-O-1&1)==1)},v.getLengthInBits=function(){return k},v.putBit=function(_){var g=Math.floor(k/8);S.length<=g&&S.push(0),_&&(S[g]|=128>>>k%8),k+=1},v},f=function(S){var k=t.MODE_NUMBER,v=S,_={};_.getMode=function(){return k},_.getLength=function(E){return v.length},_.write=function(E){for(var m=v,y=0;y+2>>8&255)*192+(b&255),E.put(b,13),y+=2}if(y>>8)},k.writeBytes=function(v,_,g){_=_||0,g=g||v.length;for(var O=0;O0&&(v+=","),v+=S[_];return v+="]",v},k},p=function(){var S=0,k=0,v=0,_="",g={},O=function(m){_+=String.fromCharCode(E(m&63))},E=function(m){if(!(m<0)){if(m<26)return 65+m;if(m<52)return 97+(m-26);if(m<62)return 48+(m-52);if(m==62)return 43;if(m==63)return 47}throw"n:"+m};return g.writeByte=function(m){for(S=S<<8|m&255,k+=8,v+=1;k>=6;)O(S>>>k-6),k-=6},g.flush=function(){if(k>0&&(O(S<<6-k),S=0,k=0),v%3!=0)for(var m=3-v%3,y=0;y=k.length){if(g==0)return-1;throw"unexpected end of file./"+g}var m=k.charAt(v);if(v+=1,m=="=")return g=0,-1;if(m.match(/^\s$/))continue;_=_<<6|E(m.charCodeAt(0)),g+=6}var y=_>>>g-8&255;return g-=8,y};var E=function(m){if(65<=m&&m<=90)return m-65;if(97<=m&&m<=122)return m-97+26;if(48<=m&&m<=57)return m-48+52;if(m==43)return 62;if(m==47)return 63;throw"c:"+m};return O},A=function(S,k){var v=S,_=k,g=new Array(S*k),O={};O.setPixel=function(b,x,D){g[x*v+b]=D},O.write=function(b){b.writeString("GIF87a"),b.writeShort(v),b.writeShort(_),b.writeByte(128),b.writeByte(0),b.writeByte(0),b.writeByte(0),b.writeByte(0),b.writeByte(0),b.writeByte(255),b.writeByte(255),b.writeByte(255),b.writeString(","),b.writeShort(0),b.writeShort(0),b.writeShort(v),b.writeShort(_),b.writeByte(0);var x=2,D=m(x);b.writeByte(x);for(var F=0;D.length-F>255;)b.writeByte(255),b.writeBytes(D,F,255),F+=255;b.writeByte(D.length-F),b.writeBytes(D,F,D.length-F),b.writeByte(0),b.writeString(";")};var E=function(b){var x=b,D=0,F=0,B={};return B.write=function(K,Z){if(K>>>Z)throw"length over";for(;D+Z>=8;)x.writeByte(255&(K<>>=8-D,F=0,D=0;F=K<0&&x.writeByte(F)},B},m=function(b){for(var x=1<>6,128|o&63):o<55296||o>=57344?n.push(224|o>>12,128|o>>6&63,128|o&63):(a++,o=65536+((o&1023)<<10|r.charCodeAt(a)&1023),n.push(240|o>>18,128|o>>12&63,128|o>>6&63,128|o&63))}return n}return t(e)}})();(function(e){typeof define=="function"&&define.amd?define([],e):typeof JE=="object"&&(e1.exports=e())})(function(){return ZE})});var Fe=function(e=[]){let t=new Float64Array(16);if(e)for(let r=0;r>24&255,e[t+1]=r>>16&255,e[t+2]=r>>8&255,e[t+3]=r&255,e[t+4]=n>>24&255,e[t+5]=n>>16&255,e[t+6]=n>>8&255,e[t+7]=n&255}function ew(e,t,r,n,a){let o,s=0;for(o=0;o>>8)-1}function $p(e,t,r,n){return ew(e,t,r,n,32)}var NM=new Uint8Array([101,120,112,97,110,100,32,51,50,45,98,121,116,101,32,107]);function Fn(e,t){let r;for(r=0;r<16;r++)e[r]=t[r]|0}function yu(e){let t,r,n=1;for(t=0;t<16;t++)r=e[t]+n+65535,n=Math.floor(r/65536),e[t]=r-n*65536;e[0]+=n-1+37*(n-1)}function Xp(e,t,r){let n,a=~(r-1);for(let o=0;o<16;o++)n=a&(e[o]^t[o]),e[o]^=n,t[o]^=n}function fi(e,t){let r,n,a,o=Fe(),s=Fe();for(r=0;r<16;r++)s[r]=t[r];for(yu(s),yu(s),yu(s),n=0;n<2;n++){for(o[0]=s[0]-65517,r=1;r<15;r++)o[r]=s[r]-65535-(o[r-1]>>16&1),o[r-1]&=65535;o[15]=s[15]-32767-(o[14]>>16&1),a=o[15]>>16&1,o[14]&=65535,Xp(s,o,1-a)}for(r=0;r<16;r++)e[2*r]=s[r]&255,e[2*r+1]=s[r]>>8}function Kp(e,t){let r=new Uint8Array(32),n=new Uint8Array(32);return fi(r,e),fi(n,t),$p(r,0,n,0)}function jp(e){let t=new Uint8Array(32);return fi(t,e),t[0]&1}function tw(e,t){let r;for(r=0;r<16;r++)e[r]=t[2*r]+(t[2*r+1]<<8);e[15]&=32767}function Ea(e,t,r){for(let n=0;n<16;n++)e[n]=t[n]+r[n]}function wa(e,t,r){for(let n=0;n<16;n++)e[n]=t[n]-r[n]}function kt(e,t,r){let n,a,o=0,s=0,c=0,u=0,f=0,d=0,w=0,R=0,h=0,p=0,T=0,A=0,C=0,S=0,k=0,v=0,_=0,g=0,O=0,E=0,m=0,y=0,b=0,x=0,D=0,F=0,B=0,K=0,Z=0,pe=0,Ie=0,be=r[0],xe=r[1],Le=r[2],Ue=r[3],Ve=r[4],te=r[5],ee=r[6],$=r[7],H=r[8],M=r[9],q=r[10],Y=r[11],j=r[12],ie=r[13],we=r[14],oe=r[15];n=t[0],o+=n*be,s+=n*xe,c+=n*Le,u+=n*Ue,f+=n*Ve,d+=n*te,w+=n*ee,R+=n*$,h+=n*H,p+=n*M,T+=n*q,A+=n*Y,C+=n*j,S+=n*ie,k+=n*we,v+=n*oe,n=t[1],s+=n*be,c+=n*xe,u+=n*Le,f+=n*Ue,d+=n*Ve,w+=n*te,R+=n*ee,h+=n*$,p+=n*H,T+=n*M,A+=n*q,C+=n*Y,S+=n*j,k+=n*ie,v+=n*we,_+=n*oe,n=t[2],c+=n*be,u+=n*xe,f+=n*Le,d+=n*Ue,w+=n*Ve,R+=n*te,h+=n*ee,p+=n*$,T+=n*H,A+=n*M,C+=n*q,S+=n*Y,k+=n*j,v+=n*ie,_+=n*we,g+=n*oe,n=t[3],u+=n*be,f+=n*xe,d+=n*Le,w+=n*Ue,R+=n*Ve,h+=n*te,p+=n*ee,T+=n*$,A+=n*H,C+=n*M,S+=n*q,k+=n*Y,v+=n*j,_+=n*ie,g+=n*we,O+=n*oe,n=t[4],f+=n*be,d+=n*xe,w+=n*Le,R+=n*Ue,h+=n*Ve,p+=n*te,T+=n*ee,A+=n*$,C+=n*H,S+=n*M,k+=n*q,v+=n*Y,_+=n*j,g+=n*ie,O+=n*we,E+=n*oe,n=t[5],d+=n*be,w+=n*xe,R+=n*Le,h+=n*Ue,p+=n*Ve,T+=n*te,A+=n*ee,C+=n*$,S+=n*H,k+=n*M,v+=n*q,_+=n*Y,g+=n*j,O+=n*ie,E+=n*we,m+=n*oe,n=t[6],w+=n*be,R+=n*xe,h+=n*Le,p+=n*Ue,T+=n*Ve,A+=n*te,C+=n*ee,S+=n*$,k+=n*H,v+=n*M,_+=n*q,g+=n*Y,O+=n*j,E+=n*ie,m+=n*we,y+=n*oe,n=t[7],R+=n*be,h+=n*xe,p+=n*Le,T+=n*Ue,A+=n*Ve,C+=n*te,S+=n*ee,k+=n*$,v+=n*H,_+=n*M,g+=n*q,O+=n*Y,E+=n*j,m+=n*ie,y+=n*we,b+=n*oe,n=t[8],h+=n*be,p+=n*xe,T+=n*Le,A+=n*Ue,C+=n*Ve,S+=n*te,k+=n*ee,v+=n*$,_+=n*H,g+=n*M,O+=n*q,E+=n*Y,m+=n*j,y+=n*ie,b+=n*we,x+=n*oe,n=t[9],p+=n*be,T+=n*xe,A+=n*Le,C+=n*Ue,S+=n*Ve,k+=n*te,v+=n*ee,_+=n*$,g+=n*H,O+=n*M,E+=n*q,m+=n*Y,y+=n*j,b+=n*ie,x+=n*we,D+=n*oe,n=t[10],T+=n*be,A+=n*xe,C+=n*Le,S+=n*Ue,k+=n*Ve,v+=n*te,_+=n*ee,g+=n*$,O+=n*H,E+=n*M,m+=n*q,y+=n*Y,b+=n*j,x+=n*ie,D+=n*we,F+=n*oe,n=t[11],A+=n*be,C+=n*xe,S+=n*Le,k+=n*Ue,v+=n*Ve,_+=n*te,g+=n*ee,O+=n*$,E+=n*H,m+=n*M,y+=n*q,b+=n*Y,x+=n*j,D+=n*ie,F+=n*we,B+=n*oe,n=t[12],C+=n*be,S+=n*xe,k+=n*Le,v+=n*Ue,_+=n*Ve,g+=n*te,O+=n*ee,E+=n*$,m+=n*H,y+=n*M,b+=n*q,x+=n*Y,D+=n*j,F+=n*ie,B+=n*we,K+=n*oe,n=t[13],S+=n*be,k+=n*xe,v+=n*Le,_+=n*Ue,g+=n*Ve,O+=n*te,E+=n*ee,m+=n*$,y+=n*H,b+=n*M,x+=n*q,D+=n*Y,F+=n*j,B+=n*ie,K+=n*we,Z+=n*oe,n=t[14],k+=n*be,v+=n*xe,_+=n*Le,g+=n*Ue,O+=n*Ve,E+=n*te,m+=n*ee,y+=n*$,b+=n*H,x+=n*M,D+=n*q,F+=n*Y,B+=n*j,K+=n*ie,Z+=n*we,pe+=n*oe,n=t[15],v+=n*be,_+=n*xe,g+=n*Le,O+=n*Ue,E+=n*Ve,m+=n*te,y+=n*ee,b+=n*$,x+=n*H,D+=n*M,F+=n*q,B+=n*Y,K+=n*j,Z+=n*ie,pe+=n*we,Ie+=n*oe,o+=38*_,s+=38*g,c+=38*O,u+=38*E,f+=38*m,d+=38*y,w+=38*b,R+=38*x,h+=38*D,p+=38*F,T+=38*B,A+=38*K,C+=38*Z,S+=38*pe,k+=38*Ie,a=1,n=o+a+65535,a=Math.floor(n/65536),o=n-a*65536,n=s+a+65535,a=Math.floor(n/65536),s=n-a*65536,n=c+a+65535,a=Math.floor(n/65536),c=n-a*65536,n=u+a+65535,a=Math.floor(n/65536),u=n-a*65536,n=f+a+65535,a=Math.floor(n/65536),f=n-a*65536,n=d+a+65535,a=Math.floor(n/65536),d=n-a*65536,n=w+a+65535,a=Math.floor(n/65536),w=n-a*65536,n=R+a+65535,a=Math.floor(n/65536),R=n-a*65536,n=h+a+65535,a=Math.floor(n/65536),h=n-a*65536,n=p+a+65535,a=Math.floor(n/65536),p=n-a*65536,n=T+a+65535,a=Math.floor(n/65536),T=n-a*65536,n=A+a+65535,a=Math.floor(n/65536),A=n-a*65536,n=C+a+65535,a=Math.floor(n/65536),C=n-a*65536,n=S+a+65535,a=Math.floor(n/65536),S=n-a*65536,n=k+a+65535,a=Math.floor(n/65536),k=n-a*65536,n=v+a+65535,a=Math.floor(n/65536),v=n-a*65536,o+=a-1+37*(a-1),a=1,n=o+a+65535,a=Math.floor(n/65536),o=n-a*65536,n=s+a+65535,a=Math.floor(n/65536),s=n-a*65536,n=c+a+65535,a=Math.floor(n/65536),c=n-a*65536,n=u+a+65535,a=Math.floor(n/65536),u=n-a*65536,n=f+a+65535,a=Math.floor(n/65536),f=n-a*65536,n=d+a+65535,a=Math.floor(n/65536),d=n-a*65536,n=w+a+65535,a=Math.floor(n/65536),w=n-a*65536,n=R+a+65535,a=Math.floor(n/65536),R=n-a*65536,n=h+a+65535,a=Math.floor(n/65536),h=n-a*65536,n=p+a+65535,a=Math.floor(n/65536),p=n-a*65536,n=T+a+65535,a=Math.floor(n/65536),T=n-a*65536,n=A+a+65535,a=Math.floor(n/65536),A=n-a*65536,n=C+a+65535,a=Math.floor(n/65536),C=n-a*65536,n=S+a+65535,a=Math.floor(n/65536),S=n-a*65536,n=k+a+65535,a=Math.floor(n/65536),k=n-a*65536,n=v+a+65535,a=Math.floor(n/65536),v=n-a*65536,o+=a-1+37*(a-1),e[0]=o,e[1]=s,e[2]=c,e[3]=u,e[4]=f,e[5]=d,e[6]=w,e[7]=R,e[8]=h,e[9]=p,e[10]=T,e[11]=A,e[12]=C,e[13]=S,e[14]=k,e[15]=v}function ra(e,t){kt(e,t,t)}function rw(e,t){let r=Fe(),n;for(n=0;n<16;n++)r[n]=t[n];for(n=253;n>=0;n--)ra(r,r),n!==2&&n!==4&&kt(r,r,t);for(n=0;n<16;n++)e[n]=r[n]}function nw(e,t){let r=Fe(),n;for(n=0;n<16;n++)r[n]=t[n];for(n=250;n>=0;n--)ra(r,r),n!==1&&kt(r,r,t);for(n=0;n<16;n++)e[n]=r[n]}var Yp=[1116352408,3609767458,1899447441,602891725,3049323471,3964484399,3921009573,2173295548,961987163,4081628472,1508970993,3053834265,2453635748,2937671579,2870763221,3664609560,3624381080,2734883394,310598401,1164996542,607225278,1323610764,1426881987,3590304994,1925078388,4068182383,2162078206,991336113,2614888103,633803317,3248222580,3479774868,3835390401,2666613458,4022224774,944711139,264347078,2341262773,604807628,2007800933,770255983,1495990901,1249150122,1856431235,1555081692,3175218132,1996064986,2198950837,2554220882,3999719339,2821834349,766784016,2952996808,2566594879,3210313671,3203337956,3336571891,1034457026,3584528711,2466948901,113926993,3758326383,338241895,168717936,666307205,1188179964,773529912,1546045734,1294757372,1522805485,1396182291,2643833823,1695183700,2343527390,1986661051,1014477480,2177026350,1206759142,2456956037,344077627,2730485921,1290863460,2820302411,3158454273,3259730800,3505952657,3345764771,106217008,3516065817,3606008344,3600352804,1432725776,4094571909,1467031594,275423344,851169720,430227734,3100823752,506948616,1363258195,659060556,3750685593,883997877,3785050280,958139571,3318307427,1322822218,3812723403,1537002063,2003034995,1747873779,3602036899,1955562222,1575990012,2024104815,1125592928,2227730452,2716904306,2361852424,442776044,2428436474,593698344,2756734187,3733110249,3204031479,2999351573,3329325298,3815920427,3391569614,3928383900,3515267271,566280711,3940187606,3454069534,4118630271,4000239992,116418474,1914138554,174292421,2731055270,289380356,3203993006,460393269,320620315,685471733,587496836,852142971,1086792851,1017036298,365543100,1126000580,2618297676,1288033470,3409855158,1501505948,4234509866,1607167915,987167468,1816402316,1246189591];function pi(e,t,r,n){let a=new Int32Array(16),o=new Int32Array(16),s,c,u,f,d,w,R,h,p,T,A,C,S,k,v,_,g,O,E,m,y,b,x,D,F,B,K=e[0],Z=e[1],pe=e[2],Ie=e[3],be=e[4],xe=e[5],Le=e[6],Ue=e[7],Ve=t[0],te=t[1],ee=t[2],$=t[3],H=t[4],M=t[5],q=t[6],Y=t[7],j=0;for(;n>=128;){for(E=0;E<16;E++)m=8*E+j,a[E]=r[m+0]<<24|r[m+1]<<16|r[m+2]<<8|r[m+3],o[E]=r[m+4]<<24|r[m+5]<<16|r[m+6]<<8|r[m+7];for(E=0;E<80;E++)if(s=K,c=Z,u=pe,f=Ie,d=be,w=xe,R=Le,h=Ue,p=Ve,T=te,A=ee,C=$,S=H,k=M,v=q,_=Y,y=Ue,b=Y,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=(be>>>14|H<<18)^(be>>>18|H<<14)^(H>>>9|be<<23),b=(H>>>14|be<<18)^(H>>>18|be<<14)^(be>>>9|H<<23),x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,y=be&xe^~be&Le,b=H&M^~H&q,x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,y=Yp[E*2],b=Yp[E*2+1],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,y=a[E%16],b=o[E%16],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,g=F&65535|B<<16,O=x&65535|D<<16,y=g,b=O,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=(K>>>28|Ve<<4)^(Ve>>>2|K<<30)^(Ve>>>7|K<<25),b=(Ve>>>28|K<<4)^(K>>>2|Ve<<30)^(K>>>7|Ve<<25),x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,y=K&Z^K&pe^Z&pe,b=Ve&te^Ve&ee^te&ee,x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,h=F&65535|B<<16,_=x&65535|D<<16,y=f,b=C,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=g,b=O,x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,f=F&65535|B<<16,C=x&65535|D<<16,Z=s,pe=c,Ie=u,be=f,xe=d,Le=w,Ue=R,K=h,te=p,ee=T,$=A,H=C,M=S,q=k,Y=v,Ve=_,E%16===15)for(m=0;m<16;m++)y=a[m],b=o[m],x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=a[(m+9)%16],b=o[(m+9)%16],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,g=a[(m+1)%16],O=o[(m+1)%16],y=(g>>>1|O<<31)^(g>>>8|O<<24)^g>>>7,b=(O>>>1|g<<31)^(O>>>8|g<<24)^(O>>>7|g<<25),x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,g=a[(m+14)%16],O=o[(m+14)%16],y=(g>>>19|O<<13)^(O>>>29|g<<3)^g>>>6,b=(O>>>19|g<<13)^(g>>>29|O<<3)^(O>>>6|g<<26),x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,a[m]=F&65535|B<<16,o[m]=x&65535|D<<16;y=K,b=Ve,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=e[0],b=t[0],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,e[0]=K=F&65535|B<<16,t[0]=Ve=x&65535|D<<16,y=Z,b=te,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=e[1],b=t[1],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,e[1]=Z=F&65535|B<<16,t[1]=te=x&65535|D<<16,y=pe,b=ee,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=e[2],b=t[2],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,e[2]=pe=F&65535|B<<16,t[2]=ee=x&65535|D<<16,y=Ie,b=$,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=e[3],b=t[3],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,e[3]=Ie=F&65535|B<<16,t[3]=$=x&65535|D<<16,y=be,b=H,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=e[4],b=t[4],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,e[4]=be=F&65535|B<<16,t[4]=H=x&65535|D<<16,y=xe,b=M,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=e[5],b=t[5],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,e[5]=xe=F&65535|B<<16,t[5]=M=x&65535|D<<16,y=Le,b=q,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=e[6],b=t[6],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,e[6]=Le=F&65535|B<<16,t[6]=q=x&65535|D<<16,y=Ue,b=Y,x=b&65535,D=b>>>16,F=y&65535,B=y>>>16,y=e[7],b=t[7],x+=b&65535,D+=b>>>16,F+=y&65535,B+=y>>>16,D+=x>>>16,F+=D>>>16,B+=F>>>16,e[7]=Ue=F&65535|B<<16,t[7]=Y=x&65535|D<<16,j+=128,n-=128}return n}function Hn(e,t,r){let n=new Int32Array(8),a=new Int32Array(8),o=new Uint8Array(256),s=r;n[0]=1779033703,n[1]=3144134277,n[2]=1013904242,n[3]=2773480762,n[4]=1359893119,n[5]=2600822924,n[6]=528734635,n[7]=1541459225,a[0]=4089235720,a[1]=2227873595,a[2]=4271175723,a[3]=1595750129,a[4]=2917565137,a[5]=725511199,a[6]=4215389547,a[7]=327033209,pi(n,a,t,r),r%=128;for(let c=0;ct.length-r){for(let a=0;r+a=0;--a)n=r[a/8|0]>>(a&7)&1,zp(e,t,n),Eu(t,e),Eu(e,e),zp(e,t,n)}function po(e,t){let r=[Fe(),Fe(),Fe(),Fe()];Fn(r[0],Vp),Fn(r[1],qp),Fn(r[2],li),kt(r[3],Vp,qp),gi(e,r,t)}function aw(e,t,r){let n=new Uint8Array(64),a=[Fe(),Fe(),Fe(),Fe()];r||mi(t,32),Hn(n,t,32),n[0]&=248,n[31]&=127,n[31]|=64,po(a,n),Aa(e,a);for(let o=0;o<32;o++)t[o+32]=e[o];return 0}var bu=new Float64Array([237,211,245,92,26,99,18,88,214,156,247,162,222,249,222,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16]);function ho(e,t){let r,n,a,o;for(n=63;n>=32;--n){for(r=0,a=n-32,o=n-12;a>4)*bu[a],r=t[a]>>8,t[a]&=255;for(a=0;a<32;a++)t[a]-=r*bu[a];for(n=0;n<32;n++)t[n+1]+=t[n]>>8,e[n]=t[n]&255}function fo(e){let t=new Float64Array(64);for(let r=0;r<64;r++)t[r]=e[r];for(let r=0;r<64;r++)e[r]=0;ho(e,t)}function ow(e,t,r,n){let a=new Uint8Array(64),o=new Uint8Array(64),s=new Uint8Array(64),c,u,f=new Float64Array(64),d=[Fe(),Fe(),Fe(),Fe()];Hn(a,n,32),a[0]&=248,a[31]&=127,a[31]|=64;let w=r+64;for(c=0;c>7&&wa(e[0],vu,e[0]),kt(e[3],e[0],e[1]),0)}function Zp(e){let t=new Uint8Array(32),r=[Fe(),Fe(),Fe(),Fe()];return po(r,e),Aa(t,r),t}function Jp(e,t){let r=new Uint8Array(32),n=[Fe(),Fe(),Fe(),Fe()],a=[Fe(),Fe(),Fe(),Fe()];if(iw(a,t))throw new Error;return gi(n,a,e),Aa(r,n),r}function sw(e,t,r,n){let a,o,s=new Uint8Array(32),c=new Uint8Array(64),u=[Fe(),Fe(),Fe(),Fe()],f=[Fe(),Fe(),Fe(),Fe()];if(o=-1,r<64||Qp(f,n))return-1;for(a=0;a=0}var fw={getRandomValues:e=>e};function uh(){let e=typeof self<"u"?self.crypto||self.msCrypto:fw,t=65536;Au(function(r,n){let a,o=new Uint8Array(n);for(a=0;a= 0x80 (not a basic code point)","invalid-input":"Invalid input"},Nu=35,fn=Math.floor,Ru=String.fromCharCode;function aa(e){throw new RangeError(gw[e])}function _w(e,t){let r=[],n=e.length;for(;n--;)r[n]=t(e[n]);return r}function dh(e,t){let r=e.split("@"),n="";r.length>1&&(n=r[0]+"@",e=r[1]),e=e.replace(mw,".");let a=e.split("."),o=_w(a,t).join(".");return n+o}function fh(e){let t=[],r=0,n=e.length;for(;r=55296&&a<=56319&&rString.fromCodePoint(...e),bw=function(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:36},lh=function(e,t){return e+22+75*+(e<26)-(+(t!=0)<<5)},ph=function(e,t,r){let n=0;for(e=r?fn(e/700):e>>1,e+=fn(e/t);e>Nu*26>>1;n+=36)e=fn(e/Nu);return fn(n+(Nu+1)*e/(e+38))},hh=function(e){let t=[],r=e.length,n=0,a=128,o=72,s=e.lastIndexOf("-");s<0&&(s=0);for(let c=0;c=128&&aa("not-basic"),t.push(e.charCodeAt(c));for(let c=s>0?s+1:0;c=r&&aa("invalid-input");let R=bw(e.charCodeAt(c++));(R>=36||R>fn((2147483647-n)/d))&&aa("overflow"),n+=R*d;let h=w<=o?1:w>=o+26?26:w-o;if(Rfn(2147483647/p)&&aa("overflow"),d*=p}let f=t.length+1;o=ph(n-u,f,u==0),fn(n/f)>2147483647-a&&aa("overflow"),a+=fn(n/f),n%=f,t.splice(n++,0,a)}return String.fromCodePoint(...t)},mh=function(e){let t=[],r=fh(e),n=r.length,a=128,o=0,s=72;for(let f of r)f<128&&t.push(Ru(f));let c=t.length,u=c;for(c&&t.push("-");u=a&&wfn((2147483647-o)/d)&&aa("overflow"),o+=(f-a)*d,a=f;for(let w of r)if(w2147483647&&aa("overflow"),w==a){let R=o;for(let h=36;;h+=36){let p=h<=s?1:h>=s+26?26:h-s;if(R=0?(a=n.slice(0,s),o=n.slice(s+1)):(a=n,o=new Uint8Array(0)),a=yh(a,43,32),o=yh(o,43,32);let c=Cu(Du(a)),u=Cu(Du(o));r.push([c,u])}return r}function Ou(e){return Tw(Lu(e))}function _h(e,t=void 0){let r="utf-8";t!==void 0&&(r=t);let n="";for(let[a,o]of e.entries()){let s=Ra(o[0],bh,!0),c=o[1];o.length>2&&o[2]!==void 0&&(o[2]==="hidden"&&s==="_charset_"?c=r:o[2]==="file"&&(c=c.name)),c=Ra(c,bh,!0),a!==0&&(n+="&"),n+=`${s}=${c}`}return n}function Nw(e,t){let r=[],n=0,a=e.indexOf(t);for(;a>=0;)r.push(e.slice(n,a)),n=a+1,a=e.indexOf(t,n);return n!==e.length&&r.push(e.slice(n)),r}function yh(e,t,r){let n=e.indexOf(t);for(;n>=0;)e[n]=r,n=e.indexOf(t,n+1);return e}function le(e){return e.codePointAt(0)}function Rw(e){let t=e.toString(16).toUpperCase();return t.length===1&&(t=`0${t}`),`%${t}`}function Du(e){let t=new Uint8Array(e.byteLength),r=0;for(let n=0;n126}var Iw=new Set([le(" "),le('"'),le("<"),le(">"),le("`")]);function Sw(e){return wi(e)||Iw.has(e)}var Cw=new Set([le(" "),le('"'),le("#"),le("<"),le(">")]);function Uu(e){return wi(e)||Cw.has(e)}function Ow(e){return Uu(e)||e===le("'")}var Dw=new Set([le("?"),le("`"),le("{"),le("}")]);function Sh(e){return Uu(e)||Dw.has(e)}var Pw=new Set([le("/"),le(":"),le(";"),le("="),le("@"),le("["),le("\\"),le("]"),le("^"),le("|")]);function Ai(e){return Sh(e)||Pw.has(e)}var Lw=new Set([le("$"),le("%"),le("&"),le("+"),le(",")]);function Uw(e){return Ai(e)||Lw.has(e)}var Mw=new Set([le("!"),le("'"),le("("),le(")"),le("~")]);function bh(e){return Uw(e)||Mw.has(e)}function Ch(e,t){let r=Lu(e),n="";for(let a of r)t(a)?n+=Rw(a):n+=String.fromCharCode(a);return n}function bi(e,t){return Ch(String.fromCodePoint(e),t)}function Ra(e,t,r=!1){let n="";for(let a of e)r&&a===" "?n+="+":n+=Ch(a,t);return n}function go(e){return e>=48&&e<=57}function yo(e){return e>=65&&e<=90||e>=97&&e<=122}function kw(e){return yo(e)||go(e)}function nn(e){return go(e)||e>=65&&e<=70||e>=97&&e<=102}var xa=class{constructor(t,{doNotStripQMark:r=!1}={}){if(this._list=[],this._url=null,!r&&typeof t=="string"&&t[0]==="?"&&(t=t.slice(1)),Array.isArray(t))for(let n of t){if(n.length!==2)throw new TypeError("Failed to construct 'URLSearchParams': parameter 1 sequence's element does not contain exactly two elements.");this._list.push([n[0],n[1]])}else if(typeof t=="object"&&Object.getPrototypeOf(t)===null)for(let n of Object.keys(t)){let a=t[n];this._list.push([n,a])}else this._list=Ou(t)}_updateSteps(){if(this._url!==null){let t=_h(this._list);t===""&&(t=null),this._url._url.query=t}}append(t,r){this._list.push([t,r]),this._updateSteps()}delete(t){let r=0;for(;r[t[0],t[1]])]}forEach(t,r){for(let n of this._list)t.call(r,n[1],n[0],this)}has(t){for(let r of this._list)if(r[0]===t)return!0;return!1}set(t,r){let n=!1,a=0;for(;at[0]r[0]?1:0),this._updateSteps()}[Symbol.iterator](){return this._list[Symbol.iterator]()}toString(){return _h(this._list)}},Oh={ftp:21,file:null,http:80,https:443,ws:80,wss:443},at=Symbol("failure");function vh(e){return[...e].length}function Eh(e,t){let r=e[t];return isNaN(r)?void 0:String.fromCodePoint(r)}function wh(e){return e==="."||e.toLowerCase()==="%2e"}function Fw(e){return e=e.toLowerCase(),e===".."||e==="%2e."||e===".%2e"||e==="%2e%2e"}function Hw(e,t){return yo(e)&&(t===le(":")||t===le("|"))}function Ah(e){return e.length===2&&yo(e.codePointAt(0))&&(e[1]===":"||e[1]==="|")}function Gw(e){return e.length===2&&yo(e.codePointAt(0))&&e[1]===":"}function Dh(e){return e.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|<|>|\?|@|\[|\\|\]|\^|\|/u)!==-1}function Bw(e){return Dh(e)||e.search(/[\u0000-\u001F]|%|\u007F/u)!==-1}function Ei(e){return Oh[e]!==void 0}function wr(e){return Ei(e.scheme)}function xu(e){return!Ei(e.scheme)}function Th(e){return Oh[e]}function Ph(e){if(e==="")return at;let t=10;if(e.length>=2&&e.charAt(0)==="0"&&e.charAt(1).toLowerCase()==="x"?(e=e.substring(2),t=16):e.length>=2&&e.charAt(0)==="0"&&(e=e.substring(1),t=8),e==="")return 0;let r=/[^0-7]/u;return t===10&&(r=/[^0-9]/u),t===16&&(r=/[^0-9A-Fa-f]/u),r.test(e)?at:parseInt(e,t)}function Ww(e){let t=e.split(".");if(t[t.length-1]===""&&t.length>1&&t.pop(),t.length>4)return at;let r=[];for(let o of t){let s=Ph(o);if(s===at)return at;r.push(s)}for(let o=0;o255)return at;if(r[r.length-1]>=256**(5-r.length))return at;let n=r.pop(),a=0;for(let o of r)n+=o*256**(3-a),++a;return n}function Vw(e){let t="",r=e;for(let n=1;n<=4;++n)t=String(r%256)+t,n!==4&&(t=`.${t}`),r=Math.floor(r/256);return t}function qw(e){let t=[0,0,0,0,0,0,0,0],r=0,n=null,a=0,o=Array.from(e,s=>s.codePointAt(0));if(o[a]===le(":")){if(o[a+1]!==le(":"))return at;a+=2,++r,n=r}for(;a6))return at;let u=0;for(;o[a]!==void 0;){let f=null;if(u>0)if(o[a]===le(".")&&u<4)++a;else return at;if(!go(o[a]))return at;for(;go(o[a]);){let d=parseInt(Eh(o,a));if(f===null)f=d;else{if(f===0)return at;f=f*10+d}if(f>255)return at;++a}t[r]=t[r]*256+f,++u,(u===2||u===4)&&++r}if(u!==4)return at;break}else if(o[a]===le(":")){if(++a,o[a]===void 0)return at}else if(o[a]!==void 0)return at;t[r]=s,++r}if(n!==null){let s=r-n;for(r=7;r!==0&&s>0;){let c=t[n+s-1];t[n+s-1]=t[r],t[r]=c,--r,--s}}else if(n===null&&r!==8)return at;return t}function Kw(e){let t="",r=$w(e),n=!1;for(let a=0;a<=7;++a)if(!(n&&e[a]===0)){if(n&&(n=!1),r===a){t+=a===0?"::":":",n=!0;continue}t+=e[a].toString(16),a!==7&&(t+=":")}return t}function Iu(e,t=!1){if(e[0]==="[")return e[e.length-1]!=="]"?at:qw(e.substring(1,e.length-1));if(t)return zw(e);let r=Cu(xw(e)),n=Xw(r);return n===at||Bw(n)?at:Yw(n)?Ww(n):n}function Yw(e){let t=e.split(".");if(t[t.length-1]===""){if(t.length===1)return!1;t.pop()}let r=t[t.length-1];return!!(Ph(r)!==at||/^[0-9]+$/u.test(r))}function zw(e){return Dh(e)?at:Ra(e,wi)}function $w(e){let t=null,r=1,n=null,a=0;for(let o=0;or&&(t=n,r=a),n=null,a=0):(n===null&&(n=o),++a);return a>r?n:t}function mo(e){return typeof e=="number"?Vw(e):e instanceof Array?`[${Kw(e)}]`:e}function Xw(e,t=!1){let r;try{r=gh.toASCII(e)}catch{return at}return r===null||r===""?at:r}function jw(e){return e.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/gu,"")}function Qw(e){return e.replace(/\u0009|\u000A|\u000D/gu,"")}function Nh(e){let{path:t}=e;t.length!==0&&(e.scheme==="file"&&t.length===1&&Zw(t[0])||t.pop())}function Rh(e){return e.username!==""||e.password!==""}function Su(e){return e.host===null||e.host===""||e.scheme==="file"}function Na(e){return typeof e.path=="string"}function Zw(e){return/^[A-Za-z]:$/u.test(e)}var Pu=class{constructor(t,r,n,a,o){if(this.table={"parse scheme start":this.parseSchemeStart,"parse scheme":this.parseScheme,"parse no scheme":this.parseNoScheme,"parse special relative or authority":this.parseSpecialRelativeOrAuthority,"parse path or authority":this.parsePathOrAuthority,"parse relative":this.parseRelative,"parse relative slash":this.parseRelativeSlash,"parse special authority slashes":this.parseSpecialAuthoritySlashes,"parse special authority ignore slashes":this.parseSpecialAuthorityIgnoreSlashes,"parse authority":this.parseAuthority,"parse host":this.parseHostName,"parse hostname":this.parseHostName,"parse port":this.parsePort,"parse file":this.parseFile,"parse file slash":this.parseFileSlash,"parse file host":this.parseFileHost,"parse path start":this.parsePathStart,"parse path":this.parsePath,"parse opaque path":this.parseOpaquePath,"parse query":this.parseQuery,"parse fragment":this.parseFragment},this.pointer=0,this.base=r||null,this.encodingOverride=n||"utf-8",this.url=a,this.failure=!1,this.parseError=!1,!this.url){this.url={scheme:"",username:"",password:"",host:null,port:null,path:[],query:null,fragment:null};let c=jw(t);c!==t&&(this.parseError=!0),t=c}let s=Qw(t);for(s!==t&&(this.parseError=!0),t=s,this.state=o||"scheme start",this.buffer="",this.atFlag=!1,this.arrFlag=!1,this.passwordTokenSeenFlag=!1,this.input=Array.from(t,c=>c.codePointAt(0));this.pointer<=this.input.length;++this.pointer){let c=this.input[this.pointer],u=isNaN(c)?void 0:String.fromCodePoint(c),f=this.table[`parse ${this.state}`].call(this,c,u);if(f){if(f===at){this.failure=!0;break}}else break}}parseSchemeStart(t,r){if(yo(t))this.buffer+=r.toLowerCase(),this.state="scheme";else if(!this.stateOverride)this.state="no scheme",--this.pointer;else return this.parseError=!0,at;return!0}parseScheme(t,r){if(kw(t)||t===le("+")||t===le("-")||t===le("."))this.buffer+=r.toLowerCase();else if(t===le(":")){if(this.stateOverride&&(wr(this.url)&&!Ei(this.buffer)||!wr(this.url)&&Ei(this.buffer)||(Rh(this.url)||this.url.port!==null)&&this.buffer==="file"||this.url.scheme==="file"&&this.url.host===""))return!1;if(this.url.scheme=this.buffer,this.stateOverride)return this.url.port===Th(this.url.scheme)&&(this.url.port=null),!1;this.buffer="",this.url.scheme==="file"?((this.input[this.pointer+1]!==le("/")||this.input[this.pointer+2]!==le("/"))&&(this.parseError=!0),this.state="file"):wr(this.url)&&this.base!==null&&this.base.scheme===this.url.scheme?this.state="special relative or authority":wr(this.url)?this.state="special authority slashes":this.input[this.pointer+1]===le("/")?(this.state="path or authority",++this.pointer):(this.url.path=[""],this.state="opaque path")}else if(!this.stateOverride)this.buffer="",this.state="no scheme",this.pointer=-1;else return this.parseError=!0,at;return!0}parseNoScheme(t){return this.base===null||Na(this.base)&&t!==le("#")?at:(Na(this.base)&&t===le("#")?(this.url.scheme=this.base.scheme,this.url.path=this.base.path,this.url.query=this.base.query,this.url.fragment="",this.state="fragment"):this.base.scheme==="file"?(this.state="file",--this.pointer):(this.state="relative",--this.pointer),!0)}parseSpecialRelativeOrAuthority(t){return t===le("/")&&this.input[this.pointer+1]===le("/")?(this.state="special authority ignore slashes",++this.pointer):(this.parseError=!0,this.state="relative",--this.pointer),!0}parsePathOrAuthority(t){return t===le("/")?this.state="authority":(this.state="path",--this.pointer),!0}parseRelative(t){return this.url.scheme=this.base.scheme,t===le("/")?this.state="relative slash":wr(this.url)&&t===le("\\")?(this.parseError=!0,this.state="relative slash"):(this.url.username=this.base.username,this.url.password=this.base.password,this.url.host=this.base.host,this.url.port=this.base.port,this.url.path=this.base.path.slice(),this.url.query=this.base.query,t===le("?")?(this.url.query="",this.state="query"):t===le("#")?(this.url.fragment="",this.state="fragment"):isNaN(t)||(this.url.query=null,this.url.path.pop(),this.state="path",--this.pointer)),!0}parseRelativeSlash(t){return wr(this.url)&&(t===le("/")||t===le("\\"))?(t===le("\\")&&(this.parseError=!0),this.state="special authority ignore slashes"):t===le("/")?this.state="authority":(this.url.username=this.base.username,this.url.password=this.base.password,this.url.host=this.base.host,this.url.port=this.base.port,this.state="path",--this.pointer),!0}parseSpecialAuthoritySlashes(t){return t===le("/")&&this.input[this.pointer+1]===le("/")?(this.state="special authority ignore slashes",++this.pointer):(this.parseError=!0,this.state="special authority ignore slashes",--this.pointer),!0}parseSpecialAuthorityIgnoreSlashes(t){return t!==le("/")&&t!==le("\\")?(this.state="authority",--this.pointer):this.parseError=!0,!0}parseAuthority(t,r){if(t===le("@")){this.parseError=!0,this.atFlag&&(this.buffer=`%40${this.buffer}`),this.atFlag=!0;let n=vh(this.buffer);for(let a=0;a2**16-1)return this.parseError=!0,at;this.url.port=n===Th(this.url.scheme)?null:n,this.buffer=""}if(this.stateOverride)return!1;this.state="path start",--this.pointer}else return this.parseError=!0,at;return!0}parseFile(t){return this.url.scheme="file",this.url.host="",t===le("/")||t===le("\\")?(t===le("\\")&&(this.parseError=!0),this.state="file slash"):this.base!==null&&this.base.scheme==="file"?(this.url.host=this.base.host,this.url.path=this.base.path.slice(),this.url.query=this.base.query,t===le("?")?(this.url.query="",this.state="query"):t===le("#")?(this.url.fragment="",this.state="fragment"):isNaN(t)||(this.url.query=null,xh(this.input,this.pointer)?(this.parseError=!0,this.url.path=[]):Nh(this.url),this.state="path",--this.pointer)):(this.state="path",--this.pointer),!0}parseFileSlash(t){return t===le("/")||t===le("\\")?(t===le("\\")&&(this.parseError=!0),this.state="file host"):(this.base!==null&&this.base.scheme==="file"&&(!xh(this.input,this.pointer)&&Gw(this.base.path[0])&&this.url.path.push(this.base.path[0]),this.url.host=this.base.host),this.state="path",--this.pointer),!0}parseFileHost(t,r){if(isNaN(t)||t===le("/")||t===le("\\")||t===le("?")||t===le("#"))if(--this.pointer,!this.stateOverride&&Ah(this.buffer))this.parseError=!0,this.state="path";else if(this.buffer===""){if(this.url.host="",this.stateOverride)return!1;this.state="path start"}else{let n=Iu(this.buffer,xu(this.url));if(n===at)return at;if(n==="localhost"&&(n=""),this.url.host=n,this.stateOverride)return!1;this.buffer="",this.state="path start"}else this.buffer+=r;return!0}parsePathStart(t){return wr(this.url)?(t===le("\\")&&(this.parseError=!0),this.state="path",t!==le("/")&&t!==le("\\")&&--this.pointer):!this.stateOverride&&t===le("?")?(this.url.query="",this.state="query"):!this.stateOverride&&t===le("#")?(this.url.fragment="",this.state="fragment"):t!==void 0?(this.state="path",t!==le("/")&&--this.pointer):this.stateOverride&&this.url.host===null&&this.url.path.push(""),!0}parsePath(t){return isNaN(t)||t===le("/")||wr(this.url)&&t===le("\\")||!this.stateOverride&&(t===le("?")||t===le("#"))?(wr(this.url)&&t===le("\\")&&(this.parseError=!0),Fw(this.buffer)?(Nh(this.url),t!==le("/")&&!(wr(this.url)&&t===le("\\"))&&this.url.path.push("")):wh(this.buffer)&&t!==le("/")&&!(wr(this.url)&&t===le("\\"))?this.url.path.push(""):wh(this.buffer)||(this.url.scheme==="file"&&this.url.path.length===0&&Ah(this.buffer)&&(this.buffer=`${this.buffer[0]}:`),this.url.path.push(this.buffer)),this.buffer="",t===le("?")&&(this.url.query="",this.state="query"),t===le("#")&&(this.url.fragment="",this.state="fragment")):(t===le("%")&&(!nn(this.input[this.pointer+1])||!nn(this.input[this.pointer+2]))&&(this.parseError=!0),this.buffer+=bi(t,Sh)),!0}parseOpaquePath(t){return t===le("?")?(this.url.query="",this.state="query"):t===le("#")?(this.url.fragment="",this.state="fragment"):(!isNaN(t)&&t!==le("%")&&(this.parseError=!0),t===le("%")&&(!nn(this.input[this.pointer+1])||!nn(this.input[this.pointer+2]))&&(this.parseError=!0),isNaN(t)||(this.url.path+=bi(t,wi))),!0}parseQuery(t,r){if((!wr(this.url)||this.url.scheme==="ws"||this.url.scheme==="wss")&&(this.encodingOverride="utf-8"),!this.stateOverride&&t===le("#")||isNaN(t)){let n=wr(this.url)?Ow:Uu;this.url.query+=Ra(this.buffer,n),this.buffer="",t===le("#")&&(this.url.fragment="",this.state="fragment")}else isNaN(t)||(t===le("%")&&(!nn(this.input[this.pointer+1])||!nn(this.input[this.pointer+2]))&&(this.parseError=!0),this.buffer+=r);return!0}parseFragment(t){return isNaN(t)||(t===le("%")&&(!nn(this.input[this.pointer+1])||!nn(this.input[this.pointer+2]))&&(this.parseError=!0),this.url.fragment+=bi(t,Sw)),!0}},Jw=new Set([le("/"),le("\\"),le("?"),le("#")]);function xh(e,t){let r=e.length-t;return r>=2&&Hw(e[t],e[t+1])&&(r===2||Jw.has(e[t+2]))}function eA(e,t){let r=`${e.scheme}:`;return e.host!==null&&(r+="//",(e.username!==""||e.password!=="")&&(r+=e.username,e.password!==""&&(r+=`:${e.password}`),r+="@"),r+=mo(e.host),e.port!==null&&(r+=`:${e.port}`)),e.host===null&&!Na(e)&&e.path.length>1&&e.path[0]===""&&(r+="/."),r+=Mu(e),e.query!==null&&(r+=`?${e.query}`),!t&&e.fragment!==null&&(r+=`#${e.fragment}`),r}function tA(e){let t=`${e.scheme}://`;return t+=mo(e.host),e.port!==null&&(t+=`:${e.port}`),t}function Mu(e){if(typeof e.path=="string")return e.path;let t="";for(let r of e.path)t+=`/${r}`;return t}function Lh(e){switch(e.scheme){case"blob":try{return Lh(aA(Mu(e)))}catch{return"null"}case"ftp":case"http":case"https":case"ws":case"wss":return tA({scheme:e.scheme,host:e.host,port:e.port});case"file":return"null";default:return"null"}}function rn(e,t){t===void 0&&(t={});let r=new Pu(e,t.baseURL,t.encodingOverride,t.url,t.stateOverride);return r.failure?null:r.url}function rA(e,t){e.username=Ra(t,Ai)}function nA(e,t){e.password=Ra(t,Ai)}function Ih(e){return String(e)}function aA(e,t){return t===void 0&&(t={}),rn(e,{baseURL:t.baseURL,encodingOverride:t.encodingOverride})}var vi=typeof URL<"u"?URL:void 0,_o=class{constructor(t,r){let n=null;if(r!==void 0&&(r instanceof URL&&(r=r.href),n=rn(r),n===null))throw new TypeError(`Invalid base URL: ${r}`);t instanceof URL&&(t=t.href);let a=rn(t,{baseURL:n});if(a===null)throw new TypeError(`Invalid URL: ${t}`);let o=a.query!==null?a.query:"";this._url=a,this._query=new xa(o,{doNotStripQMark:!0}),this._query._url=this}get href(){return eA(this._url)}set href(t){let r=rn(t);if(r===null)throw new TypeError(`Invalid URL: ${t}`);this._url=r,this._query._list.splice(0);let{query:n}=r;n!==null&&(this._query._list=Ou(n))}get origin(){return Lh(this._url)}get protocol(){return`${this._url.scheme}:`}set protocol(t){rn(`${t}:`,{url:this._url,stateOverride:"scheme start"})}get username(){return this._url.username}set username(t){Su(this._url)||rA(this._url,t)}get password(){return this._url.password}set password(t){Su(this._url)||nA(this._url,t)}get host(){let t=this._url;return t.host===null?"":t.port===null?mo(t.host):`${mo(t.host)}:${Ih(t.port)}`}set host(t){Na(this._url)||rn(t,{url:this._url,stateOverride:"host"})}get hostname(){return this._url.host===null?"":mo(this._url.host)}set hostname(t){Na(this._url)||rn(t,{url:this._url,stateOverride:"hostname"})}get port(){return this._url.port===null?"":Ih(this._url.port)}set port(t){Su(this._url)||(t===""?this._url.port=null:rn(t,{url:this._url,stateOverride:"port"}))}get pathname(){return Mu(this._url)}set pathname(t){Na(this._url)||(this._url.path=[],rn(t,{url:this._url,stateOverride:"path start"}))}get search(){return this._url.query===null||this._url.query===""?"":`?${this._url.query}`}set search(t){let r=this._url;if(t===""){r.query=null,this._query._list=[];return}let n=t[0]==="?"?t.substring(1):t;r.query="",rn(n,{url:r,stateOverride:"query"}),this._query._list=Ou(n)}get searchParams(){return this._query}get hash(){return this._url.fragment===null||this._url.fragment===""?"":`#${this._url.fragment}`}set hash(t){if(t===""){this._url.fragment=null;return}let r=t[0]==="#"?t.substring(1):t;this._url.fragment="",rn(r,{url:this._url,stateOverride:"fragment"})}toJSON(){return this.href}static createObjectURL(t){if(!vi)throw new Error("This method requires a native implementation, which does not exist");return vi.createObjectURL(t)}static revokeObjectURL(t){if(!vi)throw new Error("This method requires a native implementation, which does not exist");return vi.revokeObjectURL(t)}};(function(){typeof globalThis!="object"&&(Object.defineProperty(Object.prototype,"__magic__",{get:function(){return this},configurable:!0}),__magic__.globalThis=__magic__,delete Object.prototype.__magic__)})();var Uh=!0,Ti=globalThis.URL;(Uh||!Ti)&&(globalThis.URL=Ti=_o,Ti=_o);var oa=Ti,ku=globalThis.URLSearchParams;(Uh||!ku)&&(globalThis.URLSearchParams=xa,ku=xa);var jr=ku;function ia(e){!e.startsWith("http")&&!e.startsWith("https")&&(e="https://"+e);let t=new oa(e);return t.pathname.endsWith("/")||(t.pathname=t.pathname+"/"),t.search="",t.hash="",t.href}function pn(e){if(e=JSON.parse(JSON.stringify(e)),typeof e=="string"||typeof e=="number"||typeof e=="boolean"||e===null)return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(a=>pn(a)).join(",")}]`;let t=[];for(let n in e)t.push(n);t.sort();let r="{";for(let n=0;nt?1:0}function Ia(e){return JSON.stringify(e,void 0,2)}var bo=typeof process<"u"&&typeof process.release<"u"&&process.release.name==="node",Nt;(function(e){e.Trace="trace",e.Message="message",e.Info="info",e.Warn="warn",e.Error="error",e.None="none"})(Nt||(Nt={}));var sa=Nt.Info,Ni={},Ri=!1;Error.prototype.toString=function(){if(this===null||typeof this!="object"&&typeof this!="function")throw new TypeError;let e=this.name;e=e===void 0?"Error":`${e}`;let t=this.message;t=t===void 0?"":`${t}`;let r="";return"cause"in this&&(r=` Caused by: ${this.cause}`),`${e}: ${t}${r}`};function Mh(){return sa}function kh(e){sa=oA(e)}function oA(e){switch(e.toLowerCase()){case"trace":return Nt.Trace;case"info":return Nt.Info;case"warn":case"warning":return Nt.Warn;case"error":return Nt.Error;case"none":return Nt.None;default:return bo?process.stderr.write(`Invalid log level, defaulting to WARNING `):console.warn("Invalid log level, defaulting to WARNING"),Nt.Warn}}function xi(e,t,r,n){let a=globalThis.__nativeLog;if(a){let o;n.length==0?o=e:o=e+" "+n.toString(),a(r,t,e)}}function Ii(e,t,r,n){try{let a=`${new Date().toISOString()} ${t} ${r} ${e}`;n.length!=0?a+=` ${JSON.stringify(n,void 0,2)} `:a+=` `,process.stderr.write(a)}catch(a){let o=`${new Date().toISOString()} (logger) FATAL `;a instanceof Error?o+=`failed to write log: ${a.message} `:o+=`failed to write log `,process.stderr.write(o)}}var Dt=class{constructor(t){this.tag=t}getGlobalLogLevel(){return sa}shouldLogTrace(){switch(Ni[this.tag]??sa){case Nt.Trace:return!0;case Nt.Message:case Nt.Info:case Nt.Warn:case Nt.Error:case Nt.None:return!1}}shouldLogInfo(){switch(Ni[this.tag]??sa){case Nt.Trace:case Nt.Message:case Nt.Info:return!0;case Nt.Warn:case Nt.Error:case Nt.None:return!1}}shouldLogWarn(){switch(Ni[this.tag]??sa){case Nt.Trace:case Nt.Message:case Nt.Info:case Nt.Warn:return!0;case Nt.Error:case Nt.None:return!1}}shouldLogError(){switch(Ni[this.tag]??sa){case Nt.Trace:case Nt.Message:case Nt.Info:case Nt.Warn:case Nt.Error:return!0;case Nt.None:return!1}}info(t,...r){if(this.shouldLogInfo()){if(Ri){xi(t,this.tag,2,r);return}bo?Ii(t,this.tag,"INFO",r):console.info(`${new Date().toISOString()} ${this.tag} INFO `+t,...r)}}warn(t,...r){if(this.shouldLogWarn()){if(Ri){xi(t,this.tag,3,r);return}bo?Ii(t,this.tag,"WARN",r):console.warn(`${new Date().toISOString()} ${this.tag} INFO `+t,...r)}}error(t,...r){if(this.shouldLogError()){if(Ri){xi(t,this.tag,4,r);return}bo?Ii(t,this.tag,"ERROR",r):console.info(`${new Date().toISOString()} ${this.tag} ERROR `+t,...r)}}trace(t,...r){if(this.shouldLogTrace()){if(Ri){xi(t,this.tag,1,r);return}bo?Ii(t,this.tag,"TRACE",r):console.info(`${new Date().toISOString()} ${this.tag} TRACE `+t,...r)}}reportBreak(){if(!this.shouldLogError())return;let t=new Error("programming error");this.error(`assertion failed: ${t.stack}`)}};var Si=new Dt("codec.ts"),Rt=class e extends Error{constructor(t){super(t),Object.setPrototypeOf(this,e.prototype),this.name="DecodingError"}};function ut(e){let t=e?.path;return t?t.join("."):"(unknown)"}function Wu(e,t){return{path:(e?.path??[]).concat([t])}}var Hu=class{constructor(){this.propList=[],this.deprecatedProps=new Set,this._allowExtra=!1}property(t,r){if(!r)throw Error("inner codec must be defined");return this.propList.push({name:t,codec:r}),this}propertyStrict(t,r){if(!r)throw Error("inner codec must be defined");return this.propList.push({name:t,codec:r}),this}mixin(t){return this.propList.push(...t.getProps()),this}deprecatedProperty(t){return this.deprecatedProps.add(t),this}allowExtra(){return this._allowExtra=!0,this}build(t){let r=this.propList,n=this._allowExtra,a=this.deprecatedProps;return{decode(o,s){if(s||(s={path:[`(${t})`]}),typeof o!="object")throw new Rt(`expected object for ${t} at ${ut(s)} but got ${typeof o}`);let c={};for(let u of r){let f=o[u.name],d=u.codec.decode(f,Wu(s,u.name));c[u.name]=d}for(let u in o)u in c||(n?c[u]=o[u]:a.has(u)?Si.trace(`Deprecated property ${u} for ${t} at ${ut(s)}`):Si.warn(`Extra property ${u} for ${t} at ${ut(s)}`));return c},getProps(){return r}}}},Gu=class{constructor(t,r){this.discriminator=t,this.baseCodec=r,this.alternatives=new Map}alternativeOnMissing(t,r){if(!r)throw Error("inner codec must be defined");return this.alternatives.set(void 0,{codec:r,tagValue:t}),this}alternative(t,r){if(!r)throw Error("inner codec must be defined");return this.alternatives.set(t,{codec:r,tagValue:t}),this}build(t){let r=this.alternatives,n=this.discriminator,a=this.baseCodec;return{decode(o,s){s||(s={path:[`(${t})`]});let c=o[n];if(c===void 0&&!r.has(c))throw new Rt(`expected tag for ${t} at ${ut(s)}.${String(n)}`);let u=r.get(c);if(!u)throw new Rt(`unknown tag for ${t} ${c} at ${ut(s)}.${String(n)}`);let f=u.codec.decode(o);return a?{...a.decode(o,s),...f}:f}}}},Bu=class{discriminateOn(t,r){return new Gu(t,r)}};function W(){return new Hu}function wt(){return new Bu}function Ar(e){if(!e)throw Error("inner codec must be defined");return{decode(t,r){let n={};if(typeof t!="object")throw new Rt(`expected object at ${ut(r)}`);for(let a in t)n[a]=e.decode(t[a],Wu(r,`[${a}]`));return n}}}function Ae(e){if(!e)throw Error("inner codec must be defined");return{decode(t,r){let n=[];if(!Array.isArray(t))throw new Rt(`expected array at ${ut(r)}`);for(let a in t)n.push(e.decode(t[a],Wu(r,`[${a}]`)));return n}}}function ne(){return{decode(e,t){if(typeof e=="number")return e;throw new Rt(`expected number at ${ut(t)} but got ${typeof e}`)}}}function Se(){return{decode(e,t){if(typeof e=="boolean")return e;throw new Rt(`expected boolean at ${ut(t)} but got ${typeof e}`)}}}function L(){return{decode(e,t){if(typeof e=="string")return e;throw new Rt(`expected string at ${ut(t)} but got ${typeof e}`)}}}function ca(e){return{decode(t,r){if(typeof t!="string")throw new Rt(`expected string at ${ut(r)} but got ${typeof t}`);if(e&&!t.endsWith("/"))throw new Rt(`expected URL string that ends with slash at ${ut(r)} but got ${t}`);try{let n=new URL(t);return t}catch(n){throw n instanceof Error?new Rt(n.message):new Rt(`expected an URL string at ${ut(r)} but got "${t}"`)}}}}function He(){return{decode(e,t){return e}}}function X(e){return{decode(t,r){if(t===e)return t;throw typeof t!="string"?new Rt(`expected string constant "${e}" at ${ut(r)} but got ${typeof t}`):new Rt(`expected string constant "${e}" at ${ut(r)} but got string value "${t}"`)}}}function vo(e){return{decode(t,r){if(t===e)return t;throw new Rt(`expected number constant "${e}" at ${ut(r)} but got ${typeof t}`)}}}function U(e){return{decode(t,r){if(t!=null)return e.decode(t,r)}}}function Bt(e,t){return{decode(r,n){return r==null?t:e.decode(r,n)}}}function pt(...e){return{decode(t,r){for(let n of e)try{return n.decode(t,r)}catch{continue}throw Si.shouldLogTrace()&&Si.trace(`offending value: ${Ia(t)}`),new Rt(`No alternative matched at ${ut(r)}`)}}}var Fh=()=>{},xr=class e{get isCancelled(){return this._isCancelled}get canBeCancelled(){return this._canBeCancelled}get reason(){if(this.isCancelled)return this._reason;throw new Error("This token is not cancelled.")}racePromise(t){return this.canBeCancelled?new Promise((r,n)=>{let a=this.onCancelled(o=>n(new e.CancellationError(o)));t.then(o=>{r(o),a()},o=>{n(o),a()})}):t}throwIfCancelled(){if(this._isCancelled)throw new e.CancellationError(this._reason)}onCancelled(t){return this.canBeCancelled?this.isCancelled?(t(this.reason),Fh):(this._callbacks?.add(t),()=>this._callbacks?.delete(t)):Fh}constructor(t,r){this._isCancelled=t,this._canBeCancelled=r,this._callbacks=new Set}static create(){let t=new e(!1,!0),r=a=>{t._isCancelled||(t._isCancelled=!0,t._reason=a,t._callbacks?.forEach(o=>o(a)),n())},n=()=>{t._canBeCancelled=t.isCancelled,delete t._callbacks};return{token:t,cancel:r,dispose:n}}static timeout(t){let{token:r,cancel:n,dispose:a}=e.create(),o;o=setTimeout(()=>n(`CancellationToken.timeout ${t}`),t);let s=()=>{o!=null&&(clearTimeout(o),o=null)};return{token:r,cancel:f=>{s(),n(f)},dispose:()=>{s(),a()}}}static all(...t){if(t.some(o=>!o.canBeCancelled))return e.CONTINUE;let r=e.create(),n=t.length,a=()=>{if(--n===0){let o=t.map(s=>s._reason);r.cancel(o)}};return t.forEach(o=>o.onCancelled(a)),r.token}static race(...t){for(let o of t)if(o._isCancelled)return o;let r=e.create(),n,a=o=>{n.forEach(s=>s()),r.cancel(o)};return n=t.map(o=>o.onCancelled(a)),r.token}};xr.CANCELLED=new xr(!0,!0);xr.CONTINUE=new xr(!1,!1);(function(e){class t extends Error{constructor(n){super("Operation cancelled"),this.reason=n,Object.setPrototypeOf(this,t.prototype)}}e.CancellationError=t})(xr||(xr={}));var G;(function(e){e[e.NONE=0]="NONE",e[e.INVALID=1]="INVALID",e[e.GENERIC_CLIENT_INTERNAL_ERROR=2]="GENERIC_CLIENT_INTERNAL_ERROR",e[e.GENERIC_CLIENT_UNSUPPORTED_PROTOCOL_VERSION=3]="GENERIC_CLIENT_UNSUPPORTED_PROTOCOL_VERSION",e[e.GENERIC_INVALID_RESPONSE=10]="GENERIC_INVALID_RESPONSE",e[e.GENERIC_TIMEOUT=11]="GENERIC_TIMEOUT",e[e.GENERIC_VERSION_MALFORMED=12]="GENERIC_VERSION_MALFORMED",e[e.GENERIC_REPLY_MALFORMED=13]="GENERIC_REPLY_MALFORMED",e[e.GENERIC_CONFIGURATION_INVALID=14]="GENERIC_CONFIGURATION_INVALID",e[e.GENERIC_UNEXPECTED_REQUEST_ERROR=15]="GENERIC_UNEXPECTED_REQUEST_ERROR",e[e.GENERIC_TOKEN_PERMISSION_INSUFFICIENT=16]="GENERIC_TOKEN_PERMISSION_INSUFFICIENT",e[e.GENERIC_METHOD_INVALID=20]="GENERIC_METHOD_INVALID",e[e.GENERIC_ENDPOINT_UNKNOWN=21]="GENERIC_ENDPOINT_UNKNOWN",e[e.GENERIC_JSON_INVALID=22]="GENERIC_JSON_INVALID",e[e.GENERIC_HTTP_HEADERS_MALFORMED=23]="GENERIC_HTTP_HEADERS_MALFORMED",e[e.GENERIC_PAYTO_URI_MALFORMED=24]="GENERIC_PAYTO_URI_MALFORMED",e[e.GENERIC_PARAMETER_MISSING=25]="GENERIC_PARAMETER_MISSING",e[e.GENERIC_PARAMETER_MALFORMED=26]="GENERIC_PARAMETER_MALFORMED",e[e.GENERIC_RESERVE_PUB_MALFORMED=27]="GENERIC_RESERVE_PUB_MALFORMED",e[e.GENERIC_COMPRESSION_INVALID=28]="GENERIC_COMPRESSION_INVALID",e[e.GENERIC_PATH_SEGMENT_MALFORMED=29]="GENERIC_PATH_SEGMENT_MALFORMED",e[e.GENERIC_CURRENCY_MISMATCH=30]="GENERIC_CURRENCY_MISMATCH",e[e.GENERIC_URI_TOO_LONG=31]="GENERIC_URI_TOO_LONG",e[e.GENERIC_UPLOAD_EXCEEDS_LIMIT=32]="GENERIC_UPLOAD_EXCEEDS_LIMIT",e[e.GENERIC_PARAMETER_EXTRA=33]="GENERIC_PARAMETER_EXTRA",e[e.GENERIC_UNAUTHORIZED=40]="GENERIC_UNAUTHORIZED",e[e.GENERIC_TOKEN_UNKNOWN=41]="GENERIC_TOKEN_UNKNOWN",e[e.GENERIC_TOKEN_EXPIRED=42]="GENERIC_TOKEN_EXPIRED",e[e.GENERIC_TOKEN_MALFORMED=43]="GENERIC_TOKEN_MALFORMED",e[e.GENERIC_FORBIDDEN=44]="GENERIC_FORBIDDEN",e[e.GENERIC_DB_SETUP_FAILED=50]="GENERIC_DB_SETUP_FAILED",e[e.GENERIC_DB_START_FAILED=51]="GENERIC_DB_START_FAILED",e[e.GENERIC_DB_STORE_FAILED=52]="GENERIC_DB_STORE_FAILED",e[e.GENERIC_DB_FETCH_FAILED=53]="GENERIC_DB_FETCH_FAILED",e[e.GENERIC_DB_COMMIT_FAILED=54]="GENERIC_DB_COMMIT_FAILED",e[e.GENERIC_DB_SOFT_FAILURE=55]="GENERIC_DB_SOFT_FAILURE",e[e.GENERIC_DB_INVARIANT_FAILURE=56]="GENERIC_DB_INVARIANT_FAILURE",e[e.GENERIC_INTERNAL_INVARIANT_FAILURE=60]="GENERIC_INTERNAL_INVARIANT_FAILURE",e[e.GENERIC_FAILED_COMPUTE_JSON_HASH=61]="GENERIC_FAILED_COMPUTE_JSON_HASH",e[e.GENERIC_FAILED_COMPUTE_AMOUNT=62]="GENERIC_FAILED_COMPUTE_AMOUNT",e[e.GENERIC_PARSER_OUT_OF_MEMORY=70]="GENERIC_PARSER_OUT_OF_MEMORY",e[e.GENERIC_ALLOCATION_FAILURE=71]="GENERIC_ALLOCATION_FAILURE",e[e.GENERIC_JSON_ALLOCATION_FAILURE=72]="GENERIC_JSON_ALLOCATION_FAILURE",e[e.GENERIC_CURL_ALLOCATION_FAILURE=73]="GENERIC_CURL_ALLOCATION_FAILURE",e[e.GENERIC_FAILED_TO_LOAD_TEMPLATE=74]="GENERIC_FAILED_TO_LOAD_TEMPLATE",e[e.GENERIC_FAILED_TO_EXPAND_TEMPLATE=75]="GENERIC_FAILED_TO_EXPAND_TEMPLATE",e[e.GENERIC_FEATURE_NOT_IMPLEMENTED=76]="GENERIC_FEATURE_NOT_IMPLEMENTED",e[e.GENERIC_OS_RESOURCE_ALLOCATION_FAILURE=77]="GENERIC_OS_RESOURCE_ALLOCATION_FAILURE",e[e.GENERIC_REQUESTED_FORMAT_UNSUPPORTED=78]="GENERIC_REQUESTED_FORMAT_UNSUPPORTED",e[e.EXCHANGE_GENERIC_BAD_CONFIGURATION=1e3]="EXCHANGE_GENERIC_BAD_CONFIGURATION",e[e.EXCHANGE_GENERIC_OPERATION_UNKNOWN=1001]="EXCHANGE_GENERIC_OPERATION_UNKNOWN",e[e.EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS=1002]="EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS",e[e.EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY=1003]="EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY",e[e.EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB=1004]="EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB",e[e.EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN=1005]="EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN",e[e.EXCHANGE_DENOMINATION_SIGNATURE_INVALID=1006]="EXCHANGE_DENOMINATION_SIGNATURE_INVALID",e[e.EXCHANGE_GENERIC_KEYS_MISSING=1007]="EXCHANGE_GENERIC_KEYS_MISSING",e[e.EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE=1008]="EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE",e[e.EXCHANGE_GENERIC_DENOMINATION_EXPIRED=1009]="EXCHANGE_GENERIC_DENOMINATION_EXPIRED",e[e.EXCHANGE_GENERIC_DENOMINATION_REVOKED=1010]="EXCHANGE_GENERIC_DENOMINATION_REVOKED",e[e.EXCHANGE_GENERIC_SECMOD_TIMEOUT=1011]="EXCHANGE_GENERIC_SECMOD_TIMEOUT",e[e.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS=1012]="EXCHANGE_GENERIC_INSUFFICIENT_FUNDS",e[e.EXCHANGE_GENERIC_COIN_HISTORY_COMPUTATION_FAILED=1013]="EXCHANGE_GENERIC_COIN_HISTORY_COMPUTATION_FAILED",e[e.EXCHANGE_GENERIC_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS=1014]="EXCHANGE_GENERIC_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS",e[e.EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH=1015]="EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH",e[e.EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION=1016]="EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION",e[e.EXCHANGE_GENERIC_CIPHER_MISMATCH=1017]="EXCHANGE_GENERIC_CIPHER_MISMATCH",e[e.EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE=1018]="EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE",e[e.EXCHANGE_GENERIC_COIN_UNKNOWN=1019]="EXCHANGE_GENERIC_COIN_UNKNOWN",e[e.EXCHANGE_GENERIC_CLOCK_SKEW=1020]="EXCHANGE_GENERIC_CLOCK_SKEW",e[e.EXCHANGE_GENERIC_AMOUNT_EXCEEDS_DENOMINATION_VALUE=1021]="EXCHANGE_GENERIC_AMOUNT_EXCEEDS_DENOMINATION_VALUE",e[e.EXCHANGE_GENERIC_GLOBAL_FEES_MISSING=1022]="EXCHANGE_GENERIC_GLOBAL_FEES_MISSING",e[e.EXCHANGE_GENERIC_WIRE_FEES_MISSING=1023]="EXCHANGE_GENERIC_WIRE_FEES_MISSING",e[e.EXCHANGE_GENERIC_PURSE_PUB_MALFORMED=1024]="EXCHANGE_GENERIC_PURSE_PUB_MALFORMED",e[e.EXCHANGE_GENERIC_PURSE_UNKNOWN=1025]="EXCHANGE_GENERIC_PURSE_UNKNOWN",e[e.EXCHANGE_GENERIC_PURSE_EXPIRED=1026]="EXCHANGE_GENERIC_PURSE_EXPIRED",e[e.EXCHANGE_GENERIC_RESERVE_UNKNOWN=1027]="EXCHANGE_GENERIC_RESERVE_UNKNOWN",e[e.EXCHANGE_GENERIC_KYC_REQUIRED=1028]="EXCHANGE_GENERIC_KYC_REQUIRED",e[e.EXCHANGE_PURSE_DEPOSIT_COIN_CONFLICTING_ATTEST_VS_AGE_COMMITMENT=1029]="EXCHANGE_PURSE_DEPOSIT_COIN_CONFLICTING_ATTEST_VS_AGE_COMMITMENT",e[e.EXCHANGE_PURSE_DEPOSIT_COIN_AGE_ATTESTATION_FAILURE=1030]="EXCHANGE_PURSE_DEPOSIT_COIN_AGE_ATTESTATION_FAILURE",e[e.EXCHANGE_GENERIC_PURSE_DELETED=1031]="EXCHANGE_GENERIC_PURSE_DELETED",e[e.EXCHANGE_GENERIC_AML_OFFICER_PUB_MALFORMED=1032]="EXCHANGE_GENERIC_AML_OFFICER_PUB_MALFORMED",e[e.EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID=1033]="EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID",e[e.EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED=1034]="EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED",e[e.EXCHANGE_GENERIC_AML_PENDING=1035]="EXCHANGE_GENERIC_AML_PENDING",e[e.EXCHANGE_GENERIC_AML_FROZEN=1036]="EXCHANGE_GENERIC_AML_FROZEN",e[e.EXCHANGE_GENERIC_KYC_CONVERTER_FAILED=1037]="EXCHANGE_GENERIC_KYC_CONVERTER_FAILED",e[e.EXCHANGE_GENERIC_KYC_FAILED=1038]="EXCHANGE_GENERIC_KYC_FAILED",e[e.EXCHANGE_GENERIC_KYC_FALLBACK_FAILED=1039]="EXCHANGE_GENERIC_KYC_FALLBACK_FAILED",e[e.EXCHANGE_GENERIC_KYC_FALLBACK_UNKNOWN=1040]="EXCHANGE_GENERIC_KYC_FALLBACK_UNKNOWN",e[e.EXCHANGE_GENERIC_BANK_ACCOUNT_UNKNOWN=1041]="EXCHANGE_GENERIC_BANK_ACCOUNT_UNKNOWN",e[e.EXCHANGE_GENERIC_AML_PROGRAM_RECURSION_DETECTED=1042]="EXCHANGE_GENERIC_AML_PROGRAM_RECURSION_DETECTED",e[e.EXCHANGE_GENERIC_KYC_SANCTION_LIST_CHECK_FAILED=1043]="EXCHANGE_GENERIC_KYC_SANCTION_LIST_CHECK_FAILED",e[e.EXCHANGE_GENERIC_TYPST_TEMPLATE_FAILURE=1044]="EXCHANGE_GENERIC_TYPST_TEMPLATE_FAILURE",e[e.EXCHANGE_GENERIC_PDFTK_FAILURE=1045]="EXCHANGE_GENERIC_PDFTK_FAILURE",e[e.EXCHANGE_GENERIC_TYPST_CRASH=1046]="EXCHANGE_GENERIC_TYPST_CRASH",e[e.EXCHANGE_GENERIC_PDFTK_CRASH=1047]="EXCHANGE_GENERIC_PDFTK_CRASH",e[e.EXCHANGE_GENERIC_NO_TYPST_OR_PDFTK=1048]="EXCHANGE_GENERIC_NO_TYPST_OR_PDFTK",e[e.EXCHANGE_GENERIC_TARGET_ACCOUNT_UNKNOWN=1049]="EXCHANGE_GENERIC_TARGET_ACCOUNT_UNKNOWN",e[e.EXCHANGE_GENERIC_AML_OFFICER_READ_ONLY=1050]="EXCHANGE_GENERIC_AML_OFFICER_READ_ONLY",e[e.EXCHANGE_DEPOSITS_GET_NOT_FOUND=1100]="EXCHANGE_DEPOSITS_GET_NOT_FOUND",e[e.EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE=1101]="EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE",e[e.EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB=1102]="EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB",e[e.EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS=1103]="EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS",e[e.EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB=1104]="EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB",e[e.EXCHANGE_DEPOSITS_GET_INVALID_SIGNATURE_BY_EXCHANGE=1105]="EXCHANGE_DEPOSITS_GET_INVALID_SIGNATURE_BY_EXCHANGE",e[e.EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID=1106]="EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID",e[e.EXCHANGE_DEPOSITS_POLICY_NOT_ACCEPTED=1107]="EXCHANGE_DEPOSITS_POLICY_NOT_ACCEPTED",e[e.EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS=1150]="EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS",e[e.EXCHANGE_AGE_WITHDRAW_INSUFFICIENT_FUNDS=1151]="EXCHANGE_AGE_WITHDRAW_INSUFFICIENT_FUNDS",e[e.EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW=1152]="EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW",e[e.EXCHANGE_WITHDRAW_SIGNATURE_FAILED=1153]="EXCHANGE_WITHDRAW_SIGNATURE_FAILED",e[e.EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID=1154]="EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID",e[e.EXCHANGE_RESERVE_HISTORY_ERROR_INSUFFICIENT_FUNDS=1155]="EXCHANGE_RESERVE_HISTORY_ERROR_INSUFFICIENT_FUNDS",e[e.EXCHANGE_GET_RESERVE_HISTORY_ERROR_INSUFFICIENT_BALANCE=1156]="EXCHANGE_GET_RESERVE_HISTORY_ERROR_INSUFFICIENT_BALANCE",e[e.EXCHANGE_WITHDRAW_DENOMINATION_KEY_LOST=1158]="EXCHANGE_WITHDRAW_DENOMINATION_KEY_LOST",e[e.EXCHANGE_WITHDRAW_UNBLIND_FAILURE=1159]="EXCHANGE_WITHDRAW_UNBLIND_FAILURE",e[e.EXCHANGE_WITHDRAW_NONCE_REUSE=1160]="EXCHANGE_WITHDRAW_NONCE_REUSE",e[e.EXCHANGE_WITHDRAW_COMMITMENT_UNKNOWN=1161]="EXCHANGE_WITHDRAW_COMMITMENT_UNKNOWN",e[e.EXCHANGE_WITHDRAW_AMOUNT_OVERFLOW=1162]="EXCHANGE_WITHDRAW_AMOUNT_OVERFLOW",e[e.EXCHANGE_AGE_WITHDRAW_AMOUNT_INCORRECT=1163]="EXCHANGE_AGE_WITHDRAW_AMOUNT_INCORRECT",e[e.EXCHANGE_WITHDRAW_REVEAL_INVALID_HASH=1164]="EXCHANGE_WITHDRAW_REVEAL_INVALID_HASH",e[e.EXCHANGE_WITHDRAW_MAXIMUM_AGE_TOO_LARGE=1165]="EXCHANGE_WITHDRAW_MAXIMUM_AGE_TOO_LARGE",e[e.EXCHANGE_WITHDRAW_IDEMPOTENT_PLANCHET=1175]="EXCHANGE_WITHDRAW_IDEMPOTENT_PLANCHET",e[e.EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID=1205]="EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID",e[e.EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT=1206]="EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT",e[e.EXCHANGE_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE=1207]="EXCHANGE_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE",e[e.EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE=1208]="EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE",e[e.EXCHANGE_DEPOSIT_WIRE_DEADLINE_IS_NEVER=1209]="EXCHANGE_DEPOSIT_WIRE_DEADLINE_IS_NEVER",e[e.EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_JSON=1210]="EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_JSON",e[e.EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT=1211]="EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT",e[e.EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE=1221]="EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE",e[e.EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT=1222]="EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT",e[e.EXCHANGE_EXTENSIONS_INVALID_FULFILLMENT=1240]="EXCHANGE_EXTENSIONS_INVALID_FULFILLMENT",e[e.EXCHANGE_COIN_HISTORY_BAD_SIGNATURE=1251]="EXCHANGE_COIN_HISTORY_BAD_SIGNATURE",e[e.EXCHANGE_RESERVE_HISTORY_BAD_SIGNATURE=1252]="EXCHANGE_RESERVE_HISTORY_BAD_SIGNATURE",e[e.EXCHANGE_MELT_FEES_EXCEED_CONTRIBUTION=1302]="EXCHANGE_MELT_FEES_EXCEED_CONTRIBUTION",e[e.EXCHANGE_MELT_COIN_SIGNATURE_INVALID=1303]="EXCHANGE_MELT_COIN_SIGNATURE_INVALID",e[e.EXCHANGE_MELT_COIN_EXPIRED_NO_ZOMBIE=1305]="EXCHANGE_MELT_COIN_EXPIRED_NO_ZOMBIE",e[e.EXCHANGE_MELT_INVALID_SIGNATURE_BY_EXCHANGE=1306]="EXCHANGE_MELT_INVALID_SIGNATURE_BY_EXCHANGE",e[e.EXCHANGE_REFRESHES_REVEAL_COMMITMENT_VIOLATION=1353]="EXCHANGE_REFRESHES_REVEAL_COMMITMENT_VIOLATION",e[e.EXCHANGE_REFRESHES_REVEAL_SIGNING_ERROR=1354]="EXCHANGE_REFRESHES_REVEAL_SIGNING_ERROR",e[e.EXCHANGE_REFRESHES_REVEAL_SESSION_UNKNOWN=1355]="EXCHANGE_REFRESHES_REVEAL_SESSION_UNKNOWN",e[e.EXCHANGE_REFRESHES_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID=1356]="EXCHANGE_REFRESHES_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID",e[e.EXCHANGE_REFRESHES_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISMATCH=1358]="EXCHANGE_REFRESHES_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISMATCH",e[e.EXCHANGE_REFRESHES_REVEAL_COST_CALCULATION_OVERFLOW=1359]="EXCHANGE_REFRESHES_REVEAL_COST_CALCULATION_OVERFLOW",e[e.EXCHANGE_REFRESHES_REVEAL_AMOUNT_INSUFFICIENT=1360]="EXCHANGE_REFRESHES_REVEAL_AMOUNT_INSUFFICIENT",e[e.EXCHANGE_REFRESHES_REVEAL_LINK_SIGNATURE_INVALID=1361]="EXCHANGE_REFRESHES_REVEAL_LINK_SIGNATURE_INVALID",e[e.EXCHANGE_REFRESHES_REVEAL_INVALID_RCH=1362]="EXCHANGE_REFRESHES_REVEAL_INVALID_RCH",e[e.EXCHANGE_REFRESHES_REVEAL_OPERATION_INVALID=1363]="EXCHANGE_REFRESHES_REVEAL_OPERATION_INVALID",e[e.EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_NOT_SUPPORTED=1364]="EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_NOT_SUPPORTED",e[e.EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_COMMITMENT_INVALID=1365]="EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_COMMITMENT_INVALID",e[e.EXCHANGE_LINK_COIN_UNKNOWN=1400]="EXCHANGE_LINK_COIN_UNKNOWN",e[e.EXCHANGE_TRANSFERS_GET_WTID_MALFORMED=1450]="EXCHANGE_TRANSFERS_GET_WTID_MALFORMED",e[e.EXCHANGE_TRANSFERS_GET_WTID_NOT_FOUND=1451]="EXCHANGE_TRANSFERS_GET_WTID_NOT_FOUND",e[e.EXCHANGE_TRANSFERS_GET_WIRE_FEE_NOT_FOUND=1452]="EXCHANGE_TRANSFERS_GET_WIRE_FEE_NOT_FOUND",e[e.EXCHANGE_TRANSFERS_GET_WIRE_FEE_INCONSISTENT=1453]="EXCHANGE_TRANSFERS_GET_WIRE_FEE_INCONSISTENT",e[e.EXCHANGE_PURSES_INVALID_WAIT_TARGET=1475]="EXCHANGE_PURSES_INVALID_WAIT_TARGET",e[e.EXCHANGE_PURSES_GET_INVALID_SIGNATURE_BY_EXCHANGE=1476]="EXCHANGE_PURSES_GET_INVALID_SIGNATURE_BY_EXCHANGE",e[e.EXCHANGE_REFUND_COIN_NOT_FOUND=1500]="EXCHANGE_REFUND_COIN_NOT_FOUND",e[e.EXCHANGE_REFUND_CONFLICT_DEPOSIT_INSUFFICIENT=1501]="EXCHANGE_REFUND_CONFLICT_DEPOSIT_INSUFFICIENT",e[e.EXCHANGE_REFUND_DEPOSIT_NOT_FOUND=1502]="EXCHANGE_REFUND_DEPOSIT_NOT_FOUND",e[e.EXCHANGE_REFUND_MERCHANT_ALREADY_PAID=1503]="EXCHANGE_REFUND_MERCHANT_ALREADY_PAID",e[e.EXCHANGE_REFUND_FEE_TOO_LOW=1504]="EXCHANGE_REFUND_FEE_TOO_LOW",e[e.EXCHANGE_REFUND_FEE_ABOVE_AMOUNT=1505]="EXCHANGE_REFUND_FEE_ABOVE_AMOUNT",e[e.EXCHANGE_REFUND_MERCHANT_SIGNATURE_INVALID=1506]="EXCHANGE_REFUND_MERCHANT_SIGNATURE_INVALID",e[e.EXCHANGE_REFUND_MERCHANT_SIGNING_FAILED=1507]="EXCHANGE_REFUND_MERCHANT_SIGNING_FAILED",e[e.EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE=1508]="EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE",e[e.EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE=1509]="EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE",e[e.EXCHANGE_REFUND_INCONSISTENT_AMOUNT=1510]="EXCHANGE_REFUND_INCONSISTENT_AMOUNT",e[e.EXCHANGE_RECOUP_SIGNATURE_INVALID=1550]="EXCHANGE_RECOUP_SIGNATURE_INVALID",e[e.EXCHANGE_RECOUP_WITHDRAW_NOT_FOUND=1551]="EXCHANGE_RECOUP_WITHDRAW_NOT_FOUND",e[e.EXCHANGE_RECOUP_COIN_BALANCE_ZERO=1552]="EXCHANGE_RECOUP_COIN_BALANCE_ZERO",e[e.EXCHANGE_RECOUP_BLINDING_FAILED=1553]="EXCHANGE_RECOUP_BLINDING_FAILED",e[e.EXCHANGE_RECOUP_COIN_BALANCE_NEGATIVE=1554]="EXCHANGE_RECOUP_COIN_BALANCE_NEGATIVE",e[e.EXCHANGE_RECOUP_NOT_ELIGIBLE=1555]="EXCHANGE_RECOUP_NOT_ELIGIBLE",e[e.EXCHANGE_RECOUP_REFRESH_SIGNATURE_INVALID=1575]="EXCHANGE_RECOUP_REFRESH_SIGNATURE_INVALID",e[e.EXCHANGE_RECOUP_REFRESH_MELT_NOT_FOUND=1576]="EXCHANGE_RECOUP_REFRESH_MELT_NOT_FOUND",e[e.EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED=1578]="EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED",e[e.EXCHANGE_RECOUP_REFRESH_NOT_ELIGIBLE=1580]="EXCHANGE_RECOUP_REFRESH_NOT_ELIGIBLE",e[e.EXCHANGE_KEYS_TIMETRAVEL_FORBIDDEN=1600]="EXCHANGE_KEYS_TIMETRAVEL_FORBIDDEN",e[e.EXCHANGE_WIRE_SIGNATURE_INVALID=1650]="EXCHANGE_WIRE_SIGNATURE_INVALID",e[e.EXCHANGE_WIRE_NO_ACCOUNTS_CONFIGURED=1651]="EXCHANGE_WIRE_NO_ACCOUNTS_CONFIGURED",e[e.EXCHANGE_WIRE_INVALID_PAYTO_CONFIGURED=1652]="EXCHANGE_WIRE_INVALID_PAYTO_CONFIGURED",e[e.EXCHANGE_WIRE_FEES_NOT_CONFIGURED=1653]="EXCHANGE_WIRE_FEES_NOT_CONFIGURED",e[e.EXCHANGE_RESERVES_PURSE_CREATE_CONFLICTING_META_DATA=1675]="EXCHANGE_RESERVES_PURSE_CREATE_CONFLICTING_META_DATA",e[e.EXCHANGE_RESERVES_PURSE_MERGE_CONFLICTING_META_DATA=1676]="EXCHANGE_RESERVES_PURSE_MERGE_CONFLICTING_META_DATA",e[e.EXCHANGE_RESERVES_PURSE_CREATE_INSUFFICIENT_FUNDS=1677]="EXCHANGE_RESERVES_PURSE_CREATE_INSUFFICIENT_FUNDS",e[e.EXCHANGE_RESERVES_PURSE_FEE_TOO_LOW=1678]="EXCHANGE_RESERVES_PURSE_FEE_TOO_LOW",e[e.EXCHANGE_PURSE_DELETE_ALREADY_DECIDED=1679]="EXCHANGE_PURSE_DELETE_ALREADY_DECIDED",e[e.EXCHANGE_PURSE_DELETE_SIGNATURE_INVALID=1680]="EXCHANGE_PURSE_DELETE_SIGNATURE_INVALID",e[e.EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED=1681]="EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED",e[e.EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE=1700]="EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE",e[e.EXCHANGE_DENOMINATION_HELPER_BUG=1701]="EXCHANGE_DENOMINATION_HELPER_BUG",e[e.EXCHANGE_DENOMINATION_HELPER_TOO_EARLY=1702]="EXCHANGE_DENOMINATION_HELPER_TOO_EARLY",e[e.EXCHANGE_PURSE_DEPOSIT_EXCHANGE_SIGNATURE_INVALID=1725]="EXCHANGE_PURSE_DEPOSIT_EXCHANGE_SIGNATURE_INVALID",e[e.EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE=1750]="EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE",e[e.EXCHANGE_SIGNKEY_HELPER_BUG=1751]="EXCHANGE_SIGNKEY_HELPER_BUG",e[e.EXCHANGE_SIGNKEY_HELPER_TOO_EARLY=1752]="EXCHANGE_SIGNKEY_HELPER_TOO_EARLY",e[e.EXCHANGE_SIGNKEY_HELPER_OFFLINE_MISSING=1753]="EXCHANGE_SIGNKEY_HELPER_OFFLINE_MISSING",e[e.EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW=1775]="EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW",e[e.EXCHANGE_RESERVES_PURSE_EXPIRATION_IS_NEVER=1776]="EXCHANGE_RESERVES_PURSE_EXPIRATION_IS_NEVER",e[e.EXCHANGE_RESERVES_PURSE_MERGE_SIGNATURE_INVALID=1777]="EXCHANGE_RESERVES_PURSE_MERGE_SIGNATURE_INVALID",e[e.EXCHANGE_RESERVES_RESERVE_MERGE_SIGNATURE_INVALID=1778]="EXCHANGE_RESERVES_RESERVE_MERGE_SIGNATURE_INVALID",e[e.EXCHANGE_RESERVES_OPEN_BAD_SIGNATURE=1785]="EXCHANGE_RESERVES_OPEN_BAD_SIGNATURE",e[e.EXCHANGE_RESERVES_CLOSE_BAD_SIGNATURE=1786]="EXCHANGE_RESERVES_CLOSE_BAD_SIGNATURE",e[e.EXCHANGE_RESERVES_ATTEST_BAD_SIGNATURE=1787]="EXCHANGE_RESERVES_ATTEST_BAD_SIGNATURE",e[e.EXCHANGE_RESERVES_CLOSE_NO_TARGET_ACCOUNT=1788]="EXCHANGE_RESERVES_CLOSE_NO_TARGET_ACCOUNT",e[e.EXCHANGE_RESERVES_OPEN_INSUFFICIENT_FUNDS=1789]="EXCHANGE_RESERVES_OPEN_INSUFFICIENT_FUNDS",e[e.EXCHANGE_MANAGEMENT_AUDITOR_NOT_FOUND=1800]="EXCHANGE_MANAGEMENT_AUDITOR_NOT_FOUND",e[e.EXCHANGE_MANAGEMENT_AUDITOR_MORE_RECENT_PRESENT=1801]="EXCHANGE_MANAGEMENT_AUDITOR_MORE_RECENT_PRESENT",e[e.EXCHANGE_MANAGEMENT_AUDITOR_ADD_SIGNATURE_INVALID=1802]="EXCHANGE_MANAGEMENT_AUDITOR_ADD_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_AUDITOR_DEL_SIGNATURE_INVALID=1803]="EXCHANGE_MANAGEMENT_AUDITOR_DEL_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_DENOMINATION_REVOKE_SIGNATURE_INVALID=1804]="EXCHANGE_MANAGEMENT_DENOMINATION_REVOKE_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_SIGNKEY_REVOKE_SIGNATURE_INVALID=1805]="EXCHANGE_MANAGEMENT_SIGNKEY_REVOKE_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_WIRE_MORE_RECENT_PRESENT=1806]="EXCHANGE_MANAGEMENT_WIRE_MORE_RECENT_PRESENT",e[e.EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_UNKNOWN=1807]="EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_UNKNOWN",e[e.EXCHANGE_MANAGEMENT_WIRE_DETAILS_SIGNATURE_INVALID=1808]="EXCHANGE_MANAGEMENT_WIRE_DETAILS_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_WIRE_ADD_SIGNATURE_INVALID=1809]="EXCHANGE_MANAGEMENT_WIRE_ADD_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_WIRE_DEL_SIGNATURE_INVALID=1810]="EXCHANGE_MANAGEMENT_WIRE_DEL_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_WIRE_NOT_FOUND=1811]="EXCHANGE_MANAGEMENT_WIRE_NOT_FOUND",e[e.EXCHANGE_MANAGEMENT_WIRE_FEE_SIGNATURE_INVALID=1812]="EXCHANGE_MANAGEMENT_WIRE_FEE_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_WIRE_FEE_MISMATCH=1813]="EXCHANGE_MANAGEMENT_WIRE_FEE_MISMATCH",e[e.EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID=1814]="EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID=1815]="EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_GLOBAL_FEE_MISMATCH=1816]="EXCHANGE_MANAGEMENT_GLOBAL_FEE_MISMATCH",e[e.EXCHANGE_MANAGEMENT_GLOBAL_FEE_SIGNATURE_INVALID=1817]="EXCHANGE_MANAGEMENT_GLOBAL_FEE_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_DRAIN_PROFITS_SIGNATURE_INVALID=1818]="EXCHANGE_MANAGEMENT_DRAIN_PROFITS_SIGNATURE_INVALID",e[e.EXCHANGE_AML_DECISION_ADD_SIGNATURE_INVALID=1825]="EXCHANGE_AML_DECISION_ADD_SIGNATURE_INVALID",e[e.EXCHANGE_AML_DECISION_INVALID_OFFICER=1826]="EXCHANGE_AML_DECISION_INVALID_OFFICER",e[e.EXCHANGE_AML_DECISION_MORE_RECENT_PRESENT=1827]="EXCHANGE_AML_DECISION_MORE_RECENT_PRESENT",e[e.EXCHANGE_AML_DECISION_UNKNOWN_CHECK=1828]="EXCHANGE_AML_DECISION_UNKNOWN_CHECK",e[e.EXCHANGE_MANAGEMENT_UPDATE_AML_OFFICER_SIGNATURE_INVALID=1830]="EXCHANGE_MANAGEMENT_UPDATE_AML_OFFICER_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_AML_OFFICERS_MORE_RECENT_PRESENT=1831]="EXCHANGE_MANAGEMENT_AML_OFFICERS_MORE_RECENT_PRESENT",e[e.EXCHANGE_MANAGEMENT_CONFLICTING_DENOMINATION_META_DATA=1832]="EXCHANGE_MANAGEMENT_CONFLICTING_DENOMINATION_META_DATA",e[e.EXCHANGE_MANAGEMENT_CONFLICTING_SIGNKEY_META_DATA=1833]="EXCHANGE_MANAGEMENT_CONFLICTING_SIGNKEY_META_DATA",e[e.EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA=1850]="EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA",e[e.EXCHANGE_PURSE_CREATE_CONFLICTING_CONTRACT_STORED=1851]="EXCHANGE_PURSE_CREATE_CONFLICTING_CONTRACT_STORED",e[e.EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID=1852]="EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID",e[e.EXCHANGE_PURSE_CREATE_EXPIRATION_BEFORE_NOW=1853]="EXCHANGE_PURSE_CREATE_EXPIRATION_BEFORE_NOW",e[e.EXCHANGE_PURSE_CREATE_EXPIRATION_IS_NEVER=1854]="EXCHANGE_PURSE_CREATE_EXPIRATION_IS_NEVER",e[e.EXCHANGE_PURSE_CREATE_SIGNATURE_INVALID=1855]="EXCHANGE_PURSE_CREATE_SIGNATURE_INVALID",e[e.EXCHANGE_PURSE_ECONTRACT_SIGNATURE_INVALID=1856]="EXCHANGE_PURSE_ECONTRACT_SIGNATURE_INVALID",e[e.EXCHANGE_PURSE_CREATE_EXCHANGE_SIGNATURE_INVALID=1857]="EXCHANGE_PURSE_CREATE_EXCHANGE_SIGNATURE_INVALID",e[e.EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA=1858]="EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA",e[e.EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA=1859]="EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA",e[e.EXCHANGE_CREATE_PURSE_NEGATIVE_VALUE_AFTER_FEE=1860]="EXCHANGE_CREATE_PURSE_NEGATIVE_VALUE_AFTER_FEE",e[e.EXCHANGE_PURSE_MERGE_INVALID_MERGE_SIGNATURE=1876]="EXCHANGE_PURSE_MERGE_INVALID_MERGE_SIGNATURE",e[e.EXCHANGE_PURSE_MERGE_INVALID_RESERVE_SIGNATURE=1877]="EXCHANGE_PURSE_MERGE_INVALID_RESERVE_SIGNATURE",e[e.EXCHANGE_PURSE_NOT_FULL=1878]="EXCHANGE_PURSE_NOT_FULL",e[e.EXCHANGE_PURSE_MERGE_EXCHANGE_SIGNATURE_INVALID=1879]="EXCHANGE_PURSE_MERGE_EXCHANGE_SIGNATURE_INVALID",e[e.EXCHANGE_MERGE_PURSE_PARTNER_UNKNOWN=1880]="EXCHANGE_MERGE_PURSE_PARTNER_UNKNOWN",e[e.EXCHANGE_MANAGEMENT_ADD_PARTNER_SIGNATURE_INVALID=1890]="EXCHANGE_MANAGEMENT_ADD_PARTNER_SIGNATURE_INVALID",e[e.EXCHANGE_MANAGEMENT_ADD_PARTNER_DATA_CONFLICT=1891]="EXCHANGE_MANAGEMENT_ADD_PARTNER_DATA_CONFLICT",e[e.EXCHANGE_AUDITORS_AUDITOR_SIGNATURE_INVALID=1900]="EXCHANGE_AUDITORS_AUDITOR_SIGNATURE_INVALID",e[e.EXCHANGE_AUDITORS_AUDITOR_UNKNOWN=1901]="EXCHANGE_AUDITORS_AUDITOR_UNKNOWN",e[e.EXCHANGE_AUDITORS_AUDITOR_INACTIVE=1902]="EXCHANGE_AUDITORS_AUDITOR_INACTIVE",e[e.EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT=1918]="EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT",e[e.EXCHANGE_KYC_INFO_AUTHORIZATION_FAILED=1919]="EXCHANGE_KYC_INFO_AUTHORIZATION_FAILED",e[e.EXCHANGE_KYC_RECURSIVE_RULE_DETECTED=1920]="EXCHANGE_KYC_RECURSIVE_RULE_DETECTED",e[e.EXCHANGE_KYC_AML_FORM_INCOMPLETE=1921]="EXCHANGE_KYC_AML_FORM_INCOMPLETE",e[e.EXCHANGE_KYC_GENERIC_AML_PROGRAM_GONE=1922]="EXCHANGE_KYC_GENERIC_AML_PROGRAM_GONE",e[e.EXCHANGE_KYC_NOT_A_FORM=1923]="EXCHANGE_KYC_NOT_A_FORM",e[e.EXCHANGE_KYC_GENERIC_CHECK_GONE=1924]="EXCHANGE_KYC_GENERIC_CHECK_GONE",e[e.EXCHANGE_KYC_WALLET_SIGNATURE_INVALID=1925]="EXCHANGE_KYC_WALLET_SIGNATURE_INVALID",e[e.EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE=1926]="EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE",e[e.EXCHANGE_KYC_PROOF_BACKEND_ERROR=1927]="EXCHANGE_KYC_PROOF_BACKEND_ERROR",e[e.EXCHANGE_KYC_PROOF_BACKEND_AUTHORIZATION_FAILED=1928]="EXCHANGE_KYC_PROOF_BACKEND_AUTHORIZATION_FAILED",e[e.EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN=1929]="EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN",e[e.EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED=1930]="EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED",e[e.EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN=1931]="EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN",e[e.EXCHANGE_KYC_GENERIC_LOGIC_GONE=1932]="EXCHANGE_KYC_GENERIC_LOGIC_GONE",e[e.EXCHANGE_KYC_GENERIC_LOGIC_BUG=1933]="EXCHANGE_KYC_GENERIC_LOGIC_BUG",e[e.EXCHANGE_KYC_GENERIC_PROVIDER_ACCESS_REFUSED=1934]="EXCHANGE_KYC_GENERIC_PROVIDER_ACCESS_REFUSED",e[e.EXCHANGE_KYC_GENERIC_PROVIDER_TIMEOUT=1935]="EXCHANGE_KYC_GENERIC_PROVIDER_TIMEOUT",e[e.EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY=1936]="EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY",e[e.EXCHANGE_KYC_GENERIC_PROVIDER_RATE_LIMIT_EXCEEDED=1937]="EXCHANGE_KYC_GENERIC_PROVIDER_RATE_LIMIT_EXCEEDED",e[e.EXCHANGE_KYC_WEBHOOK_UNAUTHORIZED=1938]="EXCHANGE_KYC_WEBHOOK_UNAUTHORIZED",e[e.EXCHANGE_KYC_CHECK_REQUEST_UNKNOWN=1939]="EXCHANGE_KYC_CHECK_REQUEST_UNKNOWN",e[e.EXCHANGE_KYC_CHECK_AUTHORIZATION_KEY_UNKNOWN=1940]="EXCHANGE_KYC_CHECK_AUTHORIZATION_KEY_UNKNOWN",e[e.EXCHANGE_KYC_FORM_ALREADY_UPLOADED=1941]="EXCHANGE_KYC_FORM_ALREADY_UPLOADED",e[e.EXCHANGE_KYC_MEASURES_MALFORMED=1942]="EXCHANGE_KYC_MEASURES_MALFORMED",e[e.EXCHANGE_KYC_MEASURE_INDEX_INVALID=1943]="EXCHANGE_KYC_MEASURE_INDEX_INVALID",e[e.EXCHANGE_KYC_INVALID_LOGIC_TO_CHECK=1944]="EXCHANGE_KYC_INVALID_LOGIC_TO_CHECK",e[e.EXCHANGE_KYC_AML_PROGRAM_FAILURE=1945]="EXCHANGE_KYC_AML_PROGRAM_FAILURE",e[e.EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT=1946]="EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT",e[e.EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_REPLY=1947]="EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_REPLY",e[e.EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_CONTEXT=1948]="EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_CONTEXT",e[e.EXCHANGE_KYC_GENERIC_AML_LOGIC_BUG=1949]="EXCHANGE_KYC_GENERIC_AML_LOGIC_BUG",e[e.EXCHANGE_CONTRACTS_UNKNOWN=1950]="EXCHANGE_CONTRACTS_UNKNOWN",e[e.EXCHANGE_CONTRACTS_INVALID_CONTRACT_PUB=1951]="EXCHANGE_CONTRACTS_INVALID_CONTRACT_PUB",e[e.EXCHANGE_CONTRACTS_DECRYPTION_FAILED=1952]="EXCHANGE_CONTRACTS_DECRYPTION_FAILED",e[e.EXCHANGE_CONTRACTS_SIGNATURE_INVALID=1953]="EXCHANGE_CONTRACTS_SIGNATURE_INVALID",e[e.EXCHANGE_CONTRACTS_DECODING_FAILED=1954]="EXCHANGE_CONTRACTS_DECODING_FAILED",e[e.EXCHANGE_PURSE_DEPOSIT_COIN_SIGNATURE_INVALID=1975]="EXCHANGE_PURSE_DEPOSIT_COIN_SIGNATURE_INVALID",e[e.EXCHANGE_PURSE_DEPOSIT_DECIDED_ALREADY=1976]="EXCHANGE_PURSE_DEPOSIT_DECIDED_ALREADY",e[e.EXCHANGE_KYC_INFO_BUSY=1977]="EXCHANGE_KYC_INFO_BUSY",e[e.EXCHANGE_TOTP_KEY_INVALID=1980]="EXCHANGE_TOTP_KEY_INVALID",e[e.MERCHANT_GENERIC_INSTANCE_UNKNOWN=2e3]="MERCHANT_GENERIC_INSTANCE_UNKNOWN",e[e.MERCHANT_GENERIC_HOLE_IN_WIRE_FEE_STRUCTURE=2001]="MERCHANT_GENERIC_HOLE_IN_WIRE_FEE_STRUCTURE",e[e.MERCHANT_GENERIC_EXCHANGE_MASTER_KEY_MISMATCH=2002]="MERCHANT_GENERIC_EXCHANGE_MASTER_KEY_MISMATCH",e[e.MERCHANT_GENERIC_CATEGORY_UNKNOWN=2003]="MERCHANT_GENERIC_CATEGORY_UNKNOWN",e[e.MERCHANT_GENERIC_UNIT_UNKNOWN=2004]="MERCHANT_GENERIC_UNIT_UNKNOWN",e[e.MERCHANT_GENERIC_ORDER_UNKNOWN=2005]="MERCHANT_GENERIC_ORDER_UNKNOWN",e[e.MERCHANT_GENERIC_PRODUCT_UNKNOWN=2006]="MERCHANT_GENERIC_PRODUCT_UNKNOWN",e[e.MERCHANT_GENERIC_REWARD_ID_UNKNOWN=2007]="MERCHANT_GENERIC_REWARD_ID_UNKNOWN",e[e.MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID=2008]="MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID",e[e.MERCHANT_GENERIC_CONTRACT_HASH_DOES_NOT_MATCH_ORDER=2009]="MERCHANT_GENERIC_CONTRACT_HASH_DOES_NOT_MATCH_ORDER",e[e.MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE=2010]="MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE",e[e.MERCHANT_GENERIC_EXCHANGE_TIMEOUT=2011]="MERCHANT_GENERIC_EXCHANGE_TIMEOUT",e[e.MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE=2012]="MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE",e[e.MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED=2013]="MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED",e[e.MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS=2014]="MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS",e[e.MERCHANT_GENERIC_UNAUTHORIZED=2015]="MERCHANT_GENERIC_UNAUTHORIZED",e[e.MERCHANT_GENERIC_INSTANCE_DELETED=2016]="MERCHANT_GENERIC_INSTANCE_DELETED",e[e.MERCHANT_GENERIC_TRANSFER_UNKNOWN=2017]="MERCHANT_GENERIC_TRANSFER_UNKNOWN",e[e.MERCHANT_GENERIC_TEMPLATE_UNKNOWN=2018]="MERCHANT_GENERIC_TEMPLATE_UNKNOWN",e[e.MERCHANT_GENERIC_WEBHOOK_UNKNOWN=2019]="MERCHANT_GENERIC_WEBHOOK_UNKNOWN",e[e.MERCHANT_GENERIC_PENDING_WEBHOOK_UNKNOWN=2020]="MERCHANT_GENERIC_PENDING_WEBHOOK_UNKNOWN",e[e.MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN=2021]="MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN",e[e.MERCHANT_GENERIC_ACCOUNT_UNKNOWN=2022]="MERCHANT_GENERIC_ACCOUNT_UNKNOWN",e[e.MERCHANT_GENERIC_H_WIRE_MALFORMED=2023]="MERCHANT_GENERIC_H_WIRE_MALFORMED",e[e.MERCHANT_GENERIC_CURRENCY_MISMATCH=2024]="MERCHANT_GENERIC_CURRENCY_MISMATCH",e[e.MERCHANT_GENERIC_EXCHANGE_UNTRUSTED=2025]="MERCHANT_GENERIC_EXCHANGE_UNTRUSTED",e[e.MERCHANT_GENERIC_TOKEN_FAMILY_UNKNOWN=2026]="MERCHANT_GENERIC_TOKEN_FAMILY_UNKNOWN",e[e.MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN=2027]="MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN",e[e.MERCHANT_GENERIC_DONAU_NOT_CONFIGURED=2028]="MERCHANT_GENERIC_DONAU_NOT_CONFIGURED",e[e.MERCHANT_EXCHANGE_SIGN_PUB_UNKNOWN=2029]="MERCHANT_EXCHANGE_SIGN_PUB_UNKNOWN",e[e.MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE=2030]="MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE",e[e.MERCHANT_GENERIC_MFA_MISSING=2031]="MERCHANT_GENERIC_MFA_MISSING",e[e.MERCHANT_GENERIC_DONAU_INVALID_RESPONSE=2032]="MERCHANT_GENERIC_DONAU_INVALID_RESPONSE",e[e.MERCHANT_GENERIC_UNIT_BUILTIN=2033]="MERCHANT_GENERIC_UNIT_BUILTIN",e[e.MERCHANT_GENERIC_REPORT_UNKNOWN=2034]="MERCHANT_GENERIC_REPORT_UNKNOWN",e[e.MERCHANT_GENERIC_REPORT_GENERATOR_UNCONFIGURED=2035]="MERCHANT_GENERIC_REPORT_GENERATOR_UNCONFIGURED",e[e.MERCHANT_GENERIC_PRODUCT_GROUP_UNKNOWN=2036]="MERCHANT_GENERIC_PRODUCT_GROUP_UNKNOWN",e[e.MERCHANT_GENERIC_MONEY_POT_UNKNOWN=2037]="MERCHANT_GENERIC_MONEY_POT_UNKNOWN",e[e.MERCHANT_GENERIC_SESSION_UNKNOWN=2038]="MERCHANT_GENERIC_SESSION_UNKNOWN",e[e.MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN=2039]="MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN",e[e.MERCHANT_GENERIC_EXPECTED_TRANSFER_UNKNOWN=2040]="MERCHANT_GENERIC_EXPECTED_TRANSFER_UNKNOWN",e[e.MERCHANT_GENERIC_DONAU_UNKNOWN=2041]="MERCHANT_GENERIC_DONAU_UNKNOWN",e[e.MERCHANT_GENERIC_ACCESS_TOKEN_UNKNOWN=2042]="MERCHANT_GENERIC_ACCESS_TOKEN_UNKNOWN",e[e.MERCHANT_GENERIC_NO_TYPST_OR_PDFTK=2048]="MERCHANT_GENERIC_NO_TYPST_OR_PDFTK",e[e.MERCHANT_GET_ORDERS_EXCHANGE_TRACKING_FAILURE=2100]="MERCHANT_GET_ORDERS_EXCHANGE_TRACKING_FAILURE",e[e.MERCHANT_GET_ORDERS_ID_EXCHANGE_REQUEST_FAILURE=2103]="MERCHANT_GET_ORDERS_ID_EXCHANGE_REQUEST_FAILURE",e[e.MERCHANT_GET_ORDERS_ID_EXCHANGE_LOOKUP_START_FAILURE=2104]="MERCHANT_GET_ORDERS_ID_EXCHANGE_LOOKUP_START_FAILURE",e[e.MERCHANT_GET_ORDERS_ID_INVALID_TOKEN=2105]="MERCHANT_GET_ORDERS_ID_INVALID_TOKEN",e[e.MERCHANT_GET_ORDERS_ID_INVALID_CONTRACT_HASH=2106]="MERCHANT_GET_ORDERS_ID_INVALID_CONTRACT_HASH",e[e.MERCHANT_GET_ORDERS_ID_INVALID_CONTRACT_VERSION=2107]="MERCHANT_GET_ORDERS_ID_INVALID_CONTRACT_VERSION",e[e.MERCHANT_TAN_CHALLENGE_FAILED=2125]="MERCHANT_TAN_CHALLENGE_FAILED",e[e.MERCHANT_TAN_CHALLENGE_UNKNOWN=2126]="MERCHANT_TAN_CHALLENGE_UNKNOWN",e[e.MERCHANT_TAN_TOO_MANY_ATTEMPTS=2127]="MERCHANT_TAN_TOO_MANY_ATTEMPTS",e[e.MERCHANT_TAN_MFA_HELPER_EXEC_FAILED=2128]="MERCHANT_TAN_MFA_HELPER_EXEC_FAILED",e[e.MERCHANT_TAN_CHALLENGE_SOLVED=2129]="MERCHANT_TAN_CHALLENGE_SOLVED",e[e.MERCHANT_TAN_TOO_EARLY=2130]="MERCHANT_TAN_TOO_EARLY",e[e.MERCHANT_MFA_FORBIDDEN=2131]="MERCHANT_MFA_FORBIDDEN",e[e.MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS=2150]="MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS",e[e.MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND=2151]="MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND",e[e.MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_AUDITOR_FAILURE=2152]="MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_AUDITOR_FAILURE",e[e.MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW=2153]="MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW",e[e.MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT=2154]="MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT",e[e.MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES=2155]="MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES",e[e.MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT=2156]="MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT",e[e.MERCHANT_POST_ORDERS_ID_PAY_COIN_SIGNATURE_INVALID=2157]="MERCHANT_POST_ORDERS_ID_PAY_COIN_SIGNATURE_INVALID",e[e.MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LOOKUP_FAILED=2158]="MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LOOKUP_FAILED",e[e.MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE=2159]="MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE",e[e.MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID=2160]="MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID",e[e.MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED=2161]="MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED",e[e.MERCHANT_POST_ORDERS_ID_PAY_MERCHANT_FIELD_MISSING=2162]="MERCHANT_POST_ORDERS_ID_PAY_MERCHANT_FIELD_MISSING",e[e.MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN=2163]="MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN",e[e.MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED=2165]="MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED",e[e.MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED=2166]="MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED",e[e.MERCHANT_POST_ORDERS_ID_PAY_REFUNDED=2167]="MERCHANT_POST_ORDERS_ID_PAY_REFUNDED",e[e.MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS=2168]="MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS",e[e.MERCHANT_PRIVATE_POST_REFUND_AFTER_WIRE_DEADLINE=2169]="MERCHANT_PRIVATE_POST_REFUND_AFTER_WIRE_DEADLINE",e[e.MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_FAILED=2170]="MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_FAILED",e[e.MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING=2171]="MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING",e[e.MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH=2172]="MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH",e[e.MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED=2173]="MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED",e[e.MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING=2174]="MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING",e[e.MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED=2175]="MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED",e[e.MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING=2176]="MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING",e[e.MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS=2177]="MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS",e[e.MERCHANT_POST_ORDERS_ID_PAY_INPUT_TOKENS_MISMATCH=2178]="MERCHANT_POST_ORDERS_ID_PAY_INPUT_TOKENS_MISMATCH",e[e.MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID=2179]="MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID",e[e.MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID=2180]="MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID",e[e.MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH=2181]="MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH",e[e.MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH=2182]="MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH",e[e.MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID=2183]="MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID",e[e.MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION=2184]="MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION",e[e.MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH=2185]="MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH",e[e.MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED=2186]="MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED",e[e.MERCHANT_POST_ORDERS_ID_PAID_CONTRACT_HASH_MISMATCH=2200]="MERCHANT_POST_ORDERS_ID_PAID_CONTRACT_HASH_MISMATCH",e[e.MERCHANT_POST_ORDERS_ID_PAID_COIN_SIGNATURE_INVALID=2201]="MERCHANT_POST_ORDERS_ID_PAID_COIN_SIGNATURE_INVALID",e[e.MERCHANT_POST_TOKEN_FAMILY_CONFLICT=2225]="MERCHANT_POST_TOKEN_FAMILY_CONFLICT",e[e.MERCHANT_PATCH_TOKEN_FAMILY_NOT_FOUND=2226]="MERCHANT_PATCH_TOKEN_FAMILY_NOT_FOUND",e[e.MERCHANT_POST_ORDERS_ID_ABORT_EXCHANGE_REFUND_FAILED=2251]="MERCHANT_POST_ORDERS_ID_ABORT_EXCHANGE_REFUND_FAILED",e[e.MERCHANT_POST_ORDERS_ID_ABORT_EXCHANGE_LOOKUP_FAILED=2252]="MERCHANT_POST_ORDERS_ID_ABORT_EXCHANGE_LOOKUP_FAILED",e[e.MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_NOT_FOUND=2253]="MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_NOT_FOUND",e[e.MERCHANT_POST_ORDERS_ID_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE=2254]="MERCHANT_POST_ORDERS_ID_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE",e[e.MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_HASH_MISSMATCH=2255]="MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_HASH_MISSMATCH",e[e.MERCHANT_POST_ORDERS_ID_ABORT_COINS_ARRAY_EMPTY=2256]="MERCHANT_POST_ORDERS_ID_ABORT_COINS_ARRAY_EMPTY",e[e.MERCHANT_EXCHANGE_TRANSFERS_AWAITING_KEYS=2258]="MERCHANT_EXCHANGE_TRANSFERS_AWAITING_KEYS",e[e.MERCHANT_EXCHANGE_TRANSFERS_AWAITING_LIST=2259]="MERCHANT_EXCHANGE_TRANSFERS_AWAITING_LIST",e[e.MERCHANT_EXCHANGE_TRANSFERS_FATAL_NO_EXCHANGE=2260]="MERCHANT_EXCHANGE_TRANSFERS_FATAL_NO_EXCHANGE",e[e.MERCHANT_EXCHANGE_TRANSFERS_FATAL_NOT_FOUND=2261]="MERCHANT_EXCHANGE_TRANSFERS_FATAL_NOT_FOUND",e[e.MERCHANT_EXCHANGE_TRANSFERS_RATE_LIMITED=2262]="MERCHANT_EXCHANGE_TRANSFERS_RATE_LIMITED",e[e.MERCHANT_EXCHANGE_TRANSFERS_TRANSIENT_FAILURE=2263]="MERCHANT_EXCHANGE_TRANSFERS_TRANSIENT_FAILURE",e[e.MERCHANT_EXCHANGE_TRANSFERS_HARD_FAILURE=2264]="MERCHANT_EXCHANGE_TRANSFERS_HARD_FAILURE",e[e.MERCHANT_POST_ACCOUNTS_KYCAUTH_BANK_GATEWAY_UNREACHABLE=2275]="MERCHANT_POST_ACCOUNTS_KYCAUTH_BANK_GATEWAY_UNREACHABLE",e[e.MERCHANT_POST_ACCOUNTS_EXCHANGE_TOO_OLD=2276]="MERCHANT_POST_ACCOUNTS_EXCHANGE_TOO_OLD",e[e.MERCHANT_POST_ACCOUNTS_KYCAUTH_EXCHANGE_UNREACHABLE=2277]="MERCHANT_POST_ACCOUNTS_KYCAUTH_EXCHANGE_UNREACHABLE",e[e.MERCHANT_POST_ORDERS_ID_CLAIM_NOT_FOUND=2300]="MERCHANT_POST_ORDERS_ID_CLAIM_NOT_FOUND",e[e.MERCHANT_POST_ORDERS_ID_CLAIM_ALREADY_CLAIMED=2301]="MERCHANT_POST_ORDERS_ID_CLAIM_ALREADY_CLAIMED",e[e.MERCHANT_POST_ORDERS_ID_CLAIM_CLIENT_INTERNAL_FAILURE=2302]="MERCHANT_POST_ORDERS_ID_CLAIM_CLIENT_INTERNAL_FAILURE",e[e.MERCHANT_POST_ORDERS_UNCLAIM_SIGNATURE_INVALID=2303]="MERCHANT_POST_ORDERS_UNCLAIM_SIGNATURE_INVALID",e[e.MERCHANT_POST_ORDERS_ID_REFUND_SIGNATURE_FAILED=2350]="MERCHANT_POST_ORDERS_ID_REFUND_SIGNATURE_FAILED",e[e.MERCHANT_REWARD_PICKUP_UNBLIND_FAILURE=2400]="MERCHANT_REWARD_PICKUP_UNBLIND_FAILURE",e[e.MERCHANT_REWARD_PICKUP_EXCHANGE_ERROR=2403]="MERCHANT_REWARD_PICKUP_EXCHANGE_ERROR",e[e.MERCHANT_REWARD_PICKUP_SUMMATION_FAILED=2404]="MERCHANT_REWARD_PICKUP_SUMMATION_FAILED",e[e.MERCHANT_REWARD_PICKUP_HAS_EXPIRED=2405]="MERCHANT_REWARD_PICKUP_HAS_EXPIRED",e[e.MERCHANT_REWARD_PICKUP_AMOUNT_EXCEEDS_REWARD_REMAINING=2406]="MERCHANT_REWARD_PICKUP_AMOUNT_EXCEEDS_REWARD_REMAINING",e[e.MERCHANT_REWARD_PICKUP_DENOMINATION_UNKNOWN=2407]="MERCHANT_REWARD_PICKUP_DENOMINATION_UNKNOWN",e[e.MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE=2500]="MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE",e[e.MERCHANT_PRIVATE_POST_ORDERS_NO_LOCALTIME=2501]="MERCHANT_PRIVATE_POST_ORDERS_NO_LOCALTIME",e[e.MERCHANT_PRIVATE_POST_ORDERS_PROPOSAL_PARSE_ERROR=2502]="MERCHANT_PRIVATE_POST_ORDERS_PROPOSAL_PARSE_ERROR",e[e.MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS=2503]="MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS",e[e.MERCHANT_PRIVATE_POST_ORDERS_REFUND_AFTER_WIRE_DEADLINE=2504]="MERCHANT_PRIVATE_POST_ORDERS_REFUND_AFTER_WIRE_DEADLINE",e[e.MERCHANT_PRIVATE_POST_ORDERS_DELIVERY_DATE_IN_PAST=2505]="MERCHANT_PRIVATE_POST_ORDERS_DELIVERY_DATE_IN_PAST",e[e.MERCHANT_PRIVATE_POST_ORDERS_WIRE_DEADLINE_IS_NEVER=2506]="MERCHANT_PRIVATE_POST_ORDERS_WIRE_DEADLINE_IS_NEVER",e[e.MERCHANT_PRIVATE_POST_ORDERS_PAY_DEADLINE_IN_PAST=2507]="MERCHANT_PRIVATE_POST_ORDERS_PAY_DEADLINE_IN_PAST",e[e.MERCHANT_PRIVATE_POST_ORDERS_REFUND_DEADLINE_IN_PAST=2508]="MERCHANT_PRIVATE_POST_ORDERS_REFUND_DEADLINE_IN_PAST",e[e.MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGES_FOR_WIRE_METHOD=2509]="MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGES_FOR_WIRE_METHOD",e[e.MERCHANT_PRIVATE_PATCH_ORDERS_ID_FORGET_PATH_SYNTAX_INCORRECT=2510]="MERCHANT_PRIVATE_PATCH_ORDERS_ID_FORGET_PATH_SYNTAX_INCORRECT",e[e.MERCHANT_PRIVATE_PATCH_ORDERS_ID_FORGET_PATH_NOT_FORGETTABLE=2511]="MERCHANT_PRIVATE_PATCH_ORDERS_ID_FORGET_PATH_NOT_FORGETTABLE",e[e.MERCHANT_POST_ORDERS_ID_REFUND_EXCHANGE_TRANSACTION_LIMIT_VIOLATION=2512]="MERCHANT_POST_ORDERS_ID_REFUND_EXCHANGE_TRANSACTION_LIMIT_VIOLATION",e[e.MERCHANT_PRIVATE_POST_ORDERS_AMOUNT_EXCEEDS_LEGAL_LIMITS=2513]="MERCHANT_PRIVATE_POST_ORDERS_AMOUNT_EXCEEDS_LEGAL_LIMITS",e[e.MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGE_FOR_CURRENCY=2514]="MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGE_FOR_CURRENCY",e[e.MERCHANT_PRIVATE_DELETE_ORDERS_AWAITING_PAYMENT=2520]="MERCHANT_PRIVATE_DELETE_ORDERS_AWAITING_PAYMENT",e[e.MERCHANT_PRIVATE_DELETE_ORDERS_ALREADY_PAID=2521]="MERCHANT_PRIVATE_DELETE_ORDERS_ALREADY_PAID",e[e.MERCHANT_PRIVATE_GET_STATISTICS_REPORT_GRANULARITY_UNAVAILABLE=2525]="MERCHANT_PRIVATE_GET_STATISTICS_REPORT_GRANULARITY_UNAVAILABLE",e[e.MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_INCONSISTENT_AMOUNT=2530]="MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_INCONSISTENT_AMOUNT",e[e.MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_ORDER_UNPAID=2531]="MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_ORDER_UNPAID",e[e.MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_NOT_ALLOWED_BY_CONTRACT=2532]="MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_NOT_ALLOWED_BY_CONTRACT",e[e.MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_SLUG_UNKNOWN=2533]="MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_SLUG_UNKNOWN",e[e.MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_NOT_VALID=2534]="MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_NOT_VALID",e[e.MERCHANT_PRIVATE_POST_TRANSFERS_EXCHANGE_UNKNOWN=2550]="MERCHANT_PRIVATE_POST_TRANSFERS_EXCHANGE_UNKNOWN",e[e.MERCHANT_PRIVATE_POST_TRANSFERS_REQUEST_ERROR=2551]="MERCHANT_PRIVATE_POST_TRANSFERS_REQUEST_ERROR",e[e.MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_TRANSFERS=2552]="MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_TRANSFERS",e[e.MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_REPORTS=2553]="MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_REPORTS",e[e.MERCHANT_PRIVATE_POST_TRANSFERS_BAD_WIRE_FEE=2554]="MERCHANT_PRIVATE_POST_TRANSFERS_BAD_WIRE_FEE",e[e.MERCHANT_PRIVATE_POST_TRANSFERS_ACCOUNT_NOT_FOUND=2555]="MERCHANT_PRIVATE_POST_TRANSFERS_ACCOUNT_NOT_FOUND",e[e.MERCHANT_PRIVATE_DELETE_TRANSFERS_ALREADY_CONFIRMED=2556]="MERCHANT_PRIVATE_DELETE_TRANSFERS_ALREADY_CONFIRMED",e[e.MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_SUBMISSION=2557]="MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_SUBMISSION",e[e.MERCHANT_EXCHANGE_TRANSFERS_TARGET_ACCOUNT_UNKNOWN=2558]="MERCHANT_EXCHANGE_TRANSFERS_TARGET_ACCOUNT_UNKNOWN",e[e.MERCHANT_EXCHANGE_TRANSFERS_CONFLICTING_TRANSFERS=2563]="MERCHANT_EXCHANGE_TRANSFERS_CONFLICTING_TRANSFERS",e[e.MERCHANT_REPORT_GENERATOR_FAILED=2570]="MERCHANT_REPORT_GENERATOR_FAILED",e[e.MERCHANT_REPORT_FETCH_FAILED=2571]="MERCHANT_REPORT_FETCH_FAILED",e[e.MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS=2600]="MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS",e[e.MERCHANT_PRIVATE_POST_INSTANCES_BAD_AUTH=2601]="MERCHANT_PRIVATE_POST_INSTANCES_BAD_AUTH",e[e.MERCHANT_PRIVATE_POST_INSTANCE_AUTH_BAD_AUTH=2602]="MERCHANT_PRIVATE_POST_INSTANCE_AUTH_BAD_AUTH",e[e.MERCHANT_PRIVATE_POST_INSTANCES_PURGE_REQUIRED=2603]="MERCHANT_PRIVATE_POST_INSTANCES_PURGE_REQUIRED",e[e.MERCHANT_PRIVATE_PATCH_INSTANCES_PURGE_REQUIRED=2625]="MERCHANT_PRIVATE_PATCH_INSTANCES_PURGE_REQUIRED",e[e.MERCHANT_PRIVATE_ACCOUNT_DELETE_UNKNOWN_ACCOUNT=2626]="MERCHANT_PRIVATE_ACCOUNT_DELETE_UNKNOWN_ACCOUNT",e[e.MERCHANT_PRIVATE_ACCOUNT_EXISTS=2627]="MERCHANT_PRIVATE_ACCOUNT_EXISTS",e[e.MERCHANT_PRIVATE_ACCOUNT_NOT_ELIGIBLE_FOR_EXCHANGE=2628]="MERCHANT_PRIVATE_ACCOUNT_NOT_ELIGIBLE_FOR_EXCHANGE",e[e.MERCHANT_PRIVATE_POST_PRODUCTS_CONFLICT_PRODUCT_EXISTS=2650]="MERCHANT_PRIVATE_POST_PRODUCTS_CONFLICT_PRODUCT_EXISTS",e[e.MERCHANT_PRIVATE_POST_CATEGORIES_CONFLICT_CATEGORY_EXISTS=2651]="MERCHANT_PRIVATE_POST_CATEGORIES_CONFLICT_CATEGORY_EXISTS",e[e.MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_REDUCED=2660]="MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_REDUCED",e[e.MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_EXCEEDS_STOCKS=2661]="MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_EXCEEDS_STOCKS",e[e.MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_STOCKED_REDUCED=2662]="MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_STOCKED_REDUCED",e[e.MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_SOLD_REDUCED=2663]="MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_SOLD_REDUCED",e[e.MERCHANT_PRIVATE_POST_PRODUCTS_LOCK_INSUFFICIENT_STOCKS=2670]="MERCHANT_PRIVATE_POST_PRODUCTS_LOCK_INSUFFICIENT_STOCKS",e[e.MERCHANT_PRIVATE_DELETE_PRODUCTS_CONFLICTING_LOCK=2680]="MERCHANT_PRIVATE_DELETE_PRODUCTS_CONFLICTING_LOCK",e[e.MERCHANT_PRIVATE_PRODUCT_GROUP_CONFLICTING_NAME=2690]="MERCHANT_PRIVATE_PRODUCT_GROUP_CONFLICTING_NAME",e[e.MERCHANT_PRIVATE_MONEY_POT_CONFLICTING_NAME=2691]="MERCHANT_PRIVATE_MONEY_POT_CONFLICTING_NAME",e[e.MERCHANT_PRIVATE_MONEY_POT_CONFLICTING_TOTAL=2692]="MERCHANT_PRIVATE_MONEY_POT_CONFLICTING_TOTAL",e[e.MERCHANT_PRIVATE_POST_RESERVES_UNSUPPORTED_WIRE_METHOD=2700]="MERCHANT_PRIVATE_POST_RESERVES_UNSUPPORTED_WIRE_METHOD",e[e.MERCHANT_PRIVATE_POST_RESERVES_REWARDS_NOT_ALLOWED=2701]="MERCHANT_PRIVATE_POST_RESERVES_REWARDS_NOT_ALLOWED",e[e.MERCHANT_PRIVATE_DELETE_RESERVES_NO_SUCH_RESERVE=2710]="MERCHANT_PRIVATE_DELETE_RESERVES_NO_SUCH_RESERVE",e[e.MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_EXPIRED=2750]="MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_EXPIRED",e[e.MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_UNKNOWN=2751]="MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_UNKNOWN",e[e.MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_INSUFFICIENT_FUNDS=2752]="MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_INSUFFICIENT_FUNDS",e[e.MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_NOT_FOUND=2753]="MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_NOT_FOUND",e[e.MERCHANT_PRIVATE_GET_ORDERS_ID_AMOUNT_ARITHMETIC_FAILURE=2800]="MERCHANT_PRIVATE_GET_ORDERS_ID_AMOUNT_ARITHMETIC_FAILURE",e[e.MERCHANT_PRIVATE_POST_TEMPLATES_CONFLICT_TEMPLATE_EXISTS=2850]="MERCHANT_PRIVATE_POST_TEMPLATES_CONFLICT_TEMPLATE_EXISTS",e[e.MERCHANT_PRIVATE_POST_OTP_DEVICES_CONFLICT_OTP_DEVICE_EXISTS=2851]="MERCHANT_PRIVATE_POST_OTP_DEVICES_CONFLICT_OTP_DEVICE_EXISTS",e[e.MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT=2860]="MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT",e[e.MERCHANT_POST_USING_TEMPLATES_SUMMARY_CONFLICT_TEMPLATES_CONTRACT_SUBJECT=2861]="MERCHANT_POST_USING_TEMPLATES_SUMMARY_CONFLICT_TEMPLATES_CONTRACT_SUBJECT",e[e.MERCHANT_POST_USING_TEMPLATES_NO_AMOUNT=2862]="MERCHANT_POST_USING_TEMPLATES_NO_AMOUNT",e[e.MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY=2863]="MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY",e[e.MERCHANT_POST_USING_TEMPLATES_WRONG_TYPE=2864]="MERCHANT_POST_USING_TEMPLATES_WRONG_TYPE",e[e.MERCHANT_POST_USING_TEMPLATES_WRONG_PRODUCT=2865]="MERCHANT_POST_USING_TEMPLATES_WRONG_PRODUCT",e[e.MERCHANT_POST_USING_TEMPLATES_NO_CURRENCY=2866]="MERCHANT_POST_USING_TEMPLATES_NO_CURRENCY",e[e.MERCHANT_PRIVATE_POST_WEBHOOKS_CONFLICT_WEBHOOK_EXISTS=2900]="MERCHANT_PRIVATE_POST_WEBHOOKS_CONFLICT_WEBHOOK_EXISTS",e[e.MERCHANT_PRIVATE_POST_PENDING_WEBHOOKS_CONFLICT_PENDING_WEBHOOK_EXISTS=2910]="MERCHANT_PRIVATE_POST_PENDING_WEBHOOKS_CONFLICT_PENDING_WEBHOOK_EXISTS",e[e.AUDITOR_GENERIC_UNAUTHORIZED=3001]="AUDITOR_GENERIC_UNAUTHORIZED",e[e.AUDITOR_GENERIC_METHOD_NOT_ALLOWED=3002]="AUDITOR_GENERIC_METHOD_NOT_ALLOWED",e[e.AUDITOR_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID=3100]="AUDITOR_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID",e[e.AUDITOR_EXCHANGE_SIGNING_KEY_REVOKED=3101]="AUDITOR_EXCHANGE_SIGNING_KEY_REVOKED",e[e.AUDITOR_RESOURCE_NOT_FOUND=3102]="AUDITOR_RESOURCE_NOT_FOUND",e[e.AUDITOR_URI_MISSING_PATH_COMPONENT=3103]="AUDITOR_URI_MISSING_PATH_COMPONENT",e[e.BANK_SAME_ACCOUNT=5101]="BANK_SAME_ACCOUNT",e[e.BANK_UNALLOWED_DEBIT=5102]="BANK_UNALLOWED_DEBIT",e[e.BANK_NEGATIVE_NUMBER_AMOUNT=5103]="BANK_NEGATIVE_NUMBER_AMOUNT",e[e.BANK_NUMBER_TOO_BIG=5104]="BANK_NUMBER_TOO_BIG",e[e.BANK_UNKNOWN_ACCOUNT=5106]="BANK_UNKNOWN_ACCOUNT",e[e.BANK_TRANSACTION_NOT_FOUND=5107]="BANK_TRANSACTION_NOT_FOUND",e[e.BANK_BAD_FORMAT_AMOUNT=5108]="BANK_BAD_FORMAT_AMOUNT",e[e.BANK_REJECT_NO_RIGHTS=5109]="BANK_REJECT_NO_RIGHTS",e[e.BANK_UNMANAGED_EXCEPTION=5110]="BANK_UNMANAGED_EXCEPTION",e[e.BANK_SOFT_EXCEPTION=5111]="BANK_SOFT_EXCEPTION",e[e.BANK_TRANSFER_REQUEST_UID_REUSED=5112]="BANK_TRANSFER_REQUEST_UID_REUSED",e[e.BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT=5113]="BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT",e[e.BANK_DUPLICATE_RESERVE_PUB_SUBJECT=5114]="BANK_DUPLICATE_RESERVE_PUB_SUBJECT",e[e.BANK_ANCIENT_TRANSACTION_GONE=5115]="BANK_ANCIENT_TRANSACTION_GONE",e[e.BANK_ABORT_CONFIRM_CONFLICT=5116]="BANK_ABORT_CONFIRM_CONFLICT",e[e.BANK_CONFIRM_ABORT_CONFLICT=5117]="BANK_CONFIRM_ABORT_CONFLICT",e[e.BANK_REGISTER_CONFLICT=5118]="BANK_REGISTER_CONFLICT",e[e.BANK_POST_WITHDRAWAL_OPERATION_REQUIRED=5119]="BANK_POST_WITHDRAWAL_OPERATION_REQUIRED",e[e.BANK_RESERVED_USERNAME_CONFLICT=5120]="BANK_RESERVED_USERNAME_CONFLICT",e[e.BANK_REGISTER_USERNAME_REUSE=5121]="BANK_REGISTER_USERNAME_REUSE",e[e.BANK_REGISTER_PAYTO_URI_REUSE=5122]="BANK_REGISTER_PAYTO_URI_REUSE",e[e.BANK_ACCOUNT_BALANCE_NOT_ZERO=5123]="BANK_ACCOUNT_BALANCE_NOT_ZERO",e[e.BANK_UNKNOWN_CREDITOR=5124]="BANK_UNKNOWN_CREDITOR",e[e.BANK_UNKNOWN_DEBTOR=5125]="BANK_UNKNOWN_DEBTOR",e[e.BANK_ACCOUNT_IS_EXCHANGE=5126]="BANK_ACCOUNT_IS_EXCHANGE",e[e.BANK_ACCOUNT_IS_NOT_EXCHANGE=5127]="BANK_ACCOUNT_IS_NOT_EXCHANGE",e[e.BANK_BAD_CONVERSION=5128]="BANK_BAD_CONVERSION",e[e.BANK_MISSING_TAN_INFO=5129]="BANK_MISSING_TAN_INFO",e[e.BANK_CONFIRM_INCOMPLETE=5130]="BANK_CONFIRM_INCOMPLETE",e[e.BANK_TAN_RATE_LIMITED=5131]="BANK_TAN_RATE_LIMITED",e[e.BANK_TAN_CHANNEL_NOT_SUPPORTED=5132]="BANK_TAN_CHANNEL_NOT_SUPPORTED",e[e.BANK_TAN_CHANNEL_SCRIPT_FAILED=5133]="BANK_TAN_CHANNEL_SCRIPT_FAILED",e[e.BANK_TAN_CHALLENGE_FAILED=5134]="BANK_TAN_CHALLENGE_FAILED",e[e.BANK_NON_ADMIN_PATCH_LEGAL_NAME=5135]="BANK_NON_ADMIN_PATCH_LEGAL_NAME",e[e.BANK_NON_ADMIN_PATCH_DEBT_LIMIT=5136]="BANK_NON_ADMIN_PATCH_DEBT_LIMIT",e[e.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD=5137]="BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD",e[e.BANK_PATCH_BAD_OLD_PASSWORD=5138]="BANK_PATCH_BAD_OLD_PASSWORD",e[e.BANK_PATCH_ADMIN_EXCHANGE=5139]="BANK_PATCH_ADMIN_EXCHANGE",e[e.BANK_NON_ADMIN_PATCH_CASHOUT=5140]="BANK_NON_ADMIN_PATCH_CASHOUT",e[e.BANK_NON_ADMIN_PATCH_CONTACT=5141]="BANK_NON_ADMIN_PATCH_CONTACT",e[e.BANK_ADMIN_CREDITOR=5142]="BANK_ADMIN_CREDITOR",e[e.BANK_CHALLENGE_NOT_FOUND=5143]="BANK_CHALLENGE_NOT_FOUND",e[e.BANK_TAN_CHALLENGE_EXPIRED=5144]="BANK_TAN_CHALLENGE_EXPIRED",e[e.BANK_NON_ADMIN_SET_TAN_CHANNEL=5145]="BANK_NON_ADMIN_SET_TAN_CHANNEL",e[e.BANK_NON_ADMIN_SET_MIN_CASHOUT=5146]="BANK_NON_ADMIN_SET_MIN_CASHOUT",e[e.BANK_CONVERSION_AMOUNT_TO_SMALL=5147]="BANK_CONVERSION_AMOUNT_TO_SMALL",e[e.BANK_AMOUNT_DIFFERS=5148]="BANK_AMOUNT_DIFFERS",e[e.BANK_AMOUNT_REQUIRED=5149]="BANK_AMOUNT_REQUIRED",e[e.BANK_PASSWORD_TOO_SHORT=5150]="BANK_PASSWORD_TOO_SHORT",e[e.BANK_PASSWORD_TOO_LONG=5151]="BANK_PASSWORD_TOO_LONG",e[e.BANK_ACCOUNT_LOCKED=5152]="BANK_ACCOUNT_LOCKED",e[e.BANK_UPDATE_ABORT_CONFLICT=5153]="BANK_UPDATE_ABORT_CONFLICT",e[e.BANK_TRANSFER_WTID_REUSED=5154]="BANK_TRANSFER_WTID_REUSED",e[e.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS=5155]="BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS",e[e.BANK_CONVERSION_RATE_CLASS_UNKNOWN=5156]="BANK_CONVERSION_RATE_CLASS_UNKNOWN",e[e.BANK_NAME_REUSE=5157]="BANK_NAME_REUSE",e[e.BANK_UNSUPPORTED_SUBJECT_FORMAT=5158]="BANK_UNSUPPORTED_SUBJECT_FORMAT",e[e.BANK_DERIVATION_REUSE=5159]="BANK_DERIVATION_REUSE",e[e.BANK_BAD_SIGNATURE=5160]="BANK_BAD_SIGNATURE",e[e.BANK_OLD_TIMESTAMP=5161]="BANK_OLD_TIMESTAMP",e[e.BANK_TRANSFER_MAPPING_REUSED=5162]="BANK_TRANSFER_MAPPING_REUSED",e[e.BANK_TRANSFER_MAPPING_UNKNOWN=5163]="BANK_TRANSFER_MAPPING_UNKNOWN",e[e.SYNC_ACCOUNT_UNKNOWN=6100]="SYNC_ACCOUNT_UNKNOWN",e[e.SYNC_BAD_IF_NONE_MATCH=6101]="SYNC_BAD_IF_NONE_MATCH",e[e.SYNC_BAD_IF_MATCH=6102]="SYNC_BAD_IF_MATCH",e[e.SYNC_BAD_SYNC_SIGNATURE=6103]="SYNC_BAD_SYNC_SIGNATURE",e[e.SYNC_INVALID_SIGNATURE=6104]="SYNC_INVALID_SIGNATURE",e[e.SYNC_MALFORMED_CONTENT_LENGTH=6105]="SYNC_MALFORMED_CONTENT_LENGTH",e[e.SYNC_EXCESSIVE_CONTENT_LENGTH=6106]="SYNC_EXCESSIVE_CONTENT_LENGTH",e[e.SYNC_OUT_OF_MEMORY_ON_CONTENT_LENGTH=6107]="SYNC_OUT_OF_MEMORY_ON_CONTENT_LENGTH",e[e.SYNC_INVALID_UPLOAD=6108]="SYNC_INVALID_UPLOAD",e[e.SYNC_PAYMENT_GENERIC_TIMEOUT=6109]="SYNC_PAYMENT_GENERIC_TIMEOUT",e[e.SYNC_PAYMENT_CREATE_BACKEND_ERROR=6110]="SYNC_PAYMENT_CREATE_BACKEND_ERROR",e[e.SYNC_PREVIOUS_BACKUP_UNKNOWN=6111]="SYNC_PREVIOUS_BACKUP_UNKNOWN",e[e.SYNC_MISSING_CONTENT_LENGTH=6112]="SYNC_MISSING_CONTENT_LENGTH",e[e.SYNC_GENERIC_BACKEND_ERROR=6113]="SYNC_GENERIC_BACKEND_ERROR",e[e.SYNC_GENERIC_BACKEND_TIMEOUT=6114]="SYNC_GENERIC_BACKEND_TIMEOUT",e[e.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE=7e3]="WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE",e[e.WALLET_UNEXPECTED_EXCEPTION=7001]="WALLET_UNEXPECTED_EXCEPTION",e[e.WALLET_RECEIVED_MALFORMED_RESPONSE=7002]="WALLET_RECEIVED_MALFORMED_RESPONSE",e[e.WALLET_NETWORK_ERROR=7003]="WALLET_NETWORK_ERROR",e[e.WALLET_HTTP_REQUEST_THROTTLED=7004]="WALLET_HTTP_REQUEST_THROTTLED",e[e.WALLET_UNEXPECTED_REQUEST_ERROR=7005]="WALLET_UNEXPECTED_REQUEST_ERROR",e[e.WALLET_EXCHANGE_DENOMINATIONS_INSUFFICIENT=7006]="WALLET_EXCHANGE_DENOMINATIONS_INSUFFICIENT",e[e.WALLET_CORE_API_OPERATION_UNKNOWN=7007]="WALLET_CORE_API_OPERATION_UNKNOWN",e[e.WALLET_INVALID_TALER_PAY_URI=7008]="WALLET_INVALID_TALER_PAY_URI",e[e.WALLET_EXCHANGE_COIN_SIGNATURE_INVALID=7009]="WALLET_EXCHANGE_COIN_SIGNATURE_INVALID",e[e.WALLET_CORE_NOT_AVAILABLE=7011]="WALLET_CORE_NOT_AVAILABLE",e[e.WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK=7012]="WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK",e[e.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT=7013]="WALLET_HTTP_REQUEST_GENERIC_TIMEOUT",e[e.WALLET_ORDER_ALREADY_CLAIMED=7014]="WALLET_ORDER_ALREADY_CLAIMED",e[e.WALLET_WITHDRAWAL_GROUP_INCOMPLETE=7015]="WALLET_WITHDRAWAL_GROUP_INCOMPLETE",e[e.WALLET_REWARD_COIN_SIGNATURE_INVALID=7016]="WALLET_REWARD_COIN_SIGNATURE_INVALID",e[e.WALLET_BANK_INTEGRATION_PROTOCOL_VERSION_INCOMPATIBLE=7017]="WALLET_BANK_INTEGRATION_PROTOCOL_VERSION_INCOMPATIBLE",e[e.WALLET_CONTRACT_TERMS_BASE_URL_MISMATCH=7018]="WALLET_CONTRACT_TERMS_BASE_URL_MISMATCH",e[e.WALLET_CONTRACT_TERMS_SIGNATURE_INVALID=7019]="WALLET_CONTRACT_TERMS_SIGNATURE_INVALID",e[e.WALLET_CONTRACT_TERMS_MALFORMED=7020]="WALLET_CONTRACT_TERMS_MALFORMED",e[e.WALLET_PENDING_OPERATION_FAILED=7021]="WALLET_PENDING_OPERATION_FAILED",e[e.WALLET_PAY_MERCHANT_SERVER_ERROR=7022]="WALLET_PAY_MERCHANT_SERVER_ERROR",e[e.WALLET_CRYPTO_WORKER_ERROR=7023]="WALLET_CRYPTO_WORKER_ERROR",e[e.WALLET_CRYPTO_WORKER_BAD_REQUEST=7024]="WALLET_CRYPTO_WORKER_BAD_REQUEST",e[e.WALLET_WITHDRAWAL_KYC_REQUIRED=7025]="WALLET_WITHDRAWAL_KYC_REQUIRED",e[e.WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE=7026]="WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE",e[e.WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE=7027]="WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE",e[e.WALLET_PEER_PULL_PAYMENT_INSUFFICIENT_BALANCE=7028]="WALLET_PEER_PULL_PAYMENT_INSUFFICIENT_BALANCE",e[e.WALLET_REFRESH_GROUP_INCOMPLETE=7029]="WALLET_REFRESH_GROUP_INCOMPLETE",e[e.WALLET_EXCHANGE_BASE_URL_MISMATCH=7030]="WALLET_EXCHANGE_BASE_URL_MISMATCH",e[e.WALLET_ORDER_ALREADY_PAID=7031]="WALLET_ORDER_ALREADY_PAID",e[e.WALLET_EXCHANGE_UNAVAILABLE=7032]="WALLET_EXCHANGE_UNAVAILABLE",e[e.WALLET_EXCHANGE_ENTRY_USED=7033]="WALLET_EXCHANGE_ENTRY_USED",e[e.WALLET_DB_UNAVAILABLE=7034]="WALLET_DB_UNAVAILABLE",e[e.WALLET_TALER_URI_MALFORMED=7035]="WALLET_TALER_URI_MALFORMED",e[e.WALLET_CORE_REQUEST_CANCELLED=7036]="WALLET_CORE_REQUEST_CANCELLED",e[e.WALLET_EXCHANGE_TOS_NOT_ACCEPTED=7037]="WALLET_EXCHANGE_TOS_NOT_ACCEPTED",e[e.WALLET_EXCHANGE_ENTRY_UPDATE_CONFLICT=7038]="WALLET_EXCHANGE_ENTRY_UPDATE_CONFLICT",e[e.WALLET_EXCHANGE_ENTRY_OUTDATED=7039]="WALLET_EXCHANGE_ENTRY_OUTDATED",e[e.WALLET_PAY_MERCHANT_KYC_MISSING=7040]="WALLET_PAY_MERCHANT_KYC_MISSING",e[e.WALLET_PEER_PULL_DEBIT_PURSE_GONE=7041]="WALLET_PEER_PULL_DEBIT_PURSE_GONE",e[e.WALLET_TRANSACTION_ABORTED_BY_USER=7042]="WALLET_TRANSACTION_ABORTED_BY_USER",e[e.WALLET_TRANSACTION_ABANDONED_BY_USER=7043]="WALLET_TRANSACTION_ABANDONED_BY_USER",e[e.WALLET_PAY_MERCHANT_ORDER_GONE=7044]="WALLET_PAY_MERCHANT_ORDER_GONE",e[e.WALLET_EXCHANGE_ENTRY_NOT_FOUND=7045]="WALLET_EXCHANGE_ENTRY_NOT_FOUND",e[e.WALLET_REQUEST_TRANSACTION_STATE_UNSUPPORTED=7046]="WALLET_REQUEST_TRANSACTION_STATE_UNSUPPORTED",e[e.WALLET_TRANSACTION_PROTOCOL_VIOLATION=7047]="WALLET_TRANSACTION_PROTOCOL_VIOLATION",e[e.WALLET_CORE_API_BAD_REQUEST=7048]="WALLET_CORE_API_BAD_REQUEST",e[e.WALLET_MERCHANT_ORDER_NOT_FOUND=7049]="WALLET_MERCHANT_ORDER_NOT_FOUND",e[e.ANASTASIS_GENERIC_BACKEND_TIMEOUT=8e3]="ANASTASIS_GENERIC_BACKEND_TIMEOUT",e[e.ANASTASIS_GENERIC_INVALID_PAYMENT_REQUEST=8001]="ANASTASIS_GENERIC_INVALID_PAYMENT_REQUEST",e[e.ANASTASIS_GENERIC_BACKEND_ERROR=8002]="ANASTASIS_GENERIC_BACKEND_ERROR",e[e.ANASTASIS_GENERIC_MISSING_CONTENT_LENGTH=8003]="ANASTASIS_GENERIC_MISSING_CONTENT_LENGTH",e[e.ANASTASIS_GENERIC_MALFORMED_CONTENT_LENGTH=8004]="ANASTASIS_GENERIC_MALFORMED_CONTENT_LENGTH",e[e.ANASTASIS_GENERIC_ORDER_CREATE_BACKEND_ERROR=8005]="ANASTASIS_GENERIC_ORDER_CREATE_BACKEND_ERROR",e[e.ANASTASIS_GENERIC_PAYMENT_CHECK_UNAUTHORIZED=8006]="ANASTASIS_GENERIC_PAYMENT_CHECK_UNAUTHORIZED",e[e.ANASTASIS_GENERIC_PAYMENT_CHECK_START_FAILED=8007]="ANASTASIS_GENERIC_PAYMENT_CHECK_START_FAILED",e[e.ANASTASIS_GENERIC_PROVIDER_UNREACHABLE=8008]="ANASTASIS_GENERIC_PROVIDER_UNREACHABLE",e[e.ANASTASIS_PAYMENT_GENERIC_TIMEOUT=8009]="ANASTASIS_PAYMENT_GENERIC_TIMEOUT",e[e.ANASTASIS_TRUTH_UNKNOWN=8108]="ANASTASIS_TRUTH_UNKNOWN",e[e.ANASTASIS_TRUTH_AUTHORIZATION_METHOD_NO_LONGER_SUPPORTED=8109]="ANASTASIS_TRUTH_AUTHORIZATION_METHOD_NO_LONGER_SUPPORTED",e[e.ANASTASIS_TRUTH_CHALLENGE_RESPONSE_REQUIRED=8110]="ANASTASIS_TRUTH_CHALLENGE_RESPONSE_REQUIRED",e[e.ANASTASIS_TRUTH_CHALLENGE_FAILED=8111]="ANASTASIS_TRUTH_CHALLENGE_FAILED",e[e.ANASTASIS_TRUTH_CHALLENGE_UNKNOWN=8112]="ANASTASIS_TRUTH_CHALLENGE_UNKNOWN",e[e.ANASTASIS_TRUTH_AUTHORIZATION_START_FAILED=8114]="ANASTASIS_TRUTH_AUTHORIZATION_START_FAILED",e[e.ANASTASIS_TRUTH_KEY_SHARE_GONE=8115]="ANASTASIS_TRUTH_KEY_SHARE_GONE",e[e.ANASTASIS_TRUTH_ORDER_DISAPPEARED=8116]="ANASTASIS_TRUTH_ORDER_DISAPPEARED",e[e.ANASTASIS_TRUTH_BACKEND_EXCHANGE_BAD=8117]="ANASTASIS_TRUTH_BACKEND_EXCHANGE_BAD",e[e.ANASTASIS_TRUTH_UNEXPECTED_PAYMENT_STATUS=8118]="ANASTASIS_TRUTH_UNEXPECTED_PAYMENT_STATUS",e[e.ANASTASIS_TRUTH_PAYMENT_CREATE_BACKEND_ERROR=8119]="ANASTASIS_TRUTH_PAYMENT_CREATE_BACKEND_ERROR",e[e.ANASTASIS_TRUTH_DECRYPTION_FAILED=8120]="ANASTASIS_TRUTH_DECRYPTION_FAILED",e[e.ANASTASIS_TRUTH_RATE_LIMITED=8121]="ANASTASIS_TRUTH_RATE_LIMITED",e[e.ANASTASIS_TRUTH_CHALLENGE_WRONG_METHOD=8123]="ANASTASIS_TRUTH_CHALLENGE_WRONG_METHOD",e[e.ANASTASIS_TRUTH_UPLOAD_UUID_EXISTS=8150]="ANASTASIS_TRUTH_UPLOAD_UUID_EXISTS",e[e.ANASTASIS_TRUTH_UPLOAD_METHOD_NOT_SUPPORTED=8151]="ANASTASIS_TRUTH_UPLOAD_METHOD_NOT_SUPPORTED",e[e.ANASTASIS_SMS_PHONE_INVALID=8200]="ANASTASIS_SMS_PHONE_INVALID",e[e.ANASTASIS_SMS_HELPER_EXEC_FAILED=8201]="ANASTASIS_SMS_HELPER_EXEC_FAILED",e[e.ANASTASIS_SMS_HELPER_COMMAND_FAILED=8202]="ANASTASIS_SMS_HELPER_COMMAND_FAILED",e[e.ANASTASIS_EMAIL_INVALID=8210]="ANASTASIS_EMAIL_INVALID",e[e.ANASTASIS_EMAIL_HELPER_EXEC_FAILED=8211]="ANASTASIS_EMAIL_HELPER_EXEC_FAILED",e[e.ANASTASIS_EMAIL_HELPER_COMMAND_FAILED=8212]="ANASTASIS_EMAIL_HELPER_COMMAND_FAILED",e[e.ANASTASIS_POST_INVALID=8220]="ANASTASIS_POST_INVALID",e[e.ANASTASIS_POST_HELPER_EXEC_FAILED=8221]="ANASTASIS_POST_HELPER_EXEC_FAILED",e[e.ANASTASIS_POST_HELPER_COMMAND_FAILED=8222]="ANASTASIS_POST_HELPER_COMMAND_FAILED",e[e.ANASTASIS_IBAN_INVALID=8230]="ANASTASIS_IBAN_INVALID",e[e.ANASTASIS_IBAN_MISSING_TRANSFER=8231]="ANASTASIS_IBAN_MISSING_TRANSFER",e[e.ANASTASIS_TOTP_KEY_MISSING=8240]="ANASTASIS_TOTP_KEY_MISSING",e[e.ANASTASIS_TOTP_KEY_INVALID=8241]="ANASTASIS_TOTP_KEY_INVALID",e[e.ANASTASIS_POLICY_BAD_IF_NONE_MATCH=8301]="ANASTASIS_POLICY_BAD_IF_NONE_MATCH",e[e.ANASTASIS_POLICY_OUT_OF_MEMORY_ON_CONTENT_LENGTH=8304]="ANASTASIS_POLICY_OUT_OF_MEMORY_ON_CONTENT_LENGTH",e[e.ANASTASIS_POLICY_BAD_SIGNATURE=8305]="ANASTASIS_POLICY_BAD_SIGNATURE",e[e.ANASTASIS_POLICY_BAD_IF_MATCH=8306]="ANASTASIS_POLICY_BAD_IF_MATCH",e[e.ANASTASIS_POLICY_INVALID_UPLOAD=8307]="ANASTASIS_POLICY_INVALID_UPLOAD",e[e.ANASTASIS_POLICY_NOT_FOUND=8350]="ANASTASIS_POLICY_NOT_FOUND",e[e.ANASTASIS_REDUCER_ACTION_INVALID=8400]="ANASTASIS_REDUCER_ACTION_INVALID",e[e.ANASTASIS_REDUCER_STATE_INVALID=8401]="ANASTASIS_REDUCER_STATE_INVALID",e[e.ANASTASIS_REDUCER_INPUT_INVALID=8402]="ANASTASIS_REDUCER_INPUT_INVALID",e[e.ANASTASIS_REDUCER_AUTHENTICATION_METHOD_NOT_SUPPORTED=8403]="ANASTASIS_REDUCER_AUTHENTICATION_METHOD_NOT_SUPPORTED",e[e.ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE=8404]="ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE",e[e.ANASTASIS_REDUCER_BACKEND_FAILURE=8405]="ANASTASIS_REDUCER_BACKEND_FAILURE",e[e.ANASTASIS_REDUCER_RESOURCE_MALFORMED=8406]="ANASTASIS_REDUCER_RESOURCE_MALFORMED",e[e.ANASTASIS_REDUCER_RESOURCE_MISSING=8407]="ANASTASIS_REDUCER_RESOURCE_MISSING",e[e.ANASTASIS_REDUCER_INPUT_REGEX_FAILED=8408]="ANASTASIS_REDUCER_INPUT_REGEX_FAILED",e[e.ANASTASIS_REDUCER_INPUT_VALIDATION_FAILED=8409]="ANASTASIS_REDUCER_INPUT_VALIDATION_FAILED",e[e.ANASTASIS_REDUCER_POLICY_LOOKUP_FAILED=8410]="ANASTASIS_REDUCER_POLICY_LOOKUP_FAILED",e[e.ANASTASIS_REDUCER_BACKUP_PROVIDER_FAILED=8411]="ANASTASIS_REDUCER_BACKUP_PROVIDER_FAILED",e[e.ANASTASIS_REDUCER_PROVIDER_CONFIG_FAILED=8412]="ANASTASIS_REDUCER_PROVIDER_CONFIG_FAILED",e[e.ANASTASIS_REDUCER_POLICY_MALFORMED=8413]="ANASTASIS_REDUCER_POLICY_MALFORMED",e[e.ANASTASIS_REDUCER_NETWORK_FAILED=8414]="ANASTASIS_REDUCER_NETWORK_FAILED",e[e.ANASTASIS_REDUCER_SECRET_MALFORMED=8415]="ANASTASIS_REDUCER_SECRET_MALFORMED",e[e.ANASTASIS_REDUCER_CHALLENGE_DATA_TOO_BIG=8416]="ANASTASIS_REDUCER_CHALLENGE_DATA_TOO_BIG",e[e.ANASTASIS_REDUCER_SECRET_TOO_BIG=8417]="ANASTASIS_REDUCER_SECRET_TOO_BIG",e[e.ANASTASIS_REDUCER_PROVIDER_INVALID_CONFIG=8418]="ANASTASIS_REDUCER_PROVIDER_INVALID_CONFIG",e[e.ANASTASIS_REDUCER_INTERNAL_ERROR=8419]="ANASTASIS_REDUCER_INTERNAL_ERROR",e[e.ANASTASIS_REDUCER_PROVIDERS_ALREADY_SYNCED=8420]="ANASTASIS_REDUCER_PROVIDERS_ALREADY_SYNCED",e[e.DONAU_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION=8606]="DONAU_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION",e[e.DONAU_GENERIC_KEYS_MISSING=8607]="DONAU_GENERIC_KEYS_MISSING",e[e.DONAU_CHARITY_SIGNATURE_INVALID=8608]="DONAU_CHARITY_SIGNATURE_INVALID",e[e.DONAU_CHARITY_NOT_FOUND=8609]="DONAU_CHARITY_NOT_FOUND",e[e.DONAU_EXCEEDING_DONATION_LIMIT=8610]="DONAU_EXCEEDING_DONATION_LIMIT",e[e.DONAU_GENERIC_DONATION_UNIT_UNKNOWN=8611]="DONAU_GENERIC_DONATION_UNIT_UNKNOWN",e[e.DONAU_DONATION_UNIT_HELPER_UNAVAILABLE=8612]="DONAU_DONATION_UNIT_HELPER_UNAVAILABLE",e[e.DONAU_SIGNKEY_HELPER_UNAVAILABLE=8613]="DONAU_SIGNKEY_HELPER_UNAVAILABLE",e[e.DONAU_SIGNKEY_HELPER_BUG=8614]="DONAU_SIGNKEY_HELPER_BUG",e[e.DONAU_GENERIC_WRONG_NUMBER_OF_SEGMENTS=8615]="DONAU_GENERIC_WRONG_NUMBER_OF_SEGMENTS",e[e.DONAU_DONATION_RECEIPT_SIGNATURE_INVALID=8616]="DONAU_DONATION_RECEIPT_SIGNATURE_INVALID",e[e.DONAU_DONOR_IDENTIFIER_NONCE_REUSE=8617]="DONAU_DONOR_IDENTIFIER_NONCE_REUSE",e[e.DONAU_CHARITY_PUB_EXISTS=8618]="DONAU_CHARITY_PUB_EXISTS",e[e.LIBEUFIN_NEXUS_GENERIC_ERROR=9e3]="LIBEUFIN_NEXUS_GENERIC_ERROR",e[e.LIBEUFIN_NEXUS_UNCAUGHT_EXCEPTION=9001]="LIBEUFIN_NEXUS_UNCAUGHT_EXCEPTION",e[e.LIBEUFIN_SANDBOX_GENERIC_ERROR=9500]="LIBEUFIN_SANDBOX_GENERIC_ERROR",e[e.LIBEUFIN_SANDBOX_UNCAUGHT_EXCEPTION=9501]="LIBEUFIN_SANDBOX_UNCAUGHT_EXCEPTION",e[e.TALDIR_METHOD_NOT_SUPPORTED=9600]="TALDIR_METHOD_NOT_SUPPORTED",e[e.TALDIR_REGISTER_RATE_LIMITED=9601]="TALDIR_REGISTER_RATE_LIMITED",e[e.CHALLENGER_GENERIC_CLIENT_UNKNOWN=9750]="CHALLENGER_GENERIC_CLIENT_UNKNOWN",e[e.CHALLENGER_GENERIC_CLIENT_FORBIDDEN_BAD_REDIRECT_URI=9751]="CHALLENGER_GENERIC_CLIENT_FORBIDDEN_BAD_REDIRECT_URI",e[e.CHALLENGER_HELPER_EXEC_FAILED=9752]="CHALLENGER_HELPER_EXEC_FAILED",e[e.CHALLENGER_GRANT_UNKNOWN=9753]="CHALLENGER_GRANT_UNKNOWN",e[e.CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE=9754]="CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE",e[e.CHALLENGER_GENERIC_VALIDATION_UNKNOWN=9755]="CHALLENGER_GENERIC_VALIDATION_UNKNOWN",e[e.CHALLENGER_CLIENT_FORBIDDEN_INVALID_CODE=9756]="CHALLENGER_CLIENT_FORBIDDEN_INVALID_CODE",e[e.CHALLENGER_TOO_MANY_ATTEMPTS=9757]="CHALLENGER_TOO_MANY_ATTEMPTS",e[e.CHALLENGER_INVALID_PIN=9758]="CHALLENGER_INVALID_PIN",e[e.CHALLENGER_MISSING_ADDRESS=9759]="CHALLENGER_MISSING_ADDRESS",e[e.CHALLENGER_CLIENT_FORBIDDEN_READ_ONLY=9760]="CHALLENGER_CLIENT_FORBIDDEN_READ_ONLY",e[e.END=9999]="END"})(G||(G={}));var tr=Symbol("opaque_AbsoluteTime"),Hh;(function(e){function t(){let o=he.now();return he.toPreciseTimestamp(o)}e.now=t;function r(o){return{t_s:o.t_s}}e.round=r;function n(o){return{t_s:Math.floor(o),off_us:Math.floor((o-Math.floor(o))/1e3/1e3)}}e.fromSeconds=n;function a(o){return{t_s:Math.floor(o/1e3),off_us:Math.floor((o-Math.floor(o/1e3)*1e3)*1e3)}}e.fromMilliseconds=a})(Hh||(Hh={}));var Gh;(function(e){function t(n){return rt.toTalerProtocolDuration(rt.fromSpec(n))}e.fromSpec=t;function r(){return{d_us:"forever"}}e.forever=r})(Gh||(Gh={}));var Pi;(function(e){function t(f){return typeof f=="object"&&f!==null&&"t_s"in f&&(typeof f.t_s=="number"||f.t_s==="never")}e.isTimestamp=t;function r(){return he.toProtocolTimestamp(he.now())}e.now=r;function n(){return{t_s:0}}e.zero=n;function a(){return{t_s:"never"}}e.never=a;function o(f){return f.t_s==="never"}e.isNever=o;function s(f){return{t_s:f}}e.fromSeconds=s;function c(f,d){return f.t_s==="never"?{t_s:d.t_s}:d.t_s==="never"?{t_s:f.t_s}:{t_s:Math.min(f.t_s,d.t_s)}}e.min=c;function u(f,d){return f.t_s==="never"||d.t_s==="never"?{t_s:"never"}:{t_s:Math.max(f.t_s,d.t_s)}}e.max=u})(Pi||(Pi={}));var iA=0;var rt;(function(e){function t(v){return v.d_ms==="forever"?Number.MAX_VALUE:v.d_ms}e.toMilliseconds=t;function r(v,_=he.now()){if(v.t_ms==="never")return{d_ms:"forever"};if(_.t_ms==="never")throw Error("invalid argument for 'now'");return v.t_ms<_.t_ms?{d_ms:0}:{d_ms:v.t_ms-_.t_ms}}e.getRemaining=r;function n(v){let _=0,g="",O=!0;for(let E=0;E=48&&m<=57){if(!O)throw Error("invalid duration, unexpected number");g+=v[E];continue}if(v[E]==" "){g!=""&&(O=!1);continue}if(g=="")throw Error("invalid duration, missing number");if(v[E]==="s")v.startsWith("seconds",E)&&(E+=6),_+=1e3*Number.parseInt(g,10);else if(v[E]==="m")v.startsWith("minutes",E)&&(E+=6),_+=60*1e3*Number.parseInt(g,10);else if(v[E]==="h")v.startsWith("hours",E)&&(E+=4),_+=3600*1e3*Number.parseInt(g,10);else if(v[E]==="d")v.startsWith("days",E)&&(E+=3),_+=1440*60*1e3*Number.parseInt(g,10);else throw Error("invalid duration, unsupported unit");g="",O=!0}return{d_ms:_}}e.fromPrettyString=n;function a(v,_){return v.d_ms==="forever"?_.d_ms==="forever"?0:1:_.d_ms==="forever"?-1:v.d_ms==_.d_ms?0:v.d_ms>_.d_ms?1:-1}e.cmp=a;function o(v,_){return v.d_ms==="forever"||_.d_ms==="forever"?e.getForever():e.fromMilliseconds(v.d_ms+_.d_ms)}e.add=o;function s(v,_){return Wh(v,_)}e.max=s;function c(v,_){return Bh(v,_)}e.min=c;function u(v,_){return sA(v,_)}e.multiply=u;function f(v){if(typeof v.d_ms!="number")throw Error("infinite duration");return Math.ceil(v.d_ms/1e3/60/60/24/365)}e.toIntegerYears=f;function d(v){let _=0;return _+=(v.seconds??0)*Ci,_+=(v.minutes??0)*Oi,_+=(v.hours??0)*Di,_+=(v.days??0)*Eo,_+=(v.months??0)*Vu,_+=(v.years??0)*qu,{d_ms:_}}e.fromSpec=d;function w(v){if(!(v.seconds==null&&v.minutes==null&&v.hours==null&&v.days==null&&v.months==null&&v.years==null))return e.fromSpec(v)}e.fromSpecOrUndefined=w;function R({d_ms:v}){if(v==="forever")return;let _=v>0?v:0,g=_%qu,O=g%Vu,E=O%Eo,m=E%Di,y=m%Oi,b=y%Ci;return{years:(_-g)/qu,month:(g-O)/Vu,days:(O-E)/Eo,hours:(E-m)/Di,minutes:(m-y)/Oi,seconds:(y-b)/Ci}}e.toSpec=R;function h(){return{d_ms:"forever"}}e.getForever=h;function p(v){return v.d_ms==="forever"}e.isForever=p;function T(){return{d_ms:0}}e.getZero=T;function A(v){return v.d_us==="forever"?{d_ms:"forever"}:{d_ms:Math.floor(v.d_us/1e3)}}e.fromTalerProtocolDuration=A;function C(v){return v.d_ms==="forever"?{d_us:"forever"}:{d_us:v.d_ms*1e3}}e.toTalerProtocolDuration=C;function S(v){return{d_ms:v}}e.fromMilliseconds=S;function k(v){return Wh(Bh(v.value,v.upper),v.lower)}e.clamp=k})(rt||(rt={}));var he;(function(e){function t(){return new Date().getTime()}e.getStampMsNow=t;function r(){return Number.MAX_SAFE_INTEGER}e.getStampMsNever=r;function n(){return{t_ms:new Date().getTime()+iA,[tr]:!0}}e.now=n;function a(){return{t_ms:0,[tr]:!0}}e.zero=a;function o(){return{t_ms:"never",[tr]:!0}}e.never=o;function s(m){return{t_ms:m,[tr]:!0}}e.fromMilliseconds=s;function c(m,y){return m.t_ms==="never"?y.t_ms==="never"?0:1:y.t_ms==="never"?-1:m.t_ms==y.t_ms?0:m.t_ms>y.t_ms?1:-1}e.cmp=c;function u(m,y){return m.t_ms==="never"?{t_ms:y.t_ms,[tr]:!0}:y.t_ms==="never"?{t_ms:y.t_ms,[tr]:!0}:{t_ms:Math.min(m.t_ms,y.t_ms),[tr]:!0}}e.min=u;function f(m,y){return m.t_ms==="never"?{t_ms:"never",[tr]:!0}:y.t_ms==="never"?{t_ms:"never",[tr]:!0}:{t_ms:Math.max(m.t_ms,y.t_ms),[tr]:!0}}e.max=f;function d(m,y){return m.t_ms==="never"?{d_ms:"forever"}:y.t_ms==="never"?{d_ms:"forever"}:{d_ms:Math.abs(m.t_ms-y.t_ms)}}e.difference=d;function w(m){return c(m,n())<=0}e.isExpired=w;function R(m){return m.t_ms==="never"}e.isNever=R;function h(m){return m.t_s==="never"?{t_ms:"never",[tr]:!0}:{t_ms:m.t_s*1e3,[tr]:!0}}e.fromProtocolTimestamp=h;function p(m){return{t_ms:m,[tr]:!0}}e.fromStampMs=p;function T(m){if(m.t_s==="never")return{t_ms:"never",[tr]:!0};let y=m.off_us??0;return{t_ms:m.t_s*1e3+Math.floor(y/1e3),[tr]:!0}}e.fromPreciseTimestamp=T;function A(m){return m.t_ms==="never"?Number.MAX_SAFE_INTEGER:m.t_ms}e.toStampMs=A;function C(m){if(m.t_ms=="never")return{t_s:"never"};let y=Math.floor(m.t_ms/1e3),b=Math.floor(1e3*(m.t_ms-y*1e3));return{t_s:y,off_us:b}}e.toPreciseTimestamp=C;function S(m){return m.t_ms==="never"?{t_s:"never"}:{t_s:Math.floor(m.t_ms/1e3)}}e.toProtocolTimestamp=S;function k(m,y,b){return!(c(m,y)<0||c(m,b)>0)}e.isBetween=k;function v(m){return m.t_ms==="never"?"":new Date(m.t_ms).toISOString()}e.toIsoString=v;function _(m,y){return m.t_ms==="never"||y.d_ms==="forever"?{t_ms:"never",[tr]:!0}:{t_ms:m.t_ms+y.d_ms,[tr]:!0}}e.addDuration=_;function g(m){if(m.t_ms==="never")return rt.getForever();let y=n();if(y.t_ms==="never")throw Error("invariant violated");return rt.fromMilliseconds(Math.max(0,m.t_ms-y.t_ms))}e.remaining=g;function O(m,y){return m.t_ms==="never"?{t_ms:"never",[tr]:!0}:y.d_ms==="forever"?{t_ms:0,[tr]:!0}:{t_ms:Math.max(0,m.t_ms-y.d_ms),[tr]:!0}}e.subtractDuraction=O;function E(m){return m.t_ms==="never"?"never":new Date(m.t_ms).toISOString()}e.stringify=E})(he||(he={}));var Ci=1e3,Oi=Ci*60,Di=Oi*60,Eo=Di*24,Vu=Eo*30,qu=Eo*365;function Bh(e,t){return e.d_ms==="forever"?{d_ms:t.d_ms}:t.d_ms==="forever"?{d_ms:e.d_ms}:{d_ms:Math.min(e.d_ms,t.d_ms)}}function Wh(e,t){return e.d_ms==="forever"?{d_ms:"forever"}:t.d_ms==="forever"?{d_ms:"forever"}:{d_ms:Math.max(e.d_ms,t.d_ms)}}function sA(e,t){return e.d_ms==="forever"?{d_ms:"forever"}:{d_ms:Math.round(e.d_ms*t)}}var Br={decode(e,t){if(e===void 0)throw Error(`got undefined and expected absolute time at ${ut(t)}`);let r=e.t_ms;if(typeof r=="string"){if(r==="never")return{t_ms:"never",[tr]:!0}}else if(typeof r=="number")return{t_ms:r,[tr]:!0};throw Error(`expected timestamp at ${ut(t)}`)}},Me={decode(e,t){if(e===void 0)throw Error(`got undefined and expected timestamp at ${ut(t)}`);let r=e.t_ms;if(typeof r=="string"){if(r==="never")return{t_s:"never"}}else if(typeof r=="number")return{t_s:Math.floor(r/1e3)};let n=e.t_s;if(typeof n=="string"){if(n==="never")return{t_s:"never"};throw Error(`expected timestamp at ${ut(t)}`)}if(typeof n=="number")return{t_s:n};throw Error(`expected protocol timestamp at ${ut(t)}`)}},Ku={decode(e,t){let r=e.t_ms;if(typeof r=="string"){if(r==="never")return{t_s:"never"}}else if(typeof r=="number")return{t_s:Math.floor(r/1e3)};throw Error(`expected precise timestamp at ${ut(t)}`)}},qt={decode(e,t){let r=e.d_us;if(typeof r=="string"){if(r==="forever")return{d_us:"forever"};throw Error(`expected duration at ${ut(t)}`)}if(typeof r=="number")return{d_us:r};throw Error(`expected duration at ${ut(t)}`)}};function Li(e,t,r){!r&&!t.hint&&(r=Vh(e));let n=he.now();return{code:e,when:n,hint:r,...t}}function Vh(e){let t=G[e];return t?`Error (${t})`:"Error ()"}var Oe=class e extends Error{constructor(t,r){super(t.hint??`Error (code ${t.code})`),this.errorDetail=t,this.cause=r,Object.setPrototypeOf(this,e.prototype)}static fromDetail(t,r,n,a){n||(n=Vh(t));let o=he.now();return new e({code:t,when:o,hint:n,...r},a)}static fromUncheckedDetail(t,r){return new e({...t},r)}static fromException(t){let r=Yu(t);return new e(r,t)}hasErrorCode(t){return this.errorDetail.code===t}toString(){return`TalerError: ${JSON.stringify(this.errorDetail)}`}};function Yu(e){if(e instanceof Oe)return e.errorDetail;if(e instanceof xr.CancellationError)return Li(G.WALLET_CORE_REQUEST_CANCELLED,{});if(e instanceof Error)return Li(G.WALLET_UNEXPECTED_EXCEPTION,{stack:e.stack},`unexpected exception (message: ${e.message})`);let t;try{t=e.toString()}catch{t="can't stringify exception"}return Li(G.WALLET_UNEXPECTED_EXCEPTION,{},`unexpected exception (not an exception, ${t})`)}function ue(e){throw new Error("Didn't expect to get here")}var zu=new TextEncoder,qh=new Dt("http.ts"),$u=6e4,wo=class{constructor(){this.headerMap=new Map}get(t){let r=this.headerMap.get(t.toLowerCase());return r||null}set(t,r){let n=t.toLowerCase(),a=this.headerMap.get(n);a!==void 0?this.headerMap.set(n,a+","+r):this.headerMap.set(n,r)}toJSON(){let t={};return this.headerMap.forEach((r,n)=>t[n]=r),t}};async function it(e){let t=e.headers.get("content-type"),r;if(t&&(r=t.split(";")[0].trim().toLowerCase()),r!=="application/json")throw Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,response:await e.text(),contentType:r||""},"Error response did not even contain JSON. The request URL might be wrong or the service might be unavailable.");let n;try{n=await e.json()}catch(o){throw Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,response:await e.text(),validationError:o instanceof Error?o.message:String(o)},"Couldn't parse JSON format from error response")}if(typeof n.code!="number")throw qh.warn(`malformed error response (status ${e.status}): ${Ia(n)}`),Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,response:await e.text()},"Error response did not contain error code");return n}async function cA(e,t){if(!(e.status>=200&&e.status<300))return{isError:!0,talerErrorResponse:await it(e)};let r;try{r=await e.json()}catch(a){throw Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,response:await e.text(),validationError:a instanceof Error?a.message:String(a)},"Couldn't parse JSON format from response")}let n;try{n=t.decode(r)}catch(a){throw Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,response:await e.text(),validationError:a instanceof Error?a.message:String(a)},"Response invalid")}return{isError:!1,response:n}}async function Kh(e,t){let r;try{r=await e.json()}catch(a){throw Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,response:await e.text(),validationError:a instanceof Error?a.message:String(a)},"Couldn't parse JSON format from response")}let n;try{n=t.decode(r)}catch(a){throw Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,response:await e.text(),validationError:a instanceof Error?a.message:String(a)},"Response invalid")}return n}function uA(e,t){let r={requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,errorResponse:t};throw qh.trace(`unexpected request error: ${Ia(r)}`),Oe.fromDetail(G.WALLET_UNEXPECTED_REQUEST_ERROR,r,`Unexpected HTTP status ${e.status} in response`)}async function ua(e,t){let r=await cA(e,t);if(!r.isError)return r.response;uA(e,r.talerErrorResponse)}function Xu(e){if(e==null)return new Uint8Array(0);if(typeof e=="string")return zu.encode(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);if(e instanceof ArrayBuffer)return new Uint8Array(e);if(e instanceof URLSearchParams)return zu.encode(e.toString());if(typeof e=="object"&&e.constructor.name==="FormData")return new Uint8Array(e);if(typeof e=="object")return zu.encode(JSON.stringify(e));throw new TypeError("unsupported request body type")}function ju(e){let t={};return(e==="POST"||e==="PUT"||e==="PATCH")&&(t["Content-Type"]="application/json"),t.Accept="application/json",t}var St;(function(e){function t(a,o){let s=n(a),c=n(o);if(!(s&&c))return;let u=s.current-s.age<=c.current&&s.current>=c.current-c.age,f=Math.sign(s.current-c.current);return{compatible:u,currentCmp:f}}e.compare=t;function r(a){let o=n(a);if(!o)throw Error("invalid libtool version");return o}e.parseVersionOrThrow=r;function n(a){let[o,s,c,...u]=a.split(":");if(u.length!==0)return;let f=Number.parseInt(o),d=Number.parseInt(s),w=Number.parseInt(c);if(!Number.isNaN(f)&&!Number.isNaN(d)&&!Number.isNaN(w))return{current:f,revision:d,age:w}}e.parseVersion=n})(St||(St={}));var Tr=L;var $h=L,hn=L,Ft=L;var Nr=L,mr=()=>Ar(L()),an=()=>W().property("name",L()).property("num_fractional_input_digits",ne()).property("num_fractional_normal_digits",ne()).property("num_fractional_trailing_zero_digits",ne()).property("alt_unit_names",Ar(L())).property("common_amounts",U(Ae(me()))).deprecatedProperty("currency").build("CurrencySpecification"),Xh=()=>W().allowExtra().property("name",L()).property("version",L()).build("TalerCommonConfigResponse"),Yh;(function(e){e[e.V12=12]="V12"})(Yh||(Yh={}));var zh;(function(e){e[e.V3=3]="V3"})(zh||(zh={}));var lA=()=>W().property("creation_time",Me).property("expiration",Me).property("scope",L()).property("refreshable",Se()).property("description",U(L())).property("serial",ne()).build("TokenInfo"),Ui=()=>W().property("tokens",Ae(lA())).build("TokenInfoList"),Sa=L,jh=()=>W().property("access_token",Sa()).property("expiration",Me).build("TalerAuthentication.TokenSuccessResponse"),Qh=L;function Ca(e){return e.startsWith("secret-token:")?e:`secret-token:${encodeURIComponent(e)}`}async function se(e,t){return{type:"ok",case:"ok",body:await ua(e,t)}}function Ke(e){return{type:"ok",case:"ok",body:e}}function ke(){return{type:"ok",case:"ok",body:void 0}}function Tt(e){return{type:"fail",case:e}}function Ao(e,t){return{type:"fail",case:e,body:t}}async function rr(e,t,r,n){let a=await ua(r,Xh());if(a.name!==e)throw Oe.fromUncheckedDetail({code:G.GENERIC_UNEXPECTED_REQUEST_ERROR,requestUrl:r.requestUrl,httpStatusCode:r.status,detail:`Unexpected server component name (got ${a.name}, expected ${e}})`});if(!St.compare(t,a.version))throw Oe.fromUncheckedDetail({code:G.GENERIC_CLIENT_UNSUPPORTED_PROTOCOL_VERSION,requestUrl:r.requestUrl,httpStatusCode:r.status,detail:`Unsupported protocol version, client supports ${t}, server supports ${a.version}`});let o=await ua(r,n);return Ke(o)}async function mt(e,t,r){let n=await Kh(e,r);return{type:"fail",case:t,body:n}}async function I(e,t,r){return r||(r=await it(t)),{type:"fail",case:e,detail:r}}async function V(e,t){throw t||(t=await it(e)),Oe.fromDetail(G.WALLET_UNEXPECTED_REQUEST_ERROR,{requestUrl:e.requestUrl,requestMethod:e.requestMethod,httpStatusCode:e.status,errorResponse:t},`Unexpected HTTP status ${e.status} in response`)}function Ce(e,t){return{type:"fail",case:e,detail:t}}var Xt=1e8,Mi=8,Oa=2**52,Gn=".",dA=":",ki=class e{static from(t){return new e(J.parseOrThrow(t),0)}static zeroOfCurrency(t){return new e(J.zeroOfCurrency(t),0)}add(...t){if(this.saturated)return this;let r=J.add(this.val,...t);return new e(r.amount,r.saturated?1:0)}isZero(){return this.val.fraction===0&&this.val.value===0}sub(...t){if(this.saturated)return this;let r=J.sub(this.val,...t);return new e(r.amount,r.saturated?1:0)}mult(t){if(this.saturated)return this;let r=J.mult(this,t);return new e(r.amount,r.saturated?1:0)}toJson(){return{...this.val}}toString(){return J.stringify(this.val)}constructor(t,r){this.val=t,this.saturated=r}};function me(){return{decode(e,t){if(typeof e!="string")throw new Rt(`expected string at ${ut(t)} but got ${typeof e}`);if(J.parse(e)===void 0)throw new Rt(`invalid amount at ${ut(t)} got "${e}"`);return e}}}var Rn;(function(e){e[e.MISSING_CURRENCY=0]="MISSING_CURRENCY",e[e.CURRENCY_TOO_LONG=1]="CURRENCY_TOO_LONG",e[e.BAD_CURRENCY=2]="BAD_CURRENCY",e[e.BAD_NUMBER=3]="BAD_NUMBER",e[e.TOO_HIGH=4]="TOO_HIGH",e[e.TOO_PRECISE=5]="TOO_PRECISE"})(Rn||(Rn={}));var J=class e{constructor(){throw Error("not instantiable")}static currencyOf(t){return e.parseOrThrow(t).currency}static zeroOfAmount(t){return{currency:e.parseOrThrow(t).currency,fraction:0,value:0}}static zeroOfCurrency(t){return{currency:t,fraction:0,value:0}}static jsonifyAmount(t){return typeof t=="string"?e.parseOrThrow(t):t instanceof ki?t.toJson():t}static divmod(t,r){let n=e.jsonifyAmount(t),a=e.jsonifyAmount(r);if(n.currency!=a.currency)throw Error(`incompatible currency (${n.currency} vs${a.currency})`);let o=BigInt(n.value)*BigInt(Xt)+BigInt(n.fraction),s=BigInt(a.value)*BigInt(Xt)+BigInt(a.fraction),c=o/s,u=o%s;return{quotient:Number(c),remainder:{currency:n.currency,value:Number(u/BigInt(Xt)),fraction:Number(u%BigInt(Xt))}}}static sum(t){if(t.length<=0)throw Error("can't sum zero amounts");let r=t.map(n=>e.jsonifyAmount(n));return e.add(r[0],...r.slice(1))}static sumOrZero(t,r){if(r.length<=0)return{amount:e.zeroOfCurrency(t),saturated:!1};let n=r.map(a=>e.jsonifyAmount(a));return e.add(n[0],...n.slice(1))}static add(t,...r){let n=e.jsonifyAmount(t),a=n.currency,o=n.value+Math.floor(n.fraction/Xt);if(o>Oa)return{amount:{currency:a,value:Oa,fraction:Xt-1},saturated:!0};let s=n.fraction%Xt;for(let c of r){let u=e.jsonifyAmount(c);if(u.currency.toUpperCase()!==a.toUpperCase())throw Error(`Mismatched currency: ${u.currency} and ${a}`);if(o=o+u.value+Math.floor((s+u.fraction)/Xt),s=Math.floor((s+u.fraction)%Xt),o>Oa)return{amount:{currency:a,value:Oa,fraction:Xt-1},saturated:!0}}return{amount:{currency:a,value:o,fraction:s},saturated:!1}}static sub(t,...r){let n=e.jsonifyAmount(t),a=n.currency,o=n.value,s=n.fraction;for(let c of r){let u=e.jsonifyAmount(c);if(u.currency.toUpperCase()!==n.currency.toUpperCase())throw Error(`Mismatched currency: ${u.currency} and ${a}`);if(s=u.fraction),s-=u.fraction,oo:return 1;case as:return 1;case a===s:return 0;default:throw Error("assertion failed")}}static copy(t){return{currency:t.currency,fraction:t.fraction,value:t.value}}static divide(t,r){if(r===0)throw Error("Division by 0");if(r===1)return{value:t.value,fraction:t.fraction,currency:t.currency};let n=t.value%r;return{currency:t.currency,fraction:Math.floor((n*Xt+t.fraction)/r),value:Math.floor(t.value/r)}}static isNonZero(t){return t=e.jsonifyAmount(t),t.value>0||t.fraction>0}static isZero(t){return t=e.jsonifyAmount(t),t.value===0&&t.fraction===0}static isCurrency(t){return/^[a-zA-Z]{1,11}$/.test(t)}static parseWithError(t){let r=t.indexOf(dA);if(r===-1||r===0)return Tt(Rn.MISSING_CURRENCY);if(r>11)return Tt(Rn.MISSING_CURRENCY);let n=t.substring(0,r).toUpperCase();if(!/^[a-zA-Z]+$/.test(n))return Tt(Rn.BAD_CURRENCY);let a=t.substring(r+1),o=a.indexOf(Gn),s=o===-1?a:a.substring(0,o),c=o===-1||o===a.length?"0":a.substring(o+1);if(!/^[0-9]+$/.test(s)||!/^[0-9]+$/.test(c))return Tt(Rn.BAD_NUMBER);let u=Number.parseInt(s,10),f=Math.round(Xt*Number.parseFloat(Gn+c));return!Number.isInteger(u)||!Number.isInteger(f)?Tt(Rn.BAD_NUMBER):u>Oa?Tt(Rn.TOO_HIGH):c.length>Mi?Tt(Rn.TOO_PRECISE):Ke({currency:n,fraction:f,value:u})}static parse(t){let r=t.match(/^([a-zA-Z]{1,11}):([0-9]+)([.][0-9]{1,8})?$/);if(!r)return;let n=r[3]||Gn+"0";if(n.length>Mi+1)return;let a=Number.parseInt(r[2]);if(!(a>Oa))return{currency:r[1].toUpperCase(),fraction:Math.round(Xt*Number.parseFloat(n)),value:a}}static parseOrThrow(t){if(t instanceof ki)return t.toJson();if(typeof t=="object"){if(typeof t.currency!="string"||typeof t.value!="number"||typeof t.fraction!="number")throw Error("invalid amount object");return{currency:t.currency,value:t.value,fraction:t.fraction}}else if(typeof t=="string"){let r=e.parse(t);if(!r)throw Error(`Can't parse amount: "${t}"`);return r}else throw Error("invalid amount (illegal type)")}static min(t,r){return e.cmp(t,r)>=0?e.jsonifyAmount(r):e.jsonifyAmount(t)}static max(t,r){return e.cmp(t,r)>=0?e.jsonifyAmount(t):e.jsonifyAmount(r)}static mult(t,r){if(t=this.jsonifyAmount(t),!Number.isInteger(r))throw Error("amount can only be multiplied by an integer");if(r<0)throw Error("amount can only be multiplied by a positive integer");if(r==0)return{amount:e.zeroOfCurrency(t.currency),saturated:!1};let n=t,a=e.zeroOfCurrency(t.currency);for(;r>1;){if(r%2==0)r=r/2;else{r=(r-1)/2;let s=e.add(a,n);if(s.saturated)return s;a=s.amount}let o=e.add(n,n);if(o.saturated)return o;n=o.amount}return e.add(a,n)}static check(t){if(typeof t!="string")return!1;try{return!!e.parse(t)}catch{return!1}}static stringify(t){t=e.jsonifyAmount(t);let r=this.stringifyValue(t);return`${t.currency}:${r}`}static toPretty(t){return`${t.value+t.fraction/Xt} ${t.currency}`}static amountHasSameCurrency(t,r){let n=this.jsonifyAmount(t),a=this.jsonifyAmount(r);return n.currency.toUpperCase()===a.currency.toUpperCase()}static isSameCurrency(t,r){return t.toLowerCase()===r.toLowerCase()}static stringifyValue(t,r=0){let n=e.jsonifyAmount(t),a=n.value+Math.floor(n.fraction/Xt),o=n.fraction%Xt,s=a.toString();if(o||r){s=s+Gn;let c=o;for(let u=0;u=r);u++)s=s+Math.floor(c/Xt*10).toString(),c=c*10%Xt}return s}static maxFractionalDigits(t){if(t.fraction===0)return 0;if(t.fraction<0)return console.error("amount fraction can not be negative",t),0;let r=0,n=!0,a=t.fraction;for(;a>0&&n;)n=a%10===0,a=a/10,r++;return Mi-r+1}static stringifyValueWithSpec(t,r){let n=e.stringifyValue(t),a=n.indexOf(Gn),o=a<0?n.length:a,s=t.currency,c=Object.keys(r.alt_unit_names),u=o;if(c.length>0){let p="0";c.forEach(T=>{let A=Number.parseInt(T,10);Number.isNaN(A)||o-A<=0||o-Ar.num_fractional_normal_digits){let o=t+r.num_fractional_normal_digits+1;n=e.substring(0,o),a=e.substring(o)}else n=e,a=void 0;return{normal:n,small:a}}var Fi=class{fetch(t,r){throw new Error("Method not implemented.")}};function jt(e){return new Fi(e)}function Jh(e){var t="",r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";let n;ArrayBuffer.isView(e)?n=new Uint8Array(e.buffer,e.byteOffset,e.byteLength):n=new Uint8Array(e);for(var a=n.byteLength,o=a%3,s=a-o,c,u,f,d,w,R=0;R>18,u=(w&258048)>>12,f=(w&4032)>>6,d=w&63,t+=r[c]+r[u]+r[f]+r[d];return o==1?(w=n[s],c=(w&252)>>2,u=(w&3)<<4,t+=r[c]+r[u]+"=="):o==2&&(w=n[s]<<8|n[s+1],c=(w&64512)>>10,u=(w&1008)>>4,f=(w&15)<<2,t+=r[c]+r[u]+r[f]+"="),t}var So=ui(em(),1);var mA=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]);function Qu(e,t,r,n,a){let o,s,c,u,f,d,w,R,h,p,T,A,C;for(;a>=64;){for(o=t[0],s=t[1],c=t[2],u=t[3],f=t[4],d=t[5],w=t[6],R=t[7],p=0;p<16;p++)T=n+p*4,e[p]=(r[T]&255)<<24|(r[T+1]&255)<<16|(r[T+2]&255)<<8|r[T+3]&255;for(p=16;p<64;p++)h=e[p-2],A=(h>>>17|h<<15)^(h>>>19|h<<13)^h>>>10,h=e[p-15],C=(h>>>7|h<<25)^(h>>>18|h<<14)^h>>>3,e[p]=(A+e[p-7]|0)+(C+e[p-16]|0);for(p=0;p<64;p++)A=(((f>>>6|f<<26)^(f>>>11|f<<21)^(f>>>25|f<<7))+(f&d^~f&w)|0)+(R+(mA[p]+e[p]|0)|0)|0,C=((o>>>2|o<<30)^(o>>>13|o<<19)^(o>>>22|o<<10))+(o&s^o&c^s&c)|0,R=w,w=d,d=f,f=u+A|0,u=c,c=s,s=o,o=A+C|0;t[0]+=o,t[1]+=s,t[2]+=c,t[3]+=u,t[4]+=f,t[5]+=d,t[6]+=w,t[7]+=R,n+=64,a-=64}return n}var Gi=class{constructor(){this.digestLength=32,this.blockSize=64,this.state=new Int32Array(8),this.temp=new Int32Array(64),this.buffer=new Uint8Array(128),this.bufferLength=0,this.bytesHashed=0,this.finished=!1,this.reset()}reset(){return this.state[0]=1779033703,this.state[1]=3144134277,this.state[2]=1013904242,this.state[3]=2773480762,this.state[4]=1359893119,this.state[5]=2600822924,this.state[6]=528734635,this.state[7]=1541459225,this.bufferLength=0,this.bytesHashed=0,this.finished=!1,this}clean(){for(let t=0;t0){for(;this.bufferLength<64&&r>0;)this.buffer[this.bufferLength++]=t[n++],r--;this.bufferLength===64&&(Qu(this.temp,this.state,this.buffer,0,64),this.bufferLength=0)}for(r>=64&&(n=Qu(this.temp,this.state,t,n,r),r%=64);r>0;)this.buffer[this.bufferLength++]=t[n++],r--;return this}finish(t){if(!this.finished){let r=this.bytesHashed,n=this.bufferLength,a=r/536870912|0,o=r<<3,s=r%64<56?64:128;this.buffer[n]=128;for(let c=n+1;c>>24&255,this.buffer[s-7]=a>>>16&255,this.buffer[s-6]=a>>>8&255,this.buffer[s-5]=a>>>0&255,this.buffer[s-4]=o>>>24&255,this.buffer[s-3]=o>>>16&255,this.buffer[s-2]=o>>>8&255,this.buffer[s-1]=o>>>0&255,Qu(this.temp,this.state,this.buffer,0,s),this.finished=!0}for(let r=0;r<8;r++)t[r*4+0]=this.state[r]>>>24&255,t[r*4+1]=this.state[r]>>>16&255,t[r*4+2]=this.state[r]>>>8&255,t[r*4+3]=this.state[r]>>>0&255;return this}digest(){let t=new Uint8Array(this.digestLength);return this.finish(t),t}_saveState(t){for(let r=0;rt&&(r=e(r)),r.byteLength>25;t=(t&33554431)<<5^e[r];for(var a=0;a<5;++a)n>>a&1&&(t^=_A[a])}return t}function im(e){let t=[];for(let r=0;r>5);t.push(0);for(let r=0;r>5*(5-s)&31);return o}var Mr;(function(e){let t;(function(o){o.BECH32="bech32",o.BECH32M="bech32m"})(t=e.Encodings||(e.Encodings={}));function r(o,s,c){for(var u=s.concat(bA(o,s,c)),f=o+"1",d=0;d126)return fe.error(n.WRONG_CHARSET);o.charCodeAt(c)>=97&&o.charCodeAt(c)<=122&&(u=!0),o.charCodeAt(c)>=65&&o.charCodeAt(c)<=90&&(f=!0)}if(u&&f)return fe.error(n.MIXING_UPPER_AND_LOWER);o=o.toLowerCase();let d=o.lastIndexOf("1");if(d<1)return fe.error(n.MISSING_HRP);if(d+7>o.length)return fe.error(n.TOO_SHORT);if(o.length>90)return fe.error(n.TOO_LONG);let w=o.substring(0,d);var R=[];for(c=d+1;c>t!==0)return null;for(a=a<=r;)o-=r,s.push(a>>o&c)}if(n)o>0&&s.push(a<=t||a<16)return fe.error(t.INVALID_DATA);let u=cm(c.data.slice(1),5,8,!1);return u===null||u.length<2||u.length>40?fe.error(t.DECODING_PROBLEM):c.data[0]===0&&u.length!==20&&u.length!==32?fe.error(t.DECODING_PROBLEM):c.data[0]===0&&o===Mr.Encodings.BECH32?fe.error(t.DECODING_PROBLEM):c.data[0]!==0&&o===Mr.Encodings.BECH32M?fe.error(t.DECODING_PROBLEM):fe.of({version:c.data[0],program:u})}e.decode=r;function n(a,o,s){let c=o>0?Mr.Encodings.BECH32M:Mr.Encodings.BECH32,u=cm(s,8,5,!0);if(!u)return Tt(t.INVALID_DATA);let f=Mr.encode(a,[o].concat(u),c);return Ke(f)}e.encode=n})(To||(To={}));var No;(function(e){e.WRONG_RESERVE_PUB="wrong-reserve-pub",e.WRONG_PREFIX="wrong-prefix",e.INVALID_SEGWIT="invalid-segwit"})(No||(No={}));function um(e,t){let r=new Uint8Array(4);r.set(e.subarray(0,4));let n=new Uint8Array(4);n.set(e.subarray(0,4)),r[0]=r[0]&127,n[0]=n[0]|128;let a=new Uint8Array(r.length+e.length/2);a.set(r,0),a.set(e.subarray(0,16),4);let o=new Uint8Array(r.length+e.length/2);o.set(n,0),o.set(e.subarray(16,32),4);let s=t[0]==="t"&&t[1]=="b"?"tb":t[0]==="b"&&t[1]=="c"&&t[2]==="r"&&t[3]=="t"?"bcrt":t[0]==="b"&&t[1]=="c"?"bc":void 0;if(s===void 0)return fe.error(No.WRONG_PREFIX);let c=To.encode(s,0,Array.from(a));if(c.type==="fail")return fe.error(No.INVALID_SEGWIT);let u=To.encode(s,0,Array.from(o));if(u.type==="fail")return fe.error(No.INVALID_SEGWIT);let f=[c.body,u.body];return fe.of(f)}var Wn;(function(e){e[e.UNSUPPORTED_COUNTRY=0]="UNSUPPORTED_COUNTRY",e[e.TOO_LONG=1]="TOO_LONG",e[e.TOO_SHORT=2]="TOO_SHORT",e[e.INVALID_CHARSET=3]="INVALID_CHARSET",e[e.INVALID_CHECKSUM=4]="INVALID_CHECKSUM"})(Wn||(Wn={}));var lm=48,vA=57,dm=65,EA=90;function fm(e,t){if(t>=lm&&t<=vA)e.push(t-lm);else if(t>=dm&&t<=EA){let r=t-dm+10;e.push(Math.floor(r/10)%10),e.push(r%10)}else return!1;return!0}function wA(e){let t=0,r=0;for(;t34)return fe.error(Wn.TOO_LONG);let t=e.toUpperCase().replace(/[\s-\._]/g,""),r=t.substring(0,2);if(!AA[r])return fe.error(Wn.UNSUPPORTED_COUNTRY);let a=[];for(let s=4;s{x[K]=B});let D=b.split("/");switch(y){case Je.IBAN:{if(D.length!==1&&D.length!==2)return fe.errorWithDetail(Qt.COMPONENTS_LENGTH,{targetType:y});let F=D.length===2?D[0]:void 0,B=D.length===1?D[0]:D[1],K=pm(B);return!g.ignoreComponentError&&K.tag==="error"?fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:0,targetType:y,error:K}):fe.of(R(B,F,x))}case Je.Bitcoin:{if(D.length!==1&&D.length!==2)return fe.errorWithDetail(Qt.COMPONENTS_LENGTH,{targetType:y});let F=D[0].toLocaleLowerCase(),B=Mr.decode(F,Mr.Encodings.BECH32);if(!g.ignoreComponentError&&fe.isError(B))return fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:0,targetType:y,error:B});let K=D.length===1?void 0:o(D[1]);return!g.ignoreComponentError&&K&&fe.isError(K)?fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:1,targetType:y,error:K}):fe.of(h(F,K!=null?fe.orUndefined(K):void 0,x))}case Je.TalerBank:{if(D.length<2)return fe.errorWithDetail(Qt.COMPONENTS_LENGTH,{targetType:y});let F=s(D[0],D.slice(1,-1).join("/"));if(!g.ignoreComponentError&&!F)return fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:0,targetType:y,error:F});let B=d(D[D.length-1]);return!g.ignoreComponentError&&!B?fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:1,targetType:y,error:B}):fe.of(S(F??D[0],B??D[1],x))}case Je.TalerReserve:{if(D.length<2)return fe.errorWithDetail(Qt.COMPONENTS_LENGTH,{targetType:y});let F=s(D[0],D.slice(1,-1).join("/"));if(!g.ignoreComponentError&&!F)return fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:0,targetType:y,error:F});let B=D[D.length-1],K=o(B);return!g.ignoreComponentError&&!fe.isOk(K)?fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:1,targetType:y,error:K}):fe.of(T(F??D[0],fe.isOk(K)?K.value:nr(B),x))}case Je.TalerReserveHttp:{if(D.length<2)return fe.errorWithDetail(Qt.COMPONENTS_LENGTH,{targetType:y});let F=s(D[0],D.slice(1,-1).join("/"),"http");if(!g.ignoreComponentError&&!F)return fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:0,targetType:y,error:F});let B=D[D.length-1],K=o(B);return!g.ignoreComponentError&&!fe.isOk(K)?fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:1,targetType:y,error:K}):fe.of(C(F??D[0],fe.isOk(K)?K.value:nr(B),x))}case Je.Ethereum:{if(D.length!==1)return fe.errorWithDetail(Qt.COMPONENTS_LENGTH,{targetType:y});let F=f(D[0]);return!g.ignoreComponentError&&!F?fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:0,targetType:y,error:F}):fe.of(p(F??D[0],x))}case Je.Cyclos:{if(D.length<2)return fe.errorWithDetail(Qt.COMPONENTS_LENGTH,{targetType:y});let F=s(D[0],D.slice(1,-1).join("/"));if(!g.ignoreComponentError&&!F)return fe.errorWithDetail(Qt.INVALID_TARGET_PATH,{pos:0,targetType:y,error:F});let B=D[D.length-1];return fe.of(A(F??D[0],B,x))}default:{if(g.allowUnsupported)return fe.of(w(y,b,x));ue(y)}}}e.fromString=v})($e||($e={}));function mm(){return{decode(e,t){if(typeof e!="string")throw new Rt(`expected string at ${ut(t)} but got ${typeof e}`);return e}}}function gm(){return{decode(e,t){if(typeof e!="string")throw new Rt(`expected string at ${ut(t)} but got ${typeof e}`);if(!e.startsWith(Da))throw new Rt(`expected start with payto at ${ut(t)} but got "${e}"`);return e}}}function xt(){return{decode(e,t){if(typeof e!="string")throw new Rt(`expected string at ${ut(t)} but got ${typeof e}`);if(!e.startsWith(Da))throw new Rt(`expected start with payto at ${ut(t)} but got "${e}"`);return e}}}function TA(e){return encodeURIComponent(e).replace(/[!'()*]/g,t=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`)}var hm=TA;function NA(e){return e.map(([t,r])=>`${hm(t)}=${hm(r)}`).join("&")}var ym;(function(e){function t(r,n){if(r.ciphern.cipher)return 1;if(r.cipher===Qr.Rsa&&n.cipher===Qr.Rsa)return(r.age_mask??0)<(n.age_mask??0)?-1:(r.age_mask??0)>(n.age_mask??0)?1:Fu(r.rsa_public_key,n.rsa_public_key);if(r.cipher===Qr.ClauseSchnorr&&n.cipher===Qr.ClauseSchnorr)return(r.age_mask??0)<(n.age_mask??0)?-1:(r.age_mask??0)>(n.age_mask??0)?1:Fu(r.cs_public_key,n.cs_public_key);throw Error("unsupported cipher")}e.cmp=t})(ym||(ym={}));var tk=He();var Qr;(function(e){e.Rsa="RSA",e.ClauseSchnorr="CS"})(Qr||(Qr={}));(function(e){function t(r){switch(r){case e.Rsa:return 1;case e.ClauseSchnorr:return 2}}e.toIntTag=t})(Qr||(Qr={}));var RA=()=>W().property("cipher",X(Qr.Rsa)).property("blinded_rsa_signature",L()).build("RsaBlindedDenominationSignature"),xA=()=>wt().discriminateOn("cipher").alternative(Qr.Rsa,RA()).build("BlindedDenominationSignature");var Ju=()=>W().property("ev_sigs",Ae(xA())).build("WithdrawResponse");var wm=()=>W().property("exchange_pub",Ft()).property("exchange_sig",Nr()).property("noreveal_index",ne()).property("refresh_base_url",U(L())).build("ExchangeMeltResponse");var Am=()=>W().property("purse_pub",L()).property("econtract_sig",L()).property("econtract",L()).build("ExchangeGetContractResponse"),Tm=()=>W().property("merge_amount",me()).property("exchange_timestamp",Me).property("exchange_sig",Nr()).property("exchange_pub",Ft()).build("ExchangeMergeSuccessResponse"),el=()=>W().property("total_deposited",me()).property("exchange_timestamp",Me).property("exchange_sig",Nr()).property("exchange_pub",Ft()).build("PurseCreateSuccessResponse"),Nm=()=>W().property("merge_timestamp",Me).property("merge_sig",Nr()).property("reserve_pub",Ft()).property("partner_url",U(L())).build("ExchangeMergeConflictResponse");var tl=()=>W().property("balance",me()).property("deposit_timestamp",U(Me)).property("merge_timestamp",U(Me)).build("ExchangePurseStatus");var xo;(function(e){e.TOPS="tops",e.GLS="gls",e.TESTING="testing"})(xo||(xo={}));var on;(function(e){e.withdraw="WITHDRAW",e.deposit="DEPOSIT",e.merge="MERGE",e.aggregate="AGGREGATE",e.balance="BALANCE",e.refund="REFUND",e.close="CLOSE",e.transaction="TRANSACTION"})(on||(on={}));var bm;(function(e){e[e.normal=0]="normal",e[e.pending=1]="pending",e[e.frozen=2]="frozen"})(bm||(bm={}));var IA=pt(X(xo.GLS),X(xo.TOPS),X(xo.TESTING)),Rm=()=>W().property("version",L()).property("name",X("taler-exchange")).property("implementation",U(Qh())).property("currency",L()).property("currency_specification",an()).property("supported_kyc_requirements",U(Ae(L()))).property("aml_spa_dialect",U(IA)).deprecatedProperty("shopping_url").deprecatedProperty("wallet_balance_limit_without_kyc").build("TalerExchangeApi.ExchangeVersionResponse"),xm=()=>W().property("version",L()).property("base_url",Tr()).property("currency",L()).property("accounts",He()).property("asset_type",He()).property("auditors",He()).property("currency_specification",He()).property("zero_limits",He()).property("hard_limits",He()).property("denominations",He()).property("exchange_pub",He()).property("exchange_sig",He()).property("extensions",He()).property("extensions_sig",He()).property("global_fees",He()).property("list_issue_date",He()).property("master_public_key",He()).property("recoup",He()).property("reserve_closing_delay",He()).property("signkeys",He()).property("stefan_abs",He()).property("stefan_lin",He()).property("stefan_log",He()).property("wads",He()).property("wallet_balance_limit_without_kyc",He()).property("wire_fees",He()).property("kyc_enabled",U(Se())).property("shopping_url",U(L())).property("tiny_amount",U(me())).property("disable_direct_deposit",U(Se())).property("bank_compliance_language",U(L())).property("open_banking_gateway",U(Tr())).deprecatedProperty("rewards_allowed").build("TalerExchangeApi.ExchangeKeysResponse"),Im=()=>W().property("statistics",Ae(SA())).build("TalerExchangeApi.AmlStatisticsResponse"),SA=()=>W().property("name",L()).property("counter",ne()).build("TalerExchangeApi.EventCounter"),Sm=()=>W().property("measures",Ae(CA())).build("TalerExchangeApi.LegitimizationMeasuresList"),CA=()=>W().property("h_payto",He()).property("rowid",He()).property("start_time",He()).property("measures",He()).property("is_finished",He()).build("TalerExchangeApi.LegitimizationMeasureDetails");var Cm=()=>W().property("checks",Ar(DA())).property("programs",Ar(OA())).property("roots",Ar(Om())).property("default_rules",Ae(Um())).build("TalerExchangeApi.AvailableMeasureSummary"),OA=()=>W().property("description",L()).property("context",Ae(L())).property("inputs",Ae(L())).build("TalerExchangeApi.AmlProgramRequirement"),DA=()=>W().property("description",L()).property("description_i18n",U(mr())).property("fallback",L()).property("outputs",Ae(L())).property("requires",Ae(L())).build("TalerExchangeApi.KycCheckInformation"),Om=()=>W().property("prog_name",U(L())).property("check_name",L()).property("context",He()).property("operation_type",U(rl)).property("voluntary",U(Se())).build("TalerExchangeApi.MeasureInformation"),Dm=()=>W().property("records",Ae(LA())).build("TalerExchangeApi.AmlDecisionsResponse"),PA=()=>W().property("h_payto",mm()).property("close_time",Me).property("open_time",Me).property("comments",U(L())).property("full_payto",gm()).property("high_risk",Se()).property("rowid",ne()).property("to_investigate",Se()).build("TalerExchangeApi.CustomerAccountSummary"),Pm=()=>W().property("accounts",Ae(PA())).build("TalerExchangeApi.AmlAccountsResponse");var LA=()=>W().property("h_payto",L()).property("full_payto",U(L())).property("rowid",ne()).property("is_wallet",Se()).property("justification",U(L())).property("decision_time",Me).property("properties",U(Lm())).property("limits",UA()).property("to_investigate",Se()).property("is_active",Se()).build("TalerExchangeApi.AmlDecision"),Lm=()=>W().property("pep",U(Se())).property("sanctioned",U(Se())).property("high_risk",U(Se())).property("business_domain",U(L())).property("is_frozen",U(Se())).property("was_reported",U(Se())).allowExtra().build("TalerExchangeApi.AccountProperties"),UA=()=>W().property("expiration_time",Me).property("successor_measure",U(L())).property("rules",Ae(Um())).property("custom_measures",Ar(Om())).build("TalerExchangeApi.LegitimizationRuleSet"),Um=()=>W().property("operation_type",rl).property("threshold",me()).property("timeframe",qt).property("measures",Ae(L())).property("display_priority",ne()).property("exposed",U(Se())).property("is_and_combinator",U(Se())).property("rule_name",U(L())).build("TalerExchangeApi.KycRule"),Mm=()=>W().property("details",Ae(MA())).build("TalerExchangeApi.KycAttributes"),MA=()=>W().property("rowid",ne()).property("provider_name",U(L())).property("collection_time",Me).property("attributes",U(He())).build("TalerExchangeApi.KycAttributeCollectionEvent"),km=()=>W().property("next_threshold",U(me())).property("expiration_time",Me).build("TalerExchangeApi.WalletKycCheckResponse"),Bi=()=>W().property("code",ne()).property("hint",U(L())).property("h_payto",L()).property("account_pub",U(Ft())).property("requirement_row",ne()).property("bad_kyc_auth",U(Se())).build("TalerExchangeApi.LegitimizationNeededResponse"),Io=()=>W().property("aml_review",Se()).property("access_token",Sa()).property("limits",U(Ae(nl()))).property("rule_gen",ne()).build("TalerExchangeApi.AccountKycStatus"),rl=pt(X(on.withdraw),X(on.deposit),X(on.merge),X(on.balance),X(on.close),X(on.aggregate),X(on.transaction),X(on.refund)),nl=()=>W().property("operation_type",rl).property("timeframe",qt).property("threshold",me()).property("soft_limit",U(Se())).property("rule_name",U(L())).build("TalerExchangeApi.AccountLimit");var kA=()=>L(),FA=()=>L(),vm=()=>W().property("form",pt(X("LINK"),X("INFO"),FA())).property("description",L()).property("context",U(He())).property("description_i18n",U(mr())).property("id",U(kA())).build("TalerExchangeApi.KycRequirementInformation"),al=()=>W().property("requirements",Bt(Ae(vm()),[])).property("is_and_combinator",U(Se())).property("voluntary_measures",U(Ae(vm()))).build("TalerExchangeApi.KycProcessClientInformation"),Wi=()=>W().property("transfers",Ae(HA())).build("TalerExchangeApi.ExchangeTransferList"),HA=()=>W().property("rowid",ne()).property("payto_uri",xt()).property("amount",me()).property("execution_time",Me).build("TalerExchangeApi.ExchangeTransferListEntry"),Fm=()=>W().property("redirect_url",Tr()).build("TalerExchangeApi.KycProcessStartInformation"),Em;(function(e){e.setup="SETUP",e.withdraw="WITHDRAW",e.ageWithdraw="AGEWITHDRAW",e.credit="CREDIT",e.closing="CLOSING",e.open="OPEN",e.close="CLOSE",e.merge="MERGE"})(Em||(Em={}));var ol=()=>wt().discriminateOn("code").alternative(G.EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,GA()).alternative(G.EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA,Gm()).alternative(G.EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA,Bm()).alternative(G.EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA,Wm()).build("PurseConflict"),Hm=()=>wt().discriminateOn("code").alternative(G.EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA,Gm()).alternative(G.EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA,Bm()).alternative(G.EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA,Wm()).build("PurseConflictPartial"),GA=()=>W().property("code",ne()).property("hint",L()).property("coin_pub",L()).build("DepositDoubleSpendError"),Gm=()=>W().property("code",ne()).property("amount",me()).property("min_age",ne()).property("purse_expiration",Me).property("purse_sig",L()).property("h_contract_terms",L()).property("merge_pub",L()).build("PurseCreateConflict"),Bm=()=>W().property("code",ne()).property("coin_pub",L()).property("partner_url",U(L())).property("amount",me()).build("PurseDepositConflict"),Wm=()=>W().property("code",ne()).property("h_econtract",L()).property("econtract_sig",L()).property("contract_pub",L()).build("PurseContractConflict");function xn(e){return wu(e)}var qA=!0,Wr;qA&&(Wr=globalThis._tart);var KA="0123456789ABCDEFGHJKMNPQRSTVWXYZ",cl=class e extends Error{constructor(){super("Encoding error"),Object.setPrototypeOf(this,e.prototype)}};function YA(e){let t=e;switch(e){case"O":case"o":t="0";break;case"i":case"I":case"l":case"L":t="1";break;case"u":case"U":t="V"}if(t>="0"&&t<="9")return t.charCodeAt(0)-48;t>="a"&&t<="z"&&(t=t.toUpperCase());let r=0;if(t>="A"&&t<="Z")return"I"0;){if(s>>o-5&31;r+=KA[c],o-=5}return r}function Vi(e,t,r,n){if(Wr)return Wr.kdf(e,t,r,n);r=r??new Uint8Array(64);let a=rm(r,t);n=n??new Uint8Array(0);let o=Math.ceil(e/32),s=new Uint8Array(o*32);for(let c=0;c0;){if(a=8;){let u=n>>>r-8&255;s[c++]=u,r-=8}a==t&&r>0&&(n=n<<8-r&255,r=n==0?0:8)}return s}function dl(e){return Wr?Wr.eddsaGetPublic(e):yi(e).publicKey}var il;function gr(e){return il||(il=new TextEncoder),il.encode(e)}function Vm(e){let t=0;for(let o of e)t+=o.byteLength;let r=new ArrayBuffer(t),n=new Uint8Array(r),a=0;for(let o of e)n.set(o,a),a+=o.byteLength;return n}function In(e){return Wr?Wr.hash(e):Ta(e)}function _m(e){return In(e).subarray(0,32)}var bk=new Dt("talerCrypto.ts");function fl(e,t){if(Wr)return Wr.eddsaSign(e,t);let r=yi(t);return rh(e,r.secretKey)}function Pa(e){let t=new ArrayBuffer(4),r=new Uint8Array(t);return new DataView(t).setUint32(0,e),r}function Qm(e){let t=new ArrayBuffer(8),r=new Uint8Array(t),n=new DataView(t);if(e<0||!Number.isInteger(e))throw Error("non-negative integer expected");return n.setBigUint64(0,BigInt(e)),r}var qm;(function(e){e[e.None=0]="None",e[e.MergeFullyPaidPurse=1]="MergeFullyPaidPurse",e[e.CreateFromPurseQuota=2]="CreateFromPurseQuota",e[e.CreateWithPurseFee=3]="CreateWithPurseFee"})(qm||(qm={}));var ll=class{constructor(t){this.purposeNum=t,this.chunks=[]}put(t){return this.chunks.push(Uint8Array.from(t)),this}build(){let t=0;for(let s of this.chunks)t+=s.byteLength;let r=new ArrayBuffer(8+t),n=new Uint8Array(r),a=8;for(let s of this.chunks)n.set(s,a),a+=s.byteLength;let o=new DataView(r);return o.setUint32(0,t+4+4),o.setUint32(4,this.purposeNum),n}};function Co(e){return new ll(e)}function zA(e,t){let r=new Uint8Array(t),n=e.toArray(256).value.reverse();return r.set(n,0),r}function Km(e){let t=new Uint8Array(e);return t=t.reverse(),So.default.fromArray(Array.from(t),256,!1)}var mn;(function(e){let t=[237,211,245,92,26,99,18,88,214,156,247,162,222,249,222,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16],r=So.default.fromArray(t.reverse(),256,!1);async function n(d){return Tu(d)}e.keyCreateFromSeed=n;async function a(){return ah()}e.keyCreate=a;async function o(d){return oh(d)}e.getPublic=o;function s(d,w){throw Error("not implemented")}e.sign=s;async function c(d,w){return ul({outputLength:64,ikm:d,salt:gr("edx25519-derivation"),info:w})}async function u(d,w){let R=await o(d),h=d,p=Km(h.subarray(0,32)),T=await c(R,w),A=Km(T).mod(r),C=p.divide(8).multiply(A).mod(r).multiply(8).mod(r),S=Ta(Vm([h.subarray(32,64),T])).subarray(0,32);return Vm([zA(C,32),S])}e.privateKeyDerive=u;async function f(d,w){let R=await c(d,w),h=nh(R);return Jp(h,d)}e.publicKeyDerive=f})(mn||(mn={}));function sl(e){if(!e)throw Error("invariant failed")}var Ym;(function(e){e.AGE_UNRESTRICTED=32;function t(h){let p=new hi;for(let T of h.publicKeys)p.update(nr(T));return gt(p.finish().subarray(0,32))}e.hashCommitment=t;function r(h){let p=0,T=h;for(;T>0;)p+=T&1,T=T>>1;return p}e.countAgeGroups=r;function n(h){let p=[],T=1,A=h>>1;for(;A>0;)A&1&&p.push(T),A=A>>1,T++;return p}e.getAgeGroupsFromMask=n;function a(h,p){sl((h&1)===1);let T=0,A=h,C=p;for(;A>0&&!(C<=0);)A=A>>1,T+=A&1,C--;return T}e.getAgeGroupIndex=a;function o(h){throw Error("not implemented")}e.ageGroupSpecToMask=o;async function s(h,p){sl((h&1)===1);let T=r(h)-1,A=a(h,p),C=[],S=[];for(let k=0;kgt(k))},proof:{privateKeys:S.map(k=>gt(k))}}}e.restrictionCommit=s;let c=nr("CH0VKFDZ2GWRWHQBBGEK9MWV5YDQVJ0RXEE0KYT3NMB69F0R96TG");async function u(h,p,T){sl((h&1)===1);let A=r(h)-1,C=a(h,p),S=[],k=[];for(let v=0;vgt(v))},proof:{privateKeys:k.map(v=>gt(v))}}}e.restrictionCommitSeeded=u;async function f(h,p,T){if(h.publicKeys.length!=p.publicKeys.length)return!1;for(let A=0;Agt(C))},proof:{privateKeys:T.map(C=>gt(C))}}}e.commitmentDerive=d;function w(h,p){let T=Co(Bn.WALLET_AGE_ATTESTATION).put(Pa(h.commitment.mask)).put(Pa(p)).build(),A=a(h.commitment.mask,p);if(A===0)return new Uint8Array(64);let C=h.proof.privateKeys[A-1],S=h.commitment.publicKeys[A-1];return ih(T,nr(C),nr(S))}e.commitmentAttest=w;function R(h,p,T){let A=Co(Bn.WALLET_AGE_ATTESTATION).put(Pa(h.mask)).put(Pa(T)).build(),C=a(h.mask,T);if(C===0)return!0;let S=h.publicKeys[C-1];return sh(A,nr(p),nr(S))}e.commitmentVerify=R})(Ym||(Ym={}));var zm;(function(e){e[e.PaymentOffer=0]="PaymentOffer",e[e.PaymentRequest=1]="PaymentRequest"})(zm||(zm={}));var $m=2n**64n-1n;function pl(e){let t=new ArrayBuffer(8),r=new DataView(t),n=e.t_s==="never"?$m:BigInt(e.t_s)*1000n*1000n;if(typeof r.setBigUint64<"u")r.setBigUint64(0,n);else{let o=(e.t_s==="never"?(0,So.default)($m):(0,So.default)(e.t_s).multiply(1e6)).toArray(2**8).value,s=8-o.length;for(let c=0;cPromise.resolve()};var Ik=new Dt("bank-api-client.ts"),Zm;(function(e){e.Credit="credit",e.Debit="debit"})(Zm||(Zm={}));function pg(){return{decode(e,t){if(typeof e=="string"){let r=ia(e);if(e!==r)throw new Rt(`expected canonicalized base URL at ${ut(t)} but got value '${e}'`);return e}throw new Rt(`expected base URL at ${ut(t)} but got type ${typeof e}`)}}}var Jm;(function(e){e.Global="global",e.Exchange="exchange",e.Auditor="auditor"})(Jm||(Jm={}));var qi;(function(e){e.Effective="effective",e.Raw="raw"})(qi||(qi={}));var Bk=W().property("amount",me()).property("depositPaytoUri",xt()).property("type",pt(X(qi.Raw),X(qi.Effective))).build("ConvertAmountRequest");var eg;(function(e){e.IncomingKyc="incoming-kyc",e.IncomingAml="incoming-aml",e.IncomingConfirmation="incoming-confirmation",e.OutgoingKyc="outgoing-kyc"})(eg||(eg={}));var tg;(function(e){e.Fresh="fresh",e.DenomLoss="denom-loss",e.FreshSuspended="fresh-suspended",e.Dormant="dormant"})(tg||(tg={}));var rg;(function(e){e.Done="done",e.Pending="pending"})(rg||(rg={}));var Vr=()=>W().property("code",ne()).property("when",U(Br)).property("hint",U(L())).build("TalerErrorDetail");var ng;(function(e){e.PaymentPossible="payment-possible",e.InsufficientBalance="insufficient-balance",e.AlreadyConfirmed="already-confirmed",e.ChoiceSelection="choice-selection"})(ng||(ng={}));var ag;(function(e){e.MerchantAcceptInsufficient="merchant-accept-insufficient",e.MerchantDepositInsufficient="merchant-deposit-insufficient",e.AgeRestricted="age-restricted",e.WalletBalanceMaterialInsufficient="wallet-balance-material-insufficient",e.WalletBalanceAvailableInsufficient="wallet-balance-available-insufficient",e.ExchangeMissingGlobalFees="exchange-missing-global-fees",e.FeesNotCovered="fees-not-covered"})(ag||(ag={}));var og;(function(e){e.WalletTokensAvailableInsufficient="wallet-tokens-available-insufficient",e.MerchantUnexpected="merchant-unexpected",e.MerchantUntrusted="merchant-untrusted"})(og||(og={}));var Ki;(function(e){e.Manual="manual",e.PayMerchant="pay-merchant",e.PayDeposit="pay-deposit",e.PayPeerPush="pay-peer-push",e.PayPeerPull="pay-peer-pull",e.Refund="refund",e.AbortPay="abort-pay",e.AbortDeposit="abort-deposit",e.AbortPeerPushDebit="abort-peer-push-debit",e.AbortPeerPullDebit="abort-peer-pull-debit",e.Recoup="recoup",e.BackupRestored="backup-restored",e.Scheduled="scheduled"})(Ki||(Ki={}));var ig;(function(e){e.Pending="pending",e.Proposed="proposed",e.Accepted="accepted",e.MissingTos="missing-tos"})(ig||(ig={}));var sg;(function(e){e.Preset="preset",e.Ephemeral="ephemeral",e.Used="used"})(sg||(sg={}));var cg;(function(e){e.Initial="initial",e.InitialUpdate="initial-update",e.Suspended="suspended",e.UnavailableUpdate="unavailable-update",e.Ready="ready",e.ReadyUpdate="ready-update",e.OutdatedUpdate="outdated-update"})(cg||(cg={}));var ug;(function(e){e.Done="done",e.LegiInit="legi-init",e.Legi="legi"})(ug||(ug={}));var lg;(function(e){e.PaymentPossible="payment-possible",e.InsufficientBalance="insufficient-balance"})(lg||(lg={}));var dg;(function(e){e.Ours="ours",e.Theirs="theirs"})(dg||(dg={}));var Yi=()=>W().build("EmptyObject");var fg;(function(e){e.MeltGone="melt-gone",e.WithdrawalRedenominate="withdrawal-redenominate"})(fg||(fg={}));var qr;(function(e){e[e.V0=0]="V0",e[e.V1=1]="V1"})(qr||(qr={}));var zi;(function(e){e.Token="token"})(zi||(zi={}));var La;(function(e){e.Token="token",e.TaxReceipt="tax-receipt"})(La||(La={}));var Cn;(function(e){e.Subscription="subscription",e.Discount="discount"})(Cn||(Cn={}));var Ua=()=>W().property("country",U(L())).property("country_subdivision",U(L())).property("building_name",U(L())).property("building_number",U(L())).property("district",U(L())).property("street",U(L())).property("post_code",U(L())).property("town",U(L())).property("town_location",U(L())).property("address_lines",U(Ae(L()))).build("Location"),yg=()=>W().property("name",L()).property("address",U(Ua())).property("jurisdiction",U(Ua())).build("MerchantInfo"),bg=()=>W().property("order_id",L()).property("fulfillment_url",U(L())).property("fulfillment_message",U(L())).property("fulfillment_message_i18n",U(mr())).property("public_reorder_url",U(L())).property("merchant_base_url",L()).property("h_wire",L()).property("auto_refund",U(qt)).property("wire_method",L()).property("summary",L()).property("summary_i18n",U(mr())).property("nonce",L()).property("pay_deadline",Me).property("refund_deadline",Me).property("wire_transfer_deadline",Me).property("timestamp",Me).property("delivery_location",U(Ua())).property("delivery_date",U(Me)).property("merchant",yg()).property("merchant_pub",L()).property("exchanges",Ae(ST())).property("products",U(Ae(MT()))).property("extra",He()).property("minimum_age",U(ne())).property("default_money_pot",U(ne())).build("TalerMerchantApi.ContractTermsCommon"),hl=()=>W().property("version",U(vo(qr.V0))).property("amount",me()).property("max_fee",me()).mixin(bg()).build("TalerMerchantApi.ContractTermsV0"),XA=()=>W().property("version",vo(qr.V1)).property("choices",Ae(jA())).property("token_families",Ar(rT())).mixin(bg()).build("TalerMerchantApi.ContractTermsV1"),ml=()=>wt().discriminateOn("version").alternative(void 0,hl()).alternative(qr.V0,hl()).alternative(qr.V1,XA()).build("TalerMerchantApi.ContractTerms"),jA=()=>W().property("amount",me()).property("description",U(L())).property("description_i18n",U(mr())).property("inputs",Ae(QA())).property("outputs",Ae(JA())).property("max_fee",me()).build("TalerMerchantApi.ContractChoice"),QA=()=>wt().discriminateOn("type").alternative(zi.Token,ZA()).build("TalerMerchantApi.ContractInput"),ZA=()=>W().property("type",X(zi.Token)).property("token_family_slug",L()).property("count",U(ne())).build("TalerMerchantApi.ContractInputToken"),JA=()=>wt().discriminateOn("type").alternative(La.Token,eT()).alternative(La.TaxReceipt,tT()).build("TalerMerchantApi.ContractOutput"),eT=()=>W().property("type",X(La.Token)).property("token_family_slug",L()).property("count",U(ne())).property("key_index",ne()).build("TalerMerchantApi.ContractOutputToken"),tT=()=>W().property("type",X(La.TaxReceipt)).property("donau_urls",Ae(L())).property("amount",U(me())).build("TalerMerchantApi.ContractOutputTaxReceipt"),rT=()=>W().property("name",L()).property("description",L()).property("description_i18n",U(mr())).property("keys",Ae(nT())).property("details",iT()).property("critical",Se()).build("TalerMerchantApi.ContractTokenFamily"),nT=()=>wt().discriminateOn("cipher").alternative("RSA",aT()).alternative("CS",oT()).build("TalerMerchantApi.TokenIssuePublicKey"),aT=()=>W().property("cipher",X("RSA")).property("rsa_pub",L()).property("signature_validity_start",Me).property("signature_validity_end",Me).build("TalerMerchantApi.TokenIssueRsaPublicKey"),oT=()=>W().property("cipher",X("CS")).property("cs_pub",L()).property("signature_validity_start",Me).property("signature_validity_end",Me).build("TalerMerchantApi.TokenIssueRsaPublicKey"),iT=()=>wt().discriminateOn("class").alternative(Cn.Subscription,sT()).alternative(Cn.Discount,cT()).build("TalerMerchantApi.ContractTokenDetails"),sT=()=>W().property("class",X(Cn.Subscription)).property("trusted_domains",Ae(L())).build("TalerMerchantApi.ContractSubscriptionTokenDetails"),cT=()=>W().property("class",X(Cn.Discount)).property("expected_domains",Ae(L())).build("TalerMerchantApi.ContractDiscountTokenDetails"),sn;(function(e){e.NONE="NONE",e.SECOND="SECOND",e.MINUTE="MINUTE",e.HOUR="HOUR",e.DAY="DAY",e.WEEK="WEEK",e.MONTH="MONTH",e.QUARTER="QUARTER",e.YEAR="YEAR"})(sn||(sn={}));var hg;(function(e){e[e.AUTH_TRANSFER=1]="AUTH_TRANSFER",e[e.AML_INVESTIGATION=2]="AML_INVESTIGATION",e[e.TO_BE_OK=3]="TO_BE_OK"})(hg||(hg={}));var Ir;(function(e){e.ReadOnly="readonly",e.All="all",e.Spa="spa",e.OrderSimple="order-simple",e.OrderPos="order-pos",e.OrderManagement="order-mgmt",e.OrderFull="order-full",e.ReadOnly_Refreshable="readonly:refreshable",e.All_Refreshable="all:refreshable",e.Spa_Refreshable="spa:refreshable",e.OrderSimple_Refreshable="order-simple:refreshable",e.OrderPos_Refreshable="order-pos:refreshable",e.OrderManagement_Refreshable="order-mgmt:refreshable",e.OrderFull_Refreshable="order-full:refreshable"})(Ir||(Ir={}));var gl;(function(e){e.TOKEN="token"})(gl||(gl={}));var kr;(function(e){e.NO_EXCHANGE_KEY="no-exchange-keys",e.UNSUPPORTED_ACCOUNT="unsupported-account",e.KYC_WIRE_IMPOSSIBLE="kyc-wire-impossible",e.KYC_WIRE_REQUIRED="kyc-wire-required",e.KYC_REQUIRED="kyc-required",e.AWAITING_AML_REVIEW="awaiting-aml-review",e.READY="ready",e.LOGIC_BUG="logic-bug",e.MERCHANT_INTERNAL_ERROR="merchant-internal-error",e.EXCHANGE_INTERNAL_ERROR="exchange-internal-error",e.EXCHANGE_GATEWAY_TIMEOUT="exchange-gateway-timeout",e.EXCHANGE_UNREACHABLE="exchange-unreachable",e.EXCHANGE_STATUS_INVALID="exchange-status-invalid"})(kr||(kr={}));var mg;(function(e){e[e.OK=0]="OK",e[e.ACTION_REQUIRED=100]="ACTION_REQUIRED",e[e.WARNING=200]="WARNING",e[e.ERROR=300]="ERROR"})(mg||(mg={}));var cn;(function(e){e.FIXED_ORDER="fixed-order",e.INVENTORY_CART="inventory-cart",e.PAIVANA="paivana"})(cn||(cn={}));var $i;(function(e){e.Discount="discount",e.Subscription="subscription"})($i||($i={}));var Sn;(function(e){e.Hour="hour",e.Day="day",e.Week="week",e.Month="month",e.Quarter="quarter",e.Year="year"})(Sn||(Sn={}));var Xi;(function(e){e.Token="token"})(Xi||(Xi={}));var Ma;(function(e){e.Token="token",e.TaxReceipt="tax-receipt"})(Ma||(Ma={}));var gg;(function(e){e[e.V0=0]="V0",e[e.V1=1]="V1"})(gg||(gg={}));var vg=()=>W().property("exchanges",Ae(uT())).build("TalerMerchantApi.ExchangeStatusResponse"),uT=()=>W().property("exchange_url",pg()).property("next_download",Me).property("keys_expiration",U(Me)).property("keys_http_status",ne()).property("keys_ec",ne()).property("keys_hint",L()).build("TalerMerchantApi.ExchangeStatusDetail"),lT=()=>W().property("base_url",L()).property("currency",L()).property("master_pub",Ft()).build("TalerMerchantApi.ExchangeConfigInfo"),Eg=()=>W().property("name",X("taler-merchant")).property("currency",L()).property("default_persona",Bt(pt(X("expert"),X("offline-vending-machine"),X("point-of-sale"),X("digital-publishing"),X("e-commerce")),"expert")).property("version",L()).property("currencies",Ar(an())).property("report_generators",Bt(Ae(L()),[])).property("phone_regex",U(L())).property("exchanges",Ae(lT())).property("implementation",U(L())).property("have_self_provisioning",Bt(Se(),!1)).property("have_donau",Bt(Se(),!1)).property("mandatory_tan_channels",Bt(Ae(pt(X(Sr.SMS),X(Sr.EMAIL))),[])).property("default_pay_delay",U(qt)).property("default_refund_delay",U(qt)).property("default_wire_transfer_delay",U(qt)).property("payment_target_regex",Bt(L(),"*")).property("payment_target_types",Bt(L(),"*")).property("default_wire_transfer_rounding_interval",U(wg)).build("TalerMerchantApi.VersionResponse"),wg=pt(X(sn.NONE),X(sn.SECOND),X(sn.MINUTE),X(sn.HOUR),X(sn.DAY),X(sn.WEEK),X(sn.MONTH),X(sn.QUARTER),X(sn.YEAR)),Ag=()=>W().property("contract_terms",He()).property("sig",Nr()).build("TalerMerchantApi.ClaimResponse"),Tg=()=>W().property("pos_confirmation",U(L())).property("sig",Nr()).build("TalerMerchantApi.PaymentResponse"),Oo=()=>W().property("exchange_base_urls",Bt(Ae(L()),[])).build("TalerMerchantApi.PaymentDeniedLegallyResponse"),Ng=()=>W().property("refund_amount",me()).property("refund_pending",Se()).property("refund_taken",me()).property("refunded",Se()).property("type",X("paid")).build("TalerMerchantApi.StatusPaid"),Rg=()=>W().property("public_reorder_url",Tr()).property("type",X("goto")).build("TalerMerchantApi.StatusGotoResponse"),xg=()=>W().property("type",X("unpaid")).property("already_paid_order_id",U(L())).property("fulfillment_url",U(L())).property("taler_pay_uri",ka()).build("TalerMerchantApi.PaymentResponse"),Ig=()=>W().property("pos_confirmation",U(L())).property("refunded",Se()).build("TalerMerchantApi.PaidRefundStatusResponse"),dT=()=>W().property("exchange_pub",L()).property("exchange_sig",L()).property("exchange_status",vo(200)).property("type",X("success")).build("TalerMerchantApi.MerchantAbortPayRefundSuccessStatus"),fT=()=>W().property("exchange_code",ne()).property("exchange_reply",He()).property("exchange_status",ne()).property("type",X("failure")).build("TalerMerchantApi.MerchantAbortPayRefundFailureStatus"),pT=()=>W().property("type",X("undeposited")).build("TalerMerchantApi.MerchantAbortPayRefundUndepositedStatus"),hT=()=>wt().discriminateOn("type").alternative("success",dT()).alternative("failure",fT()).alternative("undeposited",pT()).build("TalerMerchantApi.MerchantAbortPayRefundStatus"),Sg=()=>W().property("refunds",Ae(hT())).build("TalerMerchantApi.AbortResponse"),Cg=()=>W().property("merchant_pub",Ft()).property("refund_amount",me()).property("refunds",Ae(_T())).build("TalerMerchantApi.AbortResponse"),mT=()=>W().property("type",X("success")).property("coin_pub",Ft()).property("exchange_status",vo(200)).property("exchange_sig",Nr()).property("rtransaction_id",ne()).property("refund_amount",me()).property("exchange_pub",Ft()).property("execution_time",Me).build("TalerMerchantApi.MerchantCoinRefundSuccessStatus"),gT=()=>W().property("type",X("failure")).property("coin_pub",Ft()).property("exchange_status",ne()).property("rtransaction_id",ne()).property("refund_amount",me()).property("exchange_code",U(ne())).property("exchange_reply",U(He())).property("execution_time",Me).build("TalerMerchantApi.MerchantCoinRefundFailureStatus"),_T=()=>wt().discriminateOn("type").alternative("success",mT()).alternative("failure",gT()).build("TalerMerchantApi.MerchantCoinRefundStatus"),yT=pt(X(gl.TOKEN)),Og=()=>W().property("name",L()).property("email",U(L())).property("phone_number",U(L())).property("website",U(L())).property("email_validated",U(Se())).property("phone_validated",U(Se())).property("logo",U(L())).property("merchant_pub",Ft()).property("address",Ua()).property("jurisdiction",Ua()).property("use_stefan",Se()).property("default_wire_transfer_delay",qt).property("default_pay_delay",qt).property("default_refund_delay",qt).property("default_wire_transfer_rounding_interval",U(wg)).property("auth",W().property("method",yT).build("TalerMerchantApi.QueryInstancesResponse.auth")).build("TalerMerchantApi.QueryInstancesResponse"),Dg=()=>W().property("kyc_data",Ae(vT())).build("TalerMerchantApi.MerchantAccountKycRedirectsResponse"),bT=pt(X(kr.AWAITING_AML_REVIEW),X(kr.UNSUPPORTED_ACCOUNT),X(kr.EXCHANGE_GATEWAY_TIMEOUT),X(kr.EXCHANGE_INTERNAL_ERROR),X(kr.EXCHANGE_STATUS_INVALID),X(kr.EXCHANGE_UNREACHABLE),X(kr.KYC_REQUIRED),X(kr.KYC_WIRE_IMPOSSIBLE),X(kr.KYC_WIRE_REQUIRED),X(kr.LOGIC_BUG),X(kr.NO_EXCHANGE_KEY),X(kr.READY)),vT=()=>W().property("status",bT).property("h_wire",L()).property("payto_uri",xt()).property("exchange_url",Tr()).property("exchange_currency",U(L())).property("exchange_http_status",ne()).property("no_keys",Se()).property("auth_conflict",Se()).property("exchange_code",U(ne())).property("access_token",U(Sa())).property("limits",U(Ae(nl()))).property("payto_kycauths",U(Ae(L()))).build("TalerMerchantApi.MerchantAccountKycRedirect"),ET=pt(X(Ir.All),X(Ir.Spa),X(Ir.OrderFull),X(Ir.OrderManagement),X(Ir.OrderPos),X(Ir.OrderSimple),X(Ir.ReadOnly),X(Ir.All_Refreshable),X(Ir.Spa_Refreshable),X(Ir.OrderFull_Refreshable),X(Ir.OrderManagement_Refreshable),X(Ir.OrderPos_Refreshable),X(Ir.OrderSimple_Refreshable),X(Ir.ReadOnly_Refreshable)),Pg=()=>W().property("scope",ET).property("access_token",Sa()).property("expiration",Me).property("refreshable",Se()).build("TalerMerchantApi.LoginTokenSuccessResponse");var Lg=()=>W().property("h_wire",L()).property("salt",L()).build("TalerMerchantApi.AccountAddResponse"),Ug=()=>W().property("accounts",Ae(wT())).build("TalerMerchantApi.AccountsSummaryResponse"),wT=()=>W().property("payto_uri",xt()).property("h_wire",L()).property("active",U(Se())).build("TalerMerchantApi.BankAccountEntry"),Mg=()=>W().property("payto_uri",xt()).property("h_wire",L()).property("extra_wire_subject_metadata",U(L())).property("salt",L()).property("credit_facade_url",U(Tr())).property("active",U(Se())).build("TalerMerchantApi.BankAccountEntry"),kg=()=>W().property("categories",Ae(AT())).build("TalerMerchantApi.CategoryListResponse"),AT=()=>W().property("category_id",ne()).property("name",L()).property("name_i18n",mr()).property("product_count",ne()).build("TalerMerchantApi.CategoryListEntry"),Fg=()=>W().property("name",L()).property("name_i18n",mr()).property("products",Ae(TT())).build("TalerMerchantApi.CategoryProductList"),TT=()=>W().property("product_id",L()).build("TalerMerchantApi.CategoryProductSummary"),Hg=()=>W().property("products",Ae(NT())).build("TalerMerchantApi.InventorySummaryResponse"),NT=()=>W().property("product_id",L()).property("product_serial",ne()).build("TalerMerchantApi.InventoryEntry"),RT=()=>W().property("product_serial",ne()).property("product_id",U(L())).property("product_name",U(L())).property("categories",Ae(ne())).property("description",L()).property("description_i18n",mr()).property("unit",L()).property("price",me()).property("image",L()).property("taxes",U(Ae(_l()))).property("total_stock",ne()).property("minimum_age",U(ne())).build("TalerMerchantApi.MerchantPosProductDetail"),xT=()=>W().property("id",ne()).property("name",L()).property("name_i18n",mr()).build("TalerMerchantApi.MerchantCategory"),Gg=()=>W().property("categories",Ae(xT())).property("products",Ae(RT())).build("TalerMerchantApi.FullInventoryDetailsResponse"),Bg=()=>W().property("description",L()).property("description_i18n",mr()).property("unit",L()).property("product_name",U(L())).property("price",me()).property("image",L()).property("categories",Ae(ne())).property("taxes",U(Ae(_l()))).property("address",U(Ua())).property("next_restock",U(Me)).property("total_stock",ne()).property("total_sold",ne()).property("total_lost",ne()).property("minimum_age",U(ne())).property("money_pot_id",U(ne())).property("product_group_id",U(ne())).build("TalerMerchantApi.ProductDetailResponse"),_l=()=>W().property("name",L()).property("tax",me()).build("TalerMerchantApi.Tax"),Wg=()=>W().property("order_id",L()).property("pay_deadline",U(Me)).property("token",U(L())).build("TalerMerchantApi.PostOrderResponse"),Vg=()=>W().property("product_id",L()).property("available_quantity",ne()).property("requested_quantity",ne()).property("unit_available_quantity",L()).property("unit_requested_quantity",L()).property("restock_expected",U(Me)).build("TalerMerchantApi.OutOfStockResponse"),qg=()=>W().property("orders",Ae(IT())).build("TalerMerchantApi.OrderHistory"),IT=()=>W().property("order_id",L()).property("row_id",ne()).property("timestamp",Me).property("amount",me()).property("refund_amount",U(me())).property("pending_refund_amount",U(me())).property("summary",L()).property("refundable",Se()).property("paid",Se()).build("TalerMerchantApi.OrderHistoryEntry");var ST=()=>W().property("master_pub",Ft()).property("priority",ne()).property("url",L()).property("max_contribution",U(me())).build("TalerMerchantApi.Exchange");var CT=()=>W().property("amount",me()).property("description",U(L())).property("description_i18n",U(mr())).property("max_fee",U(me())).property("inputs",U(Ae(OT()))).property("outputs",U(Ae(PT()))).build("TalerMerchantApi.OrderChoice"),OT=()=>wt().discriminateOn("type").alternative(Xi.Token,DT()).build("TalerMerchantApi.OrderInput"),DT=()=>W().property("type",X(Xi.Token)).property("token_family_slug",L()).property("count",U(ne())).build("TalerMerchantApi.OrderInputToken"),PT=()=>wt().discriminateOn("type").alternative(Ma.Token,LT()).alternative(Ma.TaxReceipt,UT()).build("TalerMerchantApi.OrderOutput"),LT=()=>W().property("type",X(Ma.Token)).property("token_family_slug",L()).property("count",U(ne())).property("valid_at",U(Ku)).build("TalerMerchantApi.OrderOutputToken"),UT=()=>W().property("type",X(Ma.TaxReceipt)).property("amount",U(me())).property("donau_urls",Ae(ca())).build("TalerMerchantApi.OrderOutputTaxReceipt"),MT=()=>W().property("product_id",U(L())).property("product_name",U(L())).property("description",L()).property("description_i18n",U(mr())).property("quantity",U(ne())).property("unit",U(L())).property("price",U(me())).property("image",U(L())).property("taxes",U(Ae(_l()))).property("delivery_date",U(Me)).property("product_money_pot",U(ne())).build("TalerMerchantApi.Product"),kT=()=>W().property("order_status",X("paid")).property("refunded",Se()).property("refund_pending",Se()).property("wired",Se()).property("deposit_total",me()).property("exchange_code",ne()).property("exchange_http_status",ne()).property("refund_amount",me()).property("contract_terms",ml()).property("choice_index",U(ne())).property("last_payment",Me).property("wire_reports",Ae(WT())).property("wire_details",Ae(BT())).property("refund_details",Ae(GT())).property("order_status_url",Tr()).build("TalerMerchantApi.CheckPaymentPaidResponse"),FT=()=>W().property("order_status",X("unpaid")).property("taler_pay_uri",ka()).property("creation_time",Me).property("pay_deadline",U(Me)).property("summary",L()).property("total_amount",U(me())).property("already_paid_order_id",U(L())).property("already_paid_fulfillment_url",U(L())).property("order_status_url",L()).build("TalerMerchantApi.CheckPaymentUnpaidResponse"),HT=()=>W().property("order_status",X("claimed")).property("contract_terms",ml()).property("order_status_url",L()).build("TalerMerchantApi.CheckPaymentClaimedResponse"),Kg=()=>wt().discriminateOn("order_status").alternative("paid",kT()).alternative("unpaid",FT()).alternative("claimed",HT()).build("TalerMerchantApi.MerchantOrderStatusResponse"),yl=()=>W().property("order_id",L()).build("TalerMerchantApi.GetSessionStatusPaidResponse");var GT=()=>W().property("reason",L()).property("pending",Se()).property("timestamp",Me).property("amount",me()).build("TalerMerchantApi.RefundDetails"),BT=()=>W().property("exchange_url",Tr()).property("wtid",L()).property("execution_time",Me).property("amount",me()).property("deposit_fee",me()).property("confirmed",Se()).property("expected_transfer_serial_id",U(ne())).build("TalerMerchantApi.TransactionWireTransfer"),WT=()=>W().property("code",ne()).property("hint",L()).property("exchange_code",ne()).property("exchange_http_status",ne()).property("coin_pub",Ft()).build("TalerMerchantApi.TransactionWireReport"),Yg=()=>W().property("taler_refund_uri",ka()).property("h_contract",L()).build("TalerMerchantApi.MerchantRefundResponse"),zg=()=>W().property("transfers",Ae(qT())).build("TalerMerchantApi.TransferList"),$g=()=>W().property("incoming",Ae(KT())).build("TalerMerchantApi.ExpectedTransferList"),VT=()=>W().property("deposit_fee",me()).property("order_id",L()).property("remaining_deposit",me()).build("TalerMerchantApi.ExchangeTransferReconciliationDetails"),Xg=()=>W().property("reconciliation_details",Ae(VT())).property("wire_fee",me()).build("TalerMerchantApi.ExpectedTransferDetails"),qT=()=>W().property("credit_amount",me()).property("wtid",L()).property("payto_uri",xt()).property("exchange_url",Tr()).property("transfer_serial_id",ne()).property("execution_time",U(Me)).property("expected",U(Se())).build("TalerMerchantApi.TransferDetails"),KT=()=>W().property("expected_credit_amount",U(me())).property("wtid",L()).property("payto_uri",xt()).property("exchange_url",Tr()).property("expected_transfer_serial_id",U(ne())).property("execution_time",U(Me)).property("validated",Se()).property("confirmed",Se()).property("last_http_status",ne()).property("last_ec",ne()).property("last_error_detail",U(He())).build("TalerMerchantApi.ExpectedTransferDetails"),jg=()=>W().property("otp_devices",Ae(YT())).build("TalerMerchantApi.OtpDeviceSummaryResponse"),YT=()=>W().property("otp_device_id",L()).property("device_description",L()).build("TalerMerchantApi.OtpDeviceEntry"),Qg=()=>W().property("device_description",L()).property("otp_algorithm",ne()).property("otp_ctr",U(ne())).property("otp_timestamp",ne()).property("otp_code",U(L())).build("TalerMerchantApi.OtpDeviceDetails"),Zg=()=>W().property("templates",Ae(zT())).build("TalerMerchantApi.TemplateSummaryResponse"),zT=()=>W().property("template_id",L()).property("template_description",L()).build("TalerMerchantApi.TemplateEntry"),Jg=()=>W().property("template_description",L()).property("otp_id",U(L())).property("template_contract",e_()).property("editable_defaults",U(t_())).build("TalerMerchantApi.TemplateDetails"),$T=()=>W().property("choices",Ae(CT())).property("website_regex",U(L())).property("currency",U(L())).property("max_pickup_duration",U(qt)).property("minimum_age",U(ne())).property("pay_duration",U(qt)).property("request_tip",U(Se())).property("summary",U(L())).property("template_type",X(cn.PAIVANA)).build("TalerMerchantApi.TemplateContractPaivana"),XT=()=>W().property("choose_one",U(Se())).property("selected_all",U(Se())).property("selected_categories",Bt(Ae(ne()),[])).property("selected_products",Bt(Ae(L()),[])).property("inventory_payload",U(He())).property("currency",U(L())).property("max_pickup_duration",U(qt)).property("minimum_age",U(ne())).property("pay_duration",U(qt)).property("request_tip",U(Se())).property("summary",U(L())).property("template_type",Bt(X(cn.INVENTORY_CART),cn.INVENTORY_CART)).build("TalerMerchantApi.TemplateContractInventoryCart"),_g=()=>W().property("amount",U(me())).property("currency",U(L())).property("max_pickup_duration",U(qt)).property("minimum_age",U(ne())).property("pay_duration",U(qt)).property("request_tip",U(Se())).property("summary",U(L())).property("template_type",Bt(X(cn.FIXED_ORDER),cn.FIXED_ORDER)).build("TalerMerchantApi.TemplateContractFixedOrder"),e_=()=>wt().discriminateOn("template_type").alternative(cn.FIXED_ORDER,_g()).alternative(cn.INVENTORY_CART,XT()).alternative(cn.PAIVANA,$T()).alternativeOnMissing(cn.FIXED_ORDER,_g()).build("TalerMerchantApi.TemplateContractDetails"),t_=()=>W().property("summary",U(L())).property("currency",U(L())).property("amount",U(me())).allowExtra().build("TalerMerchantApi.TemplateContractDetailsDefaults"),r_=()=>W().property("template_contract",e_()).property("editable_defaults",U(t_())).build("TalerMerchantApi.WalletTemplateDetails"),n_=()=>W().property("webhooks",Ae(jT())).build("TalerMerchantApi.WebhookSummaryResponse"),jT=()=>W().property("webhook_id",L()).property("event_type",L()).build("TalerMerchantApi.WebhookEntry"),a_=()=>W().property("event_type",L()).property("url",L()).property("http_method",L()).property("header_template",U(L())).property("body_template",U(L())).build("TalerMerchantApi.WebhookDetails"),o_=pt(X($i.Discount),X($i.Subscription)),bl=()=>W().property("slug",L()).property("name",L()).property("description",L()).property("description_i18n",U(mr())).property("valid_after",Me).property("valid_before",Me).property("duration",qt).property("kind",o_).property("issued",ne()).property("used",ne()).build("TalerMerchantApi.TokenFamilyDetails"),i_=()=>W().property("token_families",Ae(QT())).build("TalerMerchantApi.TokenFamiliesList"),QT=()=>W().property("slug",L()).property("name",L()).property("description",L()).property("description_i18n",mr()).property("valid_after",Me).property("valid_before",Me).property("kind",o_).build("TalerMerchantApi.TokenFamilySummary"),Xk=pt(X(Sn.Day),X(Sn.Hour),X(Sn.Day),X(Sn.Week),X(Sn.Month),X(Sn.Quarter),X(Sn.Year));var Sr;(function(e){e.SMS="sms",e.EMAIL="email"})(Sr||(Sr={}));var ZT=()=>W().property("challenge_id",L()).property("tan_channel",pt(X(Sr.SMS),X(Sr.EMAIL))).property("tan_info",L()).build("MFA.Challenge"),Or=()=>W().property("challenges",Ae(ZT())).property("combi_and",Se()).build("MFA.ChallengeResponse"),ji=()=>W().property("solve_expiration",U(Me)).property("earliest_retransmission",U(Me)).build("MFA.ChallengeRequestResponse");var s_=()=>W().property("report_serial_id",ne()).build("TalerMerchantApi.ReportAddedResponse"),c_=()=>W().property("report_serial",ne()).property("description",L()).property("program_section",L()).property("mime_type",L()).property("data_source",L()).property("target_address",L()).property("report_frequency",qt).property("report_frequency_shift",qt).property("last_error_code",U(ne())).property("last_error_detail",U(L())).build("TalerMerchantApi.ReportDetailResponse"),u_=()=>W().property("reports",Ae(JT())).build("TalerMerchantApi.ReportsSummaryResponse"),JT=()=>W().property("report_serial",ne()).property("description",L()).property("report_frequency",qt).build("TalerMerchantApi.ReportEntry"),l_=()=>W().property("groups",Ae(eN())).build("TalerMerchantApi.GroupsSummaryResponse"),eN=()=>W().property("group_name",L()).property("group_serial",ne()).property("description",L()).build("TalerMerchantApi.GroupEntry"),d_=()=>W().property("group_serial_id",ne()).build("TalerMerchantApi.GroupAddedResponse"),f_=()=>W().property("pot_serial_id",ne()).build("TalerMerchantApi.PotAddedResponse"),p_=()=>W().property("pots",Ae(tN())).build("TalerMerchantApi.PotsSummaryResponse"),tN=()=>W().property("pot_serial",ne()).property("pot_name",L()).property("pot_totals",Ae(me())).build("TalerMerchantApi.PotEntry"),h_=()=>W().property("description",L()).property("pot_name",L()).property("pot_totals",Ae(me())).build("TalerMerchantApi.PotDetailResponse");var nN=new Dt("contractTerms.ts"),m_;(function(e){function t(h,p,T){let A=JSON.parse(JSON.stringify(h));if(Array.isArray(A))for(let C=0;C!0)}e.scrub=r;function n(h,p){return t(h,[],p)}e.forgetAll=n;function a(h){let p=JSON.parse(JSON.stringify(h));if(Array.isArray(p))for(let T=0;T=Number.MIN_SAFE_INTEGER&&h<=Number.MAX_SAFE_INTEGER;if(typeof h=="boolean"||h===null)return!0;if(Array.isArray(h))return h.every(p=>s(p));if(typeof h=="object"){for(let p of Object.keys(h)){if(p.match(o)){if(s(h[p]))continue;return!1}if(p==="$forgettable"){let T=h.$forgettable;if(!T||typeof T!="object")return!1;for(let A of Object.keys(T))if(!A.match(o)||!(A in h)||typeof h.$forgettable[A]!="string")return!1}else if(p==="$forgotten"){let T=h.$forgotten;if(!T||typeof T!="object")return!1;for(let A of Object.keys(T)){if(!A.match(o)||A in h)return!1;let C=h.$forgotten[A];if(typeof C!="string")return!1;try{if(nr(C).length!=64)return!1}catch{return!1}if(h.$forgettable?.[p]!==void 0)return!1}}else return!1}return!0}return!1}e.validateForgettable=s;function c(h){throw Error("not implemented yet")}e.validateNothingForgotten=c;function u(h){if(h.version===qr.V1){let T=new RegExp("^(\\*\\.)?([\\w\\d]+\\.)+[\\w\\d]+$");for(let A in h.token_families){let C=h.token_families[A];var p=[];switch(C.details.class){case Cn.Subscription:p.push(...C.details.trusted_domains);break;case Cn.Discount:p.push(...C.details.expected_domains);break;default:ue(C.details)}for(let S in p)if(S!=="*"&&!T.test(S))return!1}}return!0}e.validateParsed=u;function f(h){let p=r(h),T=pn(p)+"\0",A=gr(T);return gt(In(A))}e.hashContractTerms=f;function d(h,p){let T,A;switch(h.version){case void 0:case qr.V0:T=h.amount,A=h.max_fee;break;case qr.V1:if(p===void 0)return nN.trace("choice index not specified for contract v1"),{available:!1,amountRaw:void 0,maxFee:void 0};if(h.choices[p]===void 0)throw Error(`invalid choice index ${p}`);T=h.choices[p].amount,A=h.choices[p].max_fee;break;default:ue(h)}return{available:!0,amountRaw:T,maxFee:A}}e.extractAmounts=d;function w(h){let p;for(let T=0;TW().property("amount_credit",me()).property("amount_debit",me()).build("TalerCorebankApi.CashoutConversionResponse"),__=()=>W().property("amount_credit",me()).property("amount_debit",me()).build("TalerCorebankApi.CashinConversionResponse"),Do=()=>W().property("cashin_fee",me()).property("cashin_min_amount",me()).property("cashin_ratio",hn()).property("cashin_rounding_mode",pt(X("zero"),X("up"),X("nearest"))).property("cashin_tiny_amount",me()).property("cashout_fee",me()).property("cashout_min_amount",me()).property("cashout_ratio",hn()).property("cashout_rounding_mode",pt(X("zero"),X("up"),X("nearest"))).property("cashout_tiny_amount",me()).build("ConversionBankConfig.ConversionInfo"),y_=()=>W().property("name",X("taler-conversion-info")).property("version",L()).property("regional_currency",L()).property("regional_currency_specification",an()).property("fiat_currency",L()).property("fiat_currency_specification",an()).property("conversion_rate",Do()).build("ConversionBankConfig.IntegrationConfig");var Po;(function(e){e[e.UPDATE_RATE=0]="UPDATE_RATE"})(Po||(Po={}));var la=class e{constructor(t,r,n){this.baseUrl=t,this.httpLib=r??jt(),this.cacheEvictor=n??gn}static isCompatible(t){return St.compare(this.PROTOCOL_VERSION,t)?.compatible??!1}async getConfig(){let t=new URL("config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return rr("taler-conversion-info",e.PROTOCOL_VERSION,r,y_());case l.NotImplemented:return I(r.status,r);default:return V(r)}}async getRate(t){let r=new URL("rate",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"GET",headers:Zt(t)});switch(n.status){case l.Ok:return se(n,Do());case l.NotImplemented:return I(n.status,n);default:return V(n)}}async getCashinRate(t,r){let n=new URL("cashin-rate",this.baseUrl);r.debit&&n.searchParams.set("amount_debit",J.stringify(r.debit)),r.credit&&n.searchParams.set("amount_credit",J.stringify(r.credit));let a=await this.httpLib.fetch(n.href,{method:"GET",headers:Zt(t)});switch(a.status){case l.Ok:return se(a,__());case l.BadRequest:{let o=await a.json(),s=Vr().decode(o);switch(s.code){case G.GENERIC_PARAMETER_MISSING:return Ce(s.code,s);case G.GENERIC_PARAMETER_MALFORMED:return Ce(s.code,s);case G.GENERIC_CURRENCY_MISMATCH:return Ce(s.code,s);default:return V(a,s)}}case l.Conflict:return I(a.status,a);case l.NotImplemented:return I(a.status,a);default:return V(a)}}async getCashoutRate(t,r){let n=new URL("cashout-rate",this.baseUrl);r.debit&&n.searchParams.set("amount_debit",J.stringify(r.debit)),r.credit&&n.searchParams.set("amount_credit",J.stringify(r.credit));let a=await this.httpLib.fetch(n.href,{method:"GET",headers:Zt(t)});switch(a.status){case l.Ok:return se(a,g_());case l.BadRequest:{let o=await a.json(),s=Vr().decode(o);switch(s.code){case G.GENERIC_PARAMETER_MISSING:return I(a.status,a);case G.GENERIC_PARAMETER_MALFORMED:return I(a.status,a);case G.GENERIC_CURRENCY_MISMATCH:return I(a.status,a);default:return V(a,s)}}case l.Conflict:return I(a.status,a);case l.NotImplemented:return I(a.status,a);default:return V(a)}}async updateConversionRate(t,r){let n=new URL("conversion-rate",this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",headers:Zt(t),body:r});switch(a.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Po.UPDATE_RATE),ke();case l.Unauthorized:return I(a.status,a);case l.NotImplemented:return I(a.status,a);default:return V(a)}}};la.PROTOCOL_VERSION="0:0:0";var tt={};Bp(tt,{MonitorTimeframeParam:()=>Uo,codecForAccountData:()=>xl,codecForAccountMinimalData:()=>E_,codecForBankAccountCreateWithdrawalResponse:()=>Ll,codecForBankAccountTransactionInfo:()=>Zi,codecForBankAccountTransactionsResponse:()=>Ol,codecForCashoutInfo:()=>A_,codecForCashoutPending:()=>Ul,codecForCashoutStatusResponse:()=>Fl,codecForCashouts:()=>Ml,codecForChallengeContactData:()=>w_,codecForConversionRateClass:()=>Qi,codecForConversionRateClassResponse:()=>Il,codecForConversionRateClasses:()=>Sl,codecForConversionRatesResponse:()=>UN,codecForCoreBankConfig:()=>Al,codecForCreateTransactionResponse:()=>Dl,codecForGlobalCashoutInfo:()=>T_,codecForGlobalCashouts:()=>kl,codecForIntegrationBankConfig:()=>wl,codecForListBankAccountsResponse:()=>Rl,codecForMonitorNoConversion:()=>N_,codecForMonitorResponse:()=>Hl,codecForMonitorWithCashout:()=>R_,codecForPublicAccountsResponse:()=>Nl,codecForRegisterAccountResponse:()=>Pl,codecForWithdrawalPublicInfo:()=>Cl});function ka(){return{decode(e,t){if(typeof e!="string")throw new Rt(`expected string at ${ut(t)} but got ${typeof e}`);if(fN(e)===void 0)throw new Rt(`invalid taler URI at ${ut(t)} but got "${e}"`);return e}}}var Fa="taler://",Lo="taler+http://",Lt;(function(e){e[e.WRONG_PREFIX=0]="WRONG_PREFIX",e[e.INCOMPLETE=1]="INCOMPLETE",e[e.UNSUPPORTED=2]="UNSUPPORTED",e[e.COMPONENTS_LENGTH=3]="COMPONENTS_LENGTH",e[e.INVALID_TARGET_PATH=4]="INVALID_TARGET_PATH",e[e.INVALID_PARAMETER=5]="INVALID_PARAMETER"})(Lt||(Lt={}));var _r;(function(e){let t={"add-contact":!0,"add-exchange":!0,"dev-experiment":!0,pay:!0,"pay-pull":!0,"pay-template":!0,"pay-push":!0,"withdraw-exchange":!0,refund:!0,restore:!0,withdraw:!0,"withdrawal-transfer-result":!0};function r(v,_,g,O={}){return{type:Ee.Pay,merchantBaseUrl:v,orderId:_,sessionId:g,...O}}e.createTalerPay=r;function n(v,_,g={}){return{type:Ee.Withdraw,bankIntegrationApiBaseUrl:v,withdrawalOperationId:_,...g}}e.createTalerWithdraw=n;function a(v,_){return{type:Ee.Refund,merchantBaseUrl:v,orderId:_}}e.createTalerRefund=a;function o(v,_){return{type:Ee.PayPull,exchangeBaseUrl:v,contractPriv:_}}e.createTalerPayPull=o;function s(v,_){return{type:Ee.PayPush,exchangeBaseUrl:v,contractPriv:_}}e.createTalerPayPush=s;function c(v,_,g={}){return{type:Ee.PayTemplate,merchantBaseUrl:v,templateId:_,fulfillmentUrl:g.fulfillmenURL,sessionId:g.sessionId}}e.createTalerPayTemplate=c;function u(v,_){return{type:Ee.Restore,providers:_,walletRootPriv:v}}e.createTalerRestore=u;function f(v,_){return{type:Ee.DevExperiment,devExperimentId:v,query:_}}e.createTalerDevExperiment=f;function d(v,_={}){return{type:Ee.WithdrawExchange,exchangeBaseUrl:v,..._}}e.createTalerWithdrawExchange=d;function w(v){return{type:Ee.AddExchange,exchangeBaseUrl:v}}e.createTalerAddExchange=w;function R(v,_,g,O,E){return{type:Ee.AddContact,alias:_,aliasType:v,mailboxBaseUri:g,mailboxIdentity:O,sourceBaseUrl:E}}e.createTalerAddContact=R;function h(v,_={}){return{type:Ee.WithdrawalTransferResult,ref:v,..._}}e.createTalerWithdrawalTransferResult=h;function p(v){let _=new oa(v);return`${_.host}${_.pathname}`}function T(v){let _=[];switch(v.type){case Ee.Withdraw:return v.externalConfirmation&&_.push(["external-confirmation","1"]),_;case Ee.Pay:return v.claimToken&&_.push(["c",v.claimToken]),v.noncePriv&&_.push(["n",v.noncePriv]),_;case Ee.WithdrawExchange:return v.amount&&_.push(["a",v.amount]),_;case Ee.WithdrawalTransferResult:return _.push(["ref",v.ref]),v.status&&_.push(["status",v.status]),_;case Ee.AddContact:return v.sourceBaseUrl&&_.push(["sourceBaseUrl",v.sourceBaseUrl]),_;case Ee.PayTemplate:return v.fulfillmentUrl&&_.push(["fulfillment_url",v.fulfillmentUrl]),v.sessionId&&_.push(["session_id",v.sessionId]),_;case Ee.Refund:case Ee.PayPush:case Ee.PayPull:case Ee.Restore:case Ee.DevExperiment:case Ee.AddExchange:return _;default:ue(v)}}function A(v){switch(v.type){case Ee.Withdraw:return v.bankIntegrationApiBaseUrl.startsWith("http://")?Lo:Fa;case Ee.Pay:case Ee.Refund:case Ee.PayTemplate:return v.merchantBaseUrl.startsWith("http://")?Lo:Fa;case Ee.PayPush:case Ee.PayPull:case Ee.AddExchange:case Ee.WithdrawExchange:return v.exchangeBaseUrl.startsWith("http://")?Lo:Fa;case Ee.Restore:case Ee.DevExperiment:case Ee.WithdrawalTransferResult:case Ee.AddContact:return Fa;default:ue(v)}}function C(v){switch(v.type){case Ee.Withdraw:return`/${p(v.bankIntegrationApiBaseUrl)}${v.withdrawalOperationId}`;case Ee.Pay:return`/${p(v.merchantBaseUrl)}${v.orderId}/${v.sessionId}`;case Ee.Refund:return`/${p(v.merchantBaseUrl)}${v.orderId}/`;case Ee.PayTemplate:return`/${p(v.merchantBaseUrl)}${v.templateId}`;case Ee.PayPush:return`/${p(v.exchangeBaseUrl)}${v.contractPriv}`;case Ee.PayPull:return`/${p(v.exchangeBaseUrl)}${v.contractPriv}`;case Ee.AddExchange:return`/${p(v.exchangeBaseUrl)}`;case Ee.WithdrawExchange:return`/${p(v.exchangeBaseUrl)}`;case Ee.Restore:return`/${v.walletRootPriv}/${v.providers.map(_=>encodeURIComponent(_)).join(",")}`;case Ee.DevExperiment:return`/${v.devExperimentId}`;case Ee.WithdrawalTransferResult:return"/";case Ee.AddContact:return`/${v.aliasType}/${v.alias}/${p(v.mailboxBaseUri)}/${v.mailboxIdentity}`;default:ue(v)}}function S(v){let _=A(v),g=C(v),O=T(v),E=new oa(`${_}${v.type}${g}`);return E.search=PN(O),E.href}e.toString=S;function k(v,_={}){let g=!1,O=_.ignoreUppercase?v.toLowerCase():v;if(!O.startsWith(Fa)&&!(g=O.startsWith(Lo)))return fe.error(Lt.WRONG_PREFIX);let E=g?"http":"https",[m,y]=v.slice((g?Lo:Fa).length).split("?",2),b=m.indexOf("/"),x=b===-1?m:m.slice(0,b),D=_.ignoreUppercase?x.toLowerCase():x;if(!t[D])return fe.errorWithDetail(Lt.UNSUPPORTED,{uriType:D});let F=m.slice(b+1);if(b===-1||!F)return fe.errorWithDetail(Lt.INCOMPLETE,{uriType:D});let B={};y&&new jr(y).forEach((pe,Ie)=>{B[Ie]=pe});let K=F.split("/");switch(D){case Ee.Pay:{if(K.length<3)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=$e.parseHostPortPath2(K[0],K.slice(1,-2).join("/"),E);if(!_.ignoreComponentError&&!Z)return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z});let pe=K[K.length-2],Ie=K[K.length-1];return fe.of(r(Z??K[0],pe,Ie,{claimToken:B.c,noncePriv:B.n}))}case Ee.Withdraw:{if(K.length<2)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=$e.parseHostPortPath2(K[0],K.slice(1,-1).join("/"),E);if(!_.ignoreComponentError&&!Z)return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z});let pe=K[K.length-1],Ie=B["external-confirmation"]?B["external-confirmation"]==="1":void 0;return fe.of(n(Z??K[0],pe,{externalConfirmation:Ie}))}case Ee.Refund:{if(K.length<3)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});if(K[K.length-1])return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:1,uriType:D});let Z=$e.parseHostPortPath2(K[0],K.slice(1,-2).join("/"),E);if(!_.ignoreComponentError&&!Z)return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z});let pe=K[K.length-2];return fe.of(a(Z??K[0],pe))}case Ee.PayPull:{if(K.length<2)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=$e.parseHostPortPath2(K[0],K.slice(1,-1).join("/"),E);if(!_.ignoreComponentError&&!Z)return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z});let pe=K[K.length-1];return fe.of(o(Z??K[0],pe))}case Ee.PayPush:{if(K.length<2)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=$e.parseHostPortPath2(K[0],K.slice(1,-1).join("/"),E);if(!_.ignoreComponentError&&!Z)return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z});let pe=K[K.length-1];return fe.of(s(Z??K[0],pe))}case Ee.PayTemplate:{if(K.length<2)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=$e.parseHostPortPath2(K[0],K.slice(1,-1).join("/"),E);if(!_.ignoreComponentError&&!Z)return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z});let pe=K[K.length-1];return fe.of(c(Z??K[0],pe))}case Ee.Restore:{if(K.length!==2)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=K[0],pe=[];return K[1].split(",").map(Ie=>{let be=decodeURIComponent(Ie),xe=!1,Le=be.startsWith("https://")?be.substring(8):(xe=be.startsWith("http://"))?be.substring(7):be,Ue=be===Le?E:xe?"http":"https",[Ve,te]=Le.split("/",1),ee=$e.parseHostPortPath2(Ve,te,Ue);pe.push(ee)}),fe.of(u(Z??K[0],pe))}case Ee.DevExperiment:{if(K.length!==1)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=K[0],pe=new jr(y);return fe.of(f(Z,pe))}case Ee.WithdrawExchange:{if(K.length<1)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});if(K.length>1&&K[K.length-1])return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:1,uriType:D});let Z=$e.parseHostPortPath2(K[0],K.slice(1,-1).join("/"),E);if(!_.ignoreComponentError&&!Z)return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z});let pe=B.a?J.parseWithError(B.a):void 0;if(!_.ignoreComponentError&&pe&&pe.type==="fail")return fe.errorWithDetail(Lt.INVALID_PARAMETER,{name:"a",uriType:D,error:pe});let Ie=pe&&pe.type==="ok"?J.stringify(pe.body):void 0;return fe.of(d(Z??K[0],{amount:Ie}))}case Ee.AddExchange:{if(K.length===1)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=$e.parseHostPortPath2(K[0],K.slice(1).join("/"),E);return!_.ignoreComponentError&&!Z?fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z}):fe.of(w(Z??K[0]))}case Ee.WithdrawalTransferResult:{if(K.length===0)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=B.ref,pe=B.status!=="aborted"&&B.status!=="success"?void 0:B.status;return fe.of(h(Z,{status:pe}))}case Ee.AddContact:{if(K.length<4)return fe.errorWithDetail(Lt.COMPONENTS_LENGTH,{uriType:D});let Z=$e.parseHostPortPath2(K[2],K.slice(2,K.length-2).join("/"),E);if(!Z)return fe.errorWithDetail(Lt.INVALID_TARGET_PATH,{pos:0,uriType:D,error:Z});let pe=K[K.length-1];return fe.of(R(K[0],K[1],Z,pe,B.sourceBaseUrl))}default:ue(D)}}e.fromString=k})(_r||(_r={}));function oN(e){let t=El(e,"withdraw");if(t.tag==="error")return t;let r=t.value.rest.split("?",2),n=r[0],a=new jr(r[1]??""),o=n.split("/");if(o.length<2)return fe.error(G.WALLET_TALER_URI_MALFORMED);let s=o[0].toLowerCase(),c=o.slice(1,o.length-1),u=o[o.length-1],f={type:Ee.Withdraw,bankIntegrationApiBaseUrl:$e.parseHostPortPath2(s,c.join("/"),t.value.innerProto),withdrawalOperationId:u,externalConfirmation:a.get("external-confirmation")=="1"};return fe.of(f)}function iN(e){let t=oN(e);if(t.tag!=="error")return t.value}function sN(e){let t=El(e,"add-exchange");if(t.tag==="error")return t;let r=t.value.rest.split("/");if(r.length<2)return fe.error(G.WALLET_TALER_URI_MALFORMED);let n=r[0].toLowerCase(),a=r.slice(1,r.length-1),o={type:Ee.AddExchange,exchangeBaseUrl:$e.parseHostPortPath2(n,a.join("/"),t.value.innerProto)};return fe.of(o)}function cN(e){let t=El(e,"add-contact");if(t.tag==="error")return t;let r=t.value.rest.split("/");if(r.length<4)return fe.error(G.WALLET_TALER_URI_MALFORMED);let n=r[2],a=r.slice(3,r.length-2),o=r[r.length-1],s=new jr(o??""),c=o.split("?")[0],u=s.get("sourceBaseUrl")??"",f=$e.parseHostPortPath2(n,a.join("/"),t.value.innerProto),d={type:Ee.AddContact,aliasType:r[0],alias:r[1],mailboxBaseUri:f,mailboxIdentity:c,sourceBaseUrl:u};return fe.of(d)}function uN(e){let t=sN(e);if(t.tag!=="error")return t.value}function lN(e){let t=cN(e);if(t.tag!=="error")return t.value}var Ee;(function(e){e.Withdraw="withdraw",e.Pay="pay",e.Refund="refund",e.PayPush="pay-push",e.PayPull="pay-pull",e.PayTemplate="pay-template",e.Restore="restore",e.DevExperiment="dev-experiment",e.AddExchange="add-exchange",e.WithdrawExchange="withdraw-exchange",e.WithdrawalTransferResult="withdrawal-transfer-result",e.AddContact="add-contact"})(Ee||(Ee={}));function Vn(e,t){let r=`taler://${t}/`,n=`taler+http://${t}/`;return e.toLowerCase().startsWith(r)?{innerProto:"https",rest:e.substring(r.length)}:e.toLowerCase().startsWith(n)?{innerProto:"http",rest:e.substring(n.length)}:void 0}function El(e,t){if(!e.toLowerCase().startsWith("taler://")&&!e.toLowerCase().startsWith("taler+http://"))return fe.error(G.WALLET_TALER_URI_MALFORMED);let r=`taler://${t}/`,n=`taler+http://${t}/`;return e.toLowerCase().startsWith(r)?fe.of({innerProto:"https",rest:e.substring(r.length)}):e.toLowerCase().startsWith(n)?fe.of({innerProto:"http",rest:e.substring(n.length)}):fe.error(G.WALLET_TALER_URI_MALFORMED)}var dN={[Ee.Pay]:pN,[Ee.PayPull]:gN,[Ee.PayPush]:mN,[Ee.PayTemplate]:hN,[Ee.Restore]:vN,[Ee.Refund]:yN,[Ee.Withdraw]:iN,[Ee.DevExperiment]:bN,[Ee.WithdrawExchange]:_N,[Ee.AddExchange]:uN,[Ee.AddContact]:lN,[Ee.WithdrawalTransferResult]:()=>{throw new Error("not supported")}};function fN(e){let t=e.startsWith("taler://"),r=e.startsWith("taler+http://");if(!t&&!r)return;let n=t?8:13,a=e.indexOf("/",n+1),o=e.substring(n,a),s=Object.values(Ee).find(c=>c===o);if(s)return dN[s](e)}function v_(e){switch(e.type){case Ee.DevExperiment:return IN(e);case Ee.Pay:return EN(e);case Ee.PayPull:return wN(e);case Ee.PayPush:return AN(e);case Ee.PayTemplate:return SN(e);case Ee.Restore:return TN(e);case Ee.Refund:return CN(e);case Ee.Withdraw:return ON(e);case Ee.WithdrawExchange:return NN(e);case Ee.AddExchange:return RN(e);case Ee.AddContact:return xN(e);case Ee.WithdrawalTransferResult:throw Error("not supported")}}function pN(e){let t=Vn(e,"pay");if(!t)return;let r=t?.rest.split("?"),n=new jr(r[1]??""),a=n.get("c")??void 0,o=n.get("n")??void 0,s=r[0].split("/");if(s.length<3)return;let c=s[0].toLowerCase(),u=s[s.length-1],f=s[s.length-2],d=s.slice(1,s.length-2),w=$e.parseHostPortPath2(c,d.join("/"),t.innerProto);return{type:Ee.Pay,merchantBaseUrl:w,orderId:f,sessionId:u,claimToken:a,noncePriv:o}}function hN(e){let t=Vn(e,Ee.PayTemplate);if(!t)return;let r=t.rest.split("?"),n=r[0].split("/");if(n.length<2)return;let a=new jr(r[1]??""),o={};a.forEach((w,R)=>{o[R]=w});let s=n[0].toLowerCase(),c=n[n.length-1],u=n.slice(1,n.length-1),f=[s,...u].join("/"),d=$e.parseHostPortPath2(s,u.join("/"),t.innerProto);return{type:Ee.PayTemplate,merchantBaseUrl:d,templateId:c,fulfillmentUrl:a.get("fulfillment_url")??void 0,sessionId:a.get("session_id")??void 0}}function mN(e){let t=Vn(e,Ee.PayPush);if(!t)return;let n=(t?.rest.split("?"))[0].split("/");if(n.length<2)return;let a=n[0].toLowerCase(),o=n[n.length-1],s=n.slice(1,n.length-1),c=[a,...s].join("/"),u=$e.parseHostPortPath2(a,s.join("/"),t.innerProto);return{type:Ee.PayPush,exchangeBaseUrl:u,contractPriv:o}}function gN(e){let t=Vn(e,Ee.PayPull);if(!t)return;let n=(t?.rest.split("?"))[0].split("/");if(n.length<2)return;let a=n[0].toLowerCase(),o=n[n.length-1],s=n.slice(1,n.length-1),c=[a,...s].join("/"),u=$e.parseHostPortPath2(a,s.join("/"),t.innerProto);return{type:Ee.PayPull,exchangeBaseUrl:u,contractPriv:o}}function _N(e){let t=Vn(e,"withdraw-exchange");if(!t)return;let r=t?.rest.split("?"),n=r[0].split("/");if(n.length<1)return;let a=n[0].toLowerCase();if(n.length>1?n[n.length-1]:void 0)return;let s=n.slice(1,n.length-1),c=[a,...s].join("/"),u=$e.parseHostPortPath2(a,s.join("/"),t.innerProto),d=new jr(r[1]??"").get("a")??void 0;return{type:Ee.WithdrawExchange,exchangeBaseUrl:u,amount:d}}function yN(e){let t=Vn(e,"refund");if(!t)return;let n=(t?.rest.split("?"))[0].split("/");if(n.length<3)return;let a=n[0].toLowerCase(),o=n[n.length-1],s=n[n.length-2],c=n.slice(1,n.length-2),u=[a,...c].join("/"),f=$e.parseHostPortPath2(a,c.join("/"),t.innerProto);return{type:Ee.Refund,merchantBaseUrl:f,orderId:s}}function bN(e){let r=Vn(e,"dev-experiment")?.rest.split("?");if(!r)return;let n=r[0].split("/");return{type:Ee.DevExperiment,devExperimentId:n[0],query:new jr(r[1]??"")}}function vN(e){let t=Vn(e,"restore");if(!t)return;let n=t.rest.split("?")[0].split("/");if(n.length<2)return;let a=n[0];if(!a)return;let o=new Array;return n[1].split(",").map(s=>{let c=decodeURIComponent(s),u=!1,f=c.startsWith("https://")?c.substring(8):(u=c.startsWith("http://"))?c.substring(7):c,d=c===f?t.innerProto:u?"http":"https",[w,R]=f.split("/",1),h=$e.parseHostPortPath2(w,R??"/",d);o.push(h)}),{type:Ee.Restore,walletRootPriv:a,providers:o}}function EN({merchantBaseUrl:e,orderId:t,sessionId:r,claimToken:n,noncePriv:a}){let{proto:o,path:s,query:c}=On(e,{c:n,n:a});return`${o}://pay/${s}${t}/${r}${c}`}function wN({contractPriv:e,exchangeBaseUrl:t}){let{proto:r,path:n}=On(t);return`${r}://pay-pull/${n}${e}`}function AN({contractPriv:e,exchangeBaseUrl:t}){let{proto:r,path:n}=On(t);return`${r}://pay-push/${n}${e}`}function TN({providers:e,walletRootPriv:t}){let r=e.map(n=>`${encodeURIComponent(new oa(n).href)}`).join(",");return`taler://restore/${t}/${r}`}function NN({exchangeBaseUrl:e,amount:t}){let{proto:r,path:n,query:a}=On(e,{a:t});return`${r}://withdraw-exchange/${n}${a}`}function RN({exchangeBaseUrl:e}){let{proto:t,path:r}=On(e);return`${t}://add-exchange/${r}`}function xN({alias:e,aliasType:t,mailboxBaseUri:r,mailboxIdentity:n,sourceBaseUrl:a}){let{proto:o,path:s}=On(r),c=`${o}://add-contact/${t}/${e}/${s}${n}`;return a?c+`?sourceBaseUrl=${encodeURIComponent(a)}`:c}function IN({devExperimentId:e}){return`taler://dev-experiment/${e}`}function SN({merchantBaseUrl:e,templateId:t,fulfillmentUrl:r,sessionId:n}){let{proto:a,path:o,query:s}=On(e,{session_id:n,fulfillment_url:r});return`${a}://pay-template/${o}${t}${s}`}function CN({merchantBaseUrl:e,orderId:t}){let{proto:r,path:n}=On(e);return`${r}://refund/${n}${t}/`}function ON({bankIntegrationApiBaseUrl:e,withdrawalOperationId:t}){let{proto:r,path:n}=On(e);return`${r}://withdraw/${n}${t}`}function On(e,t={}){let r=new oa(e),n;if(r.protocol==="https:")n="taler";else if(r.protocol==="http:")n="taler+http";else throw Error(`Unsupported URL protocol in ${e}`);let a=r.hostname;r.port&&(a=a+":"+r.port),r.pathname&&(a=a+r.pathname),a.endsWith("/")||(a=a+"/");let o=new jr,s=!1;Object.entries(t).forEach(([u,f])=>{f!==void 0&&(s=!0,o.append(u,f))});let c=s?"?"+o.toString():"";return{proto:n,path:a,query:c}}function DN(e){return encodeURIComponent(e).replace(/[!'()*]/g,t=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`)}var b_=DN;function PN(e){return e.map(([t,r])=>`${b_(t)}=${b_(r)}`).join("&")}var Uo;(function(e){e[e.hour=0]="hour",e[e.day=1]="day",e[e.month=2]="month",e[e.year=3]="year",e[e.decade=4]="decade"})(Uo||(Uo={}));var wl=()=>W().property("name",X("taler-bank-integration")).property("version",L()).property("currency",L()).property("currency_specification",an()).property("implementation",U(L())).build("TalerCorebankApi.IntegrationConfig"),Al=()=>W().property("name",pt(X("taler-corebank"),X("libeufin-bank"))).property("version",L()).property("bank_name",U(L())).property("base_url",U(L())).property("allow_conversion",U(Se())).property("allow_registrations",U(Se())).property("allow_deletions",U(Se())).property("allow_edit_name",U(Se())).property("allow_edit_cashout_payto_uri",U(Se())).property("default_debit_threshold",U(me())).property("currency",L()).property("currency_specification",an()).property("supported_tan_channels",U(Ae(pt(X(Sr.SMS),X(Sr.EMAIL))))).property("wire_type",Bt(L(),"iban")).property("wire_transfer_fees",U(me())).property("min_wire_transfer_amount",U(me())).property("max_wire_transfer_amount",U(me())).build("TalerCorebankApi.Config"),Tl=()=>W().property("amount",me()).property("credit_debit_indicator",pt(X("credit"),X("debit"))).build("TalerCorebankApi.Balance"),LN=()=>W().property("username",L()).property("balance",Tl()).property("payto_uri",xt()).property("is_taler_exchange",Se()).property("row_id",U(ne())).build("TalerCorebankApi.PublicAccount"),Nl=()=>W().property("public_accounts",Ae(LN())).build("TalerCorebankApi.PublicAccountsResponse"),E_=()=>W().property("username",L()).property("name",L()).property("payto_uri",xt()).property("balance",Tl()).property("row_id",ne()).property("debit_threshold",me()).property("is_public",Se()).property("is_taler_exchange",Se()).property("status",U(pt(X("active"),X("locked"),X("deleted")))).property("conversion_rate_class_id",U(ne())).property("conversion_rate",U(Do())).build("TalerCorebankApi.AccountMinimalData"),Rl=()=>W().property("accounts",Ae(E_())).build("TalerCorebankApi.ListBankAccountsResponse"),xl=()=>W().property("name",L()).property("balance",Tl()).property("payto_uri",xt()).property("debit_threshold",me()).property("contact_data",U(w_())).property("cashout_payto_uri",U(xt())).property("is_public",Se()).property("is_taler_exchange",Se()).property("conversion_rate_class_id",U(ne())).property("tan_channel",U(pt(X(Sr.SMS),X(Sr.EMAIL)))).property("status",U(pt(X("active"),X("locked"),X("deleted")))).build("TalerCorebankApi.AccountData"),Il=()=>W().property("conversion_rate_class_id",ne()).build("TalerCorebankApi.ConversionRateClassResponse"),Qi=()=>W().property("cashin_fee",U(me())).property("cashin_min_amount",U(me())).property("cashin_ratio",U(hn())).property("cashin_rounding_mode",U(pt(X("zero"),X("up"),X("nearest")))).property("cashout_fee",U(me())).property("cashout_min_amount",U(me())).property("cashout_ratio",U(hn())).property("cashout_rounding_mode",U(pt(X("zero"),X("up"),X("nearest")))).property("conversion_rate_class_id",ne()).property("description",U(L())).property("name",L()).property("num_users",ne()).build("TalerCorebankApi.ConversionRateClass"),Sl=()=>W().property("classes",Ae(Qi())).build("TalerCorebankApi.ConversionRateClasses"),w_=()=>W().property("email",U(L())).property("phone",U(L())).build("TalerCorebankApi.ChallengeContactData"),Cl=()=>W().property("status",pt(X("pending"),X("selected"),X("aborted"),X("confirmed"))).property("amount",U(me())).property("suggested_amount",U(me())).property("username",L()).property("selected_reserve_pub",U(L())).property("selected_exchange_account",U(xt())).property("no_amount_to_wallet",U(Se())).build("TalerCorebankApi.WithdrawalPublicInfo"),Ol=()=>W().property("transactions",Ae(Zi())).build("TalerCorebankApi.BankAccountTransactionsResponse"),Zi=()=>W().property("creditor_payto_uri",xt()).property("debtor_payto_uri",xt()).property("amount",me()).property("direction",pt(X("debit"),X("credit"))).property("subject",L()).property("row_id",ne()).property("date",Me).build("TalerCorebankApi.BankAccountTransactionInfo"),Dl=()=>W().property("row_id",ne()).build("TalerCorebankApi.CreateTransactionResponse"),Pl=()=>W().property("internal_payto_uri",xt()).build("TalerCorebankApi.RegisterAccountResponse"),Ll=()=>W().property("taler_withdraw_uri",ka()).property("withdrawal_id",L()).build("TalerCorebankApi.BankAccountCreateWithdrawalResponse"),Ul=()=>W().property("cashout_id",ne()).build("TalerCorebankApi.CashoutPending"),Ml=()=>W().property("cashouts",Ae(A_())).build("TalerCorebankApi.Cashouts"),A_=()=>W().property("cashout_id",ne()).build("TalerCorebankApi.CashoutInfo"),kl=()=>W().property("cashouts",Ae(T_())).build("TalerCorebankApi.GlobalCashouts"),T_=()=>W().property("cashout_id",ne()).property("username",L()).build("TalerCorebankApi.GlobalCashoutInfo"),Fl=()=>W().property("amount_debit",me()).property("amount_credit",me()).property("subject",L()).property("creation_time",Me).build("TalerCorebankApi.CashoutStatusResponse"),UN=()=>W().property("buy_at_ratio",hn()).property("buy_in_fee",hn()).property("sell_at_ratio",hn()).property("sell_out_fee",hn()).build("TalerCorebankApi.ConversionRatesResponse"),Hl=()=>wt().discriminateOn("type").alternative("no-conversions",N_()).alternative("with-conversions",R_()).build("TalerWireGatewayApi.IncomingBankTransaction"),N_=()=>W().property("type",X("no-conversions")).property("talerInCount",ne()).property("talerInVolume",me()).property("talerOutCount",ne()).property("talerOutVolume",me()).build("TalerCorebankApi.MonitorJustPayouts"),R_=()=>W().property("type",X("with-conversions")).property("cashinCount",ne()).property("cashinFiatVolume",me()).property("cashinRegionalVolume",me()).property("cashoutCount",ne()).property("cashoutFiatVolume",me()).property("cashoutRegionalVolume",me()).property("talerInCount",ne()).property("talerInVolume",me()).property("talerOutCount",ne()).property("talerOutVolume",me()).build("TalerCorebankApi.MonitorWithCashout");var MN=new Dt("bank-core.ts"),Gt;(function(e){e[e.DELETE_ACCOUNT=0]="DELETE_ACCOUNT",e[e.CREATE_ACCOUNT=1]="CREATE_ACCOUNT",e[e.UPDATE_ACCOUNT=2]="UPDATE_ACCOUNT",e[e.UPDATE_PASSWORD=3]="UPDATE_PASSWORD",e[e.CREATE_TRANSACTION=4]="CREATE_TRANSACTION",e[e.CONFIRM_WITHDRAWAL=5]="CONFIRM_WITHDRAWAL",e[e.ABORT_WITHDRAWAL=6]="ABORT_WITHDRAWAL",e[e.CREATE_WITHDRAWAL=7]="CREATE_WITHDRAWAL",e[e.CREATE_CASHOUT=8]="CREATE_CASHOUT",e[e.CREATE_CONVERSION_RATE_CLASS=9]="CREATE_CONVERSION_RATE_CLASS",e[e.UPDATE_CONVERSION_RATE_CLASS=10]="UPDATE_CONVERSION_RATE_CLASS",e[e.DELETE_CONVERSION_RATE_CLASS=11]="DELETE_CONVERSION_RATE_CLASS"})(Gt||(Gt={}));var Ha=class e{constructor(t,r,n){this.baseUrl=t,this.httpLib=r??jt(),this.cacheEvictor=n??gn}static isCompatible(t){return St.compare(this.PROTOCOL_VERSION,t)?.compatible??!1}checkUsernameAuthMatch(t,r){r.type==="basic"&&t!==r.username&&MN.warn("username and basic auth name do not match")}async createAccessToken(t,r,n,a={}){let o=new URL(`accounts/${t}/token`,this.baseUrl);this.checkUsernameAuthMatch(t,r);let s=Zt(r);a.challengeIds&&a.challengeIds.length>0&&(s["Taler-Challenge-Ids"]=a.challengeIds.join(", "));let c=await this.httpLib.fetch(o.href,{method:"POST",headers:s,body:n});switch(c.status){case l.Ok:return se(c,jh());case l.Accepted:return mt(c,c.status,Or());case l.Unauthorized:return I(c.status,c);case l.Forbidden:{let u=await it(c);switch(u.code){case G.GENERIC_FORBIDDEN:return Ce(u.code,u);case G.BANK_ACCOUNT_LOCKED:return Ce(u.code,u);default:return V(c,u)}}case l.NotFound:return I(c.status,c);default:return V(c)}}async createAccessTokenBasic(t,r,n){return this.createAccessToken(t,{type:"basic",username:t,password:r},n)}async deleteAccessToken(t,r){let n=new URL(`accounts/${t}/token`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"DELETE",headers:{Authorization:ve(r)}});switch(a.status){case l.Ok:return ke();case l.NoContent:return ke();case l.NotFound:return I(a.status,a);default:return V(a)}}async getAccessTokenList(t,r){let n=new URL(`accounts/${t}/token`,this.baseUrl);At(n,r);let a=await this.httpLib.fetch(n.href,{method:"GET"});switch(a.status){case l.Ok:return se(a,Ui());case l.NoContent:return Ke({public_accounts:[]});case l.NotFound:return Ke({public_accounts:[]});default:return V(a)}}async getConfig(){let t=new URL("config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return rr("taler-corebank",e.PROTOCOL_VERSION,r,Al());case l.NotFound:return I(r.status,r);default:return V(r)}}async createAccount(t,r){let n=new URL("accounts",this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:Zt(t)});switch(a.status){case l.Ok:return await this.cacheEvictor.notifySuccess(Gt.CREATE_ACCOUNT),se(a,Pl());case l.BadRequest:return I(a.status,a);case l.Unauthorized:return I(a.status,a);case l.Conflict:{let o=await it(a);switch(o.code){case G.BANK_REGISTER_USERNAME_REUSE:return Ce(o.code,o);case G.BANK_REGISTER_PAYTO_URI_REUSE:return Ce(o.code,o);case G.BANK_UNALLOWED_DEBIT:return Ce(o.code,o);case G.BANK_RESERVED_USERNAME_CONFLICT:return Ce(o.code,o);case G.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:return Ce(o.code,o);case G.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:return Ce(o.code,o);case G.BANK_NON_ADMIN_SET_TAN_CHANNEL:return Ce(o.code,o);case G.BANK_TAN_CHANNEL_NOT_SUPPORTED:return Ce(o.code,o);case G.BANK_MISSING_TAN_INFO:return Ce(o.code,o);case G.BANK_PASSWORD_TOO_SHORT:return Ce(o.code,o);case G.BANK_PASSWORD_TOO_LONG:return Ce(o.code,o);case G.BANK_CONVERSION_RATE_CLASS_UNKNOWN:return Ce(o.code,o);default:return V(a,o)}}default:return V(a)}}async deleteAccount(t,r={}){let n=new URL(`accounts/${t.username}`,this.baseUrl),a={};a.Authorization=ve(t.token),r.challengeIds&&r.challengeIds.length>0&&(a["Taler-Challenge-Ids"]=r.challengeIds.join(", "));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.Accepted:return await this.cacheEvictor.notifySuccess(Gt.DELETE_ACCOUNT),mt(o,o.status,Or());case l.NoContent:return ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);case l.Conflict:{let s=await it(o);switch(s.code){case G.BANK_RESERVED_USERNAME_CONFLICT:return Ce(s.code,s);case G.BANK_ACCOUNT_BALANCE_NOT_ZERO:return Ce(s.code,s);default:return V(o,s)}}default:return V(o)}}async updateAccount(t,r,n={}){let a=new URL(`accounts/${t.username}`,this.baseUrl),o={};o.Authorization=ve(t.token),n.challengeIds&&n.challengeIds.length>0&&(o["Taler-Challenge-Ids"]=n.challengeIds.join(", "));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:r,headers:o});switch(s.status){case l.Accepted:return mt(s,s.status,Or());case l.NoContent:return await this.cacheEvictor.notifySuccess(Gt.UPDATE_ACCOUNT),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:{let c=await it(s);switch(c.code){case G.BANK_NON_ADMIN_PATCH_LEGAL_NAME:return Ce(c.code,c);case G.BANK_NON_ADMIN_PATCH_CASHOUT:return Ce(c.code,c);case G.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:return Ce(c.code,c);case G.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:return Ce(c.code,c);case G.BANK_TAN_CHANNEL_NOT_SUPPORTED:return Ce(c.code,c);case G.BANK_MISSING_TAN_INFO:return Ce(c.code,c);case G.BANK_PASSWORD_TOO_SHORT:return Ce(c.code,c);case G.BANK_PASSWORD_TOO_LONG:return Ce(c.code,c);case G.BANK_CONVERSION_RATE_CLASS_UNKNOWN:return Ce(c.code,c);default:return V(s,c)}}default:return V(s)}}async updatePassword(t,r,n={}){let a=new URL(`accounts/${t.username}/auth`,this.baseUrl),o={};o.Authorization=ve(t.token),n.challengeIds&&n.challengeIds.length>0&&(o["Taler-Challenge-Ids"]=n.challengeIds.join(", "));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:r,headers:o});switch(s.status){case l.Accepted:return mt(s,s.status,Or());case l.NoContent:return ke();case l.NotFound:return I(s.status,s);case l.Unauthorized:return I(s.status,s);case l.Forbidden:return I(s.status,s);case l.Conflict:{let c=await it(s);switch(c.code){case G.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD:return Ce(c.code,c);case G.BANK_PATCH_BAD_OLD_PASSWORD:return Ce(c.code,c);case G.BANK_PASSWORD_TOO_SHORT:return Ce(c.code,c);case G.BANK_PASSWORD_TOO_LONG:return Ce(c.code,c);default:return V(s,c)}}default:return V(s)}}async getPublicAccounts(t={},r){let n=new URL("public-accounts",this.baseUrl);At(n,r),t.account!==void 0&&n.searchParams.set("filter_name",t.account);let a=await this.httpLib.fetch(n.href,{method:"GET"});switch(a.status){case l.Ok:return se(a,Nl());case l.NoContent:return Ke({public_accounts:[]});case l.NotFound:return Ke({public_accounts:[]});default:return V(a)}}async listAccounts(t,r){let n=new URL("accounts",this.baseUrl);At(n,r),r?.account!==void 0&&n.searchParams.set("filter_name",r.account),r?.conversionRateId!==void 0&&n.searchParams.set("conversion_rate_class_id",String(r.conversionRateId));let a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t)}});switch(a.status){case l.Ok:return se(a,Rl());case l.NoContent:return Ke({accounts:[]});case l.Unauthorized:return I(a.status,a);default:return V(a)}}async getAccount(t){let r=new URL(`accounts/${t.username}`,this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"GET",headers:{Authorization:ve(t.token)}});switch(n.status){case l.Ok:return se(n,xl());case l.Unauthorized:return I(n.status,n);case l.NotFound:return I(n.status,n);default:return V(n)}}async getTransactions(t,r){let n=new URL(`accounts/${t.username}/transactions`,this.baseUrl);At(n,r),Zr(n,r);let a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t.token)}});switch(a.status){case l.Ok:return se(a,Ol());case l.NoContent:return Ke({transactions:[]});case l.Unauthorized:return I(a.status,a);case l.NotFound:return I(a.status,a);default:return V(a)}}async getTransactionById(t,r){let n=new URL(`accounts/${t.username}/transactions/${String(r)}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t.token)}});switch(a.status){case l.Ok:return se(a,Zi());case l.NotFound:return I(a.status,a);case l.Unauthorized:return I(a.status,a);default:return V(a)}}async createTransaction(t,r,n={}){let a=new URL(`accounts/${t.username}/transactions`,this.baseUrl),o={};o.Authorization=ve(t.token),n.challengeIds&&n.challengeIds.length>0&&(o["Taler-Challenge-Ids"]=n.challengeIds.join(", "));let s=await this.httpLib.fetch(a.href,{method:"POST",headers:o,body:r});switch(s.status){case l.Ok:return await this.cacheEvictor.notifySuccess(Gt.CREATE_TRANSACTION),se(s,Dl());case l.Accepted:return mt(s,s.status,Or());case l.BadRequest:return I(s.status,s);case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:{let c=await it(s);switch(c.code){case G.BANK_ADMIN_CREDITOR:return Ce(c.code,c);case G.BANK_SAME_ACCOUNT:return Ce(c.code,c);case G.BANK_UNKNOWN_CREDITOR:return Ce(c.code,c);case G.BANK_UNALLOWED_DEBIT:return Ce(c.code,c);case G.BANK_TRANSFER_REQUEST_UID_REUSED:return Ce(c.code,c);default:return V(s,c)}}default:return V(s)}}async createWithdrawal(t,r){let n=new URL(`accounts/${t.username}/withdrawals`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",headers:{Authorization:ve(t.token)},body:r});switch(a.status){case l.Ok:return await this.cacheEvictor.notifySuccess(Gt.CREATE_WITHDRAWAL),se(a,Ll());case l.NotFound:return I(a.status,a);case l.Conflict:return I(a.status,a);case l.Unauthorized:return I(a.status,a);default:return V(a)}}async confirmWithdrawalById(t,r,n,a={}){let o=new URL(`accounts/${t.username}/withdrawals/${n}/confirm`,this.baseUrl),s={};s.Authorization=ve(t.token),a.challengeIds&&a.challengeIds.length>0&&(s["Taler-Challenge-Ids"]=a.challengeIds.join(", "));let c=await this.httpLib.fetch(o.href,{method:"POST",headers:s,body:r});switch(c.status){case l.Accepted:return mt(c,c.status,Or());case l.NoContent:return await this.cacheEvictor.notifySuccess(Gt.CONFIRM_WITHDRAWAL),ke();case l.BadRequest:return I(c.status,c);case l.NotFound:return I(c.status,c);case l.Conflict:{let u=await it(c);switch(u.code){case G.BANK_CONFIRM_ABORT_CONFLICT:return Ce(u.code,u);case G.BANK_CONFIRM_INCOMPLETE:return Ce(u.code,u);case G.BANK_UNALLOWED_DEBIT:return Ce(u.code,u);case G.BANK_AMOUNT_DIFFERS:return Ce(u.code,u);case G.BANK_AMOUNT_REQUIRED:return Ce(u.code,u);default:return V(c,u)}}default:return V(c)}}async abortWithdrawalById(t,r){let n=new URL(`accounts/${t.username}/withdrawals/${r}/abort`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",headers:{Authorization:ve(t.token)}});switch(a.status){case l.NoContent:return await this.cacheEvictor.notifySuccess(Gt.ABORT_WITHDRAWAL),ke();case l.BadRequest:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.Conflict:return I(a.status,a);default:return V(a)}}async getWithdrawalById(t,r){let n=new URL(`withdrawals/${t}`,this.baseUrl);Zr(n,r),r&&n.searchParams.set("old_state",r.old_state?r.old_state:"pending");let a=await this.httpLib.fetch(n.href,{method:"GET"});switch(a.status){case l.Ok:return se(a,Cl());case l.BadRequest:return I(a.status,a);case l.NotFound:return I(a.status,a);default:return V(a)}}async createCashout(t,r,n={}){let a=new URL(`accounts/${t.username}/cashouts`,this.baseUrl),o={};o.Authorization=ve(t.token),n.challengeIds&&n.challengeIds.length>0&&(o["Taler-Challenge-Ids"]=n.challengeIds.join(", "));let s=await this.httpLib.fetch(a.href,{method:"POST",headers:o,body:r});switch(s.status){case l.Ok:return await this.cacheEvictor.notifySuccess(Gt.CREATE_CASHOUT),se(s,Ul());case l.Accepted:return mt(s,s.status,Or());case l.NotFound:return I(s.status,s);case l.Conflict:{let u=await it(s);switch(u.code){case G.BANK_TRANSFER_REQUEST_UID_REUSED:return Ce(u.code,u);case G.BANK_BAD_CONVERSION:return Ce(u.code,u);case G.BANK_CONVERSION_AMOUNT_TO_SMALL:return Ce(u.code,u);case G.BANK_UNALLOWED_DEBIT:return Ce(u.code,u);case G.BANK_CONFIRM_INCOMPLETE:return Ce(u.code,u);default:return V(s,u)}}case l.BadGateway:{let u=await it(s);return u.code===G.BANK_TAN_CHANNEL_SCRIPT_FAILED?Ce(u.code,u):V(s,u)}case l.NotImplemented:let c=await it(s);return c.code===G.BANK_TAN_CHANNEL_NOT_SUPPORTED?Ce(c.code,c):I(s.status,s);default:return V(s)}}async getCashoutById(t,r){let n=new URL(`accounts/${t.username}/cashouts/${r}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t.token)}});switch(a.status){case l.Ok:return se(a,Fl());case l.NotFound:return I(a.status,a);case l.NotImplemented:return I(a.status,a);default:return V(a)}}async getAccountCashouts(t,r){let n=new URL(`accounts/${t.username}/cashouts`,this.baseUrl);At(n,r);let a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t.token)}});switch(a.status){case l.Ok:return se(a,Ml());case l.NoContent:return Ke({cashouts:[]});case l.NotImplemented:return I(a.status,a);default:return V(a)}}async getGlobalCashouts(t,r){let n=new URL("cashouts",this.baseUrl);At(n,r);let a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t)}});switch(a.status){case l.Ok:return se(a,kl());case l.NoContent:return Ke({cashouts:[]});case l.NotImplemented:return I(a.status,a);default:return V(a)}}async createConversionRateClass(t,r){let n=new URL("conversion-rate-classes",this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",headers:{Authorization:ve(t)},body:r});switch(a.status){case l.Ok:return await this.cacheEvictor.notifySuccess(Gt.CREATE_CONVERSION_RATE_CLASS),se(a,Il());case l.Unauthorized:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.Conflict:{let o=await it(a);return o.code===G.BANK_NAME_REUSE?Ce(o.code,o):V(a,o)}case l.NotImplemented:return I(a.status,a);default:return V(a)}}async updateConversionRateClass(t,r,n){let a=new URL(`conversion-rate-classes/${r}`,this.baseUrl),o=await this.httpLib.fetch(a.href,{method:"PATCH",headers:{Authorization:ve(t)},body:n});switch(o.status){case l.NoContent:return await this.cacheEvictor.notifySuccess(Gt.UPDATE_CONVERSION_RATE_CLASS),ke();case l.Unauthorized:return I(o.status,o);case l.Forbidden:return I(o.status,o);case l.NotFound:return I(o.status,o);case l.Conflict:{let s=await it(o);return s.code===G.BANK_NAME_REUSE?Ce(s.code,s):V(o,s)}case l.NotImplemented:return I(o.status,o);default:return V(o)}}async deleteConversionRateClass(t,r){let n=new URL(`conversion-rate-classes/${r}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"DELETE",headers:{Authorization:ve(t)}});switch(a.status){case l.NoContent:return await this.cacheEvictor.notifySuccess(Gt.DELETE_CONVERSION_RATE_CLASS),ke();case l.Unauthorized:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.NotImplemented:return I(a.status,a);default:return V(a)}}async getConversionRateClass(t,r){let n=new URL(`conversion-rate-classes/${r}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t)}});switch(a.status){case l.Ok:return se(a,Qi());case l.Unauthorized:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.NotImplemented:return I(a.status,a);default:return V(a)}}async listConversionRateClasses(t,r={}){let n=new URL("conversion-rate-classes",this.baseUrl);At(n,r),r.className&&n.searchParams.set("filter_name",r.className);let a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t)}});switch(a.status){case l.Ok:return se(a,Sl());case l.NoContent:return Ke({classes:[],default:{}});case l.Unauthorized:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.NotImplemented:return I(a.status,a);default:return V(a)}}async sendChallenge(t,r){let n=new URL(`accounts/${t}/challenge/${r}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST"});switch(a.status){case l.Ok:return se(a,ji());case l.NoContent:return Ke({});case l.Unauthorized:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.TooManyRequests:return I(a.status,a);case l.BadGateway:{let o=await it(a);return o.code===G.BANK_TAN_CHANNEL_SCRIPT_FAILED?Ce(o.code,o):V(a,o)}default:return V(a)}}async confirmChallenge(t,r,n){let a=new URL(`accounts/${t}/challenge/${r}/confirm`,this.baseUrl),o=await this.httpLib.fetch(a.href,{method:"POST",body:n});switch(o.status){case l.NoContent:return ke();case l.Unauthorized:return I(o.status,o);case l.Conflict:{let s=await it(o);switch(s.code){case G.BANK_TAN_CHALLENGE_FAILED:return Ce(s.code,s);case G.BANK_TAN_CHALLENGE_EXPIRED:return Ce(s.code,s);default:return V(o,s)}}case l.NotFound:{let s=await it(o);switch(s.code){case G.BANK_TRANSACTION_NOT_FOUND:return Ce(s.code,s);case G.BANK_TAN_CHALLENGE_EXPIRED:return Ce(s.code,s);default:return V(o,s)}}case l.TooManyRequests:return I(o.status,o);default:return V(o)}}async getMonitor(t,r={}){let n=new URL("monitor",this.baseUrl);if(r.timeframe&&n.searchParams.set("timeframe",Uo[r.timeframe]),r.date){let{t_s:o}=he.toProtocolTimestamp(r.date);o!=="never"&&n.searchParams.set("date_s",String(o))}let a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t)}});switch(a.status){case l.Ok:return se(a,Hl());case l.BadRequest:return I(a.status,a);case l.Unauthorized:return I(a.status,a);default:return V(a)}}getIntegrationAPI(){return new URL("taler-integration/",this.baseUrl)}getWireGatewayAPI(t){return new URL(`accounts/${t}/taler-wire-gateway/`,this.baseUrl)}getRevenueAPI(t){return new URL(`accounts/${t}/taler-revenue/`,this.baseUrl)}getConversionInfoAPIForUser(t){return new URL(`accounts/${t}/conversion-info/`,this.baseUrl)}getConversionInfoAPIForClass(t){return new URL(`conversion-rate-classes/${String(t)}/conversion-info/`,this.baseUrl)}getConversionInfoAPI(){return new URL("conversion-info/",this.baseUrl)}};Ha.PROTOCOL_VERSION="10:0:2";var x_=()=>W().property("status",pt(X("pending"),X("selected"),X("aborted"),X("confirmed"))).property("currency",U($h())).property("amount",U(me())).property("suggested_amount",U(me())).property("min_amount",U(me())).property("max_amount",U(me())).property("card_fees",U(me())).property("sender_wire",U(xt())).property("suggested_exchange",U(Tr())).property("required_exchange",U(Tr())).property("confirm_transfer_url",U(Tr())).property("wire_types",Ae(L())).property("selected_reserve_pub",U(L())).property("selected_exchange_account",U(L())).property("no_amount_to_wallet",U(Se())).deprecatedProperty("aborted").deprecatedProperty("selection_done").deprecatedProperty("transfer_done").build("TalerBankIntegrationApi.BankWithdrawalOperationStatus"),I_=()=>W().property("status",pt(X("selected"),X("aborted"),X("confirmed"))).property("confirm_transfer_url",U(Tr())).deprecatedProperty("transfer_done").build("TalerBankIntegrationApi.BankWithdrawalOperationPostResponse");var rF=new Dt("bank-integration.ts"),Gl=class e{constructor(t,r){this.baseUrl=t,this.httpLib=r??jt()}static isCompatible(t){return St.compare(this.PROTOCOL_VERSION,t)?.compatible??!1}async getConfig(){let t=new URL("config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});return r.status===l.Ok?rr("taler-bank-integration",e.PROTOCOL_VERSION,r,wl()):V(r)}async getWithdrawalOperationById(t,r){let n=new URL(`withdrawal-operation/${t}`,this.baseUrl);Zr(n,r),r&&n.searchParams.set("old_state",r.old_state?r.old_state:"pending");let a=await this.httpLib.fetch(n.href,{method:"GET"});switch(a.status){case l.Ok:return se(a,x_());case l.NotFound:return I(a.status,a);default:return V(a)}}async completeWithdrawalOperationById(t,r){let n=new URL(`withdrawal-operation/${t}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});switch(a.status){case l.Ok:return se(a,I_());case l.NotFound:return I(a.status,a);case l.Conflict:{let o=await it(a),s=Vr().decode(o);switch(s.code){case G.BANK_UPDATE_ABORT_CONFLICT:return Ce(s.code,s);case G.BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT:return Ce(s.code,s);case G.BANK_DUPLICATE_RESERVE_PUB_SUBJECT:return Ce(s.code,s);case G.BANK_UNKNOWN_ACCOUNT:return Ce(s.code,s);case G.BANK_ACCOUNT_IS_NOT_EXCHANGE:return Ce(s.code,s);case G.BANK_AMOUNT_DIFFERS:return Ce(s.code,s);case G.BANK_UNALLOWED_DEBIT:return Ce(s.code,s);default:return V(a,s)}}default:return V(a)}}async abortWithdrawalOperationById(t){let r=new URL(`withdrawal-operation/${t}/abort`,this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST"});switch(n.status){case l.NoContent:return ke();case l.NotFound:return I(n.status,n);case l.Conflict:return I(n.status,n);default:return V(n)}}};Gl.PROTOCOL_VERSION="5:0:0";var S_=()=>W().property("name",X("taler-revenue")).property("version",L()).property("currency",L()).property("implementation",U(L())).build("TalerRevenueApi.RevenueConfig"),C_=()=>W().property("credit_account",xt()).property("incoming_transactions",Ae(FN())).build("TalerRevenueApi.MerchantIncomingHistory"),FN=()=>W().property("row_id",ne()).property("date",Me).property("amount",me()).property("debit_account",xt()).property("subject",L()).build("TalerRevenueApi.RevenueIncomingBankTransaction");var Bl=class e{constructor(t,r){this.baseUrl=t,this.httpLib=r??jt()}static isCompatible(t){return St.compare(this.PROTOCOL_VERSION,t)?.compatible??!1}async getConfig(t){let r=new URL("config",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"GET",headers:Zt(t)});switch(n.status){case l.Ok:return rr("taler-revenue",e.PROTOCOL_VERSION,n,S_());case l.Unauthorized:return I(n.status,n);case l.NotFound:return I(n.status,n);default:return V(n)}}async getHistory(t,r){let n=new URL("history",this.baseUrl);At(n,r),Zr(n,r);let a=await this.httpLib.fetch(n.href,{method:"GET",headers:Zt(t)});switch(a.status){case l.Ok:return se(a,C_());case l.NoContent:return Ke({incoming_transactions:[],credit_account:""});case l.BadRequest:return I(a.status,a);case l.Unauthorized:return I(a.status,a);case l.NotFound:return I(a.status,a);default:return V(a)}}};Bl.PROTOCOL_VERSION="1:0:0";var O_=()=>W().property("currency",L()).property("implementation",L()).property("name",X("taler-wire-gateway")).property("support_account_check",Se()).property("version",L()).build("TalerWireGatewayApi.WireConfig"),D_=()=>W().property("row_id",ne()).property("timestamp",Me).build("TalerWireGatewayApi.TransferResponse"),P_=()=>W().property("credit_account",xt()).property("incoming_transactions",Ae(GN())).build("TalerWireGatewayApi.IncomingHistory"),GN=()=>wt().discriminateOn("type").alternative("RESERVE",BN()).alternative("KYCAUTH",WN()).alternative("WAD",VN()).build("TalerWireGatewayApi.IncomingBankTransaction"),BN=()=>W().property("amount",me()).property("date",Me).property("debit_account",xt()).property("reserve_pub",Ft()).property("row_id",ne()).property("type",X("RESERVE")).property("authorization_pub",U(Ft())).property("authorization_sig",U(Nr())).build("TalerWireGatewayApi.IncomingReserveTransaction"),WN=()=>W().property("amount",me()).property("date",Me).property("debit_account",xt()).property("account_pub",Ft()).property("row_id",ne()).property("type",X("KYCAUTH")).property("authorization_pub",U(Ft())).property("authorization_sig",U(Nr())).build("TalerWireGatewayApi.IncomingKycAuthTransaction"),VN=()=>W().property("amount",me()).property("date",Me).property("debit_account",xt()).property("origin_exchange_url",L()).property("row_id",ne()).property("type",X("WAD")).property("wad_id",L()).property("authorization_pub",U(Ft())).property("authorization_sig",U(Nr())).build("TalerWireGatewayApi.IncomingWadTransaction"),L_=()=>W().property("debit_account",xt()).property("outgoing_transactions",Ae(qN())).build("TalerWireGatewayApi.OutgoingHistory"),qN=()=>W().property("row_id",ne()).property("date",Me).property("amount",me()).property("credit_account",xt()).property("wtid",L()).property("exchange_base_url",L()).build("TalerWireGatewayApi.OutgoingBankTransaction"),Ji=()=>W().property("row_id",ne()).property("timestamp",Me).build("TalerWireGatewayApi.AddIncomingResponse"),Wl=()=>W().property("debit_account",xt()).property("transfers",Ae(KN())).build("TalerWireGatewayApi.BankWireTransferList");var KN=()=>W().property("row_id",ne()).property("status",pt(X("pending"),X("transient_failure"),X("permanent_failure"),X("success"))).property("amount",me()).property("credit_account",xt()).property("timestamp",Me).build("TalerWireGatewayApi.BankWireTransferListStatus");var Vl=class e{constructor(t,r={}){this.baseUrl=t,this.httpLib=r.httpClient??jt()}static isCompatible(t){return St.compare(this.PROTOCOL_VERSION,t)?.compatible??!1}async getConfig(){let t=new URL("config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return rr("taler-wire-gateway",e.PROTOCOL_VERSION,r,O_());case l.NotFound:return I(r.status,r);default:return V(r)}}async makeWireTransfer(t){let r=new URL("transfer",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",headers:Zt(t.auth),body:t.body});switch(n.status){case l.Ok:return se(n,D_());case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);case l.Conflict:{let a=await it(n),o=Vr().decode(a);switch(o.code){case G.BANK_TRANSFER_REQUEST_UID_REUSED:case G.BANK_TRANSFER_WTID_REUSED:return Ce(o.code,o);default:return I(n.status,n,o)}}default:return V(n)}}async getTransfers(t){let r=new URL("transfers",this.baseUrl);t.params&&t.params.status&&r.searchParams.set("status",t.params.status),At(r,t.params);let n=await this.httpLib.fetch(r.href,{method:"GET",headers:Zt(t.auth)});switch(n.status){case l.Ok:return se(n,Wl());case l.NoContent:return Ke({transfers:[],debit_account:void 0});case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);default:return V(n)}}async getTransferStatus(t){let r=new URL(`transfers/${t.rowId}`,this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"GET",headers:Zt(t.auth)});switch(n.status){case l.Ok:return se(n,Wl());case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);default:return V(n)}}async getHistoryIncoming(t){let r=new URL("history/incoming",this.baseUrl);At(r,t.params),Zr(r,t.params);let n=await this.httpLib.fetch(r.href,{method:"GET",headers:Zt(t.auth)});switch(n.status){case l.Ok:return se(n,P_());case l.NoContent:return Ke({incoming_transactions:[],credit_account:void 0});case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);default:return V(n)}}async getHistoryOutgoing(t){let r=new URL("history/outgoing",this.baseUrl);At(r,t.params),Zr(r,t.params);let n=await this.httpLib.fetch(r.href,{method:"GET",headers:Zt(t.auth)});switch(n.status){case l.Ok:return se(n,L_());case l.NoContent:return Ke({outgoing_transactions:[],debit_account:void 0});case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);default:return V(n)}}async addIncoming(t){let r=new URL("admin/add-incoming",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",headers:Zt(t.auth),body:t.body});switch(n.status){case l.Ok:return se(n,Ji());case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);case l.Conflict:{let a=await it(n),o=Vr().decode(a);return o.code===G.BANK_DUPLICATE_RESERVE_PUB_SUBJECT?Ce(o.code,o):I(n.status,n,o)}default:return V(n)}}async addKycAuth(t){let r=new URL("admin/add-kycauth",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",headers:Zt(t.auth),body:t.body});switch(n.status){case l.Ok:return se(n,Ji());case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);default:return V(n)}}async addMapped(t){let r=new URL("admin/add-mapped",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",headers:Zt(t.auth),body:t.body});switch(n.status){case l.Ok:return se(n,Ji());case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);case l.Conflict:{let a=await it(n),o=Vr().decode(a);switch(o.code){case G.BANK_TRANSFER_MAPPING_UNKNOWN:case G.BANK_TRANSFER_MAPPING_REUSED:return Ce(o.code,o);default:return I(n.status,n,o)}}default:return V(n)}}};Vl.PROTOCOL_VERSION="5:0:1";var YN=()=>pt(X("SIMPLE"),X("URI"),X("CH_QR_BILL")),M_=()=>W().property("currency",L()).property("implementation",U(L())).property("name",X("taler-prepared-transfer")).property("supported_formats",Ae(YN())).property("version",L()).build("TalerPreparedTransferApi.PreparedTransferConfig");var zN=()=>wt().discriminateOn("type").alternative("SIMPLE",$N()).alternative("URI",XN()).alternative("CH_QR_BILL",jN()).build("TalerPreparedTransferApi.TransferSubject"),$N=()=>W().property("type",X("SIMPLE")).property("credit_amount",me()).property("subject",L()).build("TalerPreparedTransferApi.SimpleSubject"),XN=()=>W().property("type",X("URI")).property("credit_amount",me()).property("uri",ca()).build("TalerPreparedTransferApi.UriSubject"),jN=()=>W().property("type",X("CH_QR_BILL")).property("credit_amount",me()).property("qr_reference_number",L()).build("TalerPreparedTransferApi.SwissQrBillSubject"),k_=()=>W().property("subjects",Ae(zN())).property("expiration",Me).build("TalerWireGatewayApi.RegistrationResponse");var ql=class e{constructor(t,r={}){this.baseUrl=t,this.httpLib=r.httpClient??jt()}static isCompatible(t){return St.compare(this.PROTOCOL_VERSION,t)?.compatible??!1}async getConfig(){let t=new URL("config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return rr("taler-prepared-transfer",e.PROTOCOL_VERSION,r,M_());case l.NotFound:return I(r.status,r);default:return V(r)}}async register(t){let r=new URL("registration",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",body:t});switch(console.log(t),n.status){case l.Ok:return se(n,k_());case l.BadRequest:case l.Unauthorized:case l.NotFound:case l.Conflict:return I(n.status,n);default:return V(n)}}async unregister(t){let r=new URL("unregistration",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",body:t});switch(n.status){case l.NoContent:return ke();case l.BadRequest:case l.Unauthorized:case l.NotFound:return I(n.status,n);case l.Conflict:{let a=await it(n),o=Vr().decode(a);switch(o.code){case G.BANK_OLD_TIMESTAMP:case G.BANK_BAD_SIGNATURE:return Ce(o.code,o);default:return I(n.status,n,o)}}default:return V(n)}}};ql.PROTOCOL_VERSION="0:0:0";var F_=()=>W().property("name",X("challenger")).property("version",L()).property("implementation",U(L())).property("restrictions",U(Ar(He()))).property("address_type",pt(X("phone"),X("email"),X("postal"),X("postal-ch"))).build("ChallengerApi.ChallengerTermsOfServiceResponse"),H_=()=>W().property("nonce",L()).build("ChallengerApi.ChallengeSetupResponse"),G_=()=>W().property("fix_address",Se()).property("solved",Se()).property("last_address",U(Ar(He()))).property("changes_left",ne()).property("retransmission_time",Me).property("pin_transmissions_left",ne()).property("auth_attempts_left",ne()).build("ChallengerApi.ChallengeStatus"),B_=()=>wt().discriminateOn("type").alternative("completed",W_()).alternative("created",ZN()).build("ChallengerApi.ChallengeResponse"),ZN=()=>W().property("attempts_left",ne()).property("type",X("created")).property("nonce",U(L())).property("address",He()).property("transmitted",Se()).property("retransmission_time",Me).build("ChallengerApi.ChallengeCreateResponse"),W_=()=>W().property("type",X("completed")).property("redirect_url",L()).build("ChallengerApi.ChallengeRedirect"),Kl=()=>W().property("ec",U(ne())).property("code",U(ne())).property("hint",He()).property("type",X("pending")).property("addresses_left",ne()).property("pin_transmissions_left",ne()).property("auth_attempts_left",ne()).property("exhausted",Se()).property("no_challenge",Se()).build("ChallengerApi.InvalidPinResponse"),V_=()=>wt().discriminateOn("type").alternative("completed",W_()).alternative("pending",Kl()).build("ChallengerApi.ChallengeSolveResponse"),q_=()=>W().property("access_token",L()).property("token_type",He()).property("expires_in",ne()).build("ChallengerApi.ChallengerAuthResponse"),K_=()=>W().property("id",ne()).property("address",He()).property("address_type",L()).property("expires",Me).build("ChallengerApi.ChallengerInfoResponse");var es;(function(e){e[e.CREATE_CHALLENGE=0]="CREATE_CHALLENGE",e[e.SOLVE_CHALLENGE=1]="SOLVE_CHALLENGE"})(es||(es={}));var ts=class e{constructor(t,r,n){this.baseUrl=t,this.httpLib=r??jt(),this.cacheEvictor=n??gn}static isCompatible(t){return St.compare(this.PROTOCOL_VERSION,t)?.compatible??!1}async getConfig(){let t=new URL("config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return rr("challenger",e.PROTOCOL_VERSION,r,F_());case l.NotFound:return I(r.status,r);default:return V(r)}}async setup(t,r,n){let a=new URL(`setup/${t}`,this.baseUrl),o=await this.httpLib.fetch(a.href,{method:"POST",body:n,headers:{Authorization:ve(r)}});switch(o.status){case l.Ok:return se(o,H_());case l.NotFound:return I(o.status,o);default:return V(o)}}async login(t,r,n,a){let o=new URL(`authorize/${t}`,this.baseUrl);o.searchParams.set("response_type","code"),o.searchParams.set("client_id",r),o.searchParams.set("redirect_uri",n),a&&o.searchParams.set("state",a);let s=await this.httpLib.fetch(o.href,{method:"POST"});switch(s.status){case l.Ok:return se(s,G_());case l.BadRequest:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.NotAcceptable:return I(s.status,s);case l.TooManyRequests:return I(s.status,s);case l.InternalServerError:return I(s.status,s);default:return V(s)}}async challenge(t,r){let n=new URL(`challenge/${t}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});switch(a.status){case l.Ok:return await this.cacheEvictor.notifySuccess(es.CREATE_CHALLENGE),se(a,B_());case l.BadRequest:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.NotAcceptable:return I(a.status,a);case l.TooManyRequests:return I(a.status,a);case l.InternalServerError:return I(a.status,a);default:return V(a)}}async solve(t,r){let n=new URL(`solve/${t}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:new URLSearchParams(Object.entries(r)).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded"},redirect:"manual"});switch(a.status){case l.Ok:return await this.cacheEvictor.notifySuccess(es.SOLVE_CHALLENGE),se(a,V_());case l.BadRequest:return I(a.status,a);case l.Forbidden:return mt(a,l.Forbidden,Kl());case l.NotFound:return I(a.status,a);case l.NotAcceptable:return I(a.status,a);case l.TooManyRequests:return I(a.status,a);case l.InternalServerError:return I(a.status,a);default:return V(a)}}async token(t,r,n,a){let o=new URL("token",this.baseUrl),s=await this.httpLib.fetch(o.href,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams(Object.entries({client_id:t,redirect_uri:r,client_secret:n,code:a,grant_type:"authorization_code"})).toString()});switch(s.status){case l.Ok:return se(s,q_());case l.Forbidden:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async info(t){let r=new URL("info",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"GET",headers:{Authorization:ve(t)}});switch(n.status){case l.Ok:return se(n,K_());case l.Forbidden:return I(n.status,n);case l.NotFound:return I(n.status,n);default:return V(n)}}};ts.PROTOCOL_VERSION="2:0:0";var Y_=()=>W().property("version",L()).property("name",X("donau")).property("currency",L()).property("legal_domain",L()).build("DonauApi.DonauVersionResponse");var eR=He(),z_=()=>W().property("version",L()).property("base_url",L()).property("currency",L()).property("signkeys",He()).property("donation_units",Ae(eR)).build("DonauApi.DonauKeysResponse"),$_=()=>wt().discriminateOn("cipher").alternative("CS",He()).alternative("RSA",He()).build("DonauApi.IssuePrepareResponse"),X_=()=>W().property("charity_id",ne()).build("DonauApi.DonauCharityResponse"),j_=()=>W().property("total",me()).property("donau_pub",Ft()).property("donation_statement_sig",Nr()).build("DonauApi.DonationStatementResponse");var Yl=class e{constructor(t,r={}){this.baseUrl=t,this.httpLib=r.httpClient??jt()}static isCompatible(t){return St.compare(e.SUPPORTED_DONAU_PROTOCOL_VERSION,t)?.compatible??!1}async getKeys(){let t=new URL("keys",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});return r.status===l.Ok?se(r,z_()):V(r)}async getSeed(){let t=new URL("keys",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:let n=await r.bytes(),a=new Uint8Array(n);return Ke(a);case l.NotFound:return I(r.status,r);default:return V(r)}}async getConfig(){let t=new URL("config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return rr("donau",e.SUPPORTED_DONAU_PROTOCOL_VERSION,r,Y_());case l.NotFound:return I(r.status,r);default:return V(r)}}async prepareIssueReceipt(t){let r=new URL("csr-issue",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",body:t});switch(n.status){case l.Ok:return se(n,$_());case l.NotFound:return Tt(n.status);case l.Gone:return Tt(n.status);default:return V(n)}}async issueReceipts(t,r){let n=new URL(`batch-issue/${t}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});switch(a.status){case l.Ok:return se(a,He());case l.Forbidden:return Tt(a.status);case l.NotFound:return Tt(a.status);case l.Conflict:return Tt(a.status);case l.Gone:return Tt(a.status);default:return V(a)}}async submitDonationReceipts(t){let r=new URL("batch-submit",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",body:t});switch(n.status){case l.Created:return ke();case l.Forbidden:return Tt(n.status);case l.NotFound:return Tt(n.status);default:return V(n)}}async getDonationStatement(t,r){let n=new URL(`donation-statement/${t}/${r}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"GET"});switch(a.status){case l.Ok:return se(a,j_());case l.Forbidden:return Tt(a.status);case l.NotFound:return Tt(a.status);default:return V(a)}}async getCharities(t){let r=new URL("charities",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"GET",headers:{Authorization:ve(t)}});switch(n.status){case l.Ok:return se(n,He());case l.NoContent:return Ke({charities:[]});default:return V(n)}}async getCharitiesById(t,r){let n=new URL(`charities/${r}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t)}});switch(a.status){case l.Ok:return se(a,He());case l.NotFound:return Tt(a.status);default:return V(a)}}async createCharity(t,r){let n=new URL("charities",this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:{Authorization:ve(t)}});switch(a.status){case l.Created:return se(a,X_());case l.NoContent:return Tt(a.status);case l.Forbidden:return Tt(a.status);case l.NotFound:return Tt(a.status);default:return V(a)}}async updateCharity(t,r,n){let a=new URL(`charities/${r}`,this.baseUrl),o=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:{Authorization:ve(t)}});switch(o.status){case l.Ok:return ke();case l.Forbidden:return Tt(o.status);case l.NotFound:return Tt(o.status);default:return V(o)}}async deleteCharity(t,r){let n=new URL(`charities/${r}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"DELETE",headers:{Authorization:ve(t)}});switch(a.status){case l.NoContent:return ke();case l.Forbidden:return Tt(a.status);case l.NotFound:return Tt(a.status);default:return V(a)}}};Yl.SUPPORTED_DONAU_PROTOCOL_VERSION="0:0:0";var tR=new Dt("exchange-client.ts"),rs;(function(e){e[e.UPLOAD_KYC_FORM=0]="UPLOAD_KYC_FORM",e[e.MAKE_AML_DECISION=1]="MAKE_AML_DECISION"})(rs||(rs={}));var ns=class e{constructor(t,r={}){this.baseUrl=t,this.httpLib=r.httpClient??jt(),this.cacheEvictor=r.cacheEvictor??gn,this.preventCompression=!!r.preventCompression,this.cancelationToken=r.cancelationToken??xr.CONTINUE,this.longPollQueue=r.longPollQueue??new as}static isCompatible(t){return St.compare(e.SUPPORTED_EXCHANGE_PROTOCOL_VERSION,t)?.compatible??!1}async fetch(t,r={},n=!1){let a=typeof t=="string"?new URL(t,this.baseUrl):t;return n||a.searchParams.has("timeout_ms")?this.longPollQueue.run(a,this.cancelationToken,async o=>(a.searchParams.set("timeout_ms",String(o)),this.httpLib.fetch(a.href,{cancellationToken:this.cancelationToken,...r}))):this.httpLib.fetch(a.href,{cancellationToken:this.cancelationToken,...r})}async getSeed(){let t=await this.fetch("seed");switch(t.status){case l.Ok:let r=await t.bytes(),n=new Uint8Array(r);return Ke(n);case l.NotFound:return I(t.status,t);default:return V(t)}}async getConfig(){let t=await this.fetch("config");switch(t.status){case l.Ok:return rr("taler-exchange",e.SUPPORTED_EXCHANGE_PROTOCOL_VERSION,t,Rm());case l.NotFound:return I(t.status,t);default:return V(t)}}async getKeys(){let t=await this.fetch("keys");return t.status===l.Ok?se(t,xm()):V(t)}async getPurseStatusAtMerge(t,r=!1){let n=await this.fetch(`purses/${t}/merge`,{},r);switch(n.status){case l.Ok:return se(n,tl());case l.Gone:case l.NotFound:return I(n.status,n);default:return V(n)}}async getPurseStatusAtDeposit(t,r=!1){let n=await this.fetch(`purses/${t}/deposit`,{},r);switch(n.status){case l.Ok:return se(n,tl());case l.Gone:case l.NotFound:return I(n.status,n);default:return V(n)}}async createPurseFromDeposit(t,r){let n=await this.fetch(`purses/${t}/create`,{method:"POST",body:r});switch(n.status){case l.Ok:return se(n,el());case l.Conflict:return mt(n,n.status,ol());case l.Forbidden:case l.NotFound:case l.TooEarly:return I(n.status,n);default:return V(n)}}async deletePurse(t,r){let n=await this.fetch(`purses/${t}`,{method:"DELETE",headers:{"taler-purse-signature":r}});switch(n.status){case l.NoContent:return ke();case l.NotFound:return I(n.status,n);case l.Conflict:return I(n.status,n);case l.Forbidden:return I(n.status,n);default:return V(n)}}async postPurseMerge(t,r){let n=await this.fetch(`purses/${t}/merge`,{method:"POST",body:r});switch(n.status){case l.Ok:return se(n,Tm());case l.UnavailableForLegalReasons:return mt(n,n.status,Bi());case l.Conflict:return mt(n,n.status,Nm());case l.Gone:case l.Forbidden:case l.NotFound:return I(n.status,n);default:return V(n)}}async createPurseFromReserve(t,r){let n=await this.fetch(`reserves/${t}/purse`,{method:"POST",body:r});switch(n.status){case l.Ok:return se(n,el());case l.PaymentRequired:case l.Forbidden:case l.NotFound:return I(n.status,n);case l.Conflict:return mt(n,n.status,Hm());case l.UnavailableForLegalReasons:return mt(n,n.status,Bi());case l.BadRequest:{let a=await it(n);return a.code===G.EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW?Ce(a.code,a):V(n,a)}default:return V(n)}}async getContract(t){let r=await this.fetch(`contracts/${t}`);switch(r.status){case l.Ok:return se(r,Am());case l.NotFound:return I(r.status,r);default:return V(r)}}async depositIntoPurse(t,r){let n=await this.fetch(`purses/${t}/deposit`,{method:"POST",body:r});switch(n.status){case l.Ok:return se(n,He());case l.Conflict:return mt(n,n.status,ol());case l.Forbidden:case l.NotFound:case l.Gone:return I(n.status,n);default:return V(n)}}async getWadInfo(){throw Error("not yet implemented")}async notifyKycBalanceLimit(t){let r=new URL("kyc-wallet",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",body:t});switch(n.status){case l.Ok:return se(n,km());case l.NoContent:return ke();case l.Forbidden:return I(n.status,n);case l.UnavailableForLegalReasons:return mt(n,n.status,Bi());default:return V(n)}}async checkKycStatus(t){let{paytoHash:r,accountPub:n,accountSig:a,longpoll:o,awaitAuth:s}=t,c=new URL(`kyc-check/${r}`,this.baseUrl);s!==void 0&&c.searchParams.set("await_auth",s?"YES":"NO");let u=await this.fetch(c,{headers:{"Account-Owner-Signature":a,"Account-Owner-Pub":n}},o);switch(u.status){case l.Ok:return se(u,Io());case l.Accepted:return mt(u,u.status,Io());case l.NoContent:return Ao(u.status,void 0);case l.Forbidden:case l.NotFound:case l.Conflict:return I(u.status,u);default:return V(u)}}async testingCheckKycStatusNoPub(t){let{paytoHash:r,accountSig:n,longpoll:a,awaitAuth:o}=t,s=new URL(`kyc-check/${r}`,this.baseUrl);o!==void 0&&s.searchParams.set("await_auth",o?"YES":"NO");let c=await this.fetch(s,{headers:{"Account-Owner-Signature":n}},a);switch(c.status){case l.Ok:return se(c,Io());case l.Accepted:return mt(c,c.status,Io());case l.NoContent:return Ao(c.status,void 0);case l.Forbidden:case l.NotFound:case l.Conflict:return I(c.status,c);default:return V(c)}}async checkKycInfo(t,r=[],n=!1){let a=await this.fetch(`kyc-info/${t}`,{method:"GET",headers:{"If-None-Match":r.length?r.map(o=>`"${o}"`).join(","):void 0}},n);switch(a.status){case l.Ok:return se(a,al());case l.Accepted:case l.NoContent:return mt(a,a.status,Yi());case l.NotModified:return I(a.status,a);default:return V(a)}}async checkKycInfoSpa(t,r,n={}){let a=new URL(`kyc-info/${t}`,this.baseUrl);Zr(a,n);let o=await this.httpLib.fetch(a.href,{method:"GET",headers:{"If-None-Match":r?`"${r}"`:void 0}});switch(o.status){case l.Ok:{let s=o.headers.get("etag")??void 0,c;s!=null&&s.startsWith('"')&&s.endsWith('"')?c=s.substring(1,s.length-1):s==null?c=s:tR.warn("malformed ETag header in kyc-info response");let u=await ua(o,al());return Ke({...u,etag:c})}case l.Accepted:return I(o.status,o);case l.NoContent:return Tt(o.status);case l.NotModified:return Tt(o.status);default:return V(o)}}async uploadKycForm(t,r){let n=await this.fetch(`kyc-upload/${t}`,{method:"POST",body:r,compress:this.preventCompression?void 0:"deflate"});switch(n.status){case l.NoContent:return this.cacheEvictor.notifySuccess(rs.UPLOAD_KYC_FORM),ke();case l.NotFound:case l.InternalServerError:case l.Conflict:case l.PayloadTooLarge:return I(n.status,n);default:return V(n)}}async startExternalKycProcess(t,r={}){let n=await this.fetch(`kyc-start/${t}`,{method:"POST",body:r});switch(n.status){case l.Ok:return se(n,Fm());case l.NotFound:case l.Conflict:case l.PayloadTooLarge:return I(n.status,n);default:return V(n)}}async completeExternalKycProcess(t,r,n){let a=await this.fetch(`kyc-proof/${t}?state=${r}&code=${n}`,{method:"GET",redirect:"manual"});switch(a.status){case l.SeeOther:return ke();case l.NotFound:return I(a.status,a);default:return V(a)}}async getAmlMeasures(t){let r=await this.fetch(`aml/${t.id}/measures`,{method:"GET",headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(r.status){case l.Ok:return se(r,Cm());case l.Conflict:case l.NotFound:case l.Forbidden:return I(r.status,r);default:return V(r)}}async getAmlKycStatistics(t,r,n={}){let a=new URL(`aml/${t.id}/kyc-statistics/${r.join(" ")}`,this.baseUrl);n.since!==void 0&&n.since.t_ms!=="never"&&a.searchParams.set("start_date",String(n.since.t_ms)),n.until!==void 0&&n.until.t_ms!=="never"&&a.searchParams.set("end_date",String(n.until.t_ms));let o=await this.fetch(a,{method:"GET",headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(o.status){case l.Ok:return se(o,Im());case l.NoContent:return Ke({statistics:r.map(s=>({counter:0,name:s}))});case l.Conflict:case l.NotFound:case l.Forbidden:return I(o.status,o);default:return V(o)}}async getAmlAccounts(t,r={}){let n=new URL(`aml/${t.id}/accounts`,this.baseUrl);At(n,r),r.investigation!==void 0&&n.searchParams.set("investigation",r.investigation?"YES":"NO"),r.open!==void 0&&r.open&&n.searchParams.set("open","YES"),r.highRisk!==void 0&&r.highRisk&&n.searchParams.set("high_risk","YES");let a=await this.fetch(n,{headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(a.status){case l.Ok:return se(a,Pm());case l.NoContent:return Ke({accounts:[]});case l.Forbidden:case l.NotFound:case l.Conflict:return I(a.status,a);default:return V(a)}}async getAmlAccountsAsOtherFormat(t,r,n={}){let a=new URL(`aml/${t.id}/accounts`,this.baseUrl);a.searchParams.set("offset","0"),a.searchParams.set("limit","99999999"),n.investigation!==void 0&&a.searchParams.set("investigation",n.investigation?"YES":"NO"),n.open!==void 0&&n.open&&a.searchParams.set("open","YES"),n.highRisk!==void 0&&n.highRisk&&a.searchParams.set("high_risk","YES");let o=await this.fetch(a,{headers:{Accept:r,"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(o.status){case l.Ok:return Ke(await o.bytes());case l.NoContent:case l.Forbidden:case l.NotFound:case l.Conflict:return I(o.status,o);default:return V(o)}}async getAmlDecisions(t,r={}){let n=new URL(`aml/${t.id}/decisions`,this.baseUrl);At(n,r),r.account!==void 0&&n.searchParams.set("h_payto",r.account),r.active!==void 0&&n.searchParams.set("active",r.active?"YES":"NO"),r.investigation!==void 0&&n.searchParams.set("investigation",r.investigation?"YES":"NO");let a=await this.fetch(n,{headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(a.status){case l.Ok:return se(a,Dm());case l.NoContent:return Ke({records:[]});case l.Forbidden:case l.NotFound:case l.Conflict:return I(a.status,a);default:return V(a)}}async getAmlLegitimizations(t,r={}){let n=new URL(`aml/${t.id}/legitimizations`,this.baseUrl);At(n,r),r.account!==void 0&&n.searchParams.set("h_payto",r.account),r.active!==void 0&&n.searchParams.set("active",r.active?"YES":"NO");let a=await this.httpLib.fetch(n.href,{headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(a.status){case l.Ok:return se(a,Sm());case l.NoContent:return Ke({measures:[]});default:return V(a)}}async getAmlAttributesForAccount(t,r,n={}){let a=new URL(`aml/${t.id}/attributes/${r}`,this.baseUrl);At(a,n);let o=await this.fetch(a,{headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(o.status){case l.Ok:return se(o,Mm());case l.NoContent:return Ke({details:[]});case l.Forbidden:case l.NotFound:case l.Conflict:return I(o.status,o);default:return V(o)}}async getAmlAttributesForAccountAsPdf(t,r,n={}){let a=new URL(`aml/${t.id}/attributes/${r}`,this.baseUrl);At(a,n);let o=await this.fetch(a,{headers:{Accept:"application/pdf","Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(o.status){case l.Ok:return Ke(await o.bytes());case l.NoContent:case l.Forbidden:case l.NotImplemented:case l.NotFound:case l.Conflict:return I(o.status,o);default:return V(o)}}async makeAmlDesicion(t,r){let n={officer_sig:gt(Q_(t.signingKey,r)),...r},a=await this.fetch(`aml/${t.id}/decision`,{method:"POST",headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))},body:n,compress:this.preventCompression?void 0:"deflate"});switch(a.status){case l.NoContent:return this.cacheEvictor.notifySuccess(rs.MAKE_AML_DECISION),ke();case l.Forbidden:case l.NotFound:case l.Conflict:return I(a.status,a);default:return V(a)}}async getTransfersCredit(t,r={}){let n=new URL(`aml/${t.id}/transfers-credit`,this.baseUrl);At(n,r),r.threshold&&n.searchParams.set("threshold",J.stringify(r.threshold)),r.account&&n.searchParams.set("h_payto",r.account);let a=await this.fetch(n,{headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(a.status){case l.Ok:return se(a,Wi());case l.NoContent:return Ke({transfers:[]});case l.Forbidden:case l.NotFound:case l.Conflict:return I(a.status,a);default:return V(a)}}async getTransfersDebit(t,r={}){let n=new URL(`aml/${t.id}/transfers-debit`,this.baseUrl);At(n,r),r.threshold&&n.searchParams.set("threshold",J.stringify(r.threshold)),r.account&&n.searchParams.set("h_payto",r.account);let a=await this.fetch(n,{headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(a.status){case l.Ok:return se(a,Wi());case l.NoContent:return Ke({transfers:[]});case l.Forbidden:case l.NotFound:case l.Conflict:return I(a.status,a);default:return V(a)}}async getTransfersKycAuth(t,r={}){let n=new URL(`aml/${t.id}/transfers-kycauth`,this.baseUrl);At(n,r),r.threshold&&n.searchParams.set("threshold",J.stringify(r.threshold)),r.account&&n.searchParams.set("h_payto",r.account);let a=await this.fetch(n,{headers:{"Taler-AML-Officer-Signature":gt(Kr(t.signingKey))}});switch(a.status){case l.Ok:return se(a,Wi());case l.NoContent:return Ke({transfers:[]});case l.Forbidden:case l.NotFound:case l.Conflict:return I(a.status,a);default:return V(a)}}async withdraw(t){let r=new URL("withdraw",this.baseUrl),n=await this.fetch(r,{method:"POST",body:t.body});switch(n.status){case l.Ok:return se(n,Ju());case l.Forbidden:return I(n.status,n);default:return V(n)}}async postMelt(t){let r=new URL("melt",this.baseUrl),n=await this.fetch(r,{method:"POST",body:t.body});switch(n.status){case l.Ok:return se(n,wm());case l.Forbidden:return I(n.status,n);default:return V(n)}}async postRevealMelt(t){let r=new URL("reveal-melt",this.baseUrl),n=await this.fetch(r,{method:"POST",body:t.body});switch(n.status){case l.Ok:return se(n,Ju());case l.Forbidden:return I(n.status,n);default:return V(n)}}};ns.SUPPORTED_EXCHANGE_PROTOCOL_VERSION="34:0:9";var zl=class e{constructor(t,r,n){this.baseUrl=t,this.httpLib=r??jt(),this.cancellationToken=n}static isCompatible(t){return St.compare(e.PROTOCOL_VERSION,t)?.compatible??!1}async getConfig(){let t=new URL("/config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return rr("taler-mailbox",e.PROTOCOL_VERSION,r,Z_());case l.NotFound:return I(r.status,r);default:return V(r)}}async sendMessage(t){let{h_address:r,body:n}=t,a=new URL(`${r.toUpperCase()}`,this.baseUrl),o=await this.httpLib.fetch(a.href,{method:"POST",body:n,cancellationToken:this.cancellationToken});switch(o.status){case l.NoContent:return ke();case l.PaymentRequired:return I(o.status,o);case l.Forbidden:return I(o.status,o);case l.TooManyRequests:return mt(o,o.status,os());default:return V(o)}}async getMessages(t){let{hMailbox:r}=t,n=new URL(`${r.toUpperCase()}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"GET",cancellationToken:this.cancellationToken});switch(a.status){case l.Ok:{let o=await a.bytes(),s=a.headers.get("etag");return Ke({messages:o,etag:s||"0"})}case l.NoContent:{let o=a.headers.get("etag"),s=o||"0";return Ke({messages:new Uint8Array,etag:s})}case l.TooManyRequests:return mt(a,a.status,os());default:return V(a)}}async deleteMessages(t){let{mailboxConf:r,matchIf:n,count:a,signature:o}=t,s=gt(dl(nr(r.privateKey))),c=new URL(`${s.toUpperCase()}?count=${a}`,this.baseUrl),u=await this.httpLib.fetch(c.href,{method:"DELETE",headers:{"If-Match":n,"Taler-Mailbox-Delete-Signature":o},cancellationToken:this.cancellationToken});switch(u.status){case l.NoContent:return ke();case l.Forbidden:case l.NotFound:return I(u.status,u);default:return V(u)}}async getMailboxInfo(t){let r=new URL(`info/${t.toUpperCase()}`,this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"GET",cancellationToken:this.cancellationToken});switch(n.status){case l.Ok:return se(n,J_());case l.NotFound:return mt(n,n.status,Yi());case l.TooManyRequests:return mt(n,n.status,os());default:return V(n)}}async registerMailbox(t){let r=new URL("register",this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",body:t,cancellationToken:this.cancellationToken});switch(n.status){case l.NoContent:return Ke({status:"ok"});case l.Forbidden:return I(n.status,n);case l.PaymentRequired:return{type:"fail",case:n.status,body:{status:"payment-required",talerUri:n.headers.get("Taler")}};default:return V(n)}}};zl.PROTOCOL_VERSION="1:0:0";var Qe;(function(e){e[e.CREATE_ORDER=0]="CREATE_ORDER",e[e.UPDATE_ORDER=1]="UPDATE_ORDER",e[e.DELETE_ORDER=2]="DELETE_ORDER",e[e.UPDATE_CURRENT_INSTANCE=3]="UPDATE_CURRENT_INSTANCE",e[e.DELETE_CURRENT_INSTANCE=4]="DELETE_CURRENT_INSTANCE",e[e.CREATE_BANK_ACCOUNT=5]="CREATE_BANK_ACCOUNT",e[e.UPDATE_BANK_ACCOUNT=6]="UPDATE_BANK_ACCOUNT",e[e.DELETE_BANK_ACCOUNT=7]="DELETE_BANK_ACCOUNT",e[e.CREATE_PRODUCT=8]="CREATE_PRODUCT",e[e.UPDATE_PRODUCT=9]="UPDATE_PRODUCT",e[e.DELETE_PRODUCT=10]="DELETE_PRODUCT",e[e.CREATE_CATEGORY=11]="CREATE_CATEGORY",e[e.UPDATE_CATEGORY=12]="UPDATE_CATEGORY",e[e.DELETE_CATEGORY=13]="DELETE_CATEGORY",e[e.CREATE_TRANSFER=14]="CREATE_TRANSFER",e[e.DELETE_TRANSFER=15]="DELETE_TRANSFER",e[e.CREATE_DEVICE=16]="CREATE_DEVICE",e[e.UPDATE_DEVICE=17]="UPDATE_DEVICE",e[e.DELETE_DEVICE=18]="DELETE_DEVICE",e[e.CREATE_TEMPLATE=19]="CREATE_TEMPLATE",e[e.UPDATE_TEMPLATE=20]="UPDATE_TEMPLATE",e[e.DELETE_TEMPLATE=21]="DELETE_TEMPLATE",e[e.CREATE_WEBHOOK=22]="CREATE_WEBHOOK",e[e.UPDATE_WEBHOOK=23]="UPDATE_WEBHOOK",e[e.DELETE_WEBHOOK=24]="DELETE_WEBHOOK",e[e.CREATE_TOKENFAMILY=25]="CREATE_TOKENFAMILY",e[e.UPDATE_TOKENFAMILY=26]="UPDATE_TOKENFAMILY",e[e.DELETE_TOKENFAMILY=27]="DELETE_TOKENFAMILY",e[e.CREATE_ACCESSTOKEN=28]="CREATE_ACCESSTOKEN",e[e.DELETE_ACCESSTOKEN=29]="DELETE_ACCESSTOKEN",e[e.CREATE_REPORTS=30]="CREATE_REPORTS",e[e.UPDATE_REPORTS=31]="UPDATE_REPORTS",e[e.DELETE_REPORTS=32]="DELETE_REPORTS",e[e.CREATE_POTS=33]="CREATE_POTS",e[e.UPDATE_POTS=34]="UPDATE_POTS",e[e.DELETE_POTS=35]="DELETE_POTS",e[e.CREATE_GROUPS=36]="CREATE_GROUPS",e[e.UPDATE_GROUPS=37]="UPDATE_GROUPS",e[e.DELETE_GROUPS=38]="DELETE_GROUPS",e[e.LAST=39]="LAST"})(Qe||(Qe={}));var ey;(function(e){e[e.CREATE_INSTANCE=40]="CREATE_INSTANCE",e[e.UPDATE_INSTANCE=41]="UPDATE_INSTANCE",e[e.DELETE_INSTANCE=42]="DELETE_INSTANCE"})(ey||(ey={}));var $l=class e{constructor(t,r,n,a){this.baseUrl=t,this.httpLib=r??jt(),this.cacheEvictor=n??gn,this.cancellationToken=a}static isCompatible(t){return St.compare(e.PROTOCOL_VERSION,t)?.compatible??!1}async getConfig(){let t=new URL("config",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return rr("taler-merchant",e.PROTOCOL_VERSION,r,Eg());case l.NotFound:return I(r.status,r);default:return V(r)}}async listExchanges(){let t=new URL("exchanges",this.baseUrl),r=await this.httpLib.fetch(t.href,{method:"GET"});switch(r.status){case l.Ok:return se(r,vg());case l.NotFound:return I(r.status,r);case l.InternalServerError:return I(r.status,r);default:return V(r)}}async createAccessToken(t,r,n,a={}){let o=new URL("private/token",this.baseUrl),s=Zt({type:"basic",username:t,password:r});a.challengeIds&&a.challengeIds.length>0&&(s["Taler-Challenge-Ids"]=a.challengeIds.join(", "));let c=await this.httpLib.fetch(o.href,{method:"POST",headers:s,body:n});switch(c.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.CREATE_ACCESSTOKEN),se(c,Pg());case l.Accepted:return mt(c,c.status,Or());case l.Unauthorized:return I(c.status,c);case l.NotFound:return I(c.status,c);default:return V(c)}}async listAccessTokens(t,r={}){let n=new URL("private/tokens",this.baseUrl);At(n,r);let a=await this.httpLib.fetch(n.href,{method:"GET",headers:{Authorization:ve(t)}});switch(a.status){case l.Ok:return se(a,Ui());case l.NoContent:return Ke({tokens:[]});case l.Unauthorized:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);default:return V(a)}}async deleteAccessToken(t,r){let n=new URL(`private/tokens/${String(r)}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_ACCESSTOKEN),ke();case l.Forbidden:return I(o.status,o);case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async claimOrder(t){let{orderId:r,body:n}=t,a=new URL(`orders/${r}/claim`,this.baseUrl),o=await this.httpLib.fetch(a.href,{method:"POST",body:n,cancellationToken:this.cancellationToken});switch(o.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.UPDATE_ORDER),se(o,Ag());case l.Conflict:return I(o.status,o);case l.NotFound:{let s=await o.json(),c=Vr().decode(s);return c.code===G.MERCHANT_POST_ORDERS_ID_CLAIM_NOT_FOUND?Ce(c.code,c):V(o,c)}default:return V(o)}}async makePayment(t,r){let n=new URL(`orders/${t}/pay`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});switch(a.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.UPDATE_ORDER),se(a,Tg());case l.BadRequest:return I(a.status,a);case l.PaymentRequired:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.RequestTimeout:return I(a.status,a);case l.Conflict:return I(a.status,a);case l.Gone:return I(a.status,a);case l.PreconditionFailed:return I(a.status,a);case l.BadGateway:return I(a.status,a);case l.GatewayTimeout:return I(a.status,a);case l.UnavailableForLegalReasons:return mt(a,a.status,Oo());default:return V(a)}}async getPaymentStatus(t,r={}){let n=new URL(`orders/${t}`,this.baseUrl);r.allowRefundedForRepurchase!==void 0&&n.searchParams.set("allow_refunded_for_repurchase",r.allowRefundedForRepurchase?"YES":"NO"),r.awaitRefundObtained!==void 0&&n.searchParams.set("await_refund_obtained",r.allowRefundedForRepurchase?"YES":"NO"),r.claimToken!==void 0&&n.searchParams.set("token",r.claimToken),r.contractTermHash!==void 0&&n.searchParams.set("h_contract",r.contractTermHash),r.refund!==void 0&&n.searchParams.set("refund",r.refund),r.sessionId!==void 0&&n.searchParams.set("session_id",r.sessionId),r.timeout!==void 0&&n.searchParams.set("timeout_ms",String(r.timeout));let a=await this.httpLib.fetch(n.href,{method:"GET"});switch(a.status){case l.Ok:return se(a,Ng());case l.Accepted:return se(a,Rg());case l.PaymentRequired:return se(a,xg());case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.NotAcceptable:return I(a.status,a);default:return V(a)}}async getOrderIdForSessionAndUrl(t,r,n={}){let a=new URL(`sessions/${t}`,this.baseUrl);r!==void 0&&a.searchParams.set("fulfillment_url",r),n.timeout&&a.searchParams.set("timeout_ms",String(n.timeout));let o=await this.httpLib.fetch(a.href,{method:"GET"});switch(o.status){case l.Ok:return{paid:!0,...await se(o,yl())};case l.Accepted:return{paid:!1,...se(o,yl())};case l.NotFound:return I(o.status,o);default:return V(o)}}async demostratePayment(t,r){let n=new URL(`orders/${t}/paid`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});switch(a.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.UPDATE_ORDER),se(a,Ig());case l.BadRequest:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);default:return V(a)}}async abortIncompletePayment(t,r){let n=new URL(`orders/${t}/abort`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});switch(a.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.UPDATE_ORDER),se(a,Sg());case l.BadRequest:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);default:return V(a)}}async obtainRefund(t,r){let n=new URL(`orders/${t}/refund`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});switch(a.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.UPDATE_ORDER),se(a,Cg());case l.BadRequest:return I(a.status,a);case l.Forbidden:return I(a.status,a);case l.NotFound:return I(a.status,a);case l.UnavailableForLegalReasons:return mt(a,a.status,Oo());default:return V(a)}}async updateCurrentInstanceAuthentication(t,r,n={}){let a=new URL("private/auth",this.baseUrl),o={};t&&(o.Authorization=ve(t)),n.challengeIds&&n.challengeIds.length>0&&(o["Taler-Challenge-Ids"]=n.challengeIds.join(", "));let s=await this.httpLib.fetch(a.href,{method:"POST",body:r,headers:o});switch(s.status){case l.Ok:return ke();case l.Accepted:return mt(s,s.status,Or());case l.NoContent:return ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async updateCurrentInstance(t,r,n={}){let a=new URL("private",this.baseUrl),o={};t&&(o.Authorization=ve(t)),n.challengeIds&&n.challengeIds.length>0&&(o["Taler-Challenge-Ids"]=n.challengeIds.join(", "));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:r,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_CURRENT_INSTANCE),ke();case l.Accepted:return mt(s,s.status,Or());case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async getCurrentInstanceDetails(t){let r=new URL("private",this.baseUrl),n={};t&&(n.Authorization=ve(t));let a=await this.httpLib.fetch(r.href,{method:"GET",headers:n});switch(a.status){case l.Ok:return se(a,Og());case l.Unauthorized:return I(a.status,a);case l.NotFound:return I(a.status,a);default:return V(a)}}async deleteCurrentInstance(t,r={}){let n=new URL("private",this.baseUrl);r.purge!==void 0&&n.searchParams.set("purge",r.purge?"YES":"NO");let a={};t&&(a.Authorization=ve(t)),r.challengeIds&&r.challengeIds.length>0&&(a["Taler-Challenge-Ids"]=r.challengeIds.join(", "));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_CURRENT_INSTANCE),ke();case l.Accepted:return mt(o,o.status,Or());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);case l.Conflict:return I(o.status,o);default:return V(o)}}async getCurrentInstanceKycStatus(t,r={}){let n=new URL("private/kyc",this.baseUrl);r.wireHash&&n.searchParams.set("h_wire",r.wireHash),r.exchangeURL&&n.searchParams.set("exchange_url",r.exchangeURL);let a={};if(r.longpoll){switch(r.longpoll.type){case"state-enter":n.searchParams.set("lp_status",r.longpoll.status);break;case"state-exit":n.searchParams.set("lp_not_status",r.longpoll.status);break;case"state-change":n.searchParams.set("lp_not_etag",r.longpoll.etag),a["If-none-match"]=`"${r.longpoll.etag}"`;break;default:ue(r.longpoll)}n.searchParams.set("timeout_ms",String(r.longpoll.timeout))}else r.timeout&&n.searchParams.set("timeout_ms",String(r.timeout)),r.reason&&n.searchParams.set("lpt",String(r.reason));t&&(a.Authorization=ve(t));let o=r.ct??this.cancellationToken,s=await this.httpLib.fetch(n.href,{method:"GET",headers:a,cancellationToken:o}),c=s.headers.get("etag")?.replace(/"/g,"");switch(s.status){case l.Ok:{let u=await se(s,Dg());return Ke({etag:c,...u.body})}case l.NoContent:return Tt(s.status);case l.NotModified:return Ao(s.status,{etag:c});case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.ServiceUnavailable:return I(s.status,s);case l.GatewayTimeout:return I(s.status,s);default:return V(s)}}async addBankAccount(t,r,n={}){let a=new URL("private/accounts",this.baseUrl),o={};t&&(o.Authorization=ve(t)),n.challengeIds&&n.challengeIds.length>0&&(o["Taler-Challenge-Ids"]=n.challengeIds.join(", "));let s=await this.httpLib.fetch(a.href,{method:"POST",body:r,headers:o});switch(s.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.CREATE_BANK_ACCOUNT),se(s,Lg());case l.Accepted:return mt(s,s.status,Or());case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async updateBankAccount(t,r,n){let a=new URL(`private/accounts/${r}`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_BANK_ACCOUNT),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async listBankAccounts(t,r){let n=new URL("private/accounts",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,Ug());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getBankAccountDetails(t,r){let n=new URL(`private/accounts/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,Mg());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async deleteBankAccount(t,r){let n=new URL(`private/accounts/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_BANK_ACCOUNT),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async listCategories(t,r){let n=new URL("private/categories",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,kg());case l.NotFound:return I(o.status,o);case l.Unauthorized:return I(o.status,o);default:return V(o)}}async getCategoryDetails(t,r){let n=new URL(`private/categories/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,Fg());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async addCategory(t,r){let n=new URL("private/categories",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.CREATE_CATEGORY),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async updateCategory(t,r,n){let a=new URL(`private/categories/${r}`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_CATEGORY),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async deleteCategory(t,r){let n=new URL(`private/categories/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_CATEGORY),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async addProduct(t,r){let n=new URL("private/products",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.CREATE_PRODUCT),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:{let s=await it(o);switch(s.code){case G.MERCHANT_GENERIC_PRODUCT_GROUP_UNKNOWN:return Ce(s.code,s);case G.MERCHANT_GENERIC_CATEGORY_UNKNOWN:return Ce(s.code,s);case G.MERCHANT_GENERIC_MONEY_POT_UNKNOWN:return Ce(s.code,s);case G.MERCHANT_GENERIC_INSTANCE_UNKNOWN:return Ce(s.code,s);default:return V(o,s)}}case l.Conflict:return I(o.status,o);default:return V(o)}}async updateProduct(t,r,n){let a=new URL(`private/products/${r}`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_PRODUCT),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async listProducts(t,r={}){let n=new URL("private/products",this.baseUrl);At(n,r),r.category&&n.searchParams.set("category_filter",r.category),r.name&&n.searchParams.set("name_filter",r.name),r.description&&n.searchParams.set("description_filter",r.description),r.groupId!==void 0&&n.searchParams.set("product_group_serial",String(r.groupId));let a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,Hg());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getPointOfSaleInventory(t){let r=new URL("private/pos",this.baseUrl),n={};t&&(n.Authorization=ve(t));let a=await this.httpLib.fetch(r.href,{method:"GET",headers:n});switch(a.status){case l.Ok:return se(a,Gg());case l.NotFound:return I(a.status,a);default:return V(a)}}async getProductDetails(t,r){let n=new URL(`private/products/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,Bg());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async lockProduct(t,r,n){let a=new URL(`private/products/${r}/lock`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"POST",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_PRODUCT),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Gone:return I(s.status,s);default:return V(s)}}async deleteProduct(t,r,n={}){let a=new URL(`private/products/${r}`,this.baseUrl),o={};t&&(o.Authorization=ve(t)),n.force&&a.searchParams.set("force","yes");let s=await this.httpLib.fetch(a.href,{method:"DELETE",headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_PRODUCT),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async createOrder(t,r){let n=new URL("private/orders",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});return this.procesOrderCreationResponse(o)}async procesOrderCreationResponse(t){switch(t.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.CREATE_ORDER),se(t,Wg());case l.NotFound:{let r=await it(t);return r.code===G.MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE?Ce(r.code,r):V(t,r)}case l.Unauthorized:return I(t.status,t);case l.UnavailableForLegalReasons:return mt(t,t.status,Oo());case l.Conflict:return I(t.status,t);case l.Gone:return mt(t,t.status,Vg());default:return V(t)}}async listOrders(t,r={}){let n=new URL("private/orders",this.baseUrl);if(r.paid!==void 0&&n.searchParams.set("paid",r.paid?"YES":"NO"),r.refunded!==void 0&&n.searchParams.set("refunded",r.refunded?"YES":"NO"),r.wired!==void 0&&n.searchParams.set("wired",r.wired?"YES":"NO"),r.date&&!he.isNever(r.date)){let c=he.toProtocolTimestamp(r.date);n.searchParams.set("date_s",String(c.t_s))}if(r.maxAge&&!rt.isForever(r.maxAge)){let c=rt.toTalerProtocolDuration(r.maxAge);n.searchParams.set("max_age",String(c.d_us))}r.timeout&&n.searchParams.set("timeout_ms",String(r.timeout)),r.sessionId&&n.searchParams.set("session_id",r.sessionId),r.fulfillmentUrl&&n.searchParams.set("fulfillment_url",r.fulfillmentUrl),r.summary&&n.searchParams.set("summary_filter",r.summary),At(n,r);let a={};t&&(a.Authorization=ve(t));let o=r.ct??this.cancellationToken,s=await this.httpLib.fetch(n.href,{method:"GET",headers:a,cancellationToken:o});switch(s.status){case l.Ok:return se(s,qg());case l.NotFound:return I(s.status,s);case l.Unauthorized:return I(s.status,s);default:return V(s)}}async listOrdersRaw(t,r){let n=new URL("private/orders",this.baseUrl);if(r.paid!==void 0&&n.searchParams.set("paid",r.paid?"YES":"NO"),r.refunded!==void 0&&n.searchParams.set("refunded",r.refunded?"YES":"NO"),r.wired!==void 0&&n.searchParams.set("wired",r.wired?"YES":"NO"),r.date&&!he.isNever(r.date)){let s=he.toProtocolTimestamp(r.date);n.searchParams.set("date_s",String(s.t_s))}if(r.maxAge&&!rt.isForever(r.maxAge)){let s=rt.toTalerProtocolDuration(r.maxAge);n.searchParams.set("max_age",String(s.d_us))}r.timeout&&n.searchParams.set("timeout_ms",String(r.timeout)),r.sessionId&&n.searchParams.set("session_id",r.sessionId),r.fulfillmentUrl&&n.searchParams.set("fulfillment_url",r.fulfillmentUrl),r.summary&&n.searchParams.set("summary_filter",r.summary),At(n,r);let a={};t&&(a.Authorization=ve(t)),a.Accept=r.mime;let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return Ke(new Uint8Array(await o.bytes()));case l.NotFound:return I(o.status,o);case l.Unauthorized:return I(o.status,o);default:return V(o)}}async getOrderDetails(t,r,n={}){let a=new URL(`private/orders/${r}`,this.baseUrl);n.allowRefundedForRepurchase!==void 0&&a.searchParams.set("allow_refunded_for_repurchase",n.allowRefundedForRepurchase?"YES":"NO"),n.sessionId&&a.searchParams.set("session_id",n.sessionId),n.timeout&&a.searchParams.set("timeout_ms",String(n.timeout));let o={};n.longpoll?(a.searchParams.set("lp_not_etag",n.longpoll.etag),o["If-none-match"]=`"${n.longpoll.etag}"`,a.searchParams.set("timeout_ms",String(n.longpoll.timeout))):n.timeout&&a.searchParams.set("timeout_ms",String(n.timeout)),t&&(o.Authorization=ve(t));let s=n.ct??this.cancellationToken,c=await this.httpLib.fetch(a.href,{method:"GET",headers:o,cancellationToken:s}),u=c.headers.get("etag")?.replace(/"/g,"");switch(c.status){case l.Ok:{let f=await se(c,Kg());return Ke({etag:u,...f.body})}case l.NotFound:{let f=await it(c);switch(f.code){case G.MERCHANT_GENERIC_ORDER_UNKNOWN:return Ce(f.code,f);case G.MERCHANT_GENERIC_INSTANCE_UNKNOWN:return Ce(f.code,f);default:return V(c,f)}}case l.Unauthorized:return I(c.status,c);default:return V(c)}}async forgetOrder(t,r,n){let a=new URL(`private/orders/${r}/forget`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.UPDATE_ORDER),ke();case l.NoContent:return ke();case l.Unauthorized:return I(s.status,s);case l.BadRequest:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async deleteOrder(t,r,n=!1){let a=new URL(`private/orders/${r}`,this.baseUrl);n&&a.searchParams.set("force","yes");let o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"DELETE",headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_ORDER),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async addRefund(t,r,n){let a=new URL(`private/orders/${r}/refund`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"POST",body:n,headers:o});switch(s.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.UPDATE_ORDER),se(s,Yg());case l.Forbidden:return I(s.status,s);case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Gone:return I(s.status,s);case l.Conflict:return I(s.status,s);case l.UnavailableForLegalReasons:return mt(s,s.status,Oo());default:return V(s)}}async informWireTransfer(t,r){let n=new URL("private/transfers",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.CREATE_TRANSFER),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);case l.Conflict:return I(o.status,o);default:return V(o)}}async listConfirmedWireTransfers(t,r={}){let n=new URL("private/transfers",this.baseUrl);r.paytoURI&&n.searchParams.set("payto_uri",r.paytoURI),r.before&&n.searchParams.set("before",String(r.before)),r.after&&n.searchParams.set("after",String(r.after)),r.expected!==void 0&&n.searchParams.set("expected",r.expected?"YES":"NO"),At(n,r);let a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,zg());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async listIncomingWireTransfers(t,r={}){let n=new URL("private/incoming",this.baseUrl);r.paytoURI&&n.searchParams.set("payto_uri",r.paytoURI),r.before&&n.searchParams.set("before",String(r.before)),r.after&&n.searchParams.set("after",String(r.after)),r.verified!==void 0&&n.searchParams.set("verified",r.verified?"YES":"NO"),r.confirmed!==void 0&&n.searchParams.set("confirmed",r.confirmed?"YES":"NO"),At(n,r);let a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,$g());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getIncomingWireTransfersDetails(t,r){let n=new URL(`private/incoming/${String(r)}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,Xg());case l.Conflict:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async addOtpDevice(t,r){let n=new URL("private/otp-devices",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.CREATE_DEVICE),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async updateOtpDevice(t,r,n){let a=new URL(`private/otp-devices/${r}`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_DEVICE),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async listOtpDevices(t,r){let n=new URL("private/otp-devices",this.baseUrl);At(n,r);let a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,jg());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getOtpDeviceDetails(t,r,n={}){let a=new URL(`private/otp-devices/${r}`,this.baseUrl);n.faketime&&a.searchParams.set("faketime",String(n.faketime)),n.price&&a.searchParams.set("price",n.price);let o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"GET",headers:o});switch(s.status){case l.Ok:return se(s,Qg());case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async deleteOtpDevice(t,r){let n=new URL(`private/otp-devices/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_DEVICE),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async addTemplate(t,r){let n=new URL("private/templates",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.CREATE_TEMPLATE),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);case l.Conflict:return I(o.status,o);default:return V(o)}}async updateTemplate(t,r,n){let a=new URL(`private/templates/${r}`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_TEMPLATE),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async listTemplates(t,r){let n=new URL("private/templates",this.baseUrl);At(n,r);let a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,Zg());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getTemplateDetails(t,r){let n=new URL(`private/templates/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,Jg());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async deleteTemplate(t,r){let n=new URL(`private/templates/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_TEMPLATE),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async useTemplateGetInfo(t){let r=new URL(`templates/${t}`,this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"GET"});switch(n.status){case l.Ok:return se(n,r_());case l.NotFound:return I(n.status,n);default:return V(n)}}async useTemplateCreateOrder(t,r){let n=new URL(`templates/${t}`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});return this.procesOrderCreationResponse(a)}async addWebhook(t,r){let n=new URL("private/webhooks",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.CREATE_WEBHOOK),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async updateWebhook(t,r,n){let a=new URL(`private/webhooks/${r}`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_WEBHOOK),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async listWebhooks(t,r){let n=new URL("private/webhooks",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,n_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getWebhookDetails(t,r){let n=new URL(`private/webhooks/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,a_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async deleteWebhook(t,r){let n=new URL(`private/webhooks/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_WEBHOOK),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async createTokenFamily(t,r){let n=new URL("private/tokenfamilies",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.CREATE_TOKENFAMILY),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);case l.Conflict:return I(o.status,o);default:return V(o)}}async updateTokenFamily(t,r,n){let a=new URL(`private/tokenfamilies/${r}`,this.baseUrl),o={};t&&(o.Authorization=ve(t));let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_TOKENFAMILY),ke();case l.Ok:return this.cacheEvictor.notifySuccess(Qe.UPDATE_TOKENFAMILY),se(s,bl());case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async listTokenFamilies(t,r){let n=new URL("private/tokenfamilies",this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,i_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getTokenFamilyDetails(t,r){let n=new URL(`private/tokenfamilies/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,bl());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async deleteTokenFamily(t,r){let n=new URL(`private/tokenfamilies/${r}`,this.baseUrl),a={};t&&(a.Authorization=ve(t));let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_TOKENFAMILY),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async sendChallenge(t){let r=new URL(`challenge/${t}`,this.baseUrl),n=await this.httpLib.fetch(r.href,{method:"POST",body:{}});switch(n.status){case l.Ok:return se(n,ji());case l.NoContent:return Ke({});case l.Unauthorized:return I(n.status,n);case l.Forbidden:return I(n.status,n);case l.NotFound:{let a=await it(n);return a.code===G.MERCHANT_TAN_CHALLENGE_UNKNOWN?Ce(a.code,a):V(n,a)}case l.Gone:{let a=await it(n);return a.code===G.MERCHANT_TAN_CHALLENGE_SOLVED?Ce(a.code,a):V(n,a)}case l.TooManyRequests:{let a=await it(n);return a.code===G.MERCHANT_TAN_TOO_EARLY?Ce(a.code,a):V(n,a)}case l.BadGateway:{let a=await it(n);return a.code===G.MERCHANT_TAN_MFA_HELPER_EXEC_FAILED?Ce(a.code,a):V(n,a)}default:return V(n)}}async confirmChallenge(t,r){let n=new URL(`challenge/${t}/confirm`,this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",body:r});switch(a.status){case l.NoContent:return ke();case l.Unauthorized:return I(a.status,a);case l.NotFound:{let o=await it(a);return o.code===G.MERCHANT_TAN_CHALLENGE_UNKNOWN?Ce(o.code,o):V(a,o)}case l.Conflict:{let o=await it(a);return o.code===G.MERCHANT_TAN_CHALLENGE_FAILED?Ce(o.code,o):V(a,o)}case l.TooManyRequests:{let o=await it(a);return o.code===G.MERCHANT_TAN_TOO_MANY_ATTEMPTS?Ce(o.code,o):V(a,o)}default:return V(a)}}async forgotPasswordSelfProvision(t,r={}){let n=new URL("forgot-password",this.baseUrl),a={};r.challengeIds&&r.challengeIds.length>0&&(a["Taler-Challenge-Ids"]=r.challengeIds.join(", "));let o=await this.httpLib.fetch(n.href,{method:"POST",body:t,headers:a});switch(o.status){case l.NoContent:return ke();case l.Accepted:return mt(o,o.status,Or());case l.NotFound:return I(o.status,o);case l.Forbidden:return I(o.status,o);case l.Unauthorized:{let s=await it(o);return s.code===G.MERCHANT_GENERIC_MFA_MISSING?Ce(s.code,s):V(o,s)}default:return V(o)}}async postDonau(t){let r={};t.token&&(r.Authorization=ve(t.token));let n=new URL("private/donau",this.baseUrl),a=await this.httpLib.fetch(n.href,{method:"POST",headers:r,body:t.body});switch(a.status){case l.NoContent:case l.Created:case l.Ok:return ke();case l.BadGateway:return I(a.status,a);default:return V(a)}}async generateReport(t,r){let n=new URL(`reports/${t}`,this.baseUrl),a={},o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.Ok:return ke();case l.NotFound:return I(o.status,o);default:return V(o)}}async createScheduledReport(t,r){let n=new URL("private/reports",this.baseUrl),a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.CREATE_REPORTS),se(o,s_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async updateScheduledReport(t,r,n){let a=new URL(`private/reports/${r}`,this.baseUrl),o={};o.Authorization=ve(t);let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_REPORTS),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async listScheduledReports(t,r={}){let n=new URL("private/reports",this.baseUrl);At(n,r);let a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,u_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getScheduledReportDetails(t,r){let n=new URL(`private/reports/${r}`,this.baseUrl),a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,c_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async deleteScheduledReport(t,r){let n=new URL(`private/reports/${r}`,this.baseUrl),a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_REPORTS),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async createMoneyPot(t,r){let n=new URL("private/pots",this.baseUrl),a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.CREATE_POTS),se(o,f_());case l.Unauthorized:return I(o.status,o);case l.Conflict:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async updateMoneyPot(t,r,n){let a=new URL(`private/pots/${r}`,this.baseUrl),o={};o.Authorization=ve(t);let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_POTS),ke();case l.Unauthorized:return I(s.status,s);case l.Conflict:return I(s.status,s);case l.NotFound:return I(s.status,s);default:return V(s)}}async listMoneyPots(t,r={}){let n=new URL("private/pots",this.baseUrl);At(n,r);let a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,p_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async getMoneyPotDetails(t,r){let n=new URL(`private/pots/${r}`,this.baseUrl),a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,h_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async deleteMoneyPot(t,r){let n=new URL(`private/pots/${r}`,this.baseUrl),a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_POTS),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async createProductGroup(t,r){let n=new URL("private/groups",this.baseUrl),a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"POST",body:r,headers:a});switch(o.status){case l.Ok:return this.cacheEvictor.notifySuccess(Qe.CREATE_GROUPS),se(o,d_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async updateProductGroup(t,r,n){let a=new URL(`private/reports/${r}`,this.baseUrl),o={};o.Authorization=ve(t);let s=await this.httpLib.fetch(a.href,{method:"PATCH",body:n,headers:o});switch(s.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.UPDATE_GROUPS),ke();case l.Unauthorized:return I(s.status,s);case l.NotFound:return I(s.status,s);case l.Conflict:return I(s.status,s);default:return V(s)}}async listProductGroups(t,r={}){let n=new URL("private/groups",this.baseUrl);At(n,r);let a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"GET",headers:a});switch(o.status){case l.Ok:return se(o,l_());case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}async deleteProductGroup(t,r){let n=new URL(`private/groups/${r}`,this.baseUrl),a={};a.Authorization=ve(t);let o=await this.httpLib.fetch(n.href,{method:"DELETE",headers:a});switch(o.status){case l.NoContent:return this.cacheEvictor.notifySuccess(Qe.DELETE_GROUPS),ke();case l.Unauthorized:return I(o.status,o);case l.NotFound:return I(o.status,o);default:return V(o)}}getAuthenticationAPI(){return new URL("private/",this.baseUrl)}};$l.PROTOCOL_VERSION="25:0:2";var ny=ui(ty(),1);var F4=new Dt("i18n/index.ts"),Ga;function ko(e,t){e=e.replace("_","-"),t[e]||(t[e]={}),Ga=new ny.Jed(t[e])}function Xl(e){let t="";for(let r=0;rtypeof a=="string"?a:`%${t++}$s`).join("").replace(/ +/g," ").trim()}var Fo={str:ry,ctx:rR,singular:ry,Translate:aR,translate:nR};function oy(){let e=null,t=null,r=new Promise((o,s)=>{e=o,t=s});if(!(e&&t))throw Error("JS implementation is broken");let n={resolve:e,reject:t,promise:r};function a(o){n.lastError=o,t(o)}return n.reject=a,n}var ss=new Dt("longpoll-queue.ts"),iy=20,as=class{constructor(){this.idCounter=0,this.queue=[],this.permits=iy}async run(t,r,n){let a=t.hostname,o=this.idCounter++,s=()=>{ss.trace(`cleaning up after long-poll ${o} to ${a}`);let u=this.queue.shift();u!=null?u():this.permits++},c=async()=>{let u=this.queue.length,f=iy-this.permits;ss.info(`running long-poll ${o} to ${a} with ${u} waiting and ${f} running`);try{let d=Math.round(Math.max(1e4,3e4/(u+1)));return await n(d)}finally{s()}};if(this.permits>0)return this.permits--,c();{ss.info(`long-poll ${o} to ${a} queued`);let u=oy();this.queue.push(u.resolve);try{await r.racePromise(u.promise)}finally{ss.info(`long-poll ${o} to ${a} cancelled while queued`),s()}return c()}}};var sy;(function(e){e.BalanceChange="balance-change",e.BankAccountChange="bank-account-change",e.BackupOperationError="backup-error",e.ContactAdded="contact-added",e.ContactDeleted="contact-deleted",e.MailboxMessageAdded="mailbox-message-added",e.MailboxMessageDeleted="mailbox-message-deleted",e.TransactionStateTransition="transaction-state-transition",e.ExchangeStateTransition="exchange-state-transition",e.Idle="idle",e.TaskObservabilityEvent="task-observability-event",e.RequestObservabilityEvent="request-observability-event"})(sy||(sy={}));var vt;(function(e){e.HttpFetchStart="http-fetch-start",e.HttpFetchFinishError="http-fetch-finish-error",e.HttpFetchFinishSuccess="http-fetch-finish-success",e.DbQueryStart="db-query-start",e.DbQueryFinishSuccess="db-query-finish-success",e.DbQueryFinishError="db-query-finish-error",e.RequestStart="request-start",e.RequestFinishSuccess="request-finish-success",e.RequestFinishError="request-finish-error",e.TaskStart="task-start",e.TaskStop="task-stop",e.TaskReset="task-reset",e.ShepherdTaskResult="shepherd-task-result",e.DeclareTaskDependency="declare-task-dependency",e.CryptoStart="crypto-start",e.CryptoFinishSuccess="crypto-finish-success",e.CryptoFinishError="crypto-finish-error",e.Message="message",e.DeclareConcernsTransaction="declare-concerns-transaction"})(vt||(vt={}));var z4=new Dt("timer.ts"),jl=class{constructor(t){this.h=t}clear(){clearInterval(this.h)}unref(){typeof this.h=="object"&&"unref"in this.h&&this.h.unref()}},Ql=class{constructor(t){this.h=t}clear(){clearTimeout(this.h)}unref(){typeof this.h=="object"&&"unref"in this.h&&this.h.unref()}},cs=typeof process<"u"&&process.hrtime?()=>process.hrtime.bigint():typeof performance<"u"?()=>BigInt(Math.floor(performance.now()*1e3))*BigInt(1e3):()=>BigInt(new Date().getTime())*BigInt(1e3)*BigInt(1e3),Jl=(e,t)=>Number((t-e)/1000n/1000n);var Zl=class{every(t,r){return new jl(setInterval(r,t))}after(t,r){return new Ql(setTimeout(r,t))}},$4=new Zl;var ed=1e3,da=class{constructor(t,r){this.impl=t,this.oc=r,this.cancelatorById=new Map}cancelRequest(t){let r=this.cancelatorById.get(t);r&&r.cancel()}async fetch(t,r){let n=`req-${ed}`;ed=ed+1;let a=xr.create();r?.cancellationToken&&r.cancellationToken.onCancelled(a.cancel),this.cancelatorById.set(n,a),this.oc.observe({id:n,when:he.now(),type:vt.HttpFetchStart,url:t,longPolling:!r?.cancellationToken});let o=r??{};o.cancellationToken=a.token;let s=cs();try{let c=await this.impl.fetch(t,o),u=cs(),f={id:n,when:he.now(),type:vt.HttpFetchFinishSuccess,url:t,status:c.status,durationMs:Jl(s,u),longPolling:!r?.cancellationToken};return this.oc.observe(f),c}catch(c){let u=cs();throw this.oc.observe({id:n,when:he.now(),type:vt.HttpFetchFinishError,url:t,error:Yu(c),durationMs:Jl(s,u),longPolling:!r?.cancellationToken}),c}finally{this.cancelatorById.delete(n)}}};var Jr;(function(e){e.HttpFetch="http-fetch",e.DbQuery="db-query",e.Crypto="crypto",e.WalletRequest="wallet-request",e.WalletTask="wallet-task"})(Jr||(Jr={}));var us;(function(e){function t(n){if((n.type===vt.HttpFetchFinishSuccess||n.type===vt.HttpFetchFinishError)&&!n.longPolling)return{type:Jr.HttpFetch,url:n.url,avgDurationMs:n.durationMs,maxDurationMs:n.durationMs,minDurationMs:n.durationMs,totalDurationMs:n.durationMs,count:1};if(n.type===vt.DbQueryFinishSuccess||n.type===vt.DbQueryFinishError)return{type:Jr.DbQuery,name:n.name,location:n.location,avgDurationMs:n.durationMs,maxDurationMs:n.durationMs,minDurationMs:n.durationMs,totalDurationMs:n.durationMs,count:1};if(n.type===vt.CryptoFinishSuccess||n.type===vt.CryptoFinishError)return{type:Jr.Crypto,operation:n.operation,avgDurationMs:n.durationMs,maxDurationMs:n.durationMs,minDurationMs:n.durationMs,totalDurationMs:n.durationMs,count:1};if(n.type===vt.RequestFinishSuccess||n.type===vt.RequestFinishError)return{type:Jr.WalletRequest,operation:n.operation,avgDurationMs:n.durationMs,maxDurationMs:n.durationMs,minDurationMs:n.durationMs,totalDurationMs:n.durationMs,count:1};if(n.type===vt.ShepherdTaskResult)return{type:Jr.WalletTask,taskId:n.taskId,avgDurationMs:n.durationMs,maxDurationMs:n.durationMs,minDurationMs:n.durationMs,totalDurationMs:n.durationMs,count:1}}e.fromNotification=t;function r(n,a){if(n.type!==a.type)return!1;if(n.type===Jr.HttpFetch)return n.url===a.url;if(n.type===Jr.DbQuery)return n.name===a.name&&n.location===a.location;if(n.type===Jr.Crypto)return n.operation===a.operation;if(n.type===Jr.WalletRequest)return n.operation===a.operation;if(n.type===Jr.WalletTask)return n.taskId===a.taskId;ue(n)}e.equals=r})(us||(us={}));var iR=500,cy;(function(e){function t(s,c){if("durationMs"in c&&typeof c.durationMs=="number"){let u=us.fromNotification(c);if(!u)return;n(s,u),a(s),o(s,u.type)}}e.insertEvent=t;function r(s,c){if(c===void 0||c===Number.MAX_VALUE)return s;let u={};for(let f of Object.keys(s)){let d=f;u[d]=s[d].slice(0,c)}return u}e.limit=r;function n(s,c){if(!s[c.type]){s[c.type]=[],s[c.type]?.push(c);return}let u=s[c.type].findIndex(f=>us.equals(f,c));if(u===-1)s[c.type]?.push(c);else{let f=s[c.type][u];f.avgDurationMs=Math.floor((f.avgDurationMs+c.totalDurationMs)/2),f.maxDurationMs=Math.max(f.maxDurationMs,c.maxDurationMs),f.minDurationMs=Math.min(f.minDurationMs,c.minDurationMs),f.totalDurationMs=f.totalDurationMs+c.totalDurationMs,f.count+=1,s[c.type][u]=f}}function a(s){for(let c of Object.keys(s))s[c].sort((f,d)=>d.avgDurationMs-f.avgDurationMs)}function o(s,c){s[c].length>iR&&s[c]?.splice(0,1)}})(cy||(cy={}));var td=new Dt("RequestThrottler.ts"),Ho=100,ls=500,ds=2e3,rd=class{constructor(){this.tokensSecond=Ho,this.tokensMinute=ls,this.tokensHour=ds,this.lastUpdate=he.now()}refill(){let t=he.now();if(he.cmp(t,this.lastUpdate)<0){this.lastUpdate=t;return}let r=he.difference(t,this.lastUpdate);if(r.d_ms==="forever")throw Error("assertion failed");r.d_ms<1e3/Ho||(this.tokensSecond=Math.min(Ho,this.tokensSecond+r.d_ms/1e3*Ho),this.tokensMinute=Math.min(ls,this.tokensMinute+r.d_ms/1e3/60*ls),this.tokensHour=Math.min(ds,this.tokensHour+r.d_ms/1e3/60/60*ds),this.lastUpdate=t)}applyThrottle(){return this.refill(),this.tokensSecond<1?(td.warn("request throttled (per second limit exceeded)"),!0):this.tokensMinute<1?(td.warn("request throttled (per minute limit exceeded)"),!0):this.tokensHour<1?(td.warn("request throttled (per hour limit exceeded)"),!0):(this.tokensSecond--,this.tokensMinute--,this.tokensHour--,!1)}},Ba=class{constructor(){this.perOriginInfo={}}getState(t){let r=this.perOriginInfo[t];return r||(this.perOriginInfo[t]=new rd)}applyThrottle(t){let r=new URL(t).origin;return this.getState(r).applyThrottle()}getThrottleStats(t){let r=new URL(t).origin,n=this.getState(r);return{tokensHour:n.tokensHour,tokensMinute:n.tokensMinute,tokensSecond:n.tokensSecond,maxTokensHour:ds,maxTokensMinute:ls,maxTokensSecond:Ho}}};var uy;(function(e){e.Withdraw="WITHDRAW",e.Credit="CREDIT",e.Recoup="RECOUP",e.Closing="CLOSING"})(uy||(uy={}));var T8=new Dt("OperationThrottler.ts");var Go;(function(e){e.None="none",e.Pending="pending",e.Done="done",e.Aborting="aborting",e.Aborted="aborted",e.Dialog="dialog",e.Finalizing="finalizing",e.Suspended="suspended",e.SuspendedFinalizing="suspended-finalizing",e.SuspendedAborting="suspended-aborting",e.Failed="failed",e.Expired="expired",e.Deleted="deleted"})(Go||(Go={}));var ly;(function(e){e.AbortingBank="aborting-bank",e.AcceptRefund="accept-refund",e.AutoRefund="auto-refund",e.BalanceKycRequired="balance-kyc",e.Bank="bank",e.BankConfirmTransfer="bank-confirm-transfer",e.BankRegisterReserve="bank-register-reserve",e.CheckRefund="check-refund",e.ClaimProposal="claim-proposal",e.CompletedByOtherWallet="completed-by-other-wallet",e.CreatePurse="create-purse",e.DeletePurse="delete-purse",e.Deposit="deposit",e.Exchange="exchange",e.ExchangeWaitReserve="exchange-wait-reserve",e.KycAuthRequired="kyc-auth",e.KycInit="kyc-init",e.KycRequired="kyc",e.Merge="merge",e.PaidByOther="paid-by-other",e.Proposed="proposed",e.Ready="ready",e.RebindSession="rebind-session",e.Refresh="refresh",e.Refused="refused",e.Repurchase="repurchase",e.SubmitPayment="submit-payment",e.Track="track",e.Unknown="unknown",e.Withdraw="withdraw"})(ly||(ly={}));var dy;(function(e){e.Delete="delete",e.Suspend="suspend",e.Resume="resume",e.Abort="abort",e.Fail="fail",e.Retry="retry"})(dy||(dy={}));var Bo;(function(e){e.Withdrawal="withdrawal",e.InternalWithdrawal="internal-withdrawal",e.Payment="payment",e.Refund="refund",e.Refresh="refresh",e.Deposit="deposit",e.PeerPushDebit="peer-push-debit",e.PeerPushCredit="peer-push-credit",e.PeerPullDebit="peer-pull-debit",e.PeerPullCredit="peer-pull-credit",e.Recoup="recoup",e.DenomLoss="denom-loss"})(Bo||(Bo={}));var fy;(function(e){e.TalerBankIntegrationApi="taler-bank-integration-api",e.ManualTransfer="manual-transfer"})(fy||(fy={}));var py;(function(e){e.DenomExpired="denom-expired",e.DenomVanished="denom-vanished",e.DenomUnoffered="denom-unoffered"})(py||(py={}));var fs;(function(e){e.Aborted="aborted",e.Failed="failed",e.Paid="paid",e.Accepted="accepted"})(fs||(fs={}));var U8=[{type:Bo.Payment,txState:{major:Go.Done},amountRaw:"KUDOS:10",amountEffective:"KUDOS:10",totalRefundRaw:"KUDOS:0",totalRefundEffective:"KUDOS:0",status:fs.Paid,refundPending:void 0,posConfirmation:void 0,pending:!1,refunds:[],timestamp:{t_s:1677166045},transactionId:"txn:payment:NRRD9KJ8970P5HDAGPW1MBA6HZHB1XMFKF5M3CNR6WA0GT98DHY0",proposalId:"NRRD9KJ8970P5HDAGPW1MBA6HZHB1XMFKF5M3CNR6WA0GT98DHY0",info:{merchant:{name:"woocommerce",website:"woocommerce.demo.taler.net",email:"foo@example.com",address:{},jurisdiction:{}},orderId:"wc_order_KQCRldghIgDRB-100",products:[{description:"Using GCC",quantity:1,price:"KUDOS:10",product_id:"28"}],summary:"WooTalerShop #100",contractTermsHash:"A02E1M6ARWKBJ87K2TV4S6WQ4X5YH7BRVR6MYCHCTVAED8MBXTFD6PZ5Q50Y7Z5K18PYBTDA14NQ56XPC1VCQW1EVRWTSB7ZYT65B5G",fulfillmentUrl:"https://woocommerce.demo.taler.net/?wc-api=wc_gnutaler_gateway&order_id=wc_order_KQCRldghIgDRB-100"},refundQueryActive:!1,frozen:!1},{type:Bo.Refresh,txState:{major:Go.Pending},refreshReason:Ki.PayMerchant,amountEffective:"KUDOS:0",amountRaw:"KUDOS:0",refreshInputAmount:"KUDOS:1.5",refreshOutputAmount:"KUDOS:1.4",originatingTransactionId:"txn:proposal:ZCGBZFE8KZ1CBYYGSC3ZC8E40KVJWV16VYCTHGC8FFSVZ5HD24BG",pending:!0,timestamp:{t_s:1681376214},transactionId:"txn:refresh:QQSWHHXCRQ269G0E3RW14JMC6F7NFDYDW26NSFHRTXSKDS6CMCZ0",frozen:!1,error:{code:7029,when:{t_ms:1681376473665},hint:"Error (WALLET_REFRESH_GROUP_INCOMPLETE)",numErrors:1,errors:[{code:7001,when:{t_ms:1681376473189},hint:"unexpected exception (message: exchange wire fee signature invalid)",stack:` at validateWireInfo (../taler-wallet-core-qjs.mjs:23166) `}]}}];var Z_=()=>W().property("version",L()).property("name",X("taler-mailbox")).property("monthly_fee",me()).property("registration_update_fee",me()).property("message_body_bytes",ne()).property("message_response_limit",ne()).property("delivery_period",qt).build("TalerMailboxApi.VersionResponse");var J_=()=>W().property("signing_key",Ft()).property("signing_key_type",X("EdDSA")).property("encryption_key",L()).property("encryption_key_type",X("X25519")).property("expiration",Me).build("TalerMailboxApi.MailboxMessageKeys"),os=()=>W().property("code",ne()).property("retry_delay",qt).property("hint",L()).build("TalerMailboxApi.MailboxRateLimitedResponse");var yr={FILE_NOTE:"FILE_NOTE",CUSTOMER_LABEL:"CUSTOMER_LABEL",ACCOUNT_OPEN:"ACCOUNT_OPEN",PEP_DOMESTIC:"PEP_DOMESTIC",PEP_FOREIGN:"PEP_FOREIGN",PEP_INTERNATIONAL_ORGANIZATION:"PEP_INTERNATIONAL_ORGANIZATION",HIGH_RISK_CUSTOMER:"HIGH_RISK_CUSTOMER",HIGH_RISK_COUNTRY:"HIGH_RISK_COUNTRY",ACCOUNT_IDLE:"ACCOUNT_IDLE",INVESTIGATION_STATE:"INVESTIGATION_STATE",INVESTIGATION_TRIGGER:"INVESTIGATION_TRIGGER",SANCTION_LIST_BEST_MATCH:"SANCTION_LIST_BEST_MATCH",SANCTION_LIST_RATING:"SANCTION_LIST_RATING",SANCTION_LIST_CONFIDENCE:"SANCTION_LIST_CONFIDENCE",SANCTION_LIST_SUPPRESS:"SANCTION_LIST_SUPPRESS"};function Q_(e,t){let r=Co(Bn.AML_DECISION),n=t.keep_investigating?1:0;r.put(pl(t.decision_time)),r.put(pl(t.attributes_expiration??Pi.fromSeconds(0))),r.put(nr(t.h_payto)),r.put(In(gr(t.justification))),r.put(In(gr(pn(t.properties)+"\0"))),r.put(In(gr(pn(t.new_rules)+"\0"))),t.new_measures!=null?r.put(In(gr(t.new_measures))):r.put(new Uint8Array(64)),t.attributes!=null?r.put(In(gr(pn(t.attributes)+"\0"))):r.put(new Uint8Array(64)),r.put(Qm(n));let a=r.build();return fl(a,e)}function Kr(e){let t=Co(Bn.AML_QUERY).build();return fl(t,e)}var eH=[yr.FILE_NOTE,yr.CUSTOMER_LABEL,yr.ACCOUNT_OPEN,yr.PEP_DOMESTIC,yr.PEP_FOREIGN,yr.PEP_INTERNATIONAL_ORGANIZATION,yr.HIGH_RISK_CUSTOMER,yr.HIGH_RISK_COUNTRY,yr.ACCOUNT_IDLE,yr.INVESTIGATION_TRIGGER,yr.INVESTIGATION_STATE,yr.SANCTION_LIST_BEST_MATCH,yr.SANCTION_LIST_RATING,yr.SANCTION_LIST_CONFIDENCE,yr.SANCTION_LIST_SUPPRESS],tH=[yr.FILE_NOTE],hy;(function(e){e[e.vqf_902_1_customer=0]="vqf_902_1_customer",e[e.vqf_902_1_officer=1]="vqf_902_1_officer",e[e.vqf_902_4=2]="vqf_902_4",e[e.vqf_902_5=3]="vqf_902_5",e[e.vqf_902_9_customer=4]="vqf_902_9_customer",e[e.vqf_902_9_officer=5]="vqf_902_9_officer",e[e.vqf_902_11_customer=6]="vqf_902_11_customer",e[e.vqf_902_11_officer=7]="vqf_902_11_officer",e[e.vqf_902_12=8]="vqf_902_12",e[e.vqf_902_13=9]="vqf_902_13",e[e.vqf_902_14=10]="vqf_902_14",e[e.vqf_902_15=11]="vqf_902_15"})(hy||(hy={}));var Dr;(function(e){e.INCR_ACCOUNT_OPEN="INCR_ACCOUNT_OPEN",e.DECR_ACCOUNT_OPEN="DECR_ACCOUNT_OPEN",e.INCR_HIGH_RISK_CUSTOMER="INCR_HIGH_RISK_CUSTOMER",e.DECR_HIGH_RISK_CUSTOMER="DECR_HIGH_RISK_CUSTOMER",e.INCR_HIGH_RISK_COUNTRY="INCR_HIGH_RISK_COUNTRY",e.DECR_HIGH_RISK_COUNTRY="DECR_HIGH_RISK_COUNTRY",e.INCR_PEP="INCR_PEP",e.DECR_PEP="DECR_PEP",e.INCR_PEP_FOREIGN="INCR_PEP_FOREIGN",e.DECR_PEP_FOREIGN="DECR_PEP_FOREIGN",e.INCR_PEP_DOMESTIC="INCR_PEP_DOMESTIC",e.DECR_PEP_DOMESTIC="DECR_PEP_DOMESTIC",e.INCR_PEP_INTERNATIONAL_ORGANIZATION="INCR_PEP_INTERNATIONAL_ORGANIZATION",e.DECR_PEP_INTERNATIONAL_ORGANIZATION="DECR_PEP_INTERNATIONAL_ORGANIZATION",e.MROS_REPORTED_SUSPICION_SIMPLE="MROS_REPORTED_SUSPICION_SIMPLE",e.MROS_REPORTED_SUSPICION_SUBSTANTIATED="MROS_REPORTED_SUSPICION_SUBSTANTIATED",e.INCR_INVESTIGATION_CONCLUDED="INCR_INVESTIGATION_CONCLUDED",e.DECR_INVESTIGATION_CONCLUDED="DECR_INVESTIGATION_CONCLUDED"})(Dr||(Dr={}));var my;(function(e){e.ACCOUNT_OPENED="ACCOUNT_OPENED",e.ACCOUNT_CLOSED="ACCOUNT_CLOSED"})(my||(my={}));var gy;(function(e){e[e.vqf_902_1_customer=0]="vqf_902_1_customer",e[e.vqf_902_1_officer=1]="vqf_902_1_officer",e[e.vqf_902_4=2]="vqf_902_4",e[e.vqf_902_5=3]="vqf_902_5",e[e.vqf_902_9_customer=4]="vqf_902_9_customer",e[e.vqf_902_9_officer=5]="vqf_902_9_officer",e[e.vqf_902_11_customer=6]="vqf_902_11_customer",e[e.vqf_902_11_officer=7]="vqf_902_11_officer",e[e.vqf_902_12=8]="vqf_902_12",e[e.vqf_902_13=9]="vqf_902_13",e[e.vqf_902_14=10]="vqf_902_14",e[e.vqf_902_15=11]="vqf_902_15"})(gy||(gy={}));var cH=Object.values(Dr);var fH={accounts_open_incr:{event:Dr.INCR_ACCOUNT_OPEN,start:void 0,end:void 0},accounts_open_decr:{event:Dr.DECR_ACCOUNT_OPEN,start:void 0,end:void 0},gwg_files_new_last_year:{event:Dr.INCR_ACCOUNT_OPEN,start:he.addDuration(he.now(),rt.fromSpec({years:-1})),end:he.now()},gwg_files_closed_last_year:{event:Dr.DECR_ACCOUNT_OPEN,start:he.addDuration(he.now(),rt.fromSpec({years:-1})),end:he.now()},gwg_files_high_risk_incr:{event:Dr.INCR_HIGH_RISK_CUSTOMER,start:void 0,end:void 0},gwg_files_high_risk_decr:{event:Dr.DECR_HIGH_RISK_CUSTOMER,start:void 0,end:void 0},gwg_files_pep_incr:{event:Dr.INCR_PEP,start:void 0,end:void 0},gwg_files_pep_decr:{event:Dr.DECR_PEP,start:void 0,end:void 0},mros_reports_art9_last_year:{event:Dr.MROS_REPORTED_SUSPICION_SUBSTANTIATED,start:he.addDuration(he.now(),rt.fromSpec({years:-1})),end:he.now()},mros_reports_art305_last_year:{event:Dr.MROS_REPORTED_SUSPICION_SIMPLE,start:he.addDuration(he.now(),rt.fromSpec({years:-1})),end:he.now()},accounts_involed_in_proceedings_last_year:{event:Dr.INCR_INVESTIGATION_CONCLUDED,start:he.addDuration(he.now(),rt.fromSpec({years:-1})),end:he.now()}};uh();Re();Be();Re();Re();Be();Re();Re();Be();Re();Re();Be();Re();Re();pa();Re();Re();pa();Re();Re();Re();Re();Re();Re();Re();Be();Re();Be();Be();Be();Be();Be();Be();Be();Be();Re();Be();Re();Be();Re();Be();Re();Be();Re();Be();Re();Be();Re();Be();Re();Re();Be();Re();Be();Re();Re();Re();Be();Re();Re();Re();Be();Re();Re();Be();Re();Be();Re();Be();Re();Re();Be();Re();Re();Be();Re();Re();Be();Re();Re();Re();Be();Re();Re();Be();Re();Re();Re();Re();Be();Be();var xR=Object.create,Mf=Object.defineProperty,IR=Object.getOwnPropertyDescriptor,$0=Object.getOwnPropertyNames,SR=Object.getPrototypeOf,CR=Object.prototype.hasOwnProperty,OR=(e,t)=>function(){return t||(0,e[$0(e)[0]])((t={exports:{}}).exports,t),t.exports},DR=(e,t)=>{for(var r in t)Mf(e,r,{get:t[r],enumerable:!0})},PR=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of $0(t))!CR.call(e,a)&&a!==r&&Mf(e,a,{get:()=>t[a],enumerable:!(n=IR(t,a))||n.enumerable});return e},LR=(e,t,r)=>(r=e!=null?xR(SR(e)):{},PR(t||!e||!e.__esModule?Mf(r,"default",{value:e,enumerable:!0}):r,e)),UR=OR({"../../node_modules/.pnpm/qrcode-generator@1.4.4/node_modules/qrcode-generator/qrcode.js"(e,t){var r=(function(){var n=function(_,g){var O=236,E=17,m=_,y=o[g],b=null,x=0,D=null,F=[],B={},K=function(H,M){x=m*4+17,b=(function(q){for(var Y=new Array(q),j=0;j=7&&xe(H),D==null&&(D=te(m,y,F)),Ue(D,M)},Z=function(H,M){for(var q=-1;q<=7;q+=1)if(!(H+q<=-1||x<=H+q))for(var Y=-1;Y<=7;Y+=1)M+Y<=-1||x<=M+Y||(0<=q&&q<=6&&(Y==0||Y==6)||0<=Y&&Y<=6&&(q==0||q==6)||2<=q&&q<=4&&2<=Y&&Y<=4?b[H+q][M+Y]=!0:b[H+q][M+Y]=!1)},pe=function(){for(var H=0,M=0,q=0;q<8;q+=1){K(!0,q);var Y=c.getLostPoint(B);(q==0||H>Y)&&(H=Y,M=q)}return M},Ie=function(){for(var H=8;H>q&1)==1;b[Math.floor(q/3)][q%3+x-8-3]=Y}for(var q=0;q<18;q+=1){var Y=!H&&(M>>q&1)==1;b[q%3+x-8-3][Math.floor(q/3)]=Y}},Le=function(H,M){for(var q=y<<3|M,Y=c.getBCHTypeInfo(q),j=0;j<15;j+=1){var ie=!H&&(Y>>j&1)==1;j<6?b[j][8]=ie:j<8?b[j+1][8]=ie:b[x-15+j][8]=ie}for(var j=0;j<15;j+=1){var ie=!H&&(Y>>j&1)==1;j<8?b[8][x-j-1]=ie:j<9?b[8][15-j-1+1]=ie:b[8][15-j-1]=ie}b[x-8][8]=!H},Ue=function(H,M){for(var q=-1,Y=x-1,j=7,ie=0,we=c.getMaskFunction(M),oe=x-1;oe>0;oe-=2)for(oe==6&&(oe-=1);;){for(var je=0;je<2;je+=1)if(b[Y][oe-je]==null){var ct=!1;ie>>j&1)==1);var qe=we(Y,oe-je);qe&&(ct=!ct),b[Y][oe-je]=ct,j-=1,j==-1&&(ie+=1,j=7)}if(Y+=q,Y<0||x<=Y){Y-=q,q=-q;break}}},Ve=function(H,M){for(var q=0,Y=0,j=0,ie=new Array(M.length),we=new Array(M.length),oe=0;oe=0?tn.getAt(Ye):0}}for(var $t=0,qe=0;qeoe*8)throw"code length overflow. ("+j.getLengthInBits()+">"+oe*8+")";for(j.getLengthInBits()+4<=oe*8&&j.put(0,4);j.getLengthInBits()%8!=0;)j.putBit(!1);for(;!(j.getLengthInBits()>=oe*8||(j.put(O,8),j.getLengthInBits()>=oe*8));)j.put(E,8);return Ve(j,Y)};B.addData=function(H,M){M=M||"Byte";var q=null;switch(M){case"Numeric":q=R(H);break;case"Alphanumeric":q=h(H);break;case"Byte":q=p(H);break;case"Kanji":q=T(H);break;default:throw"mode:"+M}F.push(q),D=null},B.isDark=function(H,M){if(H<0||x<=H||M<0||x<=M)throw H+","+M;return b[H][M]},B.getModuleCount=function(){return x},B.make=function(){if(m<1){for(var H=1;H<40;H++){for(var M=d.getRSBlocks(H,y),q=w(),Y=0;Y"u"?H*4:M;var q="";q+='";for(var j=0;j';q+=""}return q+="",q+="
    ",q},B.createSvgTag=function(H,M,q,Y){var j={};typeof arguments[0]=="object"&&(j=arguments[0],H=j.cellSize,M=j.margin,q=j.alt,Y=j.title),H=H||2,M=typeof M>"u"?H*4:M,q=typeof q=="string"?{text:q}:q||{},q.text=q.text||null,q.id=q.text?q.id||"qrcode-description":null,Y=typeof Y=="string"?{text:Y}:Y||{},Y.text=Y.text||null,Y.id=Y.text?Y.id||"qrcode-title":null;var ie=B.getModuleCount()*H+M*2,we,oe,je,ct,qe="",zt;for(zt="l"+H+",0 0,"+H+" -"+H+",0 0,-"+H+"z ",qe+=''+ee(Y.text)+"":"",qe+=q.text?''+ee(q.text)+"":"",qe+='',qe+='"u"?H*4:M;var q=B.getModuleCount()*H+M*2,Y=M,j=q-M;return v(q,q,function(ie,we){if(Y<=ie&&ie"u"?H*4:M;var Y=B.getModuleCount()*H+M*2,j="";return j+="",j};var ee=function(H){for(var M="",q=0;q":M+=">";break;case"&":M+="&";break;case'"':M+=""";break;default:M+=Y;break}}return M},$=function(H){var M=1;H=typeof H>"u"?M*2:H;var q=B.getModuleCount()*M+H*2,Y=H,j=q-H,ie,we,oe,je,ct,qe={"\u2588\u2588":"\u2588","\u2588 ":"\u2580"," \u2588":"\u2584"," ":" "},zt={"\u2588\u2588":"\u2580","\u2588 ":"\u2580"," \u2588":" "," ":" "},ir="";for(ie=0;ie=j?zt[ct]:qe[ct];ir+=` `}return q%2&&H>0?ir.substring(0,ir.length-q-1)+Array(q+1).join("\u2580"):ir.substring(0,ir.length-1)};return B.createASCII=function(H,M){if(H=H||1,H<2)return $(M);H-=1,M=typeof M>"u"?H*2:M;var q=B.getModuleCount()*H+M*2,Y=M,j=q-M,ie,we,oe,je,ct=Array(H+1).join("\u2588\u2588"),qe=Array(H+1).join(" "),zt="",ir="";for(ie=0;ie>>8),y.push(D&255)):y.push(E)}}return y}};var a={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8},o={L:1,M:0,Q:3,H:2},s={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},c=(function(){var _=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],g=1335,O=7973,E=21522,m={},y=function(b){for(var x=0;b!=0;)x+=1,b>>>=1;return x};return m.getBCHTypeInfo=function(b){for(var x=b<<10;y(x)-y(g)>=0;)x^=g<=0;)x^=O<5&&(D+=3+K-5)}for(var F=0;F=256;)m-=255;return _[m]},E})();function f(_,g){if(typeof _.length>"u")throw _.length+"/"+g;var O=(function(){for(var m=0;m<_.length&&_[m]==0;)m+=1;for(var y=new Array(_.length-m+g),b=0;b<_.length-m;b+=1)y[b]=_[b+m];return y})(),E={};return E.getAt=function(m){return O[m]},E.getLength=function(){return O.length},E.multiply=function(m){for(var y=new Array(E.getLength()+m.getLength()-1),b=0;b"u")throw"bad rs block @ typeNumber:"+m+"/errorCorrectionLevel:"+y;for(var x=b.length/3,D=[],F=0;F>>7-E%8&1)==1},O.put=function(E,m){for(var y=0;y>>m-y-1&1)==1)},O.getLengthInBits=function(){return g},O.putBit=function(E){var m=Math.floor(g/8);_.length<=m&&_.push(0),E&&(_[m]|=128>>>g%8),g+=1},O},R=function(_){var g=a.MODE_NUMBER,O=_,E={};E.getMode=function(){return g},E.getLength=function(b){return O.length},E.write=function(b){for(var x=O,D=0;D+2>>8&255)*192+(F&255),b.put(F,13),D+=2}if(D>>8)},g.writeBytes=function(O,E,m){E=E||0,m=m||O.length;for(var y=0;y0&&(O+=","),O+=_[E];return O+="]",O},g},C=function(){var _=0,g=0,O=0,E="",m={},y=function(x){E+=String.fromCharCode(b(x&63))},b=function(x){if(!(x<0)){if(x<26)return 65+x;if(x<52)return 97+(x-26);if(x<62)return 48+(x-52);if(x==62)return 43;if(x==63)return 47}throw"n:"+x};return m.writeByte=function(x){for(_=_<<8|x&255,g+=8,O+=1;g>=6;)y(_>>>g-6),g-=6},m.flush=function(){if(g>0&&(y(_<<6-g),_=0,g=0),O%3!=0)for(var x=3-O%3,D=0;D=g.length){if(m==0)return-1;throw"unexpected end of file./"+m}var x=g.charAt(O);if(O+=1,x=="=")return m=0,-1;if(x.match(/^\s$/))continue;E=E<<6|b(x.charCodeAt(0)),m+=6}var D=E>>>m-8&255;return m-=8,D};var b=function(x){if(65<=x&&x<=90)return x-65;if(97<=x&&x<=122)return x-97+26;if(48<=x&&x<=57)return x-48+52;if(x==43)return 62;if(x==47)return 63;throw"c:"+x};return y},k=function(_,g){var O=_,E=g,m=new Array(_*g),y={};y.setPixel=function(F,B,K){m[B*O+F]=K},y.write=function(F){F.writeString("GIF87a"),F.writeShort(O),F.writeShort(E),F.writeByte(128),F.writeByte(0),F.writeByte(0),F.writeByte(0),F.writeByte(0),F.writeByte(0),F.writeByte(255),F.writeByte(255),F.writeByte(255),F.writeString(","),F.writeShort(0),F.writeShort(0),F.writeShort(O),F.writeShort(E),F.writeByte(0);var B=2,K=x(B);F.writeByte(B);for(var Z=0;K.length-Z>255;)F.writeByte(255),F.writeBytes(K,Z,255),Z+=255;F.writeByte(K.length-Z),F.writeBytes(K,Z,K.length-Z),F.writeByte(0),F.writeString(";")};var b=function(F){var B=F,K=0,Z=0,pe={};return pe.write=function(Ie,be){if(Ie>>>be)throw"length over";for(;K+be>=8;)B.writeByte(255&(Ie<>>=8-K,Z=0,K=0;Z=Ie<0&&B.writeByte(Z)},pe},x=function(F){for(var B=1<>6,128|u&63):u<55296||u>=57344?s.push(224|u>>12,128|u>>6&63,128|u&63):(c++,u=65536+((u&1023)<<10|o.charCodeAt(c)&1023),s.push(240|u>>18,128|u>>12&63,128|u>>6&63,128|u&63))}return s}return a(n)}})(),(function(n){typeof define=="function"&&define.amd?define([],n):typeof e=="object"&&(t.exports=n())})(function(){return r})}}),un={};DR(un,{compose:()=>MR,composeRef:()=>vd,doAutoFocus:()=>X0,doAutoFocusWithScroll:()=>GR,onComponentUnload:()=>FR,preconnectAs:()=>HR,recursive:()=>kR,saveRef:()=>Ed,saveVNodeForInspection:()=>BR});function MR(e,t){function r(n){function a(){let o=n();if(typeof o=="function"){let u=r(o);return i(u,{})}let s=o.status,c=t[s];return i(c,o)}return a}return n=>r(()=>e(n))()}function kR(e){function t(r){function n(){let a=r();if(typeof a=="function"){let o=t(a);return i(o,{})}return a}return n}return r=>t(()=>e(r))()}function FR(e){let t=Yt();t.current=e,Ge(()=>()=>{t.current()},[])}var md=typeof document>"u"?null:document,Eb=new Set;function HR(e){md&&e.forEach(({rel:t,href:r,crossOrigin:n})=>{let a=`${t}${r}${n}`;if(Eb.has(a))return;Eb.add(a);let o=md.createElement("link");o.setAttribute("rel",t),o.setAttribute("crossOrigin",n),o.setAttribute("href",r),md.head.appendChild(o)})}function vd(...e){return t=>{e.forEach(r=>{r(t)})}}function Ed(e){return t=>{t&&(e.current=t)}}function X0(e){e&&setTimeout(()=>{e.focus({preventScroll:!0})},100)}function GR(e){e&&setTimeout(()=>{e.focus({preventScroll:!0}),e.scrollIntoView({behavior:"smooth",block:"center",inline:"center"})},100)}function BR(e){return window.showVNodeInfo=function(){wd(e)},e}function wd(e){if(!e)return;if(e.__c&&e.__c.__H){let r=e.__c.constructor.name,a=e.__c.__H.__;console.log("==============",r),a.forEach(o=>{let{__:s,c,__h:u,__H:f}=o;if(typeof c<"u"){let{__c:d}=c;console.log("context:",d,o)}else if(typeof u=="function")console.log("memo:",s,"deps:",f);else if(typeof s=="function"){let d=s.name;console.log("effect:",d,"deps:",f)}else if(typeof s.current<"u"){let d=s.current;console.log("ref:",d instanceof Element?d.outerHTML:d)}else s instanceof Array?console.log("state:",s[0]):console.log(o)})}let t=e.__k;t instanceof Array?t.forEach(r=>wd(r)):wd(t)}function Pe({type:e="info",title:t,children:r,onClose:n,timeout:a=rt.getForever()}){return i("div",{class:`group attention-${e} mt-2 shadow-lg`},i("div",{"data-timed":a.d_ms!=="forever",class:"rounded-md data-[timed=true]:rounded-b-none group-[.attention-info]:bg-blue-50 group-[.attention-low]:bg-gray-100 group-[.attention-warning]:bg-yellow-50 group-[.attention-danger]:bg-red-50 group-[.attention-success]:bg-green-50 p-4 shadow"},i("div",{class:"flex"},i("div",null,e==="low"?void 0:i("svg",{xmlns:"http://www.w3.org/2000/svg",stroke:"none",viewBox:"0 0 24 24",fill:"currentColor",class:"w-8 h-8 group-[.attention-info]:text-blue-400 group-[.attention-warning]:text-yellow-400 group-[.attention-danger]:text-red-400 group-[.attention-success]:text-green-400"},(()=>{switch(e){case"info":return i("path",{"fill-rule":"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"});case"warning":return i("path",{"fill-rule":"evenodd",d:"M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z"});case"danger":return i("path",{"fill-rule":"evenodd",d:"M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z"});case"success":return i("path",{"fill-rule":"evenodd",d:"M7.493 18.75c-.425 0-.82-.236-.975-.632A7.48 7.48 0 016 15.375c0-1.75.599-3.358 1.602-4.634.151-.192.373-.309.6-.397.473-.183.89-.514 1.212-.924a9.042 9.042 0 012.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 00.322-1.672V3a.75.75 0 01.75-.75 2.25 2.25 0 012.25 2.25c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 01-2.649 7.521c-.388.482-.987.729-1.605.729H14.23c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 00-1.423-.23h-.777zM2.331 10.977a11.969 11.969 0 00-.831 4.398 12 12 0 00.52 3.507c.26.85 1.084 1.368 1.973 1.368H4.9c.445 0 .72-.498.523-.898a8.963 8.963 0 01-.924-3.977c0-1.708.476-3.305 1.302-4.666.245-.403-.028-.959-.5-.959H4.25c-.832 0-1.612.453-1.918 1.227z"});default:ue(e)}})())),i("div",{class:"ml-3 w-full"},i("h3",{class:"text-sm font-bold group-[.attention-info]:text-blue-800 group-[.attention-success]:text-green-800 group-[.attention-warning]:text-yellow-800 group-[.attention-danger]:text-red-800"},t),i("div",{class:"mt-2 text-sm group-[.attention-info]:text-blue-700 group-[.attention-warning]:text-yellow-700 group-[.attention-danger]:text-red-700 group-[.attention-success]:text-green-700"},r)),n&&i("div",null,i("button",{type:"button",class:"font-semibold items-center rounded bg-transparent px-2 py-1 text-xs text-gray-900 hover:bg-gray-50",onClick:o=>{o.preventDefault(),n()}},i("svg",{class:"h-5 w-5",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{d:"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"})))))),a.d_ms==="forever"?void 0:i("div",{class:"meter group-[.attention-info]:bg-blue-50 group-[.attention-low]:bg-gray-100 group-[.attention-warning]:bg-yellow-50 group-[.attention-danger]:bg-red-50 group-[.attention-success]:bg-green-50 h-1 relative overflow-hidden -mt-1"},i("span",{class:"w-full h-full block"},i("span",{class:"h-full block progress group-[.attention-info]:bg-blue-600 group-[.attention-low]:bg-gray-600 group-[.attention-warning]:bg-yellow-600 group-[.attention-danger]:bg-red-600 group-[.attention-success]:bg-green-600"}))))}function WR(){return i("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"w-6 h-6"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75"}))}function VR(){return i("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"w-6 h-6"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M4.5 12.75l6 6 9-13.5"}))}function Ln({class:e,children:t,getContent:r}){let[n,a]=de(!1);function o(){!navigator.clipboard&&!window.isSecureContext&&prompt("Clipboard is not available on insecure context (http).",r()),navigator.clipboard&&(navigator.clipboard.writeText(r()||""),a(!0))}return Ge(()=>{n&&setTimeout(()=>{a(!1)},1e3)},[n]),n?i("button",{class:e,disabled:!0},i(VR,null),t):i("button",{class:e,onClick:s=>{s.preventDefault(),o()}},i(WR,null),t)}function zn({error:e}){let{i18n:t}=Ne(),[{showDebugInfo:r},n]=Qo();return i("div",{class:"text-[grey]"},i("button",{onClick:()=>n("showDebugInfo",!r)},r?i(t.Translate,null,"Hide debug info"):i(t.Translate,null,"Show more information")),r&&i("pre",{class:"whitespace-break-spaces text-black"},JSON.stringify(e,void 0,2)))}function _t({error:e}){let{i18n:t}=Ne();switch(e.errorDetail.code){case G.GENERIC_TIMEOUT:{if(e.hasErrorCode(G.GENERIC_TIMEOUT))return i(Pe,{type:"danger",title:t.str`The request reached a timeout, check your connection.`},e.message,i(zn,{error:e.errorDetail}));ue(1)}case G.GENERIC_CLIENT_INTERNAL_ERROR:{if(e.hasErrorCode(G.GENERIC_CLIENT_INTERNAL_ERROR)){let{requestMethod:r,requestUrl:n,timeoutMs:a}=e.errorDetail;return i(Pe,{type:"danger",title:t.str`The request was cancelled.`},e.message,i(zn,{error:e.errorDetail}))}ue(1)}case G.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT:{if(e.hasErrorCode(G.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT)){let{requestMethod:r,requestUrl:n,timeoutMs:a}=e.errorDetail;return i(Pe,{type:"danger",title:t.str`The request reached a timeout, check your connection.`},e.message,i(zn,{error:e.errorDetail}))}ue(1)}case G.WALLET_HTTP_REQUEST_THROTTLED:{if(e.hasErrorCode(G.WALLET_HTTP_REQUEST_THROTTLED)){let{requestMethod:r,requestUrl:n,throttleStats:a}=e.errorDetail;return i(Pe,{type:"danger",title:t.str`Too many requests were made to the server, and this action was throttled.`},e.message,i(zn,{error:e.errorDetail}))}ue(1)}case G.WALLET_RECEIVED_MALFORMED_RESPONSE:{if(e.hasErrorCode(G.WALLET_RECEIVED_MALFORMED_RESPONSE)){let{requestMethod:r,requestUrl:n,httpStatusCode:a,validationError:o}=e.errorDetail;return i(Pe,{type:"danger",title:t.str`The server's response was malformed.`},e.message,i(zn,{error:e.errorDetail}))}ue(1)}case G.WALLET_NETWORK_ERROR:{if(e.hasErrorCode(G.WALLET_NETWORK_ERROR)){let{requestMethod:r,requestUrl:n}=e.errorDetail;return i(Pe,{type:"danger",title:t.str`Could not complete the request due to a network problem.`},e.message,i(zn,{error:e.errorDetail}))}ue(1)}case G.WALLET_UNEXPECTED_REQUEST_ERROR:{if(e.hasErrorCode(G.WALLET_UNEXPECTED_REQUEST_ERROR)){let{requestMethod:r,requestUrl:n,httpStatusCode:a,errorResponse:o}=e.errorDetail;return i(Pe,{type:"danger",title:t.str`Unexpected request error`},e.message,i(zn,{error:e.errorDetail}))}ue(1)}default:return i(Pe,{type:"danger",title:t.str`Unexpected error`},e.message,i(zn,{error:e.errorDetail}))}}var wb='data:image/svg+xml,%0A%0A%0A%0A%0A%0A%0A%09%0A%09%09%0A%09%09%0A%09%09%0A%09%09%0A%09%09%0A%09%09%09%0A%09%09%09%0A%09%09%0A%09%09%0A%09%09%0A%09%09%0A%09%09%0A%09%09%0A%09%09%09%0A%09%09%0A%09%0A%0A%0A',Ab={uk:"\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430 [uk]",tr:"T\xFCrk\xE7e [tr]",ru:"\u0420\u0443\u0301\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u0301\u043A [ru]",sv:"Svenska [sv]",it:"Italiano [it]",fr:"Fran\xE7ais [fr]",es:"Espa\xF1ol [es]",de:"Deutsch [de]",en:"English [en]"};function gd(e){return Ab[e]?Ab[e]:String(e)}function Tb({type:e="select"}){let{lang:t,changeLanguage:r,completeness:n,supportedLang:a}=Ne(),[o,s]=de(!0);return Ge(()=>{function c(f){f.code==="Escape"&&s(!0)}function u(f){s(!0)}return document.body.addEventListener("click",u),document.body.addEventListener("keydown",c),()=>{document.body.removeEventListener("keydown",c),document.body.removeEventListener("click",u)}},[]),i("div",{class:"m-2 block"},(function(){switch(e){case"select":return i("button",{type:"button",class:"relative w-full rounded-md bg-white py-1.5 pl-3 pr-10 text-left text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-600 sm:text-sm sm:leading-6","aria-haspopup":"listbox","aria-expanded":"true","aria-labelledby":"listbox-label",onClick:c=>{s(!o),c.stopPropagation()}},i("span",{class:"flex items-center"},i("img",{alt:"language",class:"h-5 w-5 flex-shrink-0 rounded-full",src:wb}),i("span",{class:"ml-3 block truncate"},gd(t))),i("span",{class:"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"},i("svg",{class:"h-5 w-5 text-gray-400",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z","clip-rule":"evenodd"}))));case"icon":return i("button",{type:"button",class:"relative w-full rounded-md bg-white p-2 text-left text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-600",onClick:c=>{s(!o),c.stopPropagation()}},i("div",{class:"flex h-7 w-7"},i("img",{alt:"language",class:"h-7 w-7 flex-shrink-0 rounded-full",src:wb})))}})(),!o&&i("ul",{class:"absolute m-0 max-h-60 overflow-auto rounded-md bg-white py-1 text-base text-left shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm",tabIndex:-1,style:e==="icon"?{marginLeft:-110}:{},role:"listbox","aria-labelledby":"listbox-label","aria-activedescendant":"listbox-option-3"},e==="icon"?i(ae,null,i("li",{class:"text-gray-900 relative border-b boder-gray-200 select-none py-2 pl-3 pr-9",role:"option"},i("span",{class:"font-normal truncate flex justify-between "},i("span",null,gd(t)),i("span",null,n[t],"%")),i("span",{class:"text-indigo-600 absolute inset-y-0 right-0 flex items-center pr-4"}))):i(ae,null),Object.keys(a).filter(c=>c!==t).map(c=>i("li",{class:"text-gray-900 hover:bg-primary hover:bg-gray-300 cursor-pointer relative select-none py-2 pl-3 pr-9",role:"option",onClick:()=>{r(c),s(!0)}},i("span",{class:"font-normal truncate flex justify-between "},i("span",null,gd(c)),i("span",null,n[c],"%")),i("span",{class:"text-indigo-600 absolute inset-y-0 right-0 flex items-center pr-4"})))))}function st(){return i("div",{class:"columns is-centered is-vcentered",style:{width:"100%",height:"200px",display:"flex",margin:"auto",justifyContent:"center"}},i(qR,null))}function qR(){return i("div",{class:"lds-ring m-auto"},i("div",null),i("div",null),i("div",null),i("div",null))}var KR="data:image/png;base64,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";function j0({title:e,profileURL:t,notificationURL:r,iconLinkURL:n,sites:a,onLogout:o,children:s}){let{i18n:c}=Ne(),[u,f]=de(!1),d=Yc();return i(ae,null,i("header",{class:"bg-primary w-full mx-auto px-2 border-b border-opacity-25 border-indigo-400"},i("div",{class:"flex flex-row h-16 items-center "},i("div",{class:"flex px-2 justify-start"},i("div",{class:"flex-shrink-0 rounded-lg"},i("a",{href:n??"#",name:"logo"},i("img",{class:"h-8 w-auto m-1",src:KR,alt:"GNU Taler"}))),i("span",{class:"flex items-center text-white text-lg font-bold ml-4"},e)),i("div",{class:"flex-1 ml-6 "},i("div",{class:"flex flex-1 space-x-4"},a.map(w=>{if(w.length!==2)return;let[R,h]=w;return i("a",{href:h,name:`site header ${R}`,class:"hidden sm:block text-white hover:bg-indigo-500 hover:bg-opacity-75 rounded-md py-2 px-3 text-sm font-medium"},R)}))),i("div",{class:"flex justify-end"},r?i("a",{href:r,name:"notifications",class:"relative inline-flex items-center justify-center rounded-md bg-primary p-1 mr-2 text-indigo-200 hover:bg-indigo-500 hover:bg-opacity-75 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600","aria-controls":"mobile-menu","aria-expanded":"false"},i("span",{class:"absolute -inset-0.5"}),i("span",{class:"sr-only"},i(c.Translate,null,"Show notifications")),d.length>0?i("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"currentColor",class:"w-10 h-10"},i("path",{d:"M5.85 3.5a.75.75 0 0 0-1.117-1 9.719 9.719 0 0 0-2.348 4.876.75.75 0 0 0 1.479.248A8.219 8.219 0 0 1 5.85 3.5ZM19.267 2.5a.75.75 0 1 0-1.118 1 8.22 8.22 0 0 1 1.987 4.124.75.75 0 0 0 1.48-.248A9.72 9.72 0 0 0 19.266 2.5Z"}),i("path",{"fill-rule":"evenodd",d:"M12 2.25A6.75 6.75 0 0 0 5.25 9v.75a8.217 8.217 0 0 1-2.119 5.52.75.75 0 0 0 .298 1.206c1.544.57 3.16.99 4.831 1.243a3.75 3.75 0 1 0 7.48 0 24.583 24.583 0 0 0 4.83-1.244.75.75 0 0 0 .298-1.205 8.217 8.217 0 0 1-2.118-5.52V9A6.75 6.75 0 0 0 12 2.25ZM9.75 18c0-.034 0-.067.002-.1a25.05 25.05 0 0 0 4.496 0l.002.1a2.25 2.25 0 1 1-4.5 0Z","clip-rule":"evenodd"})):i("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"w-10 h-10"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0"}))):void 0,t?i("a",{href:t,name:"profile",class:"relative inline-flex items-center justify-center rounded-md bg-primary p-1 mr-2 text-indigo-200 hover:bg-indigo-500 hover:bg-opacity-75 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600","aria-controls":"mobile-menu","aria-expanded":"false"},i("span",{class:"absolute -inset-0.5"}),i("span",{class:"sr-only"},i(c.Translate,null,"Open profile")),i("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"w-10 h-10"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"}))):void 0,i(Tb,{type:"icon"}),i("button",{type:"button",name:"toggle sidebar",class:"relative inline-flex items-center justify-center rounded-md bg-primary p-1 text-indigo-200 hover:bg-indigo-500 hover:bg-opacity-75 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600","aria-controls":"mobile-menu","aria-expanded":"false",onClick:w=>{f(!u)}},i("span",{class:"absolute -inset-0.5"}),i("span",{class:"sr-only"},i(c.Translate,null,"Open settings")),i("svg",{class:"block h-10 w-10",fill:"none",viewBox:"0 0 24 24","stroke-width":"2",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"})))))),u&&i("div",{class:"relative z-10",name:"sidebar overlay","aria-labelledby":"slide-over-title",role:"dialog","aria-modal":"true",onClick:()=>{f(!1)}},i("div",{class:"fixed inset-0"}),i("div",{class:"fixed inset-0 overflow-hidden"},i("div",{class:"absolute inset-0 overflow-hidden"},i("div",{class:"pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10"},i("div",{class:"pointer-events-auto w-screen max-w-md"},i("div",{class:"flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl",onClick:w=>{w.stopPropagation()}},i("div",{class:"px-4 sm:px-6"},i("div",{class:"flex items-start justify-between"},i("h2",{class:"text-base font-semibold leading-6 text-gray-900",id:"slide-over-title"},i(c.Translate,null,"Menu")),i("div",{class:"ml-3 flex h-7 items-center"},i("button",{type:"button",name:"close sidebar",class:"relative rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2",onClick:w=>{f(!1)}},i("span",{class:"absolute -inset-2.5"}),i("span",{class:"sr-only"},i(c.Translate,null,"Close panel")),i("svg",{class:"h-6 w-6",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M6 18L18 6M6 6l12 12"})))))),i("div",{class:"relative mt-6 flex-1 px-4 sm:px-6"},i("nav",{class:"flex flex-1 flex-col","aria-label":"Sidebar"},i("ul",{role:"list",class:"flex flex-1 flex-col gap-y-7"},o?i("li",null,i("a",{href:"#",name:"logout",class:"text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold",onClick:()=>{o(),f(!1)}},i("svg",{class:"h-6 w-6 shrink-0 text-indigo-600",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"})),i(c.Translate,null,"Log out"))):void 0,i("li",null,i(Tb,null)),s,a.length>0?i("li",{class:"block sm:hidden"},i("div",{class:"text-xs font-semibold leading-6 text-gray-400"},i(c.Translate,null,"Sites")),i("ul",{role:"list",class:"space-y-1"},a.map(([w,R])=>i("li",null,i("a",{href:R,name:`site ${w}`,target:"_blank",rel:"noopener noreferrer",class:"text-gray-700 hover:text-indigo-600 hover:bg-gray-100 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold"},i("span",{class:"flex h-6 w-6 shrink-0 items-center justify-center rounded-lg border text-[0.625rem] font-medium bg-white text-gray-400 border-gray-200 group-hover:border-indigo-600 group-hover:text-indigo-600"},">"),i("span",{class:"truncate"},w)))))):void 0))))))))))}function Q0({testingUrlKey:e,VERSION:t,GIT_HASH:r}){let{i18n:n}=Ne(),a=e&&typeof localStorage<"u"&&localStorage.getItem(e)?localStorage.getItem(e)??void 0:void 0,o=t?r?i("a",{href:`https://git.taler.net/wallet-core.git/tree/?id=${r}`,target:"_blank",rel:"noreferrer noopener"},"Version ",t," (",r.substring(0,8),")"):t:"";return i("footer",{class:"bottom-4 my-4 mx-8 bg-slate-200"},i("div",null,i("p",{class:"text-xs leading-5 text-gray-400"},i(n.Translate,null,"Learn more about"," ",i("a",{target:"_blank",rel:"noreferrer noopener",class:"font-semibold text-gray-500 hover:text-gray-400",href:"https://taler.net"},"GNU Taler")))),i("div",{style:"flex-grow:1"}),i("p",{class:"text-xs leading-5 text-gray-400"},"Copyright \xA9 2014\u20142025 Taler Systems SA. ",o," "),e&&a&&i("p",{class:"text-xs leading-5 text-gray-300"},"Testing with ",a," ",i("a",{href:"",onClick:s=>{s.preventDefault(),localStorage.removeItem(e),window.location.reload()}},"stop testing")))}function Ze({children:e,focus:t,onClick:r,disabled:n,...a}){let[o,s]=de(!1);return i("button",{...a,disabled:o||!r||!r.args||n,ref:t?X0:void 0,onClick:c=>{c.preventDefault(),!(!r||!r.args)&&(s(!0),r.call().finally(()=>{s(!1)}))}},o?i(YR,null):e)}function YR(){return i(ae,null,i("div",{role:"status"},i("svg",{"aria-hidden":"true",class:"w-8 h-8 text-neutral-tertiary animate-spin fill-brand",viewBox:"0 0 100 101",fill:"none",xmlns:"http://www.w3.org/2000/svg"},i("path",{d:"M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z",fill:"currentColor"}),i("path",{d:"M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z",fill:"currentFill"})),i("span",{class:"sr-only"},"Loading...")))}function nt({isDirty:e,message:t}){return t&&e?i("div",{class:"text-base",style:{color:"red"}},t):i("div",{class:"text-base"}," ")}function yt({notification:e}){let{i18n:t}=Ne(),[{showDebugInfo:r}]=Qo(),[n,a]=de(!1);if(!e)return i(ae,null);switch(e.message.type){case"error":let o=e.message.description;return i("div",{class:"relative"},i("div",{class:"fixed top-0 left-0 right-0 z-20 w-full p-4"},i(Pe,{type:"danger",title:e.message.title,onClose:()=>{e.acknowledge()}},o&&o.length&&(n?o.map(s=>i("div",{class:"mt-2 text-sm text-red-700"},s)):i("div",{class:"mt-2 text-sm text-red-700"},o[0])),i("div",{class:"flex justify-between"},i("div",{class:"text-[grey]"},n||o&&o.length<2?void 0:i("button",{onClick:()=>a(!0),class:"text-grey"},i(t.Translate,null,"Show more info")))),r&&i("pre",{class:"whitespace-break-spaces text-black"},JSON.stringify(e.message.debug,void 0,2)))));case"info":return i("div",{class:"relative"},i("div",{class:"fixed top-0 left-0 right-0 z-20 w-full p-4"},i(Pe,{type:"success",title:e.message.title,onClose:()=>{e.acknowledge()}})))}}function Z0({debug:e}){let t=Yc();if(t.length===0)return i(ae,null);let r=t.filter(n=>!n.message.ack&&!n.message.timeout);return r.length===0?i(ae,null):i(zR,{msg:r[0],debug:e})}function zR({msg:e,debug:t}){switch(e.message.type){case"error":return i(Pe,{type:"danger",title:e.message.title,onClose:()=>{e.acknowledge()},timeout:t?rt.getForever():Vc},e.message.description&&i("div",{class:"mt-2 text-sm text-red-700"},e.message.description),t?i("pre",null,e.message.debug):void 0);case"info":return i(Pe,{type:"success",title:e.message.title,onClose:()=>{e.acknowledge()},timeout:Vc})}}function sr(e){if(e===null||e===!0||e===!1)return NaN;var t=Number(e);return isNaN(t)?t:t<0?Math.ceil(t):Math.floor(t)}function dt(e,t){if(t.length1?"s":"")+" required, but only "+t.length+" present")}function Rs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Rs=function(r){return typeof r}:Rs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Rs(e)}function lt(e){dt(1,arguments);var t=Object.prototype.toString.call(e);return e instanceof Date||Rs(e)==="object"&&t==="[object Date]"?new Date(e.getTime()):typeof e=="number"||t==="[object Number]"?new Date(e):((typeof e=="string"||t==="[object String]")&&typeof console<"u"&&(console.warn("Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#string-arguments"),console.warn(new Error().stack)),new Date(NaN))}function $R(e,t){dt(2,arguments);var r=lt(e),n=sr(t);return isNaN(n)?new Date(NaN):(n&&r.setDate(r.getDate()+n),r)}function XR(e,t){dt(2,arguments);var r=lt(e),n=sr(t);if(isNaN(n))return new Date(NaN);if(!n)return r;var a=r.getDate(),o=new Date(r.getTime());o.setMonth(r.getMonth()+n+1,0);var s=o.getDate();return a>=s?o:(r.setFullYear(o.getFullYear(),o.getMonth(),a),r)}function xs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?xs=function(r){return typeof r}:xs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},xs(e)}function $o(e,t){if(dt(2,arguments),!t||xs(t)!=="object")return new Date(NaN);var r=t.years?sr(t.years):0,n=t.months?sr(t.months):0,a=t.weeks?sr(t.weeks):0,o=t.days?sr(t.days):0,s=t.hours?sr(t.hours):0,c=t.minutes?sr(t.minutes):0,u=t.seconds?sr(t.seconds):0,f=lt(e),d=n||r?XR(f,n+r*12):f,w=o||a?$R(d,o+a*7):d,R=c+s*60,h=u+R*60,p=h*1e3,T=new Date(w.getTime()+p);return T}function jR(e,t){dt(2,arguments);var r=lt(e).getTime(),n=sr(t);return new Date(r+n)}var QR={};function ja(){return QR}function Ad(e){var t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()));return t.setUTCFullYear(e.getFullYear()),e.getTime()-t.getTime()}function Td(e){dt(1,arguments);var t=lt(e);return t.setHours(0,0,0,0),t}var ZR=864e5;function JR(e,t){dt(2,arguments);var r=Td(e),n=Td(t),a=r.getTime()-Ad(r),o=n.getTime()-Ad(n);return Math.round((a-o)/ZR)}function Ya(e,t){dt(2,arguments);var r=lt(e),n=lt(t),a=r.getTime()-n.getTime();return a<0?-1:a>0?1:a}var ex=365.2425,tx=Math.pow(10,8)*24*60*60*1e3,J0=6e4,ev=36e5,rx=1e3,T7=-tx,nx=3600,tv=nx*24,N7=tv*7,ax=tv*ex,ox=ax/12,R7=ox*3;function Is(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Is=function(r){return typeof r}:Is=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Is(e)}function ix(e){return dt(1,arguments),e instanceof Date||Is(e)==="object"&&Object.prototype.toString.call(e)==="[object Date]"}function sx(e){if(dt(1,arguments),!ix(e)&&typeof e!="number")return!1;var t=lt(e);return!isNaN(Number(t))}function cx(e,t){dt(2,arguments);var r=lt(e),n=lt(t),a=r.getFullYear()-n.getFullYear(),o=r.getMonth()-n.getMonth();return a*12+o}function ux(e,t){dt(2,arguments);var r=lt(e),n=lt(t);return r.getFullYear()-n.getFullYear()}function Nb(e,t){var r=e.getFullYear()-t.getFullYear()||e.getMonth()-t.getMonth()||e.getDate()-t.getDate()||e.getHours()-t.getHours()||e.getMinutes()-t.getMinutes()||e.getSeconds()-t.getSeconds()||e.getMilliseconds()-t.getMilliseconds();return r<0?-1:r>0?1:r}function lx(e,t){dt(2,arguments);var r=lt(e),n=lt(t),a=Nb(r,n),o=Math.abs(JR(r,n));r.setDate(r.getDate()-a*o);var s=+(Nb(r,n)===-a),c=a*(o-s);return c===0?0:c}function kf(e,t){return dt(2,arguments),lt(e).getTime()-lt(t).getTime()}var Rb={ceil:Math.ceil,round:Math.round,floor:Math.floor,trunc:function(t){return t<0?Math.ceil(t):Math.floor(t)}},dx="trunc";function Ff(e){return e?Rb[e]:Rb[dx]}function fx(e,t,r){dt(2,arguments);var n=kf(e,t)/ev;return Ff(r?.roundingMethod)(n)}function px(e,t,r){dt(2,arguments);var n=kf(e,t)/J0;return Ff(r?.roundingMethod)(n)}function hx(e){dt(1,arguments);var t=lt(e);return t.setHours(23,59,59,999),t}function mx(e){dt(1,arguments);var t=lt(e),r=t.getMonth();return t.setFullYear(t.getFullYear(),r+1,0),t.setHours(23,59,59,999),t}function gx(e){dt(1,arguments);var t=lt(e);return hx(t).getTime()===mx(t).getTime()}function _x(e,t){dt(2,arguments);var r=lt(e),n=lt(t),a=Ya(r,n),o=Math.abs(cx(r,n)),s;if(o<1)s=0;else{r.getMonth()===1&&r.getDate()>27&&r.setDate(30),r.setMonth(r.getMonth()-a*o);var c=Ya(r,n)===-a;gx(lt(e))&&o===1&&Ya(e,n)===1&&(c=!1),s=a*(o-Number(c))}return s===0?0:s}function yx(e,t,r){dt(2,arguments);var n=kf(e,t)/1e3;return Ff(r?.roundingMethod)(n)}function bx(e,t){dt(2,arguments);var r=lt(e),n=lt(t),a=Ya(r,n),o=Math.abs(ux(r,n));r.setFullYear(1584),n.setFullYear(1584);var s=Ya(r,n)===-a,c=a*(o-Number(s));return c===0?0:c}function vx(e,t){dt(2,arguments);var r=sr(t);return jR(e,-r)}var Ex=864e5;function wx(e){dt(1,arguments);var t=lt(e),r=t.getTime();t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0);var n=t.getTime(),a=r-n;return Math.floor(a/Ex)+1}function za(e){dt(1,arguments);var t=1,r=lt(e),n=r.getUTCDay(),a=(n=a.getTime()?r+1:t.getTime()>=s.getTime()?r:r-1}function Ax(e){dt(1,arguments);var t=rv(e),r=new Date(0);r.setUTCFullYear(t,0,4),r.setUTCHours(0,0,0,0);var n=za(r);return n}var Tx=6048e5;function nv(e){dt(1,arguments);var t=lt(e),r=za(t).getTime()-Ax(t).getTime();return Math.round(r/Tx)+1}function ma(e,t){var r,n,a,o,s,c,u,f;dt(1,arguments);var d=ja(),w=sr((r=(n=(a=(o=t?.weekStartsOn)!==null&&o!==void 0?o:t==null||(s=t.locale)===null||s===void 0||(c=s.options)===null||c===void 0?void 0:c.weekStartsOn)!==null&&a!==void 0?a:d.weekStartsOn)!==null&&n!==void 0?n:(u=d.locale)===null||u===void 0||(f=u.options)===null||f===void 0?void 0:f.weekStartsOn)!==null&&r!==void 0?r:0);if(!(w>=0&&w<=6))throw new RangeError("weekStartsOn must be between 0 and 6 inclusively");var R=lt(e),h=R.getUTCDay(),p=(h=1&&h<=7))throw new RangeError("firstWeekContainsDate must be between 1 and 7 inclusively");var p=new Date(0);p.setUTCFullYear(w+1,0,h),p.setUTCHours(0,0,0,0);var T=ma(p,t),A=new Date(0);A.setUTCFullYear(w,0,h),A.setUTCHours(0,0,0,0);var C=ma(A,t);return d.getTime()>=T.getTime()?w+1:d.getTime()>=C.getTime()?w:w-1}function Nx(e,t){var r,n,a,o,s,c,u,f;dt(1,arguments);var d=ja(),w=sr((r=(n=(a=(o=t?.firstWeekContainsDate)!==null&&o!==void 0?o:t==null||(s=t.locale)===null||s===void 0||(c=s.options)===null||c===void 0?void 0:c.firstWeekContainsDate)!==null&&a!==void 0?a:d.firstWeekContainsDate)!==null&&n!==void 0?n:(u=d.locale)===null||u===void 0||(f=u.options)===null||f===void 0?void 0:f.firstWeekContainsDate)!==null&&r!==void 0?r:1),R=Hf(e,t),h=new Date(0);h.setUTCFullYear(R,0,w),h.setUTCHours(0,0,0,0);var p=ma(h,t);return p}var Rx=6048e5;function av(e,t){dt(1,arguments);var r=lt(e),n=ma(r,t).getTime()-Nx(r,t).getTime();return Math.round(n/Rx)+1}function bt(e,t){for(var r=e<0?"-":"",n=Math.abs(e).toString();n.length0?n:1-n;return bt(r==="yy"?a%100:a,r.length)},M:function(t,r){var n=t.getUTCMonth();return r==="M"?String(n+1):bt(n+1,2)},d:function(t,r){return bt(t.getUTCDate(),r.length)},a:function(t,r){var n=t.getUTCHours()/12>=1?"pm":"am";switch(r){case"a":case"aa":return n.toUpperCase();case"aaa":return n;case"aaaaa":return n[0];default:return n==="am"?"a.m.":"p.m."}},h:function(t,r){return bt(t.getUTCHours()%12||12,r.length)},H:function(t,r){return bt(t.getUTCHours(),r.length)},m:function(t,r){return bt(t.getUTCMinutes(),r.length)},s:function(t,r){return bt(t.getUTCSeconds(),r.length)},S:function(t,r){var n=r.length,a=t.getUTCMilliseconds(),o=Math.floor(a*Math.pow(10,n-3));return bt(o,r.length)}},$n=xx,qa={am:"am",pm:"pm",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},Ix={G:function(t,r,n){var a=t.getUTCFullYear()>0?1:0;switch(r){case"G":case"GG":case"GGG":return n.era(a,{width:"abbreviated"});case"GGGGG":return n.era(a,{width:"narrow"});default:return n.era(a,{width:"wide"})}},y:function(t,r,n){if(r==="yo"){var a=t.getUTCFullYear(),o=a>0?a:1-a;return n.ordinalNumber(o,{unit:"year"})}return $n.y(t,r)},Y:function(t,r,n,a){var o=Hf(t,a),s=o>0?o:1-o;if(r==="YY"){var c=s%100;return bt(c,2)}return r==="Yo"?n.ordinalNumber(s,{unit:"year"}):bt(s,r.length)},R:function(t,r){var n=rv(t);return bt(n,r.length)},u:function(t,r){var n=t.getUTCFullYear();return bt(n,r.length)},Q:function(t,r,n){var a=Math.ceil((t.getUTCMonth()+1)/3);switch(r){case"Q":return String(a);case"QQ":return bt(a,2);case"Qo":return n.ordinalNumber(a,{unit:"quarter"});case"QQQ":return n.quarter(a,{width:"abbreviated",context:"formatting"});case"QQQQQ":return n.quarter(a,{width:"narrow",context:"formatting"});default:return n.quarter(a,{width:"wide",context:"formatting"})}},q:function(t,r,n){var a=Math.ceil((t.getUTCMonth()+1)/3);switch(r){case"q":return String(a);case"qq":return bt(a,2);case"qo":return n.ordinalNumber(a,{unit:"quarter"});case"qqq":return n.quarter(a,{width:"abbreviated",context:"standalone"});case"qqqqq":return n.quarter(a,{width:"narrow",context:"standalone"});default:return n.quarter(a,{width:"wide",context:"standalone"})}},M:function(t,r,n){var a=t.getUTCMonth();switch(r){case"M":case"MM":return $n.M(t,r);case"Mo":return n.ordinalNumber(a+1,{unit:"month"});case"MMM":return n.month(a,{width:"abbreviated",context:"formatting"});case"MMMMM":return n.month(a,{width:"narrow",context:"formatting"});default:return n.month(a,{width:"wide",context:"formatting"})}},L:function(t,r,n){var a=t.getUTCMonth();switch(r){case"L":return String(a+1);case"LL":return bt(a+1,2);case"Lo":return n.ordinalNumber(a+1,{unit:"month"});case"LLL":return n.month(a,{width:"abbreviated",context:"standalone"});case"LLLLL":return n.month(a,{width:"narrow",context:"standalone"});default:return n.month(a,{width:"wide",context:"standalone"})}},w:function(t,r,n,a){var o=av(t,a);return r==="wo"?n.ordinalNumber(o,{unit:"week"}):bt(o,r.length)},I:function(t,r,n){var a=nv(t);return r==="Io"?n.ordinalNumber(a,{unit:"week"}):bt(a,r.length)},d:function(t,r,n){return r==="do"?n.ordinalNumber(t.getUTCDate(),{unit:"date"}):$n.d(t,r)},D:function(t,r,n){var a=wx(t);return r==="Do"?n.ordinalNumber(a,{unit:"dayOfYear"}):bt(a,r.length)},E:function(t,r,n){var a=t.getUTCDay();switch(r){case"E":case"EE":case"EEE":return n.day(a,{width:"abbreviated",context:"formatting"});case"EEEEE":return n.day(a,{width:"narrow",context:"formatting"});case"EEEEEE":return n.day(a,{width:"short",context:"formatting"});default:return n.day(a,{width:"wide",context:"formatting"})}},e:function(t,r,n,a){var o=t.getUTCDay(),s=(o-a.weekStartsOn+8)%7||7;switch(r){case"e":return String(s);case"ee":return bt(s,2);case"eo":return n.ordinalNumber(s,{unit:"day"});case"eee":return n.day(o,{width:"abbreviated",context:"formatting"});case"eeeee":return n.day(o,{width:"narrow",context:"formatting"});case"eeeeee":return n.day(o,{width:"short",context:"formatting"});default:return n.day(o,{width:"wide",context:"formatting"})}},c:function(t,r,n,a){var o=t.getUTCDay(),s=(o-a.weekStartsOn+8)%7||7;switch(r){case"c":return String(s);case"cc":return bt(s,r.length);case"co":return n.ordinalNumber(s,{unit:"day"});case"ccc":return n.day(o,{width:"abbreviated",context:"standalone"});case"ccccc":return n.day(o,{width:"narrow",context:"standalone"});case"cccccc":return n.day(o,{width:"short",context:"standalone"});default:return n.day(o,{width:"wide",context:"standalone"})}},i:function(t,r,n){var a=t.getUTCDay(),o=a===0?7:a;switch(r){case"i":return String(o);case"ii":return bt(o,r.length);case"io":return n.ordinalNumber(o,{unit:"day"});case"iii":return n.day(a,{width:"abbreviated",context:"formatting"});case"iiiii":return n.day(a,{width:"narrow",context:"formatting"});case"iiiiii":return n.day(a,{width:"short",context:"formatting"});default:return n.day(a,{width:"wide",context:"formatting"})}},a:function(t,r,n){var a=t.getUTCHours(),o=a/12>=1?"pm":"am";switch(r){case"a":case"aa":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"});case"aaa":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"}).toLowerCase();case"aaaaa":return n.dayPeriod(o,{width:"narrow",context:"formatting"});default:return n.dayPeriod(o,{width:"wide",context:"formatting"})}},b:function(t,r,n){var a=t.getUTCHours(),o;switch(a===12?o=qa.noon:a===0?o=qa.midnight:o=a/12>=1?"pm":"am",r){case"b":case"bb":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"});case"bbb":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"}).toLowerCase();case"bbbbb":return n.dayPeriod(o,{width:"narrow",context:"formatting"});default:return n.dayPeriod(o,{width:"wide",context:"formatting"})}},B:function(t,r,n){var a=t.getUTCHours(),o;switch(a>=17?o=qa.evening:a>=12?o=qa.afternoon:a>=4?o=qa.morning:o=qa.night,r){case"B":case"BB":case"BBB":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"});case"BBBBB":return n.dayPeriod(o,{width:"narrow",context:"formatting"});default:return n.dayPeriod(o,{width:"wide",context:"formatting"})}},h:function(t,r,n){if(r==="ho"){var a=t.getUTCHours()%12;return a===0&&(a=12),n.ordinalNumber(a,{unit:"hour"})}return $n.h(t,r)},H:function(t,r,n){return r==="Ho"?n.ordinalNumber(t.getUTCHours(),{unit:"hour"}):$n.H(t,r)},K:function(t,r,n){var a=t.getUTCHours()%12;return r==="Ko"?n.ordinalNumber(a,{unit:"hour"}):bt(a,r.length)},k:function(t,r,n){var a=t.getUTCHours();return a===0&&(a=24),r==="ko"?n.ordinalNumber(a,{unit:"hour"}):bt(a,r.length)},m:function(t,r,n){return r==="mo"?n.ordinalNumber(t.getUTCMinutes(),{unit:"minute"}):$n.m(t,r)},s:function(t,r,n){return r==="so"?n.ordinalNumber(t.getUTCSeconds(),{unit:"second"}):$n.s(t,r)},S:function(t,r){return $n.S(t,r)},X:function(t,r,n,a){var o=a._originalDate||t,s=o.getTimezoneOffset();if(s===0)return"Z";switch(r){case"X":return Ib(s);case"XXXX":case"XX":return ha(s);default:return ha(s,":")}},x:function(t,r,n,a){var o=a._originalDate||t,s=o.getTimezoneOffset();switch(r){case"x":return Ib(s);case"xxxx":case"xx":return ha(s);default:return ha(s,":")}},O:function(t,r,n,a){var o=a._originalDate||t,s=o.getTimezoneOffset();switch(r){case"O":case"OO":case"OOO":return"GMT"+xb(s,":");default:return"GMT"+ha(s,":")}},z:function(t,r,n,a){var o=a._originalDate||t,s=o.getTimezoneOffset();switch(r){case"z":case"zz":case"zzz":return"GMT"+xb(s,":");default:return"GMT"+ha(s,":")}},t:function(t,r,n,a){var o=a._originalDate||t,s=Math.floor(o.getTime()/1e3);return bt(s,r.length)},T:function(t,r,n,a){var o=a._originalDate||t,s=o.getTime();return bt(s,r.length)}};function xb(e,t){var r=e>0?"-":"+",n=Math.abs(e),a=Math.floor(n/60),o=n%60;if(o===0)return r+String(a);var s=t||"";return r+String(a)+s+bt(o,2)}function Ib(e,t){if(e%60===0){var r=e>0?"-":"+";return r+bt(Math.abs(e)/60,2)}return ha(e,t)}function ha(e,t){var r=t||"",n=e>0?"-":"+",a=Math.abs(e),o=bt(Math.floor(a/60),2),s=bt(a%60,2);return n+o+r+s}var Sx=Ix,Sb=function(t,r){switch(t){case"P":return r.date({width:"short"});case"PP":return r.date({width:"medium"});case"PPP":return r.date({width:"long"});default:return r.date({width:"full"})}},ov=function(t,r){switch(t){case"p":return r.time({width:"short"});case"pp":return r.time({width:"medium"});case"ppp":return r.time({width:"long"});default:return r.time({width:"full"})}},Cx=function(t,r){var n=t.match(/(P+)(p+)?/)||[],a=n[1],o=n[2];if(!o)return Sb(t,r);var s;switch(a){case"P":s=r.dateTime({width:"short"});break;case"PP":s=r.dateTime({width:"medium"});break;case"PPP":s=r.dateTime({width:"long"});break;default:s=r.dateTime({width:"full"});break}return s.replace("{{date}}",Sb(a,r)).replace("{{time}}",ov(o,r))},Ox={p:ov,P:Cx},Dx=Ox,Px=["D","DD"],Lx=["YY","YYYY"];function Ux(e){return Px.indexOf(e)!==-1}function Mx(e){return Lx.indexOf(e)!==-1}function Cb(e,t,r){if(e==="YYYY")throw new RangeError("Use `yyyy` instead of `YYYY` (in `".concat(t,"`) for formatting years to the input `").concat(r,"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"));if(e==="YY")throw new RangeError("Use `yy` instead of `YY` (in `".concat(t,"`) for formatting years to the input `").concat(r,"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"));if(e==="D")throw new RangeError("Use `d` instead of `D` (in `".concat(t,"`) for formatting days of the month to the input `").concat(r,"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"));if(e==="DD")throw new RangeError("Use `dd` instead of `DD` (in `".concat(t,"`) for formatting days of the month to the input `").concat(r,"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"))}var kx={lessThanXSeconds:{one:"less than a second",other:"less than {{count}} seconds"},xSeconds:{one:"1 second",other:"{{count}} seconds"},halfAMinute:"half a minute",lessThanXMinutes:{one:"less than a minute",other:"less than {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"about 1 hour",other:"about {{count}} hours"},xHours:{one:"1 hour",other:"{{count}} hours"},xDays:{one:"1 day",other:"{{count}} days"},aboutXWeeks:{one:"about 1 week",other:"about {{count}} weeks"},xWeeks:{one:"1 week",other:"{{count}} weeks"},aboutXMonths:{one:"about 1 month",other:"about {{count}} months"},xMonths:{one:"1 month",other:"{{count}} months"},aboutXYears:{one:"about 1 year",other:"about {{count}} years"},xYears:{one:"1 year",other:"{{count}} years"},overXYears:{one:"over 1 year",other:"over {{count}} years"},almostXYears:{one:"almost 1 year",other:"almost {{count}} years"}},Fx=function(t,r,n){var a,o=kx[t];return typeof o=="string"?a=o:r===1?a=o.one:a=o.other.replace("{{count}}",r.toString()),n!=null&&n.addSuffix?n.comparison&&n.comparison>0?"in "+a:a+" ago":a},iv=Fx;function Pr(e){return function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},r=t.width?String(t.width):e.defaultWidth,n=e.formats[r]||e.formats[e.defaultWidth];return n}}var Hx={full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},Gx={full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},Bx={full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},Wx={date:Pr({formats:Hx,defaultWidth:"full"}),time:Pr({formats:Gx,defaultWidth:"full"}),dateTime:Pr({formats:Bx,defaultWidth:"full"})},Vx=Wx,qx={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"},Kx=function(t,r,n,a){return qx[t]},sv=Kx;function dr(e){return function(t,r){var n=r!=null&&r.context?String(r.context):"standalone",a;if(n==="formatting"&&e.formattingValues){var o=e.defaultFormattingWidth||e.defaultWidth,s=r!=null&&r.width?String(r.width):o;a=e.formattingValues[s]||e.formattingValues[o]}else{var c=e.defaultWidth,u=r!=null&&r.width?String(r.width):e.defaultWidth;a=e.values[u]||e.values[c]}var f=e.argumentCallback?e.argumentCallback(t):t;return a[f]}}var Yx={narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},zx={narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},$x={narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},Xx={narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},jx={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},Qx={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},Zx=function(t,r){var n=Number(t),a=n%100;if(a>20||a<10)switch(a%10){case 1:return n+"st";case 2:return n+"nd";case 3:return n+"rd"}return n+"th"},Jx={ordinalNumber:Zx,era:dr({values:Yx,defaultWidth:"wide"}),quarter:dr({values:zx,defaultWidth:"wide",argumentCallback:function(t){return t-1}}),month:dr({values:$x,defaultWidth:"wide"}),day:dr({values:Xx,defaultWidth:"wide"}),dayPeriod:dr({values:jx,defaultWidth:"wide",formattingValues:Qx,defaultFormattingWidth:"wide"})},cv=Jx;function fr(e){return function(t){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=r.width,a=n&&e.matchPatterns[n]||e.matchPatterns[e.defaultMatchWidth],o=t.match(a);if(!o)return null;var s=o[0],c=n&&e.parsePatterns[n]||e.parsePatterns[e.defaultParseWidth],u=Array.isArray(c)?tI(c,function(w){return w.test(s)}):eI(c,function(w){return w.test(s)}),f;f=e.valueCallback?e.valueCallback(u):u,f=r.valueCallback?r.valueCallback(f):f;var d=t.slice(s.length);return{value:f,rest:d}}}function eI(e,t){for(var r in e)if(e.hasOwnProperty(r)&&t(e[r]))return r}function tI(e,t){for(var r=0;r1&&arguments[1]!==void 0?arguments[1]:{},n=t.match(e.matchPattern);if(!n)return null;var a=n[0],o=t.match(e.parsePattern);if(!o)return null;var s=e.valueCallback?e.valueCallback(o[0]):o[0];s=r.valueCallback?r.valueCallback(s):s;var c=t.slice(a.length);return{value:s,rest:c}}}var rI=/^(\d+)(th|st|nd|rd)?/i,nI=/\d+/i,aI={narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},oI={any:[/^b/i,/^(a|c)/i]},iI={narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},sI={any:[/1/i,/2/i,/3/i,/4/i]},cI={narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},uI={narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},lI={narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},dI={narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},fI={narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},pI={any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},hI={ordinalNumber:qc({matchPattern:rI,parsePattern:nI,valueCallback:function(t){return parseInt(t,10)}}),era:fr({matchPatterns:aI,defaultMatchWidth:"wide",parsePatterns:oI,defaultParseWidth:"any"}),quarter:fr({matchPatterns:iI,defaultMatchWidth:"wide",parsePatterns:sI,defaultParseWidth:"any",valueCallback:function(t){return t+1}}),month:fr({matchPatterns:cI,defaultMatchWidth:"wide",parsePatterns:uI,defaultParseWidth:"any"}),day:fr({matchPatterns:lI,defaultMatchWidth:"wide",parsePatterns:dI,defaultParseWidth:"any"}),dayPeriod:fr({matchPatterns:fI,defaultMatchWidth:"any",parsePatterns:pI,defaultParseWidth:"any"})},uv=hI,mI={code:"en-US",formatDistance:iv,formatLong:Vx,formatRelative:sv,localize:cv,match:uv,options:{weekStartsOn:0,firstWeekContainsDate:1}},gI=mI,lv=gI,_I=/[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g,yI=/P+p+|P+|p+|''|'(''|[^'])+('|$)|./g,bI=/^'([^]*?)'?$/,vI=/''/g,EI=/[a-zA-Z]/;function wI(e,t,r){var n,a,o,s,c,u,f,d,w,R,h,p,T,A,C,S,k,v;dt(2,arguments);var _=String(t),g=ja(),O=(n=(a=r?.locale)!==null&&a!==void 0?a:g.locale)!==null&&n!==void 0?n:lv,E=sr((o=(s=(c=(u=r?.firstWeekContainsDate)!==null&&u!==void 0?u:r==null||(f=r.locale)===null||f===void 0||(d=f.options)===null||d===void 0?void 0:d.firstWeekContainsDate)!==null&&c!==void 0?c:g.firstWeekContainsDate)!==null&&s!==void 0?s:(w=g.locale)===null||w===void 0||(R=w.options)===null||R===void 0?void 0:R.firstWeekContainsDate)!==null&&o!==void 0?o:1);if(!(E>=1&&E<=7))throw new RangeError("firstWeekContainsDate must be between 1 and 7 inclusively");var m=sr((h=(p=(T=(A=r?.weekStartsOn)!==null&&A!==void 0?A:r==null||(C=r.locale)===null||C===void 0||(S=C.options)===null||S===void 0?void 0:S.weekStartsOn)!==null&&T!==void 0?T:g.weekStartsOn)!==null&&p!==void 0?p:(k=g.locale)===null||k===void 0||(v=k.options)===null||v===void 0?void 0:v.weekStartsOn)!==null&&h!==void 0?h:0);if(!(m>=0&&m<=6))throw new RangeError("weekStartsOn must be between 0 and 6 inclusively");if(!O.localize)throw new RangeError("locale must contain localize property");if(!O.formatLong)throw new RangeError("locale must contain formatLong property");var y=lt(e);if(!sx(y))throw new RangeError("Invalid time value");var b=Ad(y),x=vx(y,b),D={firstWeekContainsDate:E,weekStartsOn:m,locale:O,_originalDate:y},F=_.match(yI).map(function(B){var K=B[0];if(K==="p"||K==="P"){var Z=Dx[K];return Z(B,O.formatLong)}return B}).join("").match(_I).map(function(B){if(B==="''")return"'";var K=B[0];if(K==="'")return AI(B);var Z=Sx[K];if(Z)return!(r!=null&&r.useAdditionalWeekYearTokens)&&Mx(B)&&Cb(B,t,String(e)),!(r!=null&&r.useAdditionalDayOfYearTokens)&&Ux(B)&&Cb(B,t,String(e)),Z(x,B,O.localize,D);if(K.match(EI))throw new RangeError("Format string contains an unescaped latin alphabet character `"+K+"`");return B}).join("");return F}function AI(e){var t=e.match(bI);return t?t[1].replace(vI,"'"):e}var TI=["years","months","weeks","days","hours","minutes","seconds"];function NI(e,t){var r,n,a,o,s;if(arguments.length<1)throw new TypeError("1 argument required, but only ".concat(arguments.length," present"));var c=ja(),u=(r=(n=t?.locale)!==null&&n!==void 0?n:c.locale)!==null&&r!==void 0?r:lv,f=(a=t?.format)!==null&&a!==void 0?a:TI,d=(o=t?.zero)!==null&&o!==void 0?o:!1,w=(s=t?.delimiter)!==null&&s!==void 0?s:" ";if(!u.formatDistance)return"";var R=f.reduce(function(h,p){var T="x".concat(p.replace(/(^.)/,function(C){return C.toUpperCase()})),A=e[p];return typeof A=="number"&&(d||e[p])?h.concat(u.formatDistance(T,A)):h},[]).join(w);return R}function _d(e,t){var r,n;dt(1,arguments);var a=lt(e);if(isNaN(a.getTime()))throw new RangeError("Invalid time value");var o=String((r=t?.format)!==null&&r!==void 0?r:"extended"),s=String((n=t?.representation)!==null&&n!==void 0?n:"complete");if(o!=="extended"&&o!=="basic")throw new RangeError("format must be 'extended' or 'basic'");if(s!=="date"&&s!=="time"&&s!=="complete")throw new RangeError("representation must be 'date', 'time', or 'complete'");var c="",u="",f=o==="extended"?"-":"",d=o==="extended"?":":"";if(s!=="time"){var w=bt(a.getDate(),2),R=bt(a.getMonth()+1,2),h=bt(a.getFullYear(),4);c="".concat(h).concat(f).concat(R).concat(f).concat(w)}if(s!=="date"){var p=a.getTimezoneOffset();if(p!==0){var T=Math.abs(p),A=bt(Math.floor(T/60),2),C=bt(T%60,2),S=p<0?"+":"-";u="".concat(S).concat(A,":").concat(C)}else u="Z";var k=bt(a.getHours(),2),v=bt(a.getMinutes(),2),_=bt(a.getSeconds(),2),g=c===""?"":"T",O=[k,v,_].join(d);c="".concat(c).concat(g).concat(O).concat(u)}return c}function RI(e){dt(1,arguments);var t=lt(e),r=t.getMonth();return r}function xI(e){return dt(1,arguments),lt(e).getFullYear()}function II(e){dt(1,arguments);var t=lt(e.start),r=lt(e.end);if(isNaN(t.getTime()))throw new RangeError("Start Date is invalid");if(isNaN(r.getTime()))throw new RangeError("End Date is invalid");var n={};n.years=Math.abs(bx(r,t));var a=Ya(r,t),o=$o(t,{years:a*n.years});n.months=Math.abs(_x(r,o));var s=$o(o,{months:a*n.months});n.days=Math.abs(lx(r,s));var c=$o(s,{days:a*n.days});n.hours=Math.abs(fx(r,c));var u=$o(c,{hours:a*n.hours});n.minutes=Math.abs(px(r,u));var f=$o(u,{minutes:a*n.minutes});return n.seconds=Math.abs(yx(r,f)),n}function Ss(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ss=function(r){return typeof r}:Ss=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Ss(e)}function SI(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&Nd(e,t)}function Nd(e,t){return Nd=Object.setPrototypeOf||function(n,a){return n.__proto__=a,n},Nd(e,t)}function CI(e){var t=PI();return function(){var n=uc(e),a;if(t){var o=uc(this).constructor;a=Reflect.construct(n,arguments,o)}else a=n.apply(this,arguments);return OI(this,a)}}function OI(e,t){return t&&(Ss(t)==="object"||typeof t=="function")?t:DI(e)}function DI(e){if(e===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function PI(){if(typeof Reflect>"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function uc(e){return uc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},uc(e)}function dv(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Ob(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function lc(e){return lc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},lc(e)}function Lb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var KI=(function(e){BI(r,e);var t=WI(r);function r(){var n;HI(this,r);for(var a=arguments.length,o=new Array(a),s=0;s0,n=r?t:1-t,a;if(n<=50)a=e||100;else{var o=n+50,s=Math.floor(o/100)*100,c=e>=o%100;a=e+s-(c?100:0)}return r?a:1-a}function mv(e){return e%400===0||e%4===0&&e%100!==0}function Os(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Os=function(r){return typeof r}:Os=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Os(e)}function YI(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Ub(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function fc(e){return fc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},fc(e)}function Mb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var ZI=(function(e){$I(r,e);var t=XI(r);function r(){var n;YI(this,r);for(var a=arguments.length,o=new Array(a),s=0;s0}},{key:"set",value:function(a,o,s){var c=a.getUTCFullYear();if(s.isTwoDigitYear){var u=hv(s.year,c);return a.setUTCFullYear(u,0,1),a.setUTCHours(0,0,0,0),a}var f=!("era"in o)||o.era===1?s.year:1-s.year;return a.setUTCFullYear(f,0,1),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function Ds(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ds=function(r){return typeof r}:Ds=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Ds(e)}function JI(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function kb(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function pc(e){return pc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},pc(e)}function Fb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var oS=(function(e){tS(r,e);var t=rS(r);function r(){var n;JI(this,r);for(var a=arguments.length,o=new Array(a),s=0;s0}},{key:"set",value:function(a,o,s,c){var u=Hf(a,c);if(s.isTwoDigitYear){var f=hv(s.year,u);return a.setUTCFullYear(f,0,c.firstWeekContainsDate),a.setUTCHours(0,0,0,0),ma(a,c)}var d=!("era"in o)||o.era===1?s.year:1-s.year;return a.setUTCFullYear(d,0,c.firstWeekContainsDate),a.setUTCHours(0,0,0,0),ma(a,c)}}]),r})(Ct);function Ps(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ps=function(r){return typeof r}:Ps=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Ps(e)}function iS(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Hb(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function hc(e){return hc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},hc(e)}function Gb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var fS=(function(e){cS(r,e);var t=uS(r);function r(){var n;iS(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function mc(e){return mc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},mc(e)}function Wb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var bS=(function(e){mS(r,e);var t=gS(r);function r(){var n;pS(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function gc(e){return gc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},gc(e)}function qb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var RS=(function(e){wS(r,e);var t=AS(r);function r(){var n;vS(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=4}},{key:"set",value:function(a,o,s){return a.setUTCMonth((s-1)*3,1),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function Ms(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ms=function(r){return typeof r}:Ms=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Ms(e)}function xS(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Kb(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function _c(e){return _c=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},_c(e)}function Yb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var PS=(function(e){SS(r,e);var t=CS(r);function r(){var n;xS(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=4}},{key:"set",value:function(a,o,s){return a.setUTCMonth((s-1)*3,1),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function ks(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?ks=function(r){return typeof r}:ks=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},ks(e)}function LS(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function zb(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function yc(e){return yc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},yc(e)}function $b(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var GS=(function(e){MS(r,e);var t=kS(r);function r(){var n;LS(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=11}},{key:"set",value:function(a,o,s){return a.setUTCMonth(s,1),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function Fs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Fs=function(r){return typeof r}:Fs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Fs(e)}function BS(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Xb(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function bc(e){return bc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},bc(e)}function jb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var zS=(function(e){VS(r,e);var t=qS(r);function r(){var n;BS(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=11}},{key:"set",value:function(a,o,s){return a.setUTCMonth(s,1),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function $S(e,t,r){dt(2,arguments);var n=lt(e),a=sr(t),o=av(n,r)-a;return n.setUTCDate(n.getUTCDate()-o*7),n}function Hs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Hs=function(r){return typeof r}:Hs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Hs(e)}function XS(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Qb(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function vc(e){return vc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},vc(e)}function Zb(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var tC=(function(e){QS(r,e);var t=ZS(r);function r(){var n;XS(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=53}},{key:"set",value:function(a,o,s,c){return ma($S(a,s,c),c)}}]),r})(Ct);function rC(e,t){dt(2,arguments);var r=lt(e),n=sr(t),a=nv(r)-n;return r.setUTCDate(r.getUTCDate()-a*7),r}function Gs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Gs=function(r){return typeof r}:Gs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Gs(e)}function nC(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Jb(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Ec(e){return Ec=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Ec(e)}function e0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var uC=(function(e){oC(r,e);var t=iC(r);function r(){var n;nC(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=53}},{key:"set",value:function(a,o,s){return za(rC(a,s))}}]),r})(Ct);function Bs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Bs=function(r){return typeof r}:Bs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Bs(e)}function lC(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function t0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function wc(e){return wc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},wc(e)}function yd(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var gC=[31,28,31,30,31,30,31,31,30,31,30,31],_C=[31,29,31,30,31,30,31,31,30,31,30,31],yC=(function(e){fC(r,e);var t=pC(r);function r(){var n;lC(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=_C[u]:o>=1&&o<=gC[u]}},{key:"set",value:function(a,o,s){return a.setUTCDate(s),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function Vs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Vs=function(r){return typeof r}:Vs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Vs(e)}function bC(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Ac(e){return Ac=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Ac(e)}function bd(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var NC=(function(e){EC(r,e);var t=wC(r);function r(){var n;bC(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=366:o>=1&&o<=365}},{key:"set",value:function(a,o,s){return a.setUTCMonth(0,s),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function Bf(e,t,r){var n,a,o,s,c,u,f,d;dt(2,arguments);var w=ja(),R=sr((n=(a=(o=(s=r?.weekStartsOn)!==null&&s!==void 0?s:r==null||(c=r.locale)===null||c===void 0||(u=c.options)===null||u===void 0?void 0:u.weekStartsOn)!==null&&o!==void 0?o:w.weekStartsOn)!==null&&a!==void 0?a:(f=w.locale)===null||f===void 0||(d=f.options)===null||d===void 0?void 0:d.weekStartsOn)!==null&&n!==void 0?n:0);if(!(R>=0&&R<=6))throw new RangeError("weekStartsOn must be between 0 and 6 inclusively");var h=lt(e),p=sr(t),T=h.getUTCDay(),A=p%7,C=(A+7)%7,S=(C"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Tc(e){return Tc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Tc(e)}function a0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var DC=(function(e){IC(r,e);var t=SC(r);function r(){var n;RC(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=6}},{key:"set",value:function(a,o,s,c){return a=Bf(a,s,c),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function Ys(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ys=function(r){return typeof r}:Ys=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Ys(e)}function PC(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Nc(e){return Nc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Nc(e)}function i0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var HC=(function(e){UC(r,e);var t=MC(r);function r(){var n;PC(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=6}},{key:"set",value:function(a,o,s,c){return a=Bf(a,s,c),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function zs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?zs=function(r){return typeof r}:zs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},zs(e)}function GC(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function s0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Rc(e){return Rc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Rc(e)}function c0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var YC=(function(e){WC(r,e);var t=VC(r);function r(){var n;GC(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=6}},{key:"set",value:function(a,o,s,c){return a=Bf(a,s,c),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function zC(e,t){dt(2,arguments);var r=sr(t);r%7===0&&(r=r-7);var n=1,a=lt(e),o=a.getUTCDay(),s=r%7,c=(s+7)%7,u=(c"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function xc(e){return xc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},xc(e)}function l0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var e2=(function(e){jC(r,e);var t=QC(r);function r(){var n;$C(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=7}},{key:"set",value:function(a,o,s){return a=zC(a,s),a.setUTCHours(0,0,0,0),a}}]),r})(Ct);function Xs(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Xs=function(r){return typeof r}:Xs=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Xs(e)}function t2(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function d0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Ic(e){return Ic=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Ic(e)}function f0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var s2=(function(e){n2(r,e);var t=a2(r);function r(){var n;t2(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Sc(e){return Sc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Sc(e)}function h0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var h2=(function(e){l2(r,e);var t=d2(r);function r(){var n;c2(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Cc(e){return Cc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Cc(e)}function g0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var E2=(function(e){_2(r,e);var t=y2(r);function r(){var n;m2(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Oc(e){return Oc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Oc(e)}function y0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var I2=(function(e){T2(r,e);var t=N2(r);function r(){var n;w2(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=12}},{key:"set",value:function(a,o,s){var c=a.getUTCHours()>=12;return c&&s<12?a.setUTCHours(s+12,0,0,0):!c&&s===12?a.setUTCHours(0,0,0,0):a.setUTCHours(s,0,0,0),a}}]),r})(Ct);function Js(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Js=function(r){return typeof r}:Js=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},Js(e)}function S2(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function b0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Dc(e){return Dc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Dc(e)}function v0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var U2=(function(e){O2(r,e);var t=D2(r);function r(){var n;S2(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=23}},{key:"set",value:function(a,o,s){return a.setUTCHours(s,0,0,0),a}}]),r})(Ct);function ec(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?ec=function(r){return typeof r}:ec=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},ec(e)}function M2(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function E0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Pc(e){return Pc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Pc(e)}function w0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var W2=(function(e){F2(r,e);var t=H2(r);function r(){var n;M2(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=11}},{key:"set",value:function(a,o,s){var c=a.getUTCHours()>=12;return c&&s<12?a.setUTCHours(s+12,0,0,0):a.setUTCHours(s,0,0,0),a}}]),r})(Ct);function tc(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?tc=function(r){return typeof r}:tc=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},tc(e)}function V2(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function A0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Lc(e){return Lc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Lc(e)}function T0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var X2=(function(e){K2(r,e);var t=Y2(r);function r(){var n;V2(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=1&&o<=24}},{key:"set",value:function(a,o,s){var c=s<=24?s%24:s;return a.setUTCHours(c,0,0,0),a}}]),r})(Ct);function rc(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?rc=function(r){return typeof r}:rc=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},rc(e)}function j2(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function N0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Uc(e){return Uc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Uc(e)}function R0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var rO=(function(e){Z2(r,e);var t=J2(r);function r(){var n;j2(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=59}},{key:"set",value:function(a,o,s){return a.setUTCMinutes(s,0,0),a}}]),r})(Ct);function nc(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?nc=function(r){return typeof r}:nc=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},nc(e)}function nO(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function x0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Mc(e){return Mc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Mc(e)}function I0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var uO=(function(e){oO(r,e);var t=iO(r);function r(){var n;nO(this,r);for(var a=arguments.length,o=new Array(a),s=0;s=0&&o<=59}},{key:"set",value:function(a,o,s){return a.setUTCSeconds(s,0),a}}]),r})(Ct);function ac(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?ac=function(r){return typeof r}:ac=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},ac(e)}function lO(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function S0(e,t){for(var r=0;r"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function kc(e){return kc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},kc(e)}function C0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var gO=(function(e){fO(r,e);var t=pO(r);function r(){var n;lO(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Fc(e){return Fc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Fc(e)}function D0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var AO=(function(e){bO(r,e);var t=vO(r);function r(){var n;_O(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Hc(e){return Hc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Hc(e)}function L0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var CO=(function(e){RO(r,e);var t=xO(r);function r(){var n;TO(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Gc(e){return Gc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Gc(e)}function M0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var kO=(function(e){PO(r,e);var t=LO(r);function r(){var n;OO(this,r);for(var a=arguments.length,o=new Array(a),s=0;s"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function Bc(e){return Bc=Object.setPrototypeOf?Object.getPrototypeOf:function(r){return r.__proto__||Object.getPrototypeOf(r)},Bc(e)}function F0(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var qO=(function(e){GO(r,e);var t=BO(r);function r(){var n;FO(this,r);for(var a=arguments.length,o=new Array(a),s=0;s>>t&24),(t===2||e.length-o===1)&&(r+=String.fromCodePoint(Ts(a>>>18&63),Ts(a>>>12&63),Ts(a>>>6&63),Ts(a&63)),a=0);return r.substring(0,r.length-2+t)+(t===2?"":t===1?"=":"==")}function zO(e){let t,r=e.length,n=0;for(let c=0;c=65536&&c++,n+=t<128?1:t<2048?2:t<65536?3:t<2097152?4:t<67108864?5:6}let a=new Uint8Array(n),o=0,s=0;for(;o>>6),a[o++]=128+(t&63)):t<65536?(a[o++]=224+(t>>>12),a[o++]=128+(t>>>6&63),a[o++]=128+(t&63)):t<2097152?(a[o++]=240+(t>>>18),a[o++]=128+(t>>>12&63),a[o++]=128+(t>>>6&63),a[o++]=128+(t&63),s++):t<67108864?(a[o++]=248+(t>>>24),a[o++]=128+(t>>>18&63),a[o++]=128+(t>>>12&63),a[o++]=128+(t>>>6&63),a[o++]=128+(t&63),s++):(a[o++]=252+(t>>>30),a[o++]=128+(t>>>24&63),a[o++]=128+(t>>>18&63),a[o++]=128+(t>>>12&63),a[o++]=128+(t>>>6&63),a[o++]=128+(t&63),s++),s++}return a}async function $O(e,t,r={}){let n={};r.token?n.Authorization=`Bearer secret-token:${r.token}`:r.basicAuth&&(n.Authorization=`Basic ${KO(`${r.basicAuth.username}:${r.basicAuth.password}`)}`),n["Content-Type"]=!r.contentType||r.contentType==="json"?"application/json":"text/plain",r.talerAmlOfficerSignature&&(n["Taler-AML-Officer-Signature"]=r.talerAmlOfficerSignature);let a=r?.method??"GET",o=r?.data,s=r?.timeout??5*1e3,c=r.params??{},u=r.preventCache??!1,f=r.preventCors??!1,d=QO(e,t);if(!d){let A={info:{url:`${e}${t}`,payload:{},hasToken:!!r.token,status:0,options:r},type:4,exception:void 0,loading:!1,message:`invalid URL: "${e}${t}"`};throw new Xo(A)}Object.entries(c).forEach(([A,C])=>{d.searchParams.set(A,String(C))});let w;if(o!=null)if(typeof o=="string")w=o;else if(o instanceof ArrayBuffer)w=o;else if(ArrayBuffer.isView(o))w=new Uint8Array(o.buffer,o.byteOffset,o.byteLength);else if(typeof o=="object")w=JSON.stringify(o);else{let A={info:{url:d.href,payload:{},hasToken:!!r.token,status:0,options:r},type:4,exception:void 0,loading:!1,message:`unsupported request body type: "${typeof o}"`};throw new Xo(A)}let R=new AbortController,h=setTimeout(()=>{R.abort("HTTP_REQUEST_TIMEOUT")},s),p;try{p=await fetch(d.href,{headers:n,method:a,credentials:"omit",mode:f?"no-cors":"cors",cache:u?"no-cache":"default",body:w,signal:R.signal})}catch(A){let C={payload:w,url:d.href,hasToken:!!r.token,status:0,options:r};if(A instanceof Error&&A.message==="HTTP_REQUEST_TIMEOUT"){let k={info:C,type:3,message:"request timeout"};throw new Xo(k)}let S={info:C,type:4,exception:A,loading:!1,message:A instanceof Error?A.message:""};throw new Xo(S)}h&&clearTimeout(h);let T=new Headers;if(p.headers.forEach((A,C)=>{T.set(C,A)}),p.ok)return await XO(p,d.href,w,!!r.token,r);{let A=await p.text(),C=jO(d.href,A,p.status,w,r);throw new Xo(C)}}var Xo=class extends Error{constructor(e){super(e.message),this.info=e,this.cause=e}};async function XO(e,t,r,n,a){let o=await e.text();return{ok:!0,data:o?JSON.parse(o):void 0,info:{payload:r,url:t,hasToken:n,options:a,status:e.status}}}function jO(e,t,r,n,a){let o=a??{},s={payload:n,url:e,hasToken:!!o.token,options:o,status:r||0};try{let c=t?JSON.parse(t):void 0,u=!c||!c.code?"":`(code: ${c.code})`,f=!c||!c.hint?"Not hint.":`${c.hint} ${u}`;if(r&&r>=400&&r<500){let d=c===void 0?`Client error (${r}) without data.`:f;return{type:0,status:r,info:s,message:d,payload:c}}if(r&&r>=500&&r<600){let d=c===void 0?`Server error (${r}) without data.`:f;return{type:1,status:r,info:s,message:d,payload:c}}return{info:s,loading:!1,type:4,status:r,exception:void 0,message:`http status code not handled: ${r}`}}catch(c){return{info:s,loading:!1,status:r,type:2,exception:c,body:t,message:"Could not parse body as json"}}}function QO(e,t){try{return new URL(`${e}${t}`)}catch{return}}var B7=Kt({request:$O});function gv(e,t=[]){let[r,n]=de(),[a,o]=de();if(Ge(()=>{let s=!1;return e&&e().then(c=>{s||n(c)}).catch(c=>{s||(c instanceof Oe?o(c):o(Oe.fromException(c)))}),()=>{s=!0}},t),a)return a;if(r)return r}function _v(e,t,r,n=[],a={}){let o=a?.minTime??1e3,[s,c]=de(e);Ge(()=>{c(e)},[e,...n]);let u=Yt({ct:void 0,unloaded:!1,startMs:0});return Ge(()=>{let f=xr.create();if(u.current.ct=f,!t(s))return;let w=new Date().getTime()-u.current.startMs;return u.current.startMs===0||w>o?(u.current.startMs=new Date().getTime(),r(f.token,s,n).then(R=>{f.token.isCancelled||c(R)}).catch(R=>console.log(""))):ZO(o-w).then(()=>{u.current.unloaded||(u.current.startMs=new Date().getTime(),r(f.token,s,n).then(R=>{f.token.isCancelled||c(R)}).catch(R=>console.log("")))}),()=>{}},[s]),Ge(()=>()=>{u.current.unloaded=!0,u.current.startMs=0},[]),Ge(()=>()=>{u.current.ct?.cancel(),u.current.unloaded=!0,u.current.startMs=0},n),s}async function ZO(e){return new Promise((t,r)=>{setTimeout(()=>t(),e)})}function yv(e){if(e!==void 0)return Object.keys(e).some(t=>e[t]!==void 0)?e:void 0}function Wc(e=new Map){let t=new EventTarget,r={onAnyUpdate:n=>(t.addEventListener("update",n),t.addEventListener("clear",n),()=>{t.removeEventListener("update",n),t.removeEventListener("clear",n)}),onUpdate:(n,a)=>(t.addEventListener(`update-${n}`,a),t.addEventListener("clear",a),()=>{t.removeEventListener(`update-${n}`,a),t.removeEventListener("clear",a)}),delete:n=>{let a=e.delete(n);return r.size=e.length,t.dispatchEvent(new Event(`update-${n}`)),t.dispatchEvent(new Event("update")),a},set:(n,a)=>(e.set(n,a),r.size=e.length,t.dispatchEvent(new Event(`update-${n}`)),t.dispatchEvent(new Event("update")),r),clear:()=>{e.clear(),t.dispatchEvent(new Event("clear"))},entries:e.entries.bind(e),forEach:e.forEach.bind(e),get:e.get.bind(e),has:e.has.bind(e),keys:e.keys.bind(e),size:e.size,values:e.values.bind(e),[Symbol.iterator]:e[Symbol.iterator],[Symbol.toStringTag]:"theMemoryMap"};return r}function H0(){let e=new EventTarget,t={onAnyUpdate:r=>(e.addEventListener("update",r),e.addEventListener("clear",r),window.addEventListener("storage",r),()=>{window.removeEventListener("storage",r),e.removeEventListener("update",r),e.removeEventListener("clear",r)}),onUpdate:(r,n)=>{e.addEventListener(`update-${r}`,n),e.addEventListener("clear",n);function a(o){(o.key===null||o.key===r)&&n()}return window.addEventListener("storage",a),()=>{window.removeEventListener("storage",a),e.removeEventListener(`update-${r}`,n),e.removeEventListener("clear",n)}},delete:r=>{let n=localStorage.getItem(r)!==null;return localStorage.removeItem(r),t.size=localStorage.length,e.dispatchEvent(new Event(`update-${r}`)),e.dispatchEvent(new Event("update")),n},set:(r,n)=>(localStorage.setItem(r,n),t.size=localStorage.length,e.dispatchEvent(new Event(`update-${r}`)),e.dispatchEvent(new Event("update")),t),clear:()=>{localStorage.clear(),e.dispatchEvent(new Event("clear"))},entries:()=>{let r=0,n=localStorage.length;return{next(){if(r===n)return{done:!0,value:void 0};let a=localStorage.key(r);if(a===null)throw Error("key cant be null");let o=localStorage.getItem(a);if(o===null)throw Error("value cant be null");return r=r+1,{done:!1,value:[a,o]}},[Symbol.iterator](){return this}}},forEach:r=>{for(let n=0;n{let n=localStorage.getItem(r);if(n!==null)return n},has:r=>localStorage.getItem(r)===null,keys:()=>{let r=0,n=localStorage.length;return{next(){if(r===n)return{done:!0,value:void 0};let a=localStorage.key(r);if(a===null)throw Error("key cant be null");return r=r+1,{done:!1,value:a}},[Symbol.iterator](){return this}}},size:localStorage.length,values:()=>{let r=0,n=localStorage.length;return{next(){if(r===n)return{done:!0,value:void 0};let a=localStorage.key(r);if(a===null)throw Error("key cant be null");let o=localStorage.getItem(a);if(o===null)throw Error("value cant be null");return r=r+1,{done:!1,value:o}},[Symbol.iterator](){return this}}},[Symbol.iterator]:function(){return t.entries()},[Symbol.toStringTag]:"theLocalStorageMap"};return t}var Wf=typeof window<"u"&&typeof window.InstallTrigger<"u";async function JO(){return Wf?browser.storage.local.get():chrome.storage.local.get()}async function eD(e){return Wf?browser.storage.local.set(e):chrome.storage.local.set(e)}function tD(e){Wf?browser.storage.local.onChanged.addListener(e):chrome.storage.local.onChanged.addListener(e)}function G0(e){return JO().then(t=>{Object.entries(t??{}).forEach(([r,n])=>{e.set(r,n)})}),e.onAnyUpdate(async()=>{let t={};for(let[r,n]of e.entries())t[r]=n;await eD(t)}),tD(t=>{let r=Object.keys(t);if(r.length===0)e.clear();else for(let n of r)t[n].newValue?t[n].newValue!==t[n].oldValue&&e.set(n,t[n].newValue):e.delete(n)}),e}function Xn(e,t){return{id:e,codec:t??L()}}var B0=typeof window<"u",rD=typeof chrome<"u"&&typeof chrome.storage<"u",Ns=(function(){return rD?G0(B0?H0():Wc()):B0?H0():Wc()})();function ga(e,t){let r=nD(Ns.get(e.id),e,t),[n,a]=de(he.now().t_ms);Ge(()=>Ns.onUpdate(e.id,()=>{a(he.now().t_ms)}),[e.id]);let o=s=>{s===void 0?Ns.delete(e.id):Ns.set(e.id,e.codec?JSON.stringify(s):s)};return{value:r,update:o,reset:()=>{o(t)}}}function nD(e,t,r){if(e===void 0)return r;try{return t.codec.decode(JSON.parse(e))}catch(n){return console.error("Decoding error",n),r}}var W0=85;function aD(e){if(!(typeof window>"u")){if(window.navigator.language&&e[window.navigator.language]>=W0)return window.navigator.language;if(window.navigator.languages){let t=Object.entries(e).filter(([r,n])=>na.startsWith(r))!==-1).map(([r,n])=>({code:r,value:n}));if(t.length>0){let r=t[0];return t.forEach(n=>{n.value>r.value&&(r=n)}),r.code}}}}var oD=Xn("lang-preference");function iD(e,t){let r=(aD(t)||e||"en").substring(0,2);return ga(oD,r)}function br(){let[e,t]=de();function r(){t(void 0)}function n(o,s){t({challenge:o,initial:void 0,repeat:s})}function a(o,s,c){t({challenge:o,initial:s,repeat:c})}return{doCancelChallenge:r,onChallengeRequired:n,onChallengeRequiredWithInitial:a,pendingChallenge:e?.challenge,repeatCall:e?.repeat,initial:e?.initial}}var jo=Wc();function sD(e,t){let[r,n]=de(()=>{let o=jo.get(e);return o===void 0?t:o});Ge(()=>jo.onUpdate(e,()=>{let o=jo.get(e);n(o===void 0?t:o)}),[e]);let a=o=>{o===void 0?jo.delete(e):jo.set(e,o)};return{value:r,update:a,reset:()=>{a(t)}}}var $a=Wc(),Xa="notification",Vc=rt.fromSpec({seconds:5});function bv(e){let t=Ev(e),r=$a.get(Xa)??new Map,n=new Map(r);n.set(t,e),$a.set(Xa,n)}function Vf(e){let r=($a.get(Xa)??new Map).set(Ev(e),e);Vc.d_ms!=="forever"&&setTimeout(()=>{e.timeout=!0,bv(e)},Vc.d_ms),$a.set(Xa,r)}function Kc(e,t,r){Vf({type:"error",title:e,description:t?[t]:void 0,debug:r,when:he.now()})}function vv(e,t){Vf({type:"error",title:e,description:[t.message],debug:t.stack,when:he.now()})}function pr(e){Vf({type:"info",title:e,when:he.now()})}function Yc(){let[,e]=de(),t=$a.get(Xa)??new Map;return Ge(()=>$a.onUpdate(Xa,()=>{e(Date.now())})),Array.from(t.values()).map((r,n)=>({message:r,acknowledge:()=>{r.ack=!0,bv(r)}}))}function cD(e){if(e.length===0)return"0";let t=0,r;for(let n=0;n{t(void 0)}}:void 0,{i18n:n}=Ne();function a(o,s,c){function u(f,d){let w={args:f,withArgs:(...R)=>{let h=u(R,d);return h.onSuccess=w.onSuccess,h.onFail=w.onFail,h},lambda:(R,h)=>{let p=u(h?R(...h):void 0,d);return p.withArgs=(...T)=>{let A=R(...T);return A?w.withArgs(...A):w},p.onSuccess=w.onSuccess,p.onFail=w.onFail,p},call:async()=>{if(w.args)try{w.onStart();let R=await d(...w.args);switch(R.type){case"ok":{let h=w.onSuccess(R.body,...w.args);h&&t(fD(h));return}case"fail":{let h=w.onFail(R,...w.args);h&&t(pD(n,o,R,h,w.args));return}default:ue(R)}}catch(R){qf(R),dD(n,n.str`Unexpected error trying to ${o}`,t)(R,w.args);return}},onFail:(R,...h)=>n.str`Unhandled failure trying to ${o}. Code ${R.case}`,onSuccess:()=>{},onStart:()=>{}};return w}return u(c,s)}return[r,a]}function qf(e){console.error("Internal error, this is mostly a bug in the application. Please report: ",e)}function uD(e,t){if(t.code&&t.code===G.GENERIC_JSON_INVALID)return e.str`Looks like the JSON in the request was malformed.`}function Ka(e){return!!e}function lD(e,t){if(e.hasErrorCode(G.GENERIC_TIMEOUT)||e.hasErrorCode(G.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT))return[t.str`The request reached a timeout, check your connection.`,t.str`The ${e.errorDetail.requestMethod} request to ${e.errorDetail.requestUrl} failed after ${e.errorDetail.timeoutMs/1e3} seconds.`,e.errorDetail.when?t.str`The last request time is ${he.stringify(e.errorDetail.when)}`:void 0].filter(Ka);if(e.hasErrorCode(G.GENERIC_CLIENT_INTERNAL_ERROR))return[t.str`The request was cancelled.`,t.str`The ${e.errorDetail.requestMethod} request ${e.errorDetail.requestUrl} failed with code ${e.errorDetail.httpStatusCode}.`,e.errorDetail.when?t.str`The request was made at ${he.stringify(e.errorDetail.when)}`:void 0].filter(Ka);if(e.hasErrorCode(G.WALLET_HTTP_REQUEST_THROTTLED))return[t.str`Too many requests were made to the server and this action was throttled.`,t.str`The request "${e.errorDetail.requestMethod} ${e.errorDetail.requestUrl}" failed with an code ${e.errorDetail.httpStatusCode}`,e.errorDetail.when?t.str`The last request time is ${he.stringify(e.errorDetail.when)}`:void 0].filter(Ka);if(e.hasErrorCode(G.WALLET_RECEIVED_MALFORMED_RESPONSE))return[t.str`The server's response was malformed.`,t.str`The response to "${e.errorDetail.requestMethod} ${e.errorDetail.requestUrl}" failed with an code ${e.errorDetail.httpStatusCode}`,e.errorDetail.when?t.str`The request was made at ${he.stringify(e.errorDetail.when)}`:void 0,e.errorDetail.contentType?t.str`The content type is ${e.errorDetail.contentType}`:void 0,e.errorDetail.validationError?t.str`The validation error is "${e.errorDetail.validationError}"`:void 0,e.errorDetail.response?e.errorDetail.response:void 0].filter(Ka);if(e.hasErrorCode(G.WALLET_NETWORK_ERROR))return[t.str`Due to a network problem the request could not be finished.`,t.str`The ${e.errorDetail.requestMethod} request to ${e.errorDetail.requestUrl} failed.`,e.errorDetail.when?t.str`The request was made at ${he.stringify(e.errorDetail.when)}`:void 0].filter(Ka);if(e.hasErrorCode(G.WALLET_UNEXPECTED_REQUEST_ERROR)){let r="hint"in e.errorDetail.errorResponse?e.errorDetail.errorResponse.hint:void 0;return[t.str`The server's response was unexpected. This mean the client and the server are not in sync about the protocol.`,t.str`The ${e.errorDetail.requestMethod} request to ${e.errorDetail.requestUrl} failed with code ${e.errorDetail.httpStatusCode}`,e.errorDetail.when?t.str`The request was made at ${he.stringify(e.errorDetail.when)}`:void 0,uD(t,e.errorDetail.errorResponse),r?t.str`And the server say: "${r}"`:void 0].filter(Ka)}return[t.str`Unexpected error`,e.message]}function dD(e,t,r){return(n,a)=>{if(n instanceof Oe)r({title:t,type:"error",description:lD(n,e),debug:{error:n,stack:n instanceof Error?n.stack:void 0,args:V0(a),when:he.now()},when:he.now()});else{let o=n instanceof Error?n.message:String(n);r({title:t,type:"error",description:[e.str`Unexpected error, this is likely a bug. Please report `],debug:{error:String(n),stack:n instanceof Error?n.stack:void 0,args:V0(a),when:he.now()},when:he.now()})}}}function V0(e){return e.map(t=>typeof t=="string"&&t.startsWith("secret-token:")?"secret-token:...redacted...":typeof t=="object"?JSON.stringify(t,void 0,2):t).join(", ")}function fD(e){return{title:e,type:"info",when:he.now()}}function pD(e,t,r,n,a){return{title:e.str`Unable to ${t}.`,type:"error",description:[n],debug:{detail:r.detail,case:r.case,when:he.now()},when:he.now()}}var q0={lessThanXSeconds:{standalone:{one:"weniger als 1 Sekunde",other:"weniger als {{count}} Sekunden"},withPreposition:{one:"weniger als 1 Sekunde",other:"weniger als {{count}} Sekunden"}},xSeconds:{standalone:{one:"1 Sekunde",other:"{{count}} Sekunden"},withPreposition:{one:"1 Sekunde",other:"{{count}} Sekunden"}},halfAMinute:{standalone:"halbe Minute",withPreposition:"halben Minute"},lessThanXMinutes:{standalone:{one:"weniger als 1 Minute",other:"weniger als {{count}} Minuten"},withPreposition:{one:"weniger als 1 Minute",other:"weniger als {{count}} Minuten"}},xMinutes:{standalone:{one:"1 Minute",other:"{{count}} Minuten"},withPreposition:{one:"1 Minute",other:"{{count}} Minuten"}},aboutXHours:{standalone:{one:"etwa 1 Stunde",other:"etwa {{count}} Stunden"},withPreposition:{one:"etwa 1 Stunde",other:"etwa {{count}} Stunden"}},xHours:{standalone:{one:"1 Stunde",other:"{{count}} Stunden"},withPreposition:{one:"1 Stunde",other:"{{count}} Stunden"}},xDays:{standalone:{one:"1 Tag",other:"{{count}} Tage"},withPreposition:{one:"1 Tag",other:"{{count}} Tagen"}},aboutXWeeks:{standalone:{one:"etwa 1 Woche",other:"etwa {{count}} Wochen"},withPreposition:{one:"etwa 1 Woche",other:"etwa {{count}} Wochen"}},xWeeks:{standalone:{one:"1 Woche",other:"{{count}} Wochen"},withPreposition:{one:"1 Woche",other:"{{count}} Wochen"}},aboutXMonths:{standalone:{one:"etwa 1 Monat",other:"etwa {{count}} Monate"},withPreposition:{one:"etwa 1 Monat",other:"etwa {{count}} Monaten"}},xMonths:{standalone:{one:"1 Monat",other:"{{count}} Monate"},withPreposition:{one:"1 Monat",other:"{{count}} Monaten"}},aboutXYears:{standalone:{one:"etwa 1 Jahr",other:"etwa {{count}} Jahre"},withPreposition:{one:"etwa 1 Jahr",other:"etwa {{count}} Jahren"}},xYears:{standalone:{one:"1 Jahr",other:"{{count}} Jahre"},withPreposition:{one:"1 Jahr",other:"{{count}} Jahren"}},overXYears:{standalone:{one:"mehr als 1 Jahr",other:"mehr als {{count}} Jahre"},withPreposition:{one:"mehr als 1 Jahr",other:"mehr als {{count}} Jahren"}},almostXYears:{standalone:{one:"fast 1 Jahr",other:"fast {{count}} Jahre"},withPreposition:{one:"fast 1 Jahr",other:"fast {{count}} Jahren"}}},hD=function(t,r,n){var a,o=n!=null&&n.addSuffix?q0[t].withPreposition:q0[t].standalone;return typeof o=="string"?a=o:r===1?a=o.one:a=o.other.replace("{{count}}",String(r)),n!=null&&n.addSuffix?n.comparison&&n.comparison>0?"in "+a:"vor "+a:a},mD=hD,gD={full:"EEEE, do MMMM y",long:"do MMMM y",medium:"do MMM y",short:"dd.MM.y"},_D={full:"HH:mm:ss zzzz",long:"HH:mm:ss z",medium:"HH:mm:ss",short:"HH:mm"},yD={full:"{{date}} 'um' {{time}}",long:"{{date}} 'um' {{time}}",medium:"{{date}} {{time}}",short:"{{date}} {{time}}"},bD={date:Pr({formats:gD,defaultWidth:"full"}),time:Pr({formats:_D,defaultWidth:"full"}),dateTime:Pr({formats:yD,defaultWidth:"full"})},vD=bD,ED={lastWeek:"'letzten' eeee 'um' p",yesterday:"'gestern um' p",today:"'heute um' p",tomorrow:"'morgen um' p",nextWeek:"eeee 'um' p",other:"P"},wD=function(t,r,n,a){return ED[t]},AD=wD,TD={narrow:["v.Chr.","n.Chr."],abbreviated:["v.Chr.","n.Chr."],wide:["vor Christus","nach Christus"]},ND={narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1. Quartal","2. Quartal","3. Quartal","4. Quartal"]},Pf={narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","M\xE4r","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],wide:["Januar","Februar","M\xE4rz","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"]},RD={narrow:Pf.narrow,abbreviated:["Jan.","Feb.","M\xE4rz","Apr.","Mai","Juni","Juli","Aug.","Sep.","Okt.","Nov.","Dez."],wide:Pf.wide},xD={narrow:["S","M","D","M","D","F","S"],short:["So","Mo","Di","Mi","Do","Fr","Sa"],abbreviated:["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."],wide:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"]},ID={narrow:{am:"vm.",pm:"nm.",midnight:"Mitternacht",noon:"Mittag",morning:"Morgen",afternoon:"Nachm.",evening:"Abend",night:"Nacht"},abbreviated:{am:"vorm.",pm:"nachm.",midnight:"Mitternacht",noon:"Mittag",morning:"Morgen",afternoon:"Nachmittag",evening:"Abend",night:"Nacht"},wide:{am:"vormittags",pm:"nachmittags",midnight:"Mitternacht",noon:"Mittag",morning:"Morgen",afternoon:"Nachmittag",evening:"Abend",night:"Nacht"}},SD={narrow:{am:"vm.",pm:"nm.",midnight:"Mitternacht",noon:"Mittag",morning:"morgens",afternoon:"nachm.",evening:"abends",night:"nachts"},abbreviated:{am:"vorm.",pm:"nachm.",midnight:"Mitternacht",noon:"Mittag",morning:"morgens",afternoon:"nachmittags",evening:"abends",night:"nachts"},wide:{am:"vormittags",pm:"nachmittags",midnight:"Mitternacht",noon:"Mittag",morning:"morgens",afternoon:"nachmittags",evening:"abends",night:"nachts"}},CD=function(t){var r=Number(t);return r+"."},OD={ordinalNumber:CD,era:dr({values:TD,defaultWidth:"wide"}),quarter:dr({values:ND,defaultWidth:"wide",argumentCallback:function(t){return t-1}}),month:dr({values:Pf,formattingValues:RD,defaultWidth:"wide"}),day:dr({values:xD,defaultWidth:"wide"}),dayPeriod:dr({values:ID,defaultWidth:"wide",formattingValues:SD,defaultFormattingWidth:"wide"})},DD=OD,PD=/^(\d+)(\.)?/i,LD=/\d+/i,UD={narrow:/^(v\.? ?Chr\.?|n\.? ?Chr\.?)/i,abbreviated:/^(v\.? ?Chr\.?|n\.? ?Chr\.?)/i,wide:/^(vor Christus|vor unserer Zeitrechnung|nach Christus|unserer Zeitrechnung)/i},MD={any:[/^v/i,/^n/i]},kD={narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](\.)? Quartal/i},FD={any:[/1/i,/2/i,/3/i,/4/i]},HD={narrow:/^[jfmasond]/i,abbreviated:/^(j[aä]n|feb|mär[z]?|apr|mai|jun[i]?|jul[i]?|aug|sep|okt|nov|dez)\.?/i,wide:/^(januar|februar|märz|april|mai|juni|juli|august|september|oktober|november|dezember)/i},GD={narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^j[aä]/i,/^f/i,/^mär/i,/^ap/i,/^mai/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},BD={narrow:/^[smdmf]/i,short:/^(so|mo|di|mi|do|fr|sa)/i,abbreviated:/^(son?|mon?|die?|mit?|don?|fre?|sam?)\.?/i,wide:/^(sonntag|montag|dienstag|mittwoch|donnerstag|freitag|samstag)/i},WD={any:[/^so/i,/^mo/i,/^di/i,/^mi/i,/^do/i,/^f/i,/^sa/i]},VD={narrow:/^(vm\.?|nm\.?|Mitternacht|Mittag|morgens|nachm\.?|abends|nachts)/i,abbreviated:/^(vorm\.?|nachm\.?|Mitternacht|Mittag|morgens|nachm\.?|abends|nachts)/i,wide:/^(vormittags|nachmittags|Mitternacht|Mittag|morgens|nachmittags|abends|nachts)/i},qD={any:{am:/^v/i,pm:/^n/i,midnight:/^Mitte/i,noon:/^Mitta/i,morning:/morgens/i,afternoon:/nachmittags/i,evening:/abends/i,night:/nachts/i}},KD={ordinalNumber:qc({matchPattern:PD,parsePattern:LD,valueCallback:function(t){return parseInt(t)}}),era:fr({matchPatterns:UD,defaultMatchWidth:"wide",parsePatterns:MD,defaultParseWidth:"any"}),quarter:fr({matchPatterns:kD,defaultMatchWidth:"wide",parsePatterns:FD,defaultParseWidth:"any",valueCallback:function(t){return t+1}}),month:fr({matchPatterns:HD,defaultMatchWidth:"wide",parsePatterns:GD,defaultParseWidth:"any"}),day:fr({matchPatterns:BD,defaultMatchWidth:"wide",parsePatterns:WD,defaultParseWidth:"any"}),dayPeriod:fr({matchPatterns:VD,defaultMatchWidth:"wide",parsePatterns:qD,defaultParseWidth:"any"})},YD=KD,zD={code:"de",formatDistance:mD,formatLong:vD,formatRelative:AD,localize:DD,match:YD,options:{weekStartsOn:1,firstWeekContainsDate:4}},$D=zD,XD={full:"EEEE, d MMMM yyyy",long:"d MMMM yyyy",medium:"d MMM yyyy",short:"dd/MM/yyyy"},jD={full:"HH:mm:ss zzzz",long:"HH:mm:ss z",medium:"HH:mm:ss",short:"HH:mm"},QD={full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},ZD={date:Pr({formats:XD,defaultWidth:"full"}),time:Pr({formats:jD,defaultWidth:"full"}),dateTime:Pr({formats:QD,defaultWidth:"full"})},JD=ZD,e5={code:"en-GB",formatDistance:iv,formatLong:JD,formatRelative:sv,localize:cv,match:uv,options:{weekStartsOn:1,firstWeekContainsDate:4}},wv=e5,t5={lessThanXSeconds:{one:"menos de un segundo",other:"menos de {{count}} segundos"},xSeconds:{one:"1 segundo",other:"{{count}} segundos"},halfAMinute:"medio minuto",lessThanXMinutes:{one:"menos de un minuto",other:"menos de {{count}} minutos"},xMinutes:{one:"1 minuto",other:"{{count}} minutos"},aboutXHours:{one:"alrededor de 1 hora",other:"alrededor de {{count}} horas"},xHours:{one:"1 hora",other:"{{count}} horas"},xDays:{one:"1 d\xEDa",other:"{{count}} d\xEDas"},aboutXWeeks:{one:"alrededor de 1 semana",other:"alrededor de {{count}} semanas"},xWeeks:{one:"1 semana",other:"{{count}} semanas"},aboutXMonths:{one:"alrededor de 1 mes",other:"alrededor de {{count}} meses"},xMonths:{one:"1 mes",other:"{{count}} meses"},aboutXYears:{one:"alrededor de 1 a\xF1o",other:"alrededor de {{count}} a\xF1os"},xYears:{one:"1 a\xF1o",other:"{{count}} a\xF1os"},overXYears:{one:"m\xE1s de 1 a\xF1o",other:"m\xE1s de {{count}} a\xF1os"},almostXYears:{one:"casi 1 a\xF1o",other:"casi {{count}} a\xF1os"}},r5=function(t,r,n){var a,o=t5[t];return typeof o=="string"?a=o:r===1?a=o.one:a=o.other.replace("{{count}}",r.toString()),n!=null&&n.addSuffix?n.comparison&&n.comparison>0?"en "+a:"hace "+a:a},n5=r5,a5={full:"EEEE, d 'de' MMMM 'de' y",long:"d 'de' MMMM 'de' y",medium:"d MMM y",short:"dd/MM/y"},o5={full:"HH:mm:ss zzzz",long:"HH:mm:ss z",medium:"HH:mm:ss",short:"HH:mm"},i5={full:"{{date}} 'a las' {{time}}",long:"{{date}} 'a las' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},s5={date:Pr({formats:a5,defaultWidth:"full"}),time:Pr({formats:o5,defaultWidth:"full"}),dateTime:Pr({formats:i5,defaultWidth:"full"})},c5=s5,u5={lastWeek:"'el' eeee 'pasado a la' p",yesterday:"'ayer a la' p",today:"'hoy a la' p",tomorrow:"'ma\xF1ana a la' p",nextWeek:"eeee 'a la' p",other:"P"},l5={lastWeek:"'el' eeee 'pasado a las' p",yesterday:"'ayer a las' p",today:"'hoy a las' p",tomorrow:"'ma\xF1ana a las' p",nextWeek:"eeee 'a las' p",other:"P"},d5=function(t,r,n,a){return r.getUTCHours()!==1?l5[t]:u5[t]},f5=d5,p5={narrow:["AC","DC"],abbreviated:["AC","DC"],wide:["antes de cristo","despu\xE9s de cristo"]},h5={narrow:["1","2","3","4"],abbreviated:["T1","T2","T3","T4"],wide:["1\xBA trimestre","2\xBA trimestre","3\xBA trimestre","4\xBA trimestre"]},m5={narrow:["e","f","m","a","m","j","j","a","s","o","n","d"],abbreviated:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],wide:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"]},g5={narrow:["d","l","m","m","j","v","s"],short:["do","lu","ma","mi","ju","vi","s\xE1"],abbreviated:["dom","lun","mar","mi\xE9","jue","vie","s\xE1b"],wide:["domingo","lunes","martes","mi\xE9rcoles","jueves","viernes","s\xE1bado"]},_5={narrow:{am:"a",pm:"p",midnight:"mn",noon:"md",morning:"ma\xF1ana",afternoon:"tarde",evening:"tarde",night:"noche"},abbreviated:{am:"AM",pm:"PM",midnight:"medianoche",noon:"mediodia",morning:"ma\xF1ana",afternoon:"tarde",evening:"tarde",night:"noche"},wide:{am:"a.m.",pm:"p.m.",midnight:"medianoche",noon:"mediodia",morning:"ma\xF1ana",afternoon:"tarde",evening:"tarde",night:"noche"}},y5={narrow:{am:"a",pm:"p",midnight:"mn",noon:"md",morning:"de la ma\xF1ana",afternoon:"de la tarde",evening:"de la tarde",night:"de la noche"},abbreviated:{am:"AM",pm:"PM",midnight:"medianoche",noon:"mediodia",morning:"de la ma\xF1ana",afternoon:"de la tarde",evening:"de la tarde",night:"de la noche"},wide:{am:"a.m.",pm:"p.m.",midnight:"medianoche",noon:"mediodia",morning:"de la ma\xF1ana",afternoon:"de la tarde",evening:"de la tarde",night:"de la noche"}},b5=function(t,r){var n=Number(t);return n+"\xBA"},v5={ordinalNumber:b5,era:dr({values:p5,defaultWidth:"wide"}),quarter:dr({values:h5,defaultWidth:"wide",argumentCallback:function(t){return Number(t)-1}}),month:dr({values:m5,defaultWidth:"wide"}),day:dr({values:g5,defaultWidth:"wide"}),dayPeriod:dr({values:_5,defaultWidth:"wide",formattingValues:y5,defaultFormattingWidth:"wide"})},E5=v5,w5=/^(\d+)(º)?/i,A5=/\d+/i,T5={narrow:/^(ac|dc|a|d)/i,abbreviated:/^(a\.?\s?c\.?|a\.?\s?e\.?\s?c\.?|d\.?\s?c\.?|e\.?\s?c\.?)/i,wide:/^(antes de cristo|antes de la era com[uú]n|despu[eé]s de cristo|era com[uú]n)/i},N5={any:[/^ac/i,/^dc/i],wide:[/^(antes de cristo|antes de la era com[uú]n)/i,/^(despu[eé]s de cristo|era com[uú]n)/i]},R5={narrow:/^[1234]/i,abbreviated:/^T[1234]/i,wide:/^[1234](º)? trimestre/i},x5={any:[/1/i,/2/i,/3/i,/4/i]},I5={narrow:/^[efmajsond]/i,abbreviated:/^(ene|feb|mar|abr|may|jun|jul|ago|sep|oct|nov|dic)/i,wide:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i},S5={narrow:[/^e/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^en/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i]},C5={narrow:/^[dlmjvs]/i,short:/^(do|lu|ma|mi|ju|vi|s[áa])/i,abbreviated:/^(dom|lun|mar|mi[ée]|jue|vie|s[áa]b)/i,wide:/^(domingo|lunes|martes|mi[ée]rcoles|jueves|viernes|s[áa]bado)/i},O5={narrow:[/^d/i,/^l/i,/^m/i,/^m/i,/^j/i,/^v/i,/^s/i],any:[/^do/i,/^lu/i,/^ma/i,/^mi/i,/^ju/i,/^vi/i,/^sa/i]},D5={narrow:/^(a|p|mn|md|(de la|a las) (mañana|tarde|noche))/i,any:/^([ap]\.?\s?m\.?|medianoche|mediodia|(de la|a las) (mañana|tarde|noche))/i},P5={any:{am:/^a/i,pm:/^p/i,midnight:/^mn/i,noon:/^md/i,morning:/mañana/i,afternoon:/tarde/i,evening:/tarde/i,night:/noche/i}},L5={ordinalNumber:qc({matchPattern:w5,parsePattern:A5,valueCallback:function(t){return parseInt(t,10)}}),era:fr({matchPatterns:T5,defaultMatchWidth:"wide",parsePatterns:N5,defaultParseWidth:"any"}),quarter:fr({matchPatterns:R5,defaultMatchWidth:"wide",parsePatterns:x5,defaultParseWidth:"any",valueCallback:function(t){return t+1}}),month:fr({matchPatterns:I5,defaultMatchWidth:"wide",parsePatterns:S5,defaultParseWidth:"any"}),day:fr({matchPatterns:C5,defaultMatchWidth:"wide",parsePatterns:O5,defaultParseWidth:"any"}),dayPeriod:fr({matchPatterns:D5,defaultMatchWidth:"any",parsePatterns:P5,defaultParseWidth:"any"})},U5=L5,M5={code:"es",formatDistance:n5,formatLong:c5,formatRelative:f5,localize:E5,match:U5,options:{weekStartsOn:1,firstWeekContainsDate:1}},k5=M5,F5={lessThanXSeconds:{one:"moins d\u2019une seconde",other:"moins de {{count}} secondes"},xSeconds:{one:"1 seconde",other:"{{count}} secondes"},halfAMinute:"30 secondes",lessThanXMinutes:{one:"moins d\u2019une minute",other:"moins de {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"environ 1 heure",other:"environ {{count}} heures"},xHours:{one:"1 heure",other:"{{count}} heures"},xDays:{one:"1 jour",other:"{{count}} jours"},aboutXWeeks:{one:"environ 1 semaine",other:"environ {{count}} semaines"},xWeeks:{one:"1 semaine",other:"{{count}} semaines"},aboutXMonths:{one:"environ 1 mois",other:"environ {{count}} mois"},xMonths:{one:"1 mois",other:"{{count}} mois"},aboutXYears:{one:"environ 1 an",other:"environ {{count}} ans"},xYears:{one:"1 an",other:"{{count}} ans"},overXYears:{one:"plus d\u2019un an",other:"plus de {{count}} ans"},almostXYears:{one:"presqu\u2019un an",other:"presque {{count}} ans"}},H5=function(t,r,n){var a,o=F5[t];return typeof o=="string"?a=o:r===1?a=o.one:a=o.other.replace("{{count}}",String(r)),n!=null&&n.addSuffix?n.comparison&&n.comparison>0?"dans "+a:"il y a "+a:a},G5=H5,B5={full:"EEEE d MMMM y",long:"d MMMM y",medium:"d MMM y",short:"dd/MM/y"},W5={full:"HH:mm:ss zzzz",long:"HH:mm:ss z",medium:"HH:mm:ss",short:"HH:mm"},V5={full:"{{date}} '\xE0' {{time}}",long:"{{date}} '\xE0' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},q5={date:Pr({formats:B5,defaultWidth:"full"}),time:Pr({formats:W5,defaultWidth:"full"}),dateTime:Pr({formats:V5,defaultWidth:"full"})},K5=q5,Y5={lastWeek:"eeee 'dernier \xE0' p",yesterday:"'hier \xE0' p",today:"'aujourd\u2019hui \xE0' p",tomorrow:"'demain \xE0' p'",nextWeek:"eeee 'prochain \xE0' p",other:"P"},z5=function(t,r,n,a){return Y5[t]},$5=z5,X5={narrow:["av. J.-C","ap. J.-C"],abbreviated:["av. J.-C","ap. J.-C"],wide:["avant J\xE9sus-Christ","apr\xE8s J\xE9sus-Christ"]},j5={narrow:["T1","T2","T3","T4"],abbreviated:["1er trim.","2\xE8me trim.","3\xE8me trim.","4\xE8me trim."],wide:["1er trimestre","2\xE8me trimestre","3\xE8me trimestre","4\xE8me trimestre"]},Q5={narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["janv.","f\xE9vr.","mars","avr.","mai","juin","juil.","ao\xFBt","sept.","oct.","nov.","d\xE9c."],wide:["janvier","f\xE9vrier","mars","avril","mai","juin","juillet","ao\xFBt","septembre","octobre","novembre","d\xE9cembre"]},Z5={narrow:["D","L","M","M","J","V","S"],short:["di","lu","ma","me","je","ve","sa"],abbreviated:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],wide:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"]},J5={narrow:{am:"AM",pm:"PM",midnight:"minuit",noon:"midi",morning:"mat.",afternoon:"ap.m.",evening:"soir",night:"mat."},abbreviated:{am:"AM",pm:"PM",midnight:"minuit",noon:"midi",morning:"matin",afternoon:"apr\xE8s-midi",evening:"soir",night:"matin"},wide:{am:"AM",pm:"PM",midnight:"minuit",noon:"midi",morning:"du matin",afternoon:"de l\u2019apr\xE8s-midi",evening:"du soir",night:"du matin"}},eP=function(t,r){var n=Number(t),a=r?.unit;if(n===0)return"0";var o=["year","week","hour","minute","second"],s;return n===1?s=a&&o.includes(a)?"\xE8re":"er":s="\xE8me",n+s},tP={ordinalNumber:eP,era:dr({values:X5,defaultWidth:"wide"}),quarter:dr({values:j5,defaultWidth:"wide",argumentCallback:function(t){return t-1}}),month:dr({values:Q5,defaultWidth:"wide"}),day:dr({values:Z5,defaultWidth:"wide"}),dayPeriod:dr({values:J5,defaultWidth:"wide"})},rP=tP,nP=/^(\d+)(ième|ère|ème|er|e)?/i,aP=/\d+/i,oP={narrow:/^(av\.J\.C|ap\.J\.C|ap\.J\.-C)/i,abbreviated:/^(av\.J\.-C|av\.J-C|apr\.J\.-C|apr\.J-C|ap\.J-C)/i,wide:/^(avant Jésus-Christ|après Jésus-Christ)/i},iP={any:[/^av/i,/^ap/i]},sP={narrow:/^T?[1234]/i,abbreviated:/^[1234](er|ème|e)? trim\.?/i,wide:/^[1234](er|ème|e)? trimestre/i},cP={any:[/1/i,/2/i,/3/i,/4/i]},uP={narrow:/^[jfmasond]/i,abbreviated:/^(janv|févr|mars|avr|mai|juin|juill|juil|août|sept|oct|nov|déc)\.?/i,wide:/^(janvier|février|mars|avril|mai|juin|juillet|août|septembre|octobre|novembre|décembre)/i},lP={narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^av/i,/^ma/i,/^juin/i,/^juil/i,/^ao/i,/^s/i,/^o/i,/^n/i,/^d/i]},dP={narrow:/^[lmjvsd]/i,short:/^(di|lu|ma|me|je|ve|sa)/i,abbreviated:/^(dim|lun|mar|mer|jeu|ven|sam)\.?/i,wide:/^(dimanche|lundi|mardi|mercredi|jeudi|vendredi|samedi)/i},fP={narrow:[/^d/i,/^l/i,/^m/i,/^m/i,/^j/i,/^v/i,/^s/i],any:[/^di/i,/^lu/i,/^ma/i,/^me/i,/^je/i,/^ve/i,/^sa/i]},pP={narrow:/^(a|p|minuit|midi|mat\.?|ap\.?m\.?|soir|nuit)/i,any:/^([ap]\.?\s?m\.?|du matin|de l'après[-\s]midi|du soir|de la nuit)/i},hP={any:{am:/^a/i,pm:/^p/i,midnight:/^min/i,noon:/^mid/i,morning:/mat/i,afternoon:/ap/i,evening:/soir/i,night:/nuit/i}},mP={ordinalNumber:qc({matchPattern:nP,parsePattern:aP,valueCallback:function(t){return parseInt(t)}}),era:fr({matchPatterns:oP,defaultMatchWidth:"wide",parsePatterns:iP,defaultParseWidth:"any"}),quarter:fr({matchPatterns:sP,defaultMatchWidth:"wide",parsePatterns:cP,defaultParseWidth:"any",valueCallback:function(t){return t+1}}),month:fr({matchPatterns:uP,defaultMatchWidth:"wide",parsePatterns:lP,defaultParseWidth:"any"}),day:fr({matchPatterns:dP,defaultMatchWidth:"wide",parsePatterns:fP,defaultParseWidth:"any"}),dayPeriod:fr({matchPatterns:pP,defaultMatchWidth:"any",parsePatterns:hP,defaultParseWidth:"any"})},gP=mP,_P={code:"fr",formatDistance:G5,formatLong:K5,formatRelative:$5,localize:rP,match:gP,options:{weekStartsOn:1,firstWeekContainsDate:4}},yP=_P,Lf={es:"Espanol [es]",en:"English [en]",fr:"Francais [fr]",de:"Deutsch [de]"},bP={lang:"en",supportedLang:Lf,changeLanguage:()=>{},i18n:Fo,dateLocale:wv,completeness:{de:0,en:0,es:0,fr:0}},Av=Kt(bP),Tv=({initial:e,children:t,forceLang__testing:r,source:n})=>{let a=Object.keys(Lf).reduce((u,f)=>(f!=="en"&&n[f]&&n[f].completeness&&(u[f]=n[f].completeness),u),{en:100}),{value:o,update:s}=iD(e,a);Ge(()=>{r&&s(r)},[r]),Ge(()=>{ko(o,n)},[o]),r?ko(r,n):ko(o,n);let c=o==="es"?k5:o==="fr"?yP:o==="de"?$D:wv;return i(Av.Provider,{value:{lang:o,changeLanguage:s,supportedLang:Lf,i18n:Fo,dateLocale:c,completeness:a},children:t})},Ne=()=>lr(Av),vP=class{constructor(){this.observers=new Array,this.notify=this.notify.bind(this),this.subscribe=this.subscribe.bind(this)}notify(e){this.observers.forEach(t=>t(e))}subscribe(e){return this.observers.push(e),()=>{this.observers.forEach((t,r)=>{t===e&&this.observers.splice(r,1)})}}},Nv=Kt(void 0),De=()=>lr(Nv),EP=5e3,Rv=({baseUrl:e,children:t,frameOnError:r,evictors:n={}})=>{let[a,o]=de(),{i18n:s}=Ne(),{getRemoteConfig:c,VERSION:u,lib:f,cancelRequest:d,onActivity:w}=wP(e,n);if(Ge(()=>{let h=!0;async function p(){try{let T=await c();St.compare(u,T.version)?o({type:"ok",config:T,hints:[]}):o({type:"incompatible",result:T,supported:u})}catch(T){T instanceof Oe?(h&&setTimeout(()=>{p()},EP),o({type:"error",error:T})):o({type:"error",error:Oe.fromException(T)})}}return p(),()=>{h=!1}},[]),a===void 0)return i(r,{children:i("div",{},"checking compatibility with server...")});if(a.type==="error")return i(r,{children:i(_t,{error:a.error})});if(a.type==="incompatible")return i(r,{children:i("div",{},s.str`The server version is not supported. Supported version "${a.supported}", server version "${a.result.version}"`)});let R={url:e,config:a.config,onActivity:w,lib:f,cancelRequest:d,hints:a.hints};return i(Nv.Provider,{value:R,children:t})};function wP(e,t){let r=new UP({enableThrottling:!0,requireTls:!1}),n=new vP,a=new da(r,{observe(u){n.notify(u)}}),o=new Ha(e.href,a,t.bank),s=new la(o.getConversionInfoAPI().href,a,t.conversion);async function c(){let u=await o.getConfig();if(u.type==="fail")throw u.detail?Oe.fromUncheckedDetail(u.detail):Oe.fromException(new Error("failed to get bank remote config"));return u.body}return{getRemoteConfig:c,VERSION:Ha.PROTOCOL_VERSION,lib:{bank:o,conversion:s,conversionForClass(u){return new la(o.getConversionInfoAPIForClass(u).href,a,t.conversion)},conversionForUser(u){return new la(o.getConversionInfoAPIForUser(u).href,a,t.conversion)}},onActivity:n.subscribe,cancelRequest:a.cancelRequest}}var cB=Kt(void 0);var fB=Kt(void 0);var gB=Kt(void 0);function Ut(e,t){let r=t;return{pattern:new RegExp(e),url:r}}var bB={pattern:new RegExp(/.*/),url:()=>""};function AP(e,t,r,n){for(let a=0;a{c[u]=f}),{name:o,parent:e,values:c,params:n}}}return{name:void 0,parent:e,values:{},params:n}}var xv=Kt(void 0),Qa=()=>lr(xv);function Kf(e){let t=Object.keys(e),{path:r,params:n}=Qa();return AP(e,t,r,n)}function Uf(){let e=typeof window<"u"?window.location.hash.substring(1):"/",t={};if(typeof window<"u")for(let[r,n]of new URLSearchParams(window.location.search))t[r]||(t[r]=[]),t[r].push(n);return{path:e,params:t}}var{path:TP,params:NP}=Uf(),K0="popstate",Iv=({children:e})=>{let[{path:t,params:r},n]=de({path:TP,params:NP});if(typeof window>"u")throw Error("Can't use BrowserHashNavigationProvider if there is no window object");function a(o){let{params:s}=Uf();n({path:o,params:s}),window.location.href=o}return Ge(()=>{function o(){n(Uf())}return window.addEventListener(K0,o),()=>{window.removeEventListener(K0,o)}},[]),i(xv.Provider,{value:{path:t,params:r,navigateTo:a},children:e})},RP=()=>W().allowExtra().property("showDebugInfo",Bt(Se(),!1)).build("CommonPreferences"),xP=Xn("common-preferences",RP()),IP={showDebugInfo:!1,toggleShowDebugInfo(){}};function Qo(){let{value:e,update:t}=sD(xP.id,IP);function r(n,a){let o={...e,[n]:a};t(o)}return[e,r]}function SP(e,t){let r=document.createElement("meta");r.setAttribute("name","taler-uri"),r.setAttribute("content",v_(e)),document.head.appendChild(r);let n=!1;window.addEventListener("beforeunload",()=>{n=!0}),setTimeout(()=>{!n&&t&&t()},10)}var Sv=Kt(void 0),zc=()=>lr(Sv),Cv=({children:e})=>{let t={publishTalerAction:SP};return i(Sv.Provider,{value:t,children:e})};var qB=RI(new Date),KB=xI(new Date),YB=Td(new Date);function Ov(e){throw Error(`Field ${e.toString()} doesn't have handler and is not in a form provider context.`)}var CP=i("svg",{class:"w-5 h-5",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor"},i("path",{"fill-rule":"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-3a1 1 0 00-.867.5 1 1 0 11-1.731-1A3 3 0 0113 8a3.001 3.001 0 01-2 2.83V11a1 1 0 11-2 0v-1a1 1 0 011-1 1 1 0 100-2zm0 8a1 1 0 100-2 1 1 0 000 2z","clip-rule":"evenodd"}));function Dv({label:e,required:t,tooltip:r,name:n}){let a=i("div",{class:"flex justify-between"},i("label",{for:n,class:"block text-sm font-medium leading-6 text-gray-900"},e)),o=r?i("div",{class:"relative flex flex-grow items-stretch focus-within:z-10"},a,i("span",{class:"relative flex items-center group pl-2"},CP,i("div",{class:"absolute bottom-0 -ml-10 hidden flex-col items-center mb-6 group-hover:flex w-28"},i("div",{class:"relative z-10 p-2 text-xs leading-none text-white whitespace-no-wrap bg-black shadow-lg"},r),i("div",{class:"w-3 h-3 -mt-2 rotate-45 bg-black"})))):a;return t?i("div",{class:"flex justify-between w-fit"},o,i("span",{class:"text-xl bold leading-6 text-red-600 pl-2"},"*")):o}function Y0({disabled:e,addon:t,reverse:r}){switch(t.type){case"text":return i("span",{class:"inline-flex items-center data-[right=true]:rounded-r-md data-[left=true]:rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm"},t.text);case"icon":return i("div",{class:"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"},t.icon);case"button":return i("button",{type:"button",disabled:e,onClick:t.onClick,"data-left":!r,"data-right":r,class:"relative -ml-px inline-flex items-center gap-x-1.5 data-[right=true]:rounded-r-md data-[left=true]:rounded-l-md px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 disabled:bg-gray-50 disabled:cursor-not-allowed"},t.children)}}function z0({children:e,label:t,tooltip:r,before:n,after:a,help:o,error:s,disabled:c,required:u,name:f}){return i("div",{class:"sm:col-span-6 "},i(Dv,{label:t,required:u,tooltip:r,name:f}),i("div",{class:"relative mt-2 flex rounded-md shadow-sm"},n&&i(Y0,{disabled:c,addon:n}),e,a&&i(Y0,{disabled:c,addon:a,reverse:!0})),s&&i("p",{class:"mt-2 text-sm text-red-600",id:"email-error"},s),o&&i("p",{class:"mt-2 text-sm text-gray-500",id:"email-description"},o))}function OP(e){return e===void 0?"":typeof e!="object"?String(e):""}function DP(e){return e}function PP(e){let{name:t,placeholder:r,before:n,after:a,converter:o,type:s,disabled:c,hidden:u}=e,f=Yt(),{value:d,onChange:w,error:R}=e.handler??Ov(e.name),h=o?.fromStringUI??DP,p=o?.toStringUI??OP;if(Ge(()=>{f.current&&f.current!==document.activeElement&&(f.current.value=d?p(d):"")},[d]),u)return i(ae,null);let T="block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200";if(n)switch(n.type){case"icon":{T+=" pl-10";break}case"button":{T+=" rounded-none rounded-r-md ";break}case"text":{T+=" min-w-0 flex-1 rounded-r-md rounded-none ";break}}if(a)switch(a.type){case"icon":{T+=" pr-10";break}case"button":{T+=" rounded-none rounded-l-md";break}case"text":{T+=" min-w-0 flex-1 rounded-l-md rounded-none ";break}}let A=d!==void 0&&R;return A?T+=" text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-red-500":T+=" text-gray-900 ring-gray-300 placeholder:text-gray-400 focus:ring-indigo-600",s==="text-area"?i(z0,{...e,help:e.help,disabled:c??!1,error:A?R:void 0},i("textarea",{rows:4,ref:vd(Ed(f)),name:String(t),onChange:C=>{w(h(C.currentTarget.value))},defaultValue:e.defaultValue,placeholder:r||void 0,disabled:c??!1,"aria-invalid":A,class:T})):i(z0,{...e,help:e.help,disabled:c??!1,error:A?R:void 0},i("input",{name:String(t),ref:vd(Ed(f)),type:s,onChange:C=>{w(h(C.currentTarget.value))},placeholder:r||void 0,defaultValue:p(d),disabled:c??!1,"aria-invalid":A,class:T}))}function Yf(e){return i(PP,{type:"text",...e})}function Pv(e){let{label:t,tooltip:r,help:n,required:a,threeState:o,disabled:s,trueValue:c=!0,falseValue:u=!1,onlyTrueValue:f=!1}=e,{value:d,onChange:w,error:R}=e.handler??Ov(e.name),[h,p]=de(),T=c===d;return e.hidden?i(ae,null):i("div",{class:"col-span-6"},i("div",{class:"flex items-center justify-between"},i(Dv,{label:t,required:a,tooltip:r,name:e.name}),i("button",{type:"button","data-state":T?"on":d===void 0?"undefined":"off",class:"bg-indigo-600 data-[state=off]:bg-gray-200 data-[state=undefined]:bg-gray-200 relative inline-flex h-6 w-12 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch",disabled:s,"aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>(p(!0),w(d===u&&o||f&&d===c?void 0:d===c?u:c))},i("span",{"data-state":T?"on":d===void 0&&o?"undefined":"off",class:"translate-x-6 data-[state=off]:translate-x-0 data-[state=undefined]:translate-x-3 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"}))),n&&i("p",{class:"mt-2 text-sm text-gray-500",id:"email-description"},n),h!==void 0&&R&&i("p",{class:"mt-2 text-sm text-red-600",id:"email-error"},R))}var z9=new Dt("browserHttpLib");async function LP(e,t){if(!e)return t;let r=new CompressionStream(e),n=r.writable.getWriter();n.write(new Uint8Array(t)),n.close();let a=await new Response(r.readable).arrayBuffer();return new Uint8Array(a)}var UP=class{constructor(e){this.throttle=new Ba,this.throttlingEnabled=!0,this.requireTls=!1,this.throttlingEnabled=e?.enableThrottling??!0,this.requireTls=e?.requireTls??!1}async fetch(e,t){let r=t?.method??"GET",n=t?.body,a=t?.headers,o=t?.timeout??rt.fromMilliseconds($u),s=t?.cancellationToken,c=t?.redirect,u=new URL(e);if(this.throttlingEnabled&&this.throttle.applyThrottle(e))throw Oe.fromDetail(G.WALLET_HTTP_REQUEST_THROTTLED,{requestMethod:r,requestUrl:e,throttleStats:this.throttle.getThrottleStats(e)},`request to origin ${u.origin} was throttled`);if(this.requireTls&&u.protocol!=="https:")throw Oe.fromDetail(G.WALLET_NETWORK_ERROR,{requestMethod:r,requestUrl:e},`request to ${u.origin} is not possible with protocol ${u.protocol}`);let f=r==="POST"||r==="PUT"||r==="PATCH"?Xu(n):void 0,d=!t?.compress||!f?f:await LP(t.compress,f),w=ju(r);a&&Object.entries(a).forEach(([p,T])=>{T!==void 0&&(w[p]=T)}),t?.compress&&(w["Content-Encoding"]=t.compress),n instanceof FormData?delete w["Content-Type"]:n instanceof URLSearchParams&&(w["Content-Type"]="application/x-www-form-urlencoded");let R=new AbortController,h;o.d_ms!=="forever"&&(h=setTimeout(()=>{R.abort(G.GENERIC_TIMEOUT)},o.d_ms)),s&&s.onCancelled(p=>{R.abort(p)});try{let p=await fetch(e,{headers:w,body:d!=null?new Uint8Array(d):void 0,method:r,signal:R.signal,redirect:c});h&&clearTimeout(h);let T=new wo;p.headers.forEach((S,k)=>{T.set(k,S)});let A=MP(p,e,r),C=kP(p,e,r,A);return{headers:T,status:p.status,requestMethod:r,requestUrl:e,json:C,text:A,bytes:async()=>{let k=await(await p.blob()).arrayBuffer();return new Uint8Array(k)}}}catch(p){throw p instanceof Error?R.signal.aborted?Oe.fromDetail(R.signal.reason,{requestUrl:e,requestMethod:r,timeoutMs:o.d_ms==="forever"?0:o.d_ms},`HTTP request aborted: ${p.message}`):Oe.fromDetail(G.WALLET_NETWORK_ERROR,{requestUrl:e,requestMethod:r},`HTTP request failed: ${p.message}`):p}}};function MP(e,t,r){let n=!0,a,o;return async function(){if(n){n=!1;try{a=await e.text()}catch(c){o=Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:t,requestMethod:r,httpStatusCode:e.status,validationError:c instanceof Error?c.message:String(c)},"Invalid text from HTTP response")}}if(o!==void 0)throw o;return a}}function kP(e,t,r,n){let a=!0,o,s;return async function(){if(a){let u;try{u=await n()}catch(f){let d=f instanceof Error?`Couldn't read HTTP response: ${f.message}`:"Couldn't read HTTP response";s=Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:t,requestMethod:r,httpStatusCode:e.status,validationError:f instanceof Error?f.message:String(f)},d)}if(!s){try{o=JSON.parse(u)}catch(f){let d=f instanceof Error?`Invalid JSON from HTTP response: ${f.message}`:"Invalid JSON from HTTP response";s=Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:t,requestMethod:r,response:u,httpStatusCode:e.status,validationError:f instanceof Error?f.message:String(f)},d)}(o===null||typeof o!="object")&&(s=Oe.fromDetail(G.WALLET_RECEIVED_MALFORMED_RESPONSE,{requestUrl:t,requestMethod:r,response:JSON.stringify(o),httpStatusCode:e.status},"Invalid JSON from HTTP response: null or not object"))}}if(s!==void 0)throw s;return o}}Re();Be();pa();var Qv=ui(kv(),1);pa();var vn=new WeakMap,$f={},$c={},jn=()=>{},zr=jn(),Zo=Object,Mt=e=>e===zr,dn=e=>typeof e=="function",En=(e,t)=>({...e,...t}),tp="undefined",Qc=typeof window!=tp,jf=typeof document!=tp,zP=()=>Qc&&typeof window.requestAnimationFrame!=tp,rp=(e,t)=>{let r=vn.get(e);return[()=>e.get(t)||$f,n=>{if(!Mt(t)){let a=e.get(t);t in $c||($c[t]=a),r[5](t,En(a,n),a||$f)}},r[6],()=>!Mt(t)&&t in $c?$c[t]:e.get(t)||$f]},Xc=new WeakMap,$P=0,Jo=e=>{let t=typeof e,r=e&&e.constructor,n=r==Date,a,o;if(Zo(e)===e&&!n&&r!=RegExp){if(a=Xc.get(e),a)return a;if(a=++$P+"~",Xc.set(e,a),r==Array){for(a="@",o=0;oQf,[Zf,Jf]=Qc&&window.addEventListener?[window.addEventListener.bind(window),window.removeEventListener.bind(window)]:[jn,jn],jP=()=>{let e=jf&&document.visibilityState;return Mt(e)||e!=="hidden"},QP=e=>(jf&&document.addEventListener("visibilitychange",e),Zf("focus",e),()=>{jf&&document.removeEventListener("visibilitychange",e),Jf("focus",e)}),ZP=e=>{let t=()=>{Qf=!0,e()},r=()=>{Qf=!1};return Zf("online",t),Zf("offline",r),()=>{Jf("online",t),Jf("offline",r)}},JP={isOnline:XP,isVisible:jP},eL={initFocus:QP,initReconnect:ZP},np=!As.useId,Ja=!Qc||"Deno"in window,Gv=e=>zP()?window.requestAnimationFrame(e):setTimeout(e,1),ei=Ja?Ge:Kn,Xf=typeof navigator<"u"&&navigator.connection,Fv=!Ja&&Xf&&(["slow-2g","2g"].includes(Xf.effectiveType)||Xf.saveData),Zc=e=>{if(dn(e))try{e=e()}catch{e=""}let t=e;return e=typeof e=="string"?e:(Array.isArray(e)?e.length:e)?Jo(e):"",[e,t]},tL=0,jc=()=>++tL,Bv=0,Wv=1,Vv=2,Jc={__proto__:null,FOCUS_EVENT:Bv,RECONNECT_EVENT:Wv,MUTATE_EVENT:Vv};async function ap(...e){let[t,r,n,a]=e,o=En({populateCache:!0,throwOnError:!0},typeof a=="boolean"?{revalidate:a}:a||{}),s=o.populateCache,c=o.rollbackOnError,u=o.optimisticData,f=o.revalidate!==!1,d=h=>typeof c=="function"?c(h):c!==!1,w=o.throwOnError;if(dn(r)){let h=r,p=[],T=t.keys();for(let A=T.next();!A.done;A=T.next()){let C=A.value;!C.startsWith("$inf$")&&h(t.get(C)._k)&&p.push(C)}return Promise.all(p.map(R))}return R(r);async function R(h){let[p]=Zc(h);if(!p)return;let[T,A]=rp(t,p),[C,S,k]=vn.get(t),v=C[p],_=()=>f&&(delete k[p],v&&v[0])?v[0](Vv).then(()=>T().data):T().data;if(e.length<3)return _();let g=n,O,E=jc();S[p]=[E,0];let m=!Mt(u),y=T(),b=y.data,x=y._c,D=Mt(x)?b:x;if(m&&(u=dn(u)?u(D):u,A({data:u,_c:D})),dn(g))try{g=g(D)}catch(B){O=B}if(g&&dn(g.then))if(g=await g.catch(B=>{O=B}),E!==S[p][0]){if(O)throw O;return g}else O&&m&&d(O)&&(s=!0,g=D,A({data:g,_c:zr}));s&&(O||(dn(s)&&(g=s(g,D)),A({data:g,_c:zr}))),S[p][1]=jc();let F=await _();if(A({_c:zr}),O){if(w)throw O;return}return s?F:g}}var Hv=(e,t)=>{for(let r in e)e[r][0]&&e[r][0](t)},qv=(e,t)=>{if(!vn.has(e)){let r=En(eL,t),n={},a=ap.bind(zr,e),o=jn,s={},c=(d,w)=>{let R=s[d]||[];return s[d]=R,R.push(w),()=>R.splice(R.indexOf(w),1)},u=(d,w,R)=>{e.set(d,w);let h=s[d];if(h)for(let p=h.length;p--;)h[p](w,R)},f=()=>{if(!vn.has(e)&&(vn.set(e,[n,{},{},{},a,u,c]),!Ja)){let d=r.initFocus(setTimeout.bind(zr,Hv.bind(zr,n,Bv))),w=r.initReconnect(setTimeout.bind(zr,Hv.bind(zr,n,Wv)));o=()=>{d&&d(),w&&w(),vn.delete(e)}}};return f(),[e,a,f,o]}return[e,vn.get(e)[4]]},rL=(e,t,r,n,a)=>{let o=r.errorRetryCount,s=a.retryCount,c=~~((Math.random()+.5)*(1<<(s<8?s:8)))*r.errorRetryInterval;!Mt(o)&&s>o||setTimeout(n,c,a)},nL=(e,t)=>Jo(e)==Jo(t),[op,vr]=qv(new Map),ip=En({onLoadingSlow:jn,onSuccess:jn,onError:jn,onErrorRetry:rL,onDiscarded:jn,revalidateOnFocus:!0,revalidateOnReconnect:!0,revalidateIfStale:!0,shouldRetryOnError:!0,errorRetryInterval:Fv?1e4:5e3,focusThrottleInterval:5*1e3,dedupingInterval:2*1e3,loadingTimeout:Fv?5e3:3e3,compare:nL,isPaused:()=>!1,cache:op,mutate:vr,fallback:{}},JP),Kv=(e,t)=>{let r=En(e,t);if(t){let{use:n,fallback:a}=e,{use:o,fallback:s}=t;n&&o&&(r.use=n.concat(o)),a&&s&&(r.fallback=En(a,s))}return r},ep=Kt({}),Yv=e=>{let{value:t}=e,r=lr(ep),n=dn(t),a=en(()=>n?t(r):t,[n,r,t]),o=en(()=>n?a:Kv(r,a),[n,r,a]),s=a&&a.provider,[c]=de(()=>s?qv(s(o.cache||op),a):zr);return c&&(o.cache=c[0],o.mutate=c[1]),ei(()=>{if(c)return c[2]&&c[2](),c[3]},[]),i(ep.Provider,En(e,{value:o}))},zv=Qc&&window.__SWR_DEVTOOLS_USE__,aL=zv?window.__SWR_DEVTOOLS_USE__:[],oL=()=>{zv&&(window.__SWR_DEVTOOLS_REACT__=As)},iL=e=>dn(e[1])?[e[0],e[1],e[2]||{}]:[e[0],null,(e[1]===null?e[2]:e[1])||{}],$v=()=>En(ip,lr(ep));var sL=e=>(t,r,n)=>e(t,r&&((...o)=>{let s=Zc(t)[0],[,,,c]=vn.get(op),u=c[s];return u?(delete c[s],u):r(...o)}),n),cL=aL.concat(sL),Xv=e=>function(...r){let n=$v(),[a,o,s]=iL(r),c=Kv(n,s),u=e,{use:f}=c,d=(f||[]).concat(cL);for(let w=d.length;w--;)u=d[w](u);return u(a,o||c.fetcher||null,c)};var jv=(e,t,r)=>{let n=t[e]||(t[e]=[]);return n.push(r),()=>{let a=n.indexOf(r);a>=0&&(n[a]=n[n.length-1],n.pop())}};oL();var sp={dedupe:!0},uL=(e,t,r)=>{let{cache:n,compare:a,suspense:o,fallbackData:s,revalidateOnMount:c,revalidateIfStale:u,refreshInterval:f,refreshWhenHidden:d,refreshWhenOffline:w,keepPreviousData:R}=r,[h,p,T]=vn.get(n),[A,C]=Zc(e),S=Yt(!1),k=Yt(!1),v=Yt(A),_=Yt(t),g=Yt(r),O=()=>g.current,E=()=>O().isVisible()&&O().isOnline(),[m,y,b,x]=rp(n,A),D=Yt({}).current,F=Mt(s)?r.fallback[A]:s,B=(Y,j)=>{let ie=!0;for(let we in D){let oe=we;oe==="data"?a(j[oe],Y[oe])||Mt(Y[oe])&&a(j[oe],Ve)||(ie=!1):j[oe]!==Y[oe]&&(ie=!1)}return ie},K=en(()=>{let Y=!A||!t?!1:Mt(c)?O().isPaused()||o?!1:Mt(u)?!0:u:c,j=oe=>{let je=En(oe);return delete je._k,Y?{isValidating:!0,isLoading:!0,...je}:je},ie=j(m()),we=j(x());return[()=>{let oe=j(m());return B(oe,ie)?ie:ie=oe},()=>we]},[n,A]),Z=(0,Qv.useSyncExternalStore)(Yn(Y=>b(A,(j,ie)=>{B(ie,j)||Y()}),[n,A]),K[0],K[1]),pe=!S.current,Ie=h[A]&&h[A].length>0,be=Z.data,xe=Mt(be)?F:be,Le=Z.error,Ue=Yt(xe),Ve=R?Mt(be)?Ue.current:be:xe,te=Ie&&!Mt(Le)?!1:pe&&!Mt(c)?c:O().isPaused()?!1:o?Mt(xe)?!1:u:Mt(xe)||u,ee=!!(A&&t&&pe&&te),$=Mt(Z.isValidating)?ee:Z.isValidating,H=Mt(Z.isLoading)?ee:Z.isLoading,M=Yn(async Y=>{let j=_.current;if(!A||!j||k.current||O().isPaused())return!1;let ie,we,oe=!0,je=Y||{},ct=!T[A]||!je.dedupe,qe=()=>np?!k.current&&A===v.current&&S.current:A===v.current,zt={isValidating:!1,isLoading:!1},ir=()=>{y(zt)},tn=()=>{let $t=T[A];$t&&$t[1]===we&&delete T[A]},Ye={isValidating:!0};Mt(m().data)&&(Ye.isLoading=!0);try{if(ct&&(y(Ye),r.loadingTimeout&&Mt(m().data)&&setTimeout(()=>{oe&&qe()&&O().onLoadingSlow(A,r)},r.loadingTimeout),T[A]=[j(C),jc()]),[ie,we]=T[A],ie=await ie,ct&&setTimeout(tn,r.dedupingInterval),!T[A]||T[A][1]!==we)return ct&&qe()&&O().onDiscarded(A),!1;zt.error=zr;let $t=p[A];if(!Mt($t)&&(we<=$t[0]||we<=$t[1]||$t[1]===0))return ir(),ct&&qe()&&O().onDiscarded(A),!1;let N=m().data;zt.data=a(N,ie)?N:ie,ct&&qe()&&O().onSuccess(ie,A,r)}catch($t){tn();let N=O(),{shouldRetryOnError:P}=N;N.isPaused()||(zt.error=$t,ct&&qe()&&(N.onError($t,A,N),(P===!0||dn(P)&&P($t))&&E()&&N.onErrorRetry($t,A,N,M,{retryCount:(je.retryCount||0)+1,dedupe:!0})))}return oe=!1,ir(),!0},[A,n]),q=Yn((...Y)=>ap(n,v.current,...Y),[]);if(ei(()=>{_.current=t,g.current=r,Mt(be)||(Ue.current=be)}),ei(()=>{if(!A)return;let Y=M.bind(zr,sp),j=0,we=jv(A,h,oe=>{if(oe==Jc.FOCUS_EVENT){let je=Date.now();O().revalidateOnFocus&&je>j&&E()&&(j=je+O().focusThrottleInterval,Y())}else if(oe==Jc.RECONNECT_EVENT)O().revalidateOnReconnect&&E()&&Y();else if(oe==Jc.MUTATE_EVENT)return M()});return k.current=!1,v.current=A,S.current=!0,y({_k:C}),te&&(Mt(xe)||Ja?Y():Gv(Y)),()=>{k.current=!0,we()}},[A]),ei(()=>{let Y;function j(){let we=dn(f)?f(xe):f;we&&Y!==-1&&(Y=setTimeout(ie,we))}function ie(){!m().error&&(d||O().isVisible())&&(w||O().isOnline())?M(sp).then(j):j()}return j(),()=>{Y&&(clearTimeout(Y),Y=-1)}},[f,d,w,A]),Yo(Ve),o&&Mt(xe)&&A)throw!np&&Ja?new Error("Fallback data is required when using suspense in SSR."):(_.current=t,g.current=r,k.current=!1,Mt(Le)?M(sp):Le);return{mutate:q,get data(){return D.data=!0,Ve},get error(){return D.error=!0,Le},get isValidating(){return D.isValidating=!0,$},get isLoading(){return D.isLoading=!0,H}}},Zv=Zo.defineProperty(Yv,"defaultValue",{value:ip});var eu=Xv(uL);Re();Be();Re();Be();function Ht(e){return Object.keys(e).some(t=>e[t]!==void 0)?e:void 0}var lL=20,Un=lL+1,dL={AE:"U.A.E.",AF:"Afghanistan",AL:"Albania",AM:"Armenia",AN:"Netherlands Antilles",AR:"Argentina",AT:"Austria",AU:"Australia",AZ:"Azerbaijan",BA:"Bosnia and Herzegovina",BD:"Bangladesh",BE:"Belgium",BG:"Bulgaria",BH:"Bahrain",BN:"Brunei Darussalam",BO:"Bolivia",BR:"Brazil",BT:"Bhutan",BY:"Belarus",BZ:"Belize",CA:"Canada",CG:"Congo",CH:"Switzerland",CI:"Cote d'Ivoire",CL:"Chile",CM:"Cameroon",CN:"People's Republic of China",CO:"Colombia",CR:"Costa Rica",CS:"Serbia and Montenegro",CZ:"Czech Republic",DE:"Germany",DK:"Denmark",DO:"Dominican Republic",DZ:"Algeria",EC:"Ecuador",EE:"Estonia",EG:"Egypt",ER:"Eritrea",ES:"Spain",ET:"Ethiopia",FI:"Finland",FO:"Faroe Islands",FR:"France",GB:"United Kingdom",GD:"Caribbean",GE:"Georgia",GL:"Greenland",GR:"Greece",GT:"Guatemala",HK:"Hong Kong",HN:"Honduras",HR:"Croatia",HT:"Haiti",HU:"Hungary",ID:"Indonesia",IE:"Ireland",IL:"Israel",IN:"India",IQ:"Iraq",IR:"Iran",IS:"Iceland",IT:"Italy",JM:"Jamaica",JO:"Jordan",JP:"Japan",KE:"Kenya",KG:"Kyrgyzstan",KH:"Cambodia",KR:"South Korea",KW:"Kuwait",KZ:"Kazakhstan",LA:"Laos",LB:"Lebanon",LI:"Liechtenstein",LK:"Sri Lanka",LT:"Lithuania",LU:"Luxembourg",LV:"Latvia",LY:"Libya",MA:"Morocco",MC:"Principality of Monaco",MD:"Moldava",ME:"Montenegro",MK:"Former Yugoslav Republic of Macedonia",ML:"Mali",MM:"Myanmar",MN:"Mongolia",MO:"Macau S.A.R.",MT:"Malta",MV:"Maldives",MX:"Mexico",MY:"Malaysia",NG:"Nigeria",NI:"Nicaragua",NL:"Netherlands",NO:"Norway",NP:"Nepal",NZ:"New Zealand",OM:"Oman",PA:"Panama",PE:"Peru",PH:"Philippines",PK:"Islamic Republic of Pakistan",PL:"Poland",PR:"Puerto Rico",PT:"Portugal",PY:"Paraguay",QA:"Qatar",RE:"Reunion",RO:"Romania",RS:"Serbia",RU:"Russia",RW:"Rwanda",SA:"Saudi Arabia",SE:"Sweden",SG:"Singapore",SI:"Slovenia",SK:"Slovak",SN:"Senegal",SO:"Somalia",SR:"Suriname",SV:"El Salvador",SY:"Syria",TH:"Thailand",TJ:"Tajikistan",TM:"Turkmenistan",TN:"Tunisia",TR:"Turkey",TT:"Trinidad and Tobago",TW:"Taiwan",TZ:"Tanzania",UA:"Ukraine",US:"United States",UY:"Uruguay",VA:"Vatican",VE:"Venezuela",VN:"Viet Nam",YE:"Yemen",ZA:"South Africa",ZW:"Zimbabwe"},fL=/^[A-Z][A-Z0-9]*$/;function eo(e,t){if(!fL.test(e))return t.str`An IBAN consists of capital letters and numbers only`;if(e.length<4)return t.str`IBAN numbers have more that 4 digits`;if(e.length>34)return t.str`IBAN numbers have less that 34 digits`;let r=65,n=90,a=e.toUpperCase();if(!(a.substring(0,2)in dL))return t.str`IBAN country code not found`;let c=a.substring(4)+e.substring(0,4),u=Array.from(c).map(d=>{let w=d.charCodeAt(0);return wn?d:`${d.charCodeAt(0)-65+10}`}).join("");if(Jv(u)!==1)return t.str`IBAN number is not valid, checksum is wrong`}function Jv(e){let t=e.substring(0,5),r=e.substring(5),a=parseInt(t,10)%97;return r.length>0?Jv(`${a}${r}`):a}var pL=/^[a-zA-Z0-9\-\.\_\~]*$/;function to(e,t){if(!pL.test(e))return t.str`Use letters, numbers or any of these characters: - . _ ~`}Re();Be();Re();Be();function hL({challenge:e,onCancel:t,onSolved:r,username:n,expiration:a}){let{i18n:o}=Ne(),[s,c]=de(),{lib:{bank:u}}=De(),[f,d]=ht(),[w,R]=de(a!==void 0&&he.isExpired(a)),h=yv({code:s?void 0:o.str`Required`});Ge(()=>{if(w)return;let T=he.remaining(a).d_ms;if(T==="forever")return;let A=setTimeout(()=>{R(!0)},T);return()=>{clearTimeout(A)}},[]);let p=d(o.str`confirm MFA challenge`,T=>u.confirmChallenge(n,e.challenge_id,{tan:T}),h?void 0:[s]);return p.onFail=T=>{switch(T.case){case G.BANK_TRANSACTION_NOT_FOUND:return o.str`Unknown challenge.`;case l.Unauthorized:return o.str`Failed to validate the verification code.`;case l.TooManyRequests:return o.str`Too many challenges are active right now, you must wait or confirm current challenges.`;case G.BANK_TAN_CHALLENGE_FAILED:return o.str`Wrong authentication number.`;case G.BANK_TAN_CHALLENGE_EXPIRED:return o.str`Expired challenge.`;default:ue(T)}},p.onSuccess=r,i(ae,null,i(yt,{notification:f}),i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i("span",{class:"text-sm text-black font-semibold leading-6 ",id:"availability-label"},i(o.Translate,null,"Submit the transmitted code number."))),i("p",{class:"mt-2 text-sm text-gray-500"},(function(T){switch(T.tan_channel){case Sr.EMAIL:return i(o.Translate,null,"The verification code sent to the email address starting with ",i("b",null,'"',T.tan_info,'"'));case Sr.SMS:return i(o.Translate,null,"The verification code sent to the phone number ending with"," ",i("b",null,'"',T.tan_info,'"'))}})(e))),i("div",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"},i("div",{class:"px-4 mt-4 "},i("form",{class:"space-y-6",noValidate:!0,onSubmit:T=>{T.preventDefault()},autoCapitalize:"none",autoCorrect:"off"},i("div",null,i("label",{for:"username",class:"block text-sm font-medium leading-6 text-gray-900"},i(o.Translate,null,"Code")),i("div",{class:"mt-2"},i("input",{ref:or,type:"text",name:"username",id:"username",class:"block w-full disabled:bg-gray-200 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",value:s??"",enterkeyhint:"next",placeholder:"T-12345678",autocomplete:"username",title:o.str`Username of the account`,required:!0,onInput:T=>{c(T.currentTarget.value)}}),i(nt,{message:h?.code,isDirty:s!==void 0})))),a.t_ms==="never"?void 0:i("p",{class:"text-gray-400 text-sm mt-2"},i(o.Translate,null,"It will expired at"," ",i(ln,{format:"HH:mm",timestamp:a}))),w?i("p",{class:"text-sm"},i(o.Translate,null,"The challenge is expired and can't be solved but you can go back and create a new challenge.")):void 0,i("div",{class:"mt-6 mb-4 flex justify-between"},i("button",{type:"button",name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900",onClick:t},i(o.Translate,null,"Back")),i(Ze,{type:"submit",name:"send again",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:p},i(o.Translate,null,"Verify")))))))}function Er({currentChallenge:e,username:t,description:r,onCompleted:n,onCancel:a}){let{i18n:o}=Ne(),[s,c]=de([]),[u,f]=de(),[d,w]=ht(),{lib:{bank:R}}=De(),[h,p]=de({});if(u)return i(hL,{onCancel:()=>f(void 0),challenge:u.ch,expiration:u.expiration,username:t,onSolved:()=>{f(void 0);let v=[...s,u.ch.challenge_id];(e.combi_and?v.length===e.challenges.length:v.length>0)?n.withArgs(v).call():c(v)}});let T=e.challenges.filter(({challenge_id:v})=>s.indexOf(v)!==-1),A=e.combi_and?T.length===e.challenges.length:T.length>0,C=w(o.str`send MFA challenge`,v=>R.sendChallenge(t,v.challenge_id));C.onSuccess=(v,_)=>{v.earliest_retransmission&&p({...h,[_.challenge_id]:he.fromProtocolTimestamp(v.earliest_retransmission)}),f({ch:_,expiration:v.solve_expiration?he.fromProtocolTimestamp(v.solve_expiration):he.never()})},C.onFail=v=>{switch(v.case){case l.Unauthorized:return o.str`Failed to send the verification code.`;case l.Forbidden:return o.str`The request was valid, but the server is refusing action.`;case l.NotFound:return o.str`The backend is not aware of the specified MFA challenge.`;case l.TooManyRequests:return o.str`It is too early to request another transmission of the challenge.`;case G.BANK_TAN_CHANNEL_SCRIPT_FAILED:return o.str`Code transmission failed.`;default:ue(v)}};let S=n.withArgs(s),k=w(o.str`select challenge`,async v=>(f({ch:v,expiration:he.never()}),ke()));return k.onFail=v=>{},i(ae,null,i(yt,{notification:d}),i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i("span",{class:"text-sm text-black font-semibold leading-6 ",id:"availability-label"},i(o.Translate,null,"Multi-factor authentication required"))),i("p",{class:"mt-2 text-sm text-gray-500"},i(o.Translate,null,"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided."))),i("div",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"},i("div",{class:"px-4 mt-4 "},i("div",{class:"w-full"},i("div",{class:"border-gray-100"},i("h2",{class:"text-base font-semibold leading-10 text-gray-900"},i("span",{class:" text-black font-semibold leading-6 "},r)))),i("h2",{class:"text-base leading-7 text-gray-900 "},i("span",{class:"text-sm leading-6 ",id:"availability-label"},e.challenges.length===1?i(o.Translate,null,"The next challenge needs to be completed to confirm the operation."):e.combi_and?i(o.Translate,null,"All the next challenges need to be completed to confirm the operation."):i(o.Translate,null,"One of the next challenges need to be completed to confirm the operation."))),e.challenges.map(v=>{let _=h[v.challenge_id]??he.now(),g=!he.isExpired(_),O=A||s.indexOf(v.challenge_id)!==-1,E=O?k:k.withArgs(v),m=g||O?C:C.withArgs(v);return i("div",{class:"rounded-xl border px-2 my-2"},i("dl",{class:"divide-y divide-gray-100"},i("div",{class:"px-4 py-2 sm:grid sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},(y=>{switch(y){case Sr.SMS:return i(o.Translate,null,'To an phone ending with "',v.tan_info,'"');case Sr.EMAIL:return i(o.Translate,null,'To an email starting with "',v.tan_info,'"')}})(v.tan_channel)),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:mt-0"},i("div",{class:"flex justify-between"},i(Ze,{type:"button",name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900",onClick:E},i(o.Translate,null,"I have a code")),i(Ze,{type:"submit",name:"send again",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:m},i(o.Translate,null,"Send me a message")))),g&&_.t_ms!=="never"?i("p",{class:"text-sm text-gray-600"},i(o.Translate,null,"You have to wait until"," ",i(ln,{format:"HH:mm",timestamp:_})," to send a new code.")):void 0)))}),i("div",{class:"mt-6 mb-4 flex justify-between"},i("button",{type:"button",name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900",onClick:a},i(o.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"send again",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:S},i(o.Translate,null,"Complete")))))))}Re();Be();Be();var cp=eu;function ro(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="getAccount",void 0,{revalidate:!0})}function $r(e){let{state:t}=We(),{lib:{bank:r}}=De();async function n([c,u]){return await r.getAccount({username:c,token:u})}let a=t.status!=="loggedIn"?void 0:t.token,{data:o,error:s}=cp([e,a,"getAccount"],n,{});if(o)return o;if(s)return s}function tu(e){let{lib:{bank:t}}=De(),r=gv(e===void 0?void 0:()=>t.getWithdrawalById(e,void 0));return _v(r,a=>{if(!a||a instanceof Oe||a.type==="fail")return!1;let{status:o}=a.body;return o==="pending"||o==="selected"},async(a,o)=>!o||o instanceof Oe||o.type==="fail"||o.body.status==="confirmed"||o.body.status==="aborted"?void 0:await t.getWithdrawalById(e,{old_state:o.body.status,timeoutMs:5e3,ct:a}),[e])}async function up(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="getPublicAccounts",void 0,{revalidate:!0})}function eE(e,t){let[r,n]=de(t),{lib:{bank:a}}=De();async function o([u,f]){return await a.getPublicAccounts({account:u},{limit:Un,offset:f?String(f):void 0,order:"asc"})}let{data:s,error:c}=cp([e,r,"getPublicAccounts"],o,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(c)return c;if(s!==void 0)return no(s.body.public_accounts,r,n,u=>u.row_id??0)}function no(e,t,r,n){let a=e.length{if(!s.length)return;let c=n(s[s.length-1]);r(c)},loadFirst:o?void 0:()=>{r(void 0)}}}function ao(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="getTransactions",void 0,{revalidate:!0})}function tE(e,t){let{state:r}=We(),n=r.status!=="loggedIn"?void 0:r.token,[a,o]=de(t),{lib:{bank:s}}=De();async function c([d,w,R]){return await s.getTransactions({username:d,token:w},{limit:Un,offset:R?String(R):void 0,order:"dec"})}let{data:u,error:f}=cp([e,n,a,"getTransactions"],c,{refreshInterval:1e4,refreshWhenHidden:!1,refreshWhenOffline:!1,revalidateIfStale:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,shouldRetryOnError:!0});if(f)return f;if(u!==void 0)return u.type!=="ok"?u:no(u.body.transactions,a,o,d=>d.row_id)}Be();var Mn=eu;function lp(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="getConversionInfoAPI")}function Lr(){let{lib:{conversion:e},config:t}=De();async function r(){return await e.getConfig()}let{data:n,error:a}=Mn(t.allow_conversion?["getConversionInfoAPI"]:void 0,r,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(n)return n;if(a)return a}function nE(e,t){let{lib:{conversionForUser:r},config:n}=De();async function a(){return await r(e).getRate(t!=null?{type:"bearer",token:t}:void 0)}let{data:o,error:s}=Mn(n.allow_conversion?["useConversionInfoForUser"]:void 0,a,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(o)return o;if(s)return s}function rE(e,t,r){return async(n,a)=>{let o=t!=null?{type:"bearer",token:t}:void 0,s;switch(r){case"cashin-rate-from-credit":{s=await e.getCashinRate(o,{credit:n});break}case"cashin-rate-from-debit":{s=await e.getCashinRate(o,{debit:n});break}case"cashout-rate-from-credit":{s=await e.getCashoutRate(o,{credit:n});break}case"cashout-rate-from-debit":{s=await e.getCashoutRate(o,{debit:n});break}default:ue(r)}if(s.type==="fail")return s;let c=J.parseOrThrow(s.body.amount_credit),u=J.parseOrThrow(s.body.amount_debit),f=J.add(c,a).amount;return Ke({debit:u,beforeFee:f,credit:c})}}function ti(e,t){let{state:r}=We(),n=r.status==="loggedIn"?r.token:void 0;return{estimateByCredit:rE(e,n,t=="cashin"?"cashin-rate-from-credit":"cashout-rate-from-credit"),estimateByDebit:rE(e,n,t=="cashin"?"cashin-rate-from-debit":"cashout-rate-from-debit")}}function aE(){let{lib:{conversion:e}}=De();return ti(e,"cashin")}function oE(){let{lib:{conversion:e}}=De();return ti(e,"cashout")}function iE(e){let{lib:{conversionForClass:t}}=De();return ti(t(e),"cashin")}function sE(e){let{lib:{conversionForClass:t}}=De();return ti(t(e),"cashout")}function cE(e){let{lib:{conversionForUser:t}}=De();return ti(t(e),"cashout")}async function dp(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="listAccounts",void 0,{revalidate:!0})}function uE(){let{state:e}=We(),t=e.status!=="loggedIn"?void 0:e.token,{lib:{bank:r}}=De(),[n,a]=de();function o([u,f]){return r.listAccounts(u,{limit:Un,offset:f?String(f):void 0,order:"asc"})}let{data:s,error:c}=Mn([t,n??0,"listAccounts"],o,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(c)return c;if(s!==void 0)return s.type!=="ok"?s:no(s.body.accounts,n,a,u=>u.row_id??0)}function mL(e){return e!==void 0}function fp(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="useCashouts")}function lE(e){let{state:t}=We(),{lib:{bank:r},config:n}=De(),a=t.status!=="loggedIn"?void 0:t.token;async function o([u,f]){let d=await r.getAccountCashouts({username:u,token:f});if(d.type!=="ok")return d;let R=(await Promise.all(d.body.cashouts.map(async h=>{let p=await r.getCashoutById({username:u,token:f},h.cashout_id);if(p.type!=="fail")return{...p.body,id:h.cashout_id}}))).filter(mL);return Ke({cashouts:R})}let{data:s,error:c}=Mn(n.allow_conversion?[e,a,"useCashouts"]:void 0,o,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(s)return s;if(c)return c}function dE(e){let{state:t}=We(),r=t.status!=="loggedIn"?void 0:t,{lib:{bank:n}}=De();async function a([c,u,f]){return n.getCashoutById({username:c,token:u},f)}let{data:o,error:s}=Mn(e===void 0?void 0:[r?.username,r?.token,e,"getCashoutById"],a,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(o)return o;if(s)return s}function fE(e,t,r){let{lib:{bank:n}}=De(),{state:a}=We(),o=a.status!=="loggedIn"?void 0:a.token;async function s([f,d]){let[w,R]=await Promise.all([n.getMonitor(f,{timeframe:d,date:e}),n.getMonitor(f,{timeframe:d,date:t})]);return{current:w,previous:R}}let{data:c,error:u}=Mn(o?[o,r,"useLastMonitorInfo"]:void 0,s,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(c)return c;if(u)return u}function pE(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="useConversionRateClasses",void 0,{revalidate:!0})}function hE(){let{state:e}=We(),t=e.status!=="loggedIn"?void 0:e.token,{lib:{bank:r}}=De(),[n,a]=de();function o([u,f]){return r.listConversionRateClasses(u,{limit:Un,offset:f?String(f):void 0,order:"asc"})}let{data:s,error:c}=Mn([t,n??0,"useConversionRateClasses"],o,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(c)return c;if(s!==void 0)return s.type!=="ok"?s:no(s.body.classes,n,a,u=>u.conversion_rate_class_id)}function ri(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="useConversionRateClassDetails",void 0,{revalidate:!0})}function mE(e){let{state:t}=We(),r=t.status!=="loggedIn"?void 0:t.token,{lib:{bank:n}}=De();async function a([c,u]){return await n.getConversionRateClass(u,c)}let{data:o,error:s}=Mn([e,r,"useConversionRateClassDetails"],a,{});if(o)return o;if(s)return s}function pp(){return vr(e=>Array.isArray(e)&&e[e.length-1]==="useConversionRateClassUsers",void 0,{revalidate:!0})}function gE(e,t){let{state:r}=We(),n=r.status!=="loggedIn"?void 0:r.token,{lib:{bank:a}}=De(),[o,s]=de();function c([d,w,R,h]){return a.listAccounts(d,{limit:Un,offset:w?String(w):void 0,order:"asc",account:R,conversionRateId:h})}let{data:u,error:f}=Mn([n,o??0,t,e,"useConversionRateClassUsers"],c,{refreshInterval:0,refreshWhenHidden:!1,revalidateOnFocus:!1,revalidateOnReconnect:!1,refreshWhenOffline:!1,errorRetryCount:0,errorRetryInterval:1,shouldRetryOnError:!1,keepPreviousData:!0});if(f)return f;if(u!==void 0)return u.type!=="ok"?u:no(u.body.accounts,o,s,d=>d.row_id)}var gL=gt(xn(32));function ru({account:e,onCashout:t,focus:r,routeClose:n}){let{i18n:a}=Ne(),{config:o}=De();if(!o.allow_conversion)return i(ae,null,i(Pe,{type:"warning",title:a.str`Unable to create a cashout`},i(a.Translate,null,"The bank configuration does not support cashout operations.")),i("div",{class:"mt-5 sm:mt-6"},i("a",{href:n.url({}),name:"close",class:"inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(a.Translate,null,"Close"))));let s=$r(e),{state:c}=We(),u=c.status!=="loggedIn"?void 0:c,f=nE(e,u?.token),d=Lr();if(s){if(s instanceof Oe)return i(_t,{error:s});if(s.type==="fail")switch(s.case){case l.Unauthorized:return i(er,{currentUser:e});case l.NotFound:return i(er,{currentUser:e});default:ue(s)}}else return i(st,null);if(d){if(d instanceof Oe)return i(_t,{error:d});if(d.type==="fail"){if(d.case===l.NotImplemented)return i(Pe,{type:"danger",title:a.str`Cashout is disabled`},i(a.Translate,null,"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));ue(d)}}else return i(st,null);if(f){if(f instanceof Oe)return i(_t,{error:f});if(f.type==="fail"){if(f.case===l.NotImplemented)return i(Pe,{type:"danger",title:a.str`Cashout is disabled`},i(a.Translate,null,"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));ue(f)}}else return i(st,null);return f.body?u?i(_L,{accountData:s.body,account:e,onCashout:t,routeClose:n,focus:r,convConfig:d.body,rate:f.body,session:u}):i("div",null,"authentication required"):i("div",null,"conversion enabled but server replied without conversion_rate")}function _L({onCashout:e,account:t,accountData:r,focus:n,routeClose:a,convConfig:{fiat_currency:o,fiat_currency_specification:s,regional_currency:c,regional_currency_specification:u},session:f,rate:d}){let{estimateByCredit:w,estimateByDebit:R}=cE(t),[h,p]=de({isDebit:!0}),[T,A]=ht(),C=br(),{i18n:S}=Ne(),{lib:{bank:k}}=De(),v=J.zeroOfCurrency(c),_=J.zeroOfCurrency(o),g={balance:J.parseOrThrow(r.balance.amount),balanceIsDebit:r.balance.credit_debit_indicator=="debit",debitThreshold:J.parseOrThrow(r.debit_threshold)},O=wn.toIntAmount(g.balance,g.balanceIsDebit).increment(g.debitThreshold),E={debit:v,credit:_,beforeFee:_},[m,y]=de(E),b=J.parseOrThrow(d.cashout_fee),x=d.cashout_ratio,D=J.parseOrThrow(`${h.isDebit?c:o}:${h.amount?h.amount:"0"}`),F=h.isDebit?J.cmp(D,d.cashout_min_amount)>=0:!0,B=J.isNonZero(D),K=A(S.str`calculate conversion fee`,async(M,q,Y)=>B&&F?M?R(q,Y):w(q,Y):Ke(E),[h.isDebit??!1,D,b]);K.onSuccess=M=>y(M),K.onFail=M=>{switch(M.case){case l.BadRequest:return S.str`The server didn't understand the request.`;case l.Conflict:return S.str`The amount is too small`;case l.NotImplemented:return S.str`Conversion is not implemented.`;case G.GENERIC_PARAMETER_MISSING:return S.str`At least debit or credit needs to be provided`;case G.GENERIC_PARAMETER_MALFORMED:return S.str`The amount is malfored`;case G.GENERIC_CURRENCY_MISMATCH:return S.str`The currency is not supported`;default:ue(M)}},Ge(()=>{K.call()},[h.amount,h.isDebit,B,F,d.cashout_fee]);let Z=m||E,pe=wn.toIntAmount(g.balance,g.balanceIsDebit).deduce(Z.debit).result;function Ie(M){p(M)}let be=Ht({subject:h.subject?void 0:S.str`Required`,amount:h.amount?D?m?J.isZero(O.deduce(m.debit).getResultZeroIfNegative())?S.str`Balance is not enough`:J.cmp(m.debit,d.cashout_min_amount)<0?S.str`It is not possible to cashout less than ${J.stringifyValueWithSpec(J.parseOrThrow(d.cashout_min_amount),u).normal}: ${J.stringify(m.debit)}`:J.isZero(m.credit)?S.str`The total transfer to the destination will be zero`:void 0:S.str`Amount needs to be higher`:S.str`Invalid`:S.str`Required`}),xe=h.amount?.trim(),Le=h.subject,Ue=A(S.str`create cashout`,(M,q,Y)=>k.createCashout(f,{request_uid:gL,amount_credit:J.stringify(M.credit),amount_debit:J.stringify(M.debit),subject:q},{challengeIds:Y}),be||!Le?void 0:[Z,Le,[]]);Ue.onSuccess=M=>{pr(S.str`Cashout created`),e()},Ue.onFail=M=>{switch(M.case){case l.Accepted:return C.onChallengeRequired(M.body),S.str`Second factor authentication required.`;case l.NotFound:return S.str`Account not found`;case G.BANK_TRANSFER_REQUEST_UID_REUSED:return S.str`Duplicated request detected, check if the operation succeeded or try again.`;case G.BANK_BAD_CONVERSION:return S.str`The conversion rate was applied incorrectly`;case G.BANK_UNALLOWED_DEBIT:return S.str`The account does not have sufficient funds`;case l.NotImplemented:return S.str`Cashout is disabled`;case G.BANK_CONFIRM_INCOMPLETE:return S.str`Missing cashout URI in the profile`;case G.BANK_CONVERSION_AMOUNT_TO_SMALL:return S.str`The amount is below the minimum amount permitted.`;case G.BANK_TAN_CHANNEL_SCRIPT_FAILED:return S.str`Sending the confirmation message failed, retry later or contact the administrator.`;case G.BANK_TAN_CHANNEL_NOT_SUPPORTED:return S.str`The server doesn't support the current TAN channel.`;default:ue(M)}};let Ve=Ue.lambda(M=>[Ue.args[0],Ue.args[1],M]),te=!r.cashout_payto_uri,ee=r.cashout_payto_uri?$e.fromString(r.cashout_payto_uri):void 0,$=!ee||ee.tag==="error"?void 0:ee.value.displayName,H=!ee||ee.tag==="error"?void 0:ee.value.params["receiver-name"];return C.pendingChallenge?i(Er,{currentChallenge:C.pendingChallenge,username:r.name,description:S.str`Create cashout.`,onCancel:C.doCancelChallenge,onCompleted:Ve}):i("div",null,i(yt,{notification:T}),i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("section",{class:"mt-4 rounded-sm px-4 py-6 p-8 "},i("h2",{id:"summary-heading",class:"font-medium text-lg"},i(S.Translate,null,"Cashout")),i("dl",{class:"mt-4 space-y-4"},i("div",{class:"justify-between items-center flex"},i("dt",{class:"text-sm text-gray-600"},i(S.Translate,null,"Conversion rate")),i("dd",{class:"text-sm text-gray-900"},x)),i("div",{class:"flex items-center justify-between border-t-2 afu pt-4"},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(S.Translate,null,"Balance"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:g.balance,negative:g.balanceIsDebit,withSign:!0,spec:u}))),i("div",{class:"flex items-center justify-between border-t-2 afu pt-4"},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(S.Translate,null,"Fee"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:b,negative:!0,withSign:!0,spec:s}))),$&&H?i(ae,null,i("div",{class:"flex items-center justify-between border-t-2 afu pt-4"},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(S.Translate,null,"To account"))),i("dd",{class:"text-sm text-gray-900"},$)),i("div",{class:"flex items-center justify-between border-t-2 afu pt-4"},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(S.Translate,null,"Legal name"))),i("dd",{class:"text-sm text-gray-900"},H)),i("p",{class:"mt-2 text-sm text-gray-500"},i(S.Translate,null,"If this name doesn't match the account holder's name, your transaction may fail."))):i("div",{class:"flex items-center justify-between border-t-2 afu pt-4"},i(Pe,{type:"warning",title:S.str`Unable to cashout`},i(S.Translate,null,"Before being able to cashout to a bank account, you need to complete your profile"))))),i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:M=>{M.preventDefault()}},i("div",{class:"px-4 py-6 sm:p-8"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"subject"},S.str`Transfer subject`,i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("input",{ref:n?or:void 0,type:"text",class:"block w-full rounded-md disabled:bg-gray-200 border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"subject",id:"subject",disabled:te,"data-error":!!be?.subject&&h.subject!==void 0,value:h.subject??"",onChange:M=>{h.subject=M.currentTarget.value,Ie(structuredClone(h))},autocomplete:"off"}),i(nt,{message:be?.subject,isDirty:h.subject!==void 0}))),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"subject"},S.str`Currency`),i("div",{class:"mt-2"},i("button",{type:"button",name:"set 50",class:" inline-flex p-4 text-sm items-center rounded-l-md bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10",onClick:M=>{M.preventDefault(),h.isDebit=!0,Ie(structuredClone(h))}},h.isDebit?i("svg",{class:"self-center flex-none h-5 w-5 text-indigo-600",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"})):i("svg",{fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"w-5 h-5"},i("path",{d:"M15 12H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"})),i(S.Translate,null,"Send ",c)),i("button",{type:"button",name:"set 25",class:" -ml-px -mr-px inline-flex p-4 text-sm items-center rounded-r-md bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10",onClick:M=>{M.preventDefault(),h.isDebit=!1,Ie(structuredClone(h))}},h.isDebit?i("svg",{fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"w-5 h-5"},i("path",{d:"M15 12H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"})):i("svg",{class:"self-center flex-none h-5 w-5 text-indigo-600",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"})),i(S.Translate,null,"Receive ",o)))),i("div",{class:"sm:col-span-5"},i("div",{class:"flex justify-between"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"amount"},S.str`Amount`,i("b",{class:"text-[red]"}," *"))),i("div",{class:"mt-2"},i(Fr,{name:"amount",left:!0,currency:h.isDebit?c:o,value:xe,onChange:te?void 0:M=>{h.amount=M,Ie(structuredClone(h))}}),i(nt,{message:be?.amount,isDirty:h.amount!==void 0}))),J.isZero(Z.credit)?void 0:i("div",{class:"sm:col-span-5"},i("dl",{class:"mt-4 space-y-4"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(S.Translate,null,"Total cost")),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:Z.debit,negative:!0,withColor:!0,spec:u}))),i("div",{class:"flex items-center justify-between border-t-2 afu pt-4"},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(S.Translate,null,"Balance left"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:pe,negative:pe.negative,withSign:!0,spec:u}))),J.isZero(b)||J.isZero(Z.beforeFee)?void 0:i("div",{class:"flex items-center justify-between border-t-2 afu pt-4"},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(S.Translate,null,"Before fee"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:Z.beforeFee,spec:s}))),i("div",{class:"flex justify-between items-center border-t-2 afu pt-4"},i("dt",{class:"text-lg text-gray-900 font-medium"},i(S.Translate,null,"Total cashout transfer")),i("dd",{class:"text-lg text-gray-900 font-medium"},i(Xe,{value:Z.credit,withColor:!0,spec:s}))))))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{href:a.url({}),name:"cancel",type:"button",class:"text-sm font-semibold leading-6 text-gray-900"},i(S.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"cashout",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:Ue},i(S.Translate,null,"Cashout"))))))}var wn=class e{constructor(t,r=!1,n=!1){this.result={...t,negative:r,saturated:n}}static from(t){return new e(t,t.negative,t.saturated)}static toIntAmount(t,r=!1){return new e(t,r)}getResultZeroIfNegative(){return this.result.negative?e.toIntAmount(J.zeroOfCurrency(this.result.currency)).result:this.result}merge(t){return t.negative?this.deduce(t):this.increment(t)}deduce(t){if(this.result.negative){let{amount:r,saturated:n}=J.add(this.result,t);return e.from({...r,saturated:n,negative:!0})}else{let r=J.cmp(this.result,t)<0,{amount:n,saturated:a}=r?J.sub(t,this.result):J.sub(this.result,t);return e.from({...n,negative:r,saturated:a})}}increment(t){if(this.result.negative){let r=J.cmp(this.result,t)>0,{amount:n,saturated:a}=r?J.sub(this.result,t):J.sub(t,this.result);return e.from({...n,negative:r,saturated:a})}else{let{amount:r,saturated:n}=J.add(this.result,t);return e.from({...r,saturated:n,negative:!1})}}};function nu({focus:e,withAccount:t,withSubject:r,withAmount:n,onSuccess:a,routeCancel:o,routeCashout:s,limit:c,balance:u}){let[f,d]=de("form"),w=f!=="form",{state:R}=We(),{lib:{bank:h},config:p,url:T}=De(),A=t!==void 0,[C,S]=de(t),[k,v]=de(r),[_,g]=de(n),[O,E]=de(void 0),{i18n:m}=Ne(),y=p.wire_transfer_fees===void 0?J.zeroOfCurrency(p.currency):J.parseOrThrow(p.wire_transfer_fees),b=_?.trim(),x=wn.from(c).deduce(y).getResultZeroIfNegative(),D=J.parse(`${x.currency}:${b}`),[F,B]=ht(),K=br(),Z=p.wire_type==="X_TALER_BANK"?"x-taler-bank":"iban",pe=Ht({account:C?Z==="iban"?eo(C,m):Z==="x-taler-bank"?to(C,m):void 0:m.str`Required`,subject:k?yE(k,m):m.str`Required`,amount:b?D?_E(D,x,m):m.str`Not valid`:m.str`Required`}),Ie=EL(O),be=Ie?$e.fromString(Ie):void 0,xe=Ht({rawPaytoInput:O?!be||be.tag==="error"?m.str`Does not follow the pattern`:yL(be.value,x,T.host,m,Z):m.str`Required`}),Le,Ue;if(w){let $=$e.fromString(O);$&&$.tag==="ok"&&(Le=$.value,Ue=Le.params.amount,delete Le.params.amount)}else if(C&&k){switch(Z){case"x-taler-bank":{Le=$e.createTalerBank(T.href,C);break}case"iban":{Le=$e.createIban(C,void 0);break}default:ue(Z)}Le.params.message=k,Ue=`${x.currency}:${b}`}let Ve=Ue,te=B(m.str`send transaction`,($,H,M,q)=>h.createTransaction($,{payto_uri:$e.toFullString(M),amount:H},{challengeIds:q}),(w?xe:pe)||!Ve||!Le||R.status!=="loggedIn"?void 0:[R,Ve,Le,[]]);te.onSuccess=$=>{pr(m.str`The wire transfer was successfully completed!`),a(),g(void 0),S(void 0),v(void 0),E(void 0)},te.onFail=($,H,M,q)=>{switch($.case){case l.BadRequest:return m.str`The request was invalid or the payto://-URI used unacceptable features.`;case l.Unauthorized:return m.str`Not enough permission to complete the operation.`;case G.BANK_ADMIN_CREDITOR:return m.str`The bank administrator cannot be the transfer creditor.`;case G.BANK_UNKNOWN_CREDITOR:return m.str`The destination account "${q.displayName}" was not found.`;case G.BANK_SAME_ACCOUNT:return m.str`The origin and the destination of the transfer can't be the same.`;case G.BANK_UNALLOWED_DEBIT:return m.str`Your balance is not sufficient for the operation.`;case l.NotFound:return m.str`The origin account "${q.displayName}" was not found.`;case G.BANK_TRANSFER_REQUEST_UID_REUSED:return m.str`The attempt to create the transaction has failed. Please try again.`;case l.Accepted:return K.onChallengeRequired($.body),m.str`A second factor authentication is required.`;default:ue($)}};let ee=te.lambda($=>[te.args[0],te.args[1],te.args[2],$]);return K.pendingChallenge?i(Er,{currentChallenge:K.pendingChallenge,description:m.str`Confirm wire transfer.`,onCancel:K.doCancelChallenge,username:te.args[0].username,onCompleted:ee}):i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 my-4 md:grid-cols-3 bg-gray-100 px-4 pb-4 rounded-lg"},i("div",null,i("fieldset",{class:"px-2 grid grid-cols-1 gap-y-4 sm:gap-x-4"},i("legend",{class:"sr-only"},i(m.Translate,null,"Input wire transfer detail")),i("div",{class:"-space-y-px rounded-md "},i("label",{"data-checked":f==="form",class:"group rounded-tl-md rounded-tr-md relative flex cursor-pointer border p-4 focus:outline-none bg-white data-[checked=true]:z-10 data-[checked=true]:border-indigo-200 data-[checked=true]:bg-indigo-50"},i("input",{type:"radio",name:"input-type",onChange:()=>{if(be&&be.tag==="ok"){switch(be.value.targetType){case Je.Ethereum:case Je.Bitcoin:case void 0:case Je.TalerReserve:case Je.TalerReserveHttp:break;case Je.IBAN:{S(be.value.iban);break}case Je.TalerBank:{S(be.value.account);break}case Je.Cyclos:{S(be.value.account);break}default:ue(be.value)}let $=be.value.params?be.value.params.amount:void 0;if($){let M=J.parse($);M&&g(J.stringifyValue(M))}let H=be.value.params.message?be.value.params.message:be.value.params.subject;H&&v(H)}d("form")},checked:f==="form",value:"form",class:"mt-0.5 h-4 w-4 shrink-0 cursor-pointer text-indigo-600 border-gray-300 focus:ring-indigo-600 active:ring-2 active:ring-offset-2 active:ring-indigo-600"}),i("span",{class:"ml-3 flex flex-col"},i("span",{"data-checked":f==="form",class:"block text-sm font-medium data-[checked=true]:text-indigo-900"},i(m.Translate,null,"Using a form")))),A?void 0:i(ae,null,i("label",{"data-checked":f==="payto",class:"relative flex cursor-pointer border p-4 focus:outline-none bg-white data-[checked=true]:z-10 data-[checked=true]:border-indigo-200 data-[checked=true]:bg-indigo-50"},i("input",{type:"radio",name:"input-type",onChange:()=>{if(C){let $;switch(Z){case"x-taler-bank":{$=$e.createTalerBank(T.href,C),D&&($.params.amount=J.stringify(D)),k&&($.params.message=k);break}case"iban":{$=$e.createIban(C,void 0),D&&($.params.amount=J.stringify(D)),k&&($.params.message=k);break}default:ue(Z)}E($e.toFullString($))}d("payto")},checked:f==="payto",value:"payto",class:"mt-0.5 h-4 w-4 shrink-0 cursor-pointer text-indigo-600 border-gray-300 focus:ring-indigo-600 active:ring-2 active:ring-offset-2 active:ring-indigo-600"}),i("span",{class:"ml-3 flex flex-col"},i("span",{"data-checked":f==="payto",class:"block font-medium data-[checked=true]:text-indigo-900"},"payto:// URI"),i("span",{"data-checked":f==="payto",class:"block text-sm text-gray-500 data-[checked=true]:text-indigo-600"},i(m.Translate,null,"A special URI that specifies the amount to be transferred and the destination account.")))),!1)),s&&p.allow_conversion?i("a",{name:"do cashout",href:s.url({}),class:"bg-white p-4 rounded-lg text-sm font-semibold leading-6 text-gray-900"},i(m.Translate,null,"Cashout")):void 0)),i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 rounded-md sm:rounded-xl md:col-span-2 w-fit mx-auto",autoCapitalize:"none",autoCorrect:"off",onSubmit:$=>{$.preventDefault()}},i("div",{class:"m-4"},w?i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6 w-full"},i("div",{class:"sm:col-span-6"},i("label",{for:"address",class:"block text-sm font-medium leading-6 text-gray-900"},m.str`Payto URI:`,i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("textarea",{ref:e?or:void 0,name:"address",id:"address",type:"textarea",rows:5,class:"block overflow-hidden w-44 sm:w-96 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",value:O??"",required:!0,title:m.str`Uniform resource identifier of the target account`,placeholder:(()=>{switch(Z){case"x-taler-bank":return m.str`payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[${x.currency}:X.Y]`;case"iban":return m.str`payto://iban/[receiver-iban]?message=[subject]&amount=[${x.currency}:X.Y]`}})(),onInput:$=>{E($.currentTarget.value)}}),i(nt,{message:xe?.rawPaytoInput,isDirty:O!==void 0})))):i("div",{class:"grid max-w-xs grid-cols-1 gap-x-6 gap-y-8 "},(()=>{switch(Z){case"x-taler-bank":return i(ni,{id:"x-taler-bank",required:!0,label:m.str`Recipient`,help:m.str`ID of the recipient's account`,error:pe?.account,onChange:S,value:C,placeholder:m.str`username`,focus:e,disabled:A});case"iban":return i(ni,{id:"iban",required:!0,label:m.str`Recipient`,help:m.str`IBAN of the recipient's account`,placeholder:"CC0123456789",error:pe?.account,onChange:$=>S($.toUpperCase()),value:C,focus:e,disabled:A});default:ue(Z)}})(),i("div",{class:"sm:col-span-5"},i("label",{for:"subject",class:"block text-sm font-medium leading-6 text-gray-900"},m.str`Transfer subject`,i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("textarea",{type:"textarea",rows:3,class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"subject",id:"subject",autocomplete:"off",placeholder:m.str`Subject`,value:k??"",required:!0,onInput:$=>{v($.currentTarget.value)}}),i(nt,{message:pe?.subject,isDirty:k!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(m.Translate,null,"Some text to identify the transfer"))),i("div",{class:"sm:col-span-5"},i("label",{for:"amount",class:"block text-sm font-medium leading-6 text-gray-900"},m.str`Amount`,i("b",{class:"text-[red]"}," *")),i(Fr,{name:"amount",left:!0,currency:x.currency,value:b,onChange:$=>{g($)}}),i(nt,{message:pe?.amount,isDirty:b!==void 0}),i("p",{class:"mt-2 text-sm text-gray-500"},i(m.Translate,null,"Amount to transfer")))),J.isNonZero(x)?i("p",{class:"mt-2 text-sm text-gray-900"},i(m.Translate,null,"The maximum amount for a wire transfer is"," ",i(Xe,{value:x,spec:p.currency_specification}))):void 0),J.isZero(y)?void 0:i("div",{class:"px-4 my-4"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-6"},i("dl",{class:"mt-4 space-y-4"},i(ae,null,i("div",{class:"flex items-center justify-between "},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(m.Translate,null,"Cost"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:y,negative:!0,withColor:!0,spec:p.currency_specification})))))))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},o?i("a",{name:"cancel",href:o.url({}),class:"text-sm font-semibold leading-6 text-gray-900"},i(m.Translate,null,"Cancel")):i("div",null),i(Ze,{type:"submit",name:"send",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:te},i(m.Translate,null,"Send"))),i(yt,{notification:F})))}function or(e){e&&setTimeout(()=>{e.focus({preventScroll:!0}),e.scrollIntoView({behavior:"smooth",block:"center",inline:"center"})},100)}function Fr({currency:e,name:t,value:r,left:n,placeholder:a,onChange:o},s){let{config:c}=De();return i("div",{class:"mt-2"},i("div",{class:"flex rounded-md shadow-sm border-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600"},i("div",{class:"pointer-events-none inset-y-0 flex items-center px-3"},i("span",{class:"text-gray-500 sm:text-sm"},e)),i("input",{type:"number","data-left":n,class:"disabled:bg-gray-200 text-right rounded-md rounded-l-none data-[left=true]:text-left w-full py-1.5 pl-3 text-gray-900 placeholder:text-gray-400 sm:text-sm sm:leading-6",placeholder:a??"0.00","aria-describedby":"price-currency",ref:s,name:t,id:t,autocomplete:"off",value:r??"",disabled:!o,onInput:u=>{if(!o)return;let f=u.currentTarget.value.length,d=u.currentTarget.value.indexOf(Gn);d!==-1&&f-d-1>c.currency_specification.num_fractional_input_digits&&(u.currentTarget.value=u.currentTarget.value.substring(0,d+c.currency_specification.num_fractional_input_digits+1)),o(u.currentTarget.value)}})))}function yL(e,t,r,n,a){let o;switch(a){case"x-taler-bank":{if(e.targetType!=="x-taler-bank")return n.str`Only "x-taler-bank" target are supported`;if(e.host!==r)return n.str`Only this host is allowed. Use "${r}"`;if(!e.account)return n.str`Account name is missing`;let c=to(e.account,n);if(c)return c;break}case"iban":{if(e.targetType!=="iban")return n.str`Only "IBAN" target are supported`;let c=eo(e.iban,n);if(c)return c;break}default:ue(a)}if(!e.params.amount)return n.str`Missing "amount" parameter to specify the amount to be transferred`;let s=J.parse(e.params.amount);if(!s)return n.str`The "amount" parameter is not valid`;if(o=_E(s,t,n),o)return o;if(!e.params.message)return n.str`"message" parameters to specify a reference text for the transfer are missing`;if(o=yE(e.params.message,n),o)return o}function _E(e,t,r){if(e.currency!==t.currency)return r.str`The only currency allowed is "${t.currency}"`;if(J.isZero(e))return r.str`You cannot transfer an amount of zero.`;if(J.cmp(t,e)===-1)return r.str`The balance is not sufficient`}function yE(e,t){if(e.length<2)return t.str`Please enter a longer subject`}function bL({withIcon:e,children:t}){return e?i("div",{class:"flex justify-between"},t):i(ae,null,t)}function ni({id:e,label:t,help:r,focus:n,disabled:a,onChange:o,placeholder:s,rightIcons:c,required:u,value:f,error:d}){return i("div",{class:"sm:col-span-5"},i("label",{for:e,class:"block text-sm font-medium leading-6 text-gray-900"},t,u&&i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i(bL,{withIcon:c!==void 0},i("input",{ref:n?or:void 0,type:"text",class:"block w-full disabled:bg-gray-200 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:e,id:e,disabled:a,value:f??"",placeholder:s,autocomplete:"off",required:!0,onInput:w=>{o(w.currentTarget.value)}}),c),i(nt,{message:d,isDirty:f!==void 0})),r&&i("p",{class:"mt-2 text-sm text-gray-500"},r))}var vL=/(?:payto:\/\/[^\s]*)/;function EL(e){if(!e)return;let t=vL.exec(e);if(t)return t[0]}Re();Be();Re();Be();var wL={},bE=Kt(wL),An=()=>lr(bE),vE=({children:e,value:t})=>i(bE.Provider,{value:t,children:e});var AL=()=>W().allowExtra().property("showWithdrawalSuccess",Se()).property("hideDemo",Bt(Se(),!1)).property("showInstallWallet",Se()).property("fastWithdrawalForm",Se()).build("Preferences"),TL={showWithdrawalSuccess:!0,hideDemo:!0,showInstallWallet:!0,fastWithdrawalForm:!1},NL=Xn("bank-preferences",AL());function Hr(){let{value:e,update:t}=ga(NL,TL);function r(n,a){let o={...e,[n]:a};t(o)}return[e,r]}function EE(e){return e.showDemoDescription?["hideDemo","showInstallWallet","showWithdrawalSuccess","fastWithdrawalForm"]:["showInstallWallet","showWithdrawalSuccess","fastWithdrawalForm"]}function wE(e,t){switch(e){case"showWithdrawalSuccess":return t.str`Show withdrawal confirmation`;case"fastWithdrawalForm":return t.str`Withdraw without setting amount`;case"hideDemo":return t.str`Hide demo hint.`;case"showInstallWallet":return t.str`Show install wallet first`}}var AE=["people","history","way","art","world","information","map","two","family","government","health","system","computer","meat","year","thanks","music","person","reading","method","data","food","understanding","theory","law","bird","literature","problem","software","control","knowledge","power","ability","economics","love","internet","television","science","library","nature","fact","product","idea","temperature","investment","area","society","activity","story","industry","media","thing","oven","community","definition","safety","quality","development","language","management","player","variety","video","week","security","country","exam","movie","organization","equipment","physics","analysis","policy","series","thought","basis","boyfriend","direction","strategy","technology","army","camera","freedom","paper","environment","child","instance","month","truth","marketing","university","writing","article","department","difference","goal","news","audience","fishing","growth","income","marriage","user","combination","failure","meaning","medicine","philosophy","teacher","communication","night","chemistry","disease","disk","energy","nation","road","role","soup","advertising","location","success","addition","apartment","education","math","moment","painting","politics","attention","decision","event","property","shopping","student","wood","competition","distribution","entertainment","office","population","president","unit","category","cigarette","context","introduction","opportunity","performance","driver","flight","length","magazine","newspaper","relationship","teaching","cell","dealer","finding","lake","member","message","phone","scene","appearance","association","concept","customer","death","discussion","housing","inflation","insurance","mood","woman","advice","blood","effort","expression","importance","opinion","payment","reality","responsibility","situation","skill","statement","wealth","application","city","county","depth","estate","foundation","grandmother","heart","perspective","photo","recipe","studio","topic","collection","depression","imagination","passion","percentage","resource","setting","ad","agency","college","connection","criticism","debt","description","memory","patience","secretary","solution","administration","aspect","attitude","director","personality","psychology","recommendation","response","selection","storage","version","alcohol","argument","complaint","contract","emphasis","highway","loss","membership","possession","preparation","steak","union","agreement","cancer","currency","employment","engineering","entry","interaction","mixture","preference","region","republic","tradition","virus","actor","classroom","delivery","device","difficulty","drama","election","engine","football","guidance","hotel","owner","priority","protection","suggestion","tension","variation","anxiety","atmosphere","awareness","bath","bread","candidate","climate","comparison","confusion","construction","elevator","emotion","employee","employer","guest","height","leadership","mall","manager","operation","recording","sample","transportation","charity","cousin","disaster","editor","efficiency","excitement","extent","feedback","guitar","homework","leader","mom","outcome","permission","presentation","promotion","reflection","refrigerator","resolution","revenue","session","singer","tennis","basket","bonus","cabinet","childhood","church","clothes","coffee","dinner","drawing","hair","hearing","initiative","judgment","lab","measurement","mode","mud","orange","poetry","police","possibility","procedure","queen","ratio","relation","restaurant","satisfaction","sector","signature","significance","song","tooth","town","vehicle","volume","wife","accident","airport","appointment","arrival","assumption","baseball","chapter","committee","conversation","database","enthusiasm","error","explanation","farmer","gate","girl","hall","historian","hospital","injury","instruction","maintenance","manufacturer","meal","perception","pie","poem","presence","proposal","reception","replacement","revolution","river","son","speech","tea","village","warning","winner","worker","writer","assistance","breath","buyer","chest","chocolate","conclusion","contribution","cookie","courage","dad","desk","drawer","establishment","examination","garbage","grocery","honey","impression","improvement","independence","insect","inspection","inspector","king","ladder","menu","penalty","piano","potato","profession","professor","quantity","reaction","requirement","salad","sister","supermarket","tongue","weakness","wedding","affair","ambition","analyst","apple","assignment","assistant","bathroom","bedroom","beer","birthday","celebration","championship","cheek","client","consequence","departure","diamond","dirt","ear","fortune","friendship","funeral","gene","girlfriend","hat","indication","intention","lady","midnight","negotiation","obligation","passenger","pizza","platform","poet","pollution","recognition","reputation","shirt","sir","speaker","stranger","surgery","sympathy","tale","throat","trainer","uncle","youth","time","work","film","water","money","example","while","business","study","game","life","form","air","day","place","number","part","field","fish","back","process","heat","hand","experience","job","book","end","point","type","home","economy","value","body","market","guide","interest","state","radio","course","company","price","size","card","list","mind","trade","line","care","group","risk","word","fat","force","key","light","training","name","school","top","amount","level","order","practice","research","sense","service","piece","web","boss","sport","fun","house","page","term","test","answer","sound","focus","matter","kind","soil","board","oil","picture","access","garden","range","rate","reason","future","site","demand","exercise","image","case","cause","coast","action","age","bad","boat","record","result","section","building","mouse","cash","class","nothing","period","plan","store","tax","side","subject","space","rule","stock","weather","chance","figure","man","model","source","beginning","earth","program","chicken","design","feature","head","material","purpose","question","rock","salt","act","birth","car","dog","object","scale","sun","note","profit","rent","speed","style","war","bank","craft","half","inside","outside","standard","bus","exchange","eye","fire","position","pressure","stress","advantage","benefit","box","frame","issue","step","cycle","face","item","metal","paint","review","room","screen","structure","view","account","ball","discipline","medium","share","balance","bit","black","bottom","choice","gift","impact","machine","shape","tool","wind","address","average","career","culture","morning","pot","sign","table","task","condition","contact","credit","egg","hope","ice","network","north","square","attempt","date","effect","link","post","star","voice","capital","challenge","friend","self","shot","brush","couple","debate","exit","front","function","lack","living","plant","plastic","spot","summer","taste","theme","track","wing","brain","button","click","desire","foot","gas","influence","notice","rain","wall","base","damage","distance","feeling","pair","savings","staff","sugar","target","text","animal","author","budget","discount","file","ground","lesson","minute","officer","phase","reference","register","sky","stage","stick","title","trouble","bowl","bridge","campaign","character","club","edge","evidence","fan","letter","lock","maximum","novel","option","pack","park","plenty","quarter","skin","sort","weight","baby","background","carry","dish","factor","fruit","glass","joint","master","muscle","red","strength","traffic","trip","vegetable","appeal","chart","gear","ideal","kitchen","land","log","mother","net","party","principle","relative","sale","season","signal","spirit","street","tree","wave","belt","bench","commission","copy","drop","minimum","path","progress","project","sea","south","status","stuff","ticket","tour","angle","blue","breakfast","confidence","daughter","degree","doctor","dot","dream","duty","essay","father","fee","finance","hour","juice","limit","luck","milk","mouth","peace","pipe","seat","stable","storm","substance","team","trick","afternoon","bat","beach","blank","catch","chain","consideration","cream","crew","detail","gold","interview","kid","mark","match","mission","pain","pleasure","score","screw","sex","shop","shower","suit","tone","window","agent","band","block","bone","calendar","cap","coat","contest","corner","court","cup","district","door","east","finger","garage","guarantee","hole","hook","implement","layer","lecture","lie","manner","meeting","nose","parking","partner","profile","respect","rice","routine","schedule","swimming","telephone","tip","winter","airline","bag","battle","bed","bill","bother","cake","code","curve","designer","dimension","dress","ease","emergency","evening","extension","farm","fight","gap","grade","holiday","horror","horse","host","husband","loan","mistake","mountain","nail","noise","occasion","package","patient","pause","phrase","proof","race","relief","sand","sentence","shoulder","smoke","stomach","string","tourist","towel","vacation","west","wheel","wine","arm","aside","associate","bet","blow","border","branch","breast","brother","buddy","bunch","chip","coach","cross","document","draft","dust","expert","floor","god","golf","habit","iron","judge","knife","landscape","league","mail","mess","native","opening","parent","pattern","pin","pool","pound","request","salary","shame","shelter","shoe","silver","tackle","tank","trust","assist","bake","bar","bell","bike","blame","boy","brick","chair","closet","clue","collar","comment","conference","devil","diet","fear","fuel","glove","jacket","lunch","monitor","mortgage","nurse","pace","panic","peak","plane","reward","row","sandwich","shock","spite","spray","surprise","till","transition","weekend","welcome","yard","alarm","bend","bicycle","bite","blind","bottle","cable","candle","clerk","cloud","concert","counter","flower","grandfather","harm","knee","lawyer","leather","load","mirror","neck","pension","plate","purple","ruin","ship","skirt","slice","snow","specialist","stroke","switch","trash","tune","zone","anger","award","bid","bitter","boot","bug","camp","candy","carpet","cat","champion","channel","clock","comfort","cow","crack","engineer","entrance","fault","grass","guy","hell","highlight","incident","island","joke","jury","leg","lip","mate","motor","nerve","passage","pen","pride","priest","prize","promise","resident","resort","ring","roof","rope","sail","scheme","script","sock","station","toe","tower","truck","witness","a","you","it","can","will","if","one","many","most","other","use","make","good","look","help","go","great","being","few","might","still","public","read","keep","start","give","human","local","general","she","specific","long","play","feel","high","tonight","put","common","set","change","simple","past","big","possible","particular","today","major","personal","current","national","cut","natural","physical","show","try","check","second","call","move","pay","let","increase","single","individual","turn","ask","buy","guard","hold","main","offer","potential","professional","international","travel","cook","alternative","following","special","working","whole","dance","excuse","cold","commercial","low","purchase","deal","primary","worth","fall","necessary","positive","produce","search","present","spend","talk","creative","tell","cost","drive","green","support","glad","remove","return","run","complex","due","effective","middle","regular","reserve","independent","leave","original","reach","rest","serve","watch","beautiful","charge","active","break","negative","safe","stay","visit","visual","affect","cover","report","rise","walk","white","beyond","junior","pick","unique","anything","classic","final","lift","mix","private","stop","teach","western","concern","familiar","fly","official","broad","comfortable","gain","maybe","rich","save","stand","young","fail","heavy","hello","lead","listen","valuable","worry","handle","leading","meet","release","sell","finish","normal","press","ride","secret","spread","spring","tough","wait","brown","deep","display","flow","hit","objective","shoot","touch","cancel","chemical","cry","dump","extreme","push","conflict","eat","fill","formal","jump","kick","opposite","pass","pitch","remote","total","treat","vast","abuse","beat","burn","deposit","print","raise","sleep","somewhere","advance","anywhere","consist","dark","double","draw","equal","fix","hire","internal","join","kill","sensitive","tap","win","attack","claim","constant","drag","drink","guess","minor","pull","raw","soft","solid","wear","weird","wonder","annual","count","dead","doubt","feed","forever","impress","nobody","repeat","round","sing","slide","strip","whereas","wish","combine","command","dig","divide","equivalent","hang","hunt","initial","march","mention","smell","spiritual","survey","tie","adult","brief","crazy","escape","gather","hate","prior","repair","rough","sad","scratch","sick","strike","employ","external","hurt","illegal","laugh","lay","mobile","nasty","ordinary","respond","royal","senior","split","strain","struggle","swim","train","upper","wash","yellow","convert","crash","dependent","fold","funny","grab","hide","miss","permit","quote","recover","resolve","roll","sink","slip","spare","suspect","sweet","swing","twist","upstairs","usual","abroad","brave","calm","concentrate","estimate","grand","male","mine","prompt","quiet","refuse","regret","reveal","rush","shake","shift","shine","steal","suck","surround","anybody","bear","brilliant","dare","dear","delay","drunk","female","hurry","inevitable","invite","kiss","neat","pop","punch","quit","reply","representative","resist","rip","rub","silly","smile","spell","stretch","stupid","tear","temporary","tomorrow","wake","wrap","yesterday"],TE=["abandoned","able","absolute","adorable","adventurous","academic","acceptable","acclaimed","accomplished","accurate","aching","acidic","acrobatic","active","actual","adept","admirable","admired","adolescent","adorable","adored","advanced","afraid","affectionate","aged","aggravating","aggressive","agile","agitated","agonizing","agreeable","ajar","alarmed","alarming","alert","alienated","alive","all","altruistic","amazing","ambitious","ample","amused","amusing","anchored","ancient","angelic","angry","anguished","animated","annual","another","antique","anxious","any","apprehensive","appropriate","apt","arctic","arid","aromatic","artistic","ashamed","assured","astonishing","athletic","attached","attentive","attractive","austere","authentic","authorized","automatic","avaricious","average","aware","awesome","awful","awkward","babyish","bad","back","baggy","bare","barren","basic","beautiful","belated","beloved","beneficial","better","best","bewitched","big","big-hearted","biodegradable","bite-sized","bitter","black","black-and-white","bland","blank","blaring","bleak","blind","blissful","blond","blue","blushing","bogus","boiling","bold","bony","boring","bossy","both","bouncy","bountiful","bowed","brave","breakable","brief","bright","brilliant","brisk","broken","bronze","brown","bruised","bubbly","bulky","bumpy","buoyant","burdensome","burly","bustling","busy","buttery","buzzing","calculating","calm","candid","canine","capital","carefree","careful","careless","caring","cautious","cavernous","celebrated","charming","cheap","cheerful","cheery","chief","chilly","chubby","circular","classic","clean","clear","clear-cut","clever","close","closed","cloudy","clueless","clumsy","cluttered","coarse","cold","colorful","colorless","colossal","comfortable","common","compassionate","competent","complete","complex","complicated","composed","concerned","concrete","confused","conscious","considerate","constant","content","conventional","cooked","cool","cooperative","coordinated","corny","corrupt","costly","courageous","courteous","crafty","crazy","creamy","creative","creepy","criminal","crisp","critical","crooked","crowded","cruel","crushing","cuddly","cultivated","cultured","cumbersome","curly","curvy","cute","cylindrical","damaged","damp","dangerous","dapper","daring","darling","dark","dazzling","dead","deadly","deafening","dear","dearest","decent","decimal","decisive","deep","defenseless","defensive","defiant","deficient","definite","definitive","delayed","delectable","delicious","delightful","delirious","demanding","dense","dental","dependable","dependent","descriptive","deserted","detailed","determined","devoted","different","difficult","digital","diligent","dim","dimpled","dimwitted","direct","disastrous","discrete","disfigured","disgusting","disloyal","dismal","distant","downright","dreary","dirty","disguised","dishonest","dismal","distant","distinct","distorted","dizzy","dopey","doting","double","downright","drab","drafty","dramatic","dreary","droopy","dry","dual","dull","dutiful","each","eager","earnest","early","easy","easy-going","ecstatic","edible","educated","elaborate","elastic","elated","elderly","electric","elegant","elementary","elliptical","embarrassed","embellished","eminent","emotional","empty","enchanted","enchanting","energetic","enlightened","enormous","enraged","entire","envious","equal","equatorial","essential","esteemed","ethical","euphoric","even","evergreen","everlasting","every","evil","exalted","excellent","exemplary","exhausted","excitable","excited","exciting","exotic","expensive","experienced","expert","extraneous","extroverted","extra-large","extra-small","fabulous","failing","faint","fair","faithful","fake","false","familiar","famous","fancy","fantastic","far","faraway","far-flung","far-off","fast","fat","fatal","fatherly","favorable","favorite","fearful","fearless","feisty","feline","female","feminine","few","fickle","filthy","fine","finished","firm","first","firsthand","fitting","fixed","flaky","flamboyant","flashy","flat","flawed","flawless","flickering","flimsy","flippant","flowery","fluffy","fluid","flustered","focused","fond","foolhardy","foolish","forceful","forked","formal","forsaken","forthright","fortunate","fragrant","frail","frank","frayed","free","French","fresh","frequent","friendly","frightened","frightening","frigid","frilly","frizzy","frivolous","front","frosty","frozen","frugal","fruitful","full","fumbling","functional","funny","fussy","fuzzy","gargantuan","gaseous","general","generous","gentle","genuine","giant","giddy","gigantic","gifted","giving","glamorous","glaring","glass","gleaming","gleeful","glistening","glittering","gloomy","glorious","glossy","glum","golden","good","good-natured","gorgeous","graceful","gracious","grand","grandiose","granular","grateful","grave","gray","great","greedy","green","gregarious","grim","grimy","gripping","grizzled","gross","grotesque","grouchy","grounded","growing","growling","grown","grubby","gruesome","grumpy","guilty","gullible","gummy","hairy","half","handmade","handsome","handy","happy","happy-go-lucky","hard","hard-to-find","harmful","harmless","harmonious","harsh","hasty","hateful","haunting","healthy","heartfelt","hearty","heavenly","heavy","hefty","helpful","helpless","hidden","hideous","high","high-level","hilarious","hoarse","hollow","homely","honest","honorable","honored","hopeful","horrible","hospitable","hot","huge","humble","humiliating","humming","humongous","hungry","hurtful","husky","icky","icy","ideal","idealistic","identical","idle","idiotic","idolized","ignorant","ill","illegal","ill-fated","ill-informed","illiterate","illustrious","imaginary","imaginative","immaculate","immaterial","immediate","immense","impassioned","impeccable","impartial","imperfect","imperturbable","impish","impolite","important","impossible","impractical","impressionable","impressive","improbable","impure","inborn","incomparable","incompatible","incomplete","inconsequential","incredible","indelible","inexperienced","indolent","infamous","infantile","infatuated","inferior","infinite","informal","innocent","insecure","insidious","insignificant","insistent","instructive","insubstantial","intelligent","intent","intentional","interesting","internal","international","intrepid","ironclad","irresponsible","irritating","itchy","jaded","jagged","jam-packed","jaunty","jealous","jittery","joint","jolly","jovial","joyful","joyous","jubilant","judicious","juicy","jumbo","junior","jumpy","juvenile","kaleidoscopic","keen","key","kind","kindhearted","kindly","klutzy","knobby","knotty","knowledgeable","knowing","known","kooky","kosher","lame","lanky","large","last","lasting","late","lavish","lawful","lazy","leading","lean","leafy","left","legal","legitimate","light","lighthearted","likable","likely","limited","limp","limping","linear","lined","liquid","little","live","lively","livid","loathsome","lone","lonely","long","long-term","loose","lopsided","lost","loud","lovable","lovely","loving","low","loyal","lucky","lumbering","luminous","lumpy","lustrous","luxurious","mad","made-up","magnificent","majestic","major","male","mammoth","married","marvelous","masculine","massive","mature","meager","mealy","mean","measly","meaty","medical","mediocre","medium","meek","mellow","melodic","memorable","menacing","merry","messy","metallic","mild","milky","mindless","miniature","minor","minty","miserable","miserly","misguided","misty","mixed","modern","modest","moist","monstrous","monthly","monumental","moral","mortified","motherly","motionless","mountainous","muddy","muffled","multicolored","mundane","murky","mushy","musty","muted","mysterious","naive","narrow","nasty","natural","naughty","nautical","near","neat","necessary","needy","negative","neglected","negligible","neighboring","nervous","new","next","nice","nifty","nimble","nippy","nocturnal","noisy","nonstop","normal","notable","noted","noteworthy","novel","noxious","numb","nutritious","nutty","obedient","obese","oblong","oily","oblong","obvious","occasional","odd","oddball","offbeat","offensive","official","old","old-fashioned","only","open","optimal","optimistic","opulent","orange","orderly","organic","ornate","ornery","ordinary","original","other","our","outlying","outgoing","outlandish","outrageous","outstanding","oval","overcooked","overdue","overjoyed","overlooked","palatable","pale","paltry","parallel","parched","partial","passionate","past","pastel","peaceful","peppery","perfect","perfumed","periodic","perky","personal","pertinent","pesky","pessimistic","petty","phony","physical","piercing","pink","pitiful","plain","plaintive","plastic","playful","pleasant","pleased","pleasing","plump","plush","polished","polite","political","pointed","pointless","poised","poor","popular","portly","posh","positive","possible","potable","powerful","powerless","practical","precious","present","prestigious","pretty","precious","previous","pricey","prickly","primary","prime","pristine","private","prize","probable","productive","profitable","profuse","proper","proud","prudent","punctual","pungent","puny","pure","purple","pushy","putrid","puzzled","puzzling","quaint","qualified","quarrelsome","quarterly","queasy","querulous","questionable","quick","quick-witted","quiet","quintessential","quirky","quixotic","quizzical","radiant","ragged","rapid","rare","rash","raw","recent","reckless","rectangular","ready","real","realistic","reasonable","red","reflecting","regal","regular","reliable","relieved","remarkable","remorseful","remote","repentant","required","respectful","responsible","repulsive","revolving","rewarding","rich","rigid","right","ringed","ripe","roasted","robust","rosy","rotating","rotten","rough","round","rowdy","royal","rubbery","rundown","ruddy","rude","runny","rural","rusty","sad","safe","salty","same","sandy","sane","sarcastic","sardonic","satisfied","scaly","scarce","scared","scary","scented","scholarly","scientific","scornful","scratchy","scrawny","second","secondary","second-hand","secret","self-assured","self-reliant","selfish","sentimental","separate","serene","serious","serpentine","several","severe","shabby","shadowy","shady","shallow","shameful","shameless","sharp","shimmering","shiny","shocked","shocking","shoddy","short","short-term","showy","shrill","shy","sick","silent","silky","silly","silver","similar","simple","simplistic","sinful","single","sizzling","skeletal","skinny","sleepy","slight","slim","slimy","slippery","slow","slushy","small","smart","smoggy","smooth","smug","snappy","snarling","sneaky","sniveling","snoopy","sociable","soft","soggy","solid","somber","some","spherical","sophisticated","sore","sorrowful","soulful","soupy","sour","Spanish","sparkling","sparse","specific","spectacular","speedy","spicy","spiffy","spirited","spiteful","splendid","spotless","spotted","spry","square","squeaky","squiggly","stable","staid","stained","stale","standard","starchy","stark","starry","steep","sticky","stiff","stimulating","stingy","stormy","straight","strange","steel","strict","strident","striking","striped","strong","studious","stunning","stupendous","stupid","sturdy","stylish","subdued","submissive","substantial","subtle","suburban","sudden","sugary","sunny","super","superb","superficial","superior","supportive","sure-footed","surprised","suspicious","svelte","sweaty","sweet","sweltering","swift","sympathetic","tall","talkative","tame","tan","tangible","tart","tasty","tattered","taut","tedious","teeming","tempting","tender","tense","tepid","terrible","terrific","testy","thankful","that","these","thick","thin","third","thirsty","this","thorough","thorny","those","thoughtful","threadbare","thrifty","thunderous","tidy","tight","timely","tinted","tiny","tired","torn","total","tough","traumatic","treasured","tremendous","tragic","trained","tremendous","triangular","tricky","trifling","trim","trivial","troubled","true","trusting","trustworthy","trusty","truthful","tubby","turbulent","twin","ugly","ultimate","unacceptable","unaware","uncomfortable","uncommon","unconscious","understated","unequaled","uneven","unfinished","unfit","unfolded","unfortunate","unhappy","unhealthy","uniform","unimportant","unique","united","unkempt","unknown","unlawful","unlined","unlucky","unnatural","unpleasant","unrealistic","unripe","unruly","unselfish","unsightly","unsteady","unsung","untidy","untimely","untried","untrue","unused","unusual","unwelcome","unwieldy","unwilling","unwitting","unwritten","upbeat","upright","upset","urban","usable","used","useful","useless","utilized","utter","vacant","vague","vain","valid","valuable","vapid","variable","vast","velvety","venerated","vengeful","verifiable","vibrant","vicious","victorious","vigilant","vigorous","villainous","violet","violent","virtual","virtuous","visible","vital","vivacious","vivid","voluminous","wan","warlike","warm","warmhearted","warped","wary","wasteful","watchful","waterlogged","watery","wavy","wealthy","weak","weary","webbed","weed","weekly","weepy","weighty","weird","welcome","well-documented","well-groomed","well-informed","well-lit","well-made","well-off","well-to-do","well-worn","wet","which","whimsical","whirlwind","whispered","white","whole","whopping","wicked","wide","wide-eyed","wiggly","wild","willing","wilted","winding","windy","winged","wiry","wise","witty","wobbly","woeful","wonderful","wooden","woozy","wordy","worldly","worn","worried","worrisome","worse","worst","worthless","worthwhile","worthy","wrathful","wretched","writhing","wrong","wry","yawning","yearly","yellow","yellowish","young","youthful","yummy","zany","zealous","zesty","zigzag"];function NE(){let e=Math.floor(Math.random()*AE.length),t=Math.floor(Math.random()*TE.length);return{first:TE[t],second:AE[e]}}function RE(){return gt(xn(16))}var IE=110;hp.SCREEN_ID=IE;function hp({onRegistrationSuccesful:e,routeCancel:t}){let{i18n:r}=Ne(),{config:n}=De();return n.allow_registrations?i(SE,{onRegistrationSuccesful:e,routeCancel:t}):i("p",null,r.str`Currently, the bank is not accepting new registrations!`)}var mp=/^[a-zA-Z0-9\-\.\_\~]*$/;SE.SCREEN_ID=IE;function SE({onRegistrationSuccesful:e,routeCancel:t}){let[r,n]=de(),[a,o]=de(),[s,c]=de(),[u,f]=de(),[d,w]=ht(),R=An(),[h]=Hr(),{lib:{bank:p}}=De(),{i18n:T}=Ne(),A=Ht({name:a?void 0:T.str`The name is missing`,username:r?mp.test(r)?void 0:T.str`Use letters, numbers or any of these characters: - . _ ~`:T.str`Missing username`,password:s?s.length<8?T.str`The password should be longer than 8 letters`:void 0:T.str`Missing password`,repeatPassword:u?u!==s?T.str`The passwords do not match`:void 0:T.str`Missing password`}),C=!a||!r||!s||A?void 0:{name:a,username:r,password:s},S=w(T.str`register new account`,v=>p.createAccount(void 0,v),A||!C?void 0:[C]);S.onSuccess=(v,_)=>{n(void 0),c(void 0),f(void 0),o(void 0),e(_.username,_.password)},S.onFail=v=>{switch(v.case){case l.BadRequest:return T.str`Server replied with invalid phone or email.`;case l.Unauthorized:return T.str`You are not authorised to create this account.`;case G.BANK_UNALLOWED_DEBIT:return T.str`Registration is disabled because the bank ran out of bonus credit.`;case G.BANK_RESERVED_USERNAME_CONFLICT:return T.str`That username can't be used because is reserved.`;case G.BANK_REGISTER_USERNAME_REUSE:return T.str`That username is already taken.`;case G.BANK_REGISTER_PAYTO_URI_REUSE:return T.str`That account ID is already taken.`;case G.BANK_MISSING_TAN_INFO:return T.str`No information for the selected authentication channel.`;case G.BANK_TAN_CHANNEL_NOT_SUPPORTED:return T.str`Authentication channel is not supported.`;case G.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:return T.str`Only an administrator is allowed to set the debt limit.`;case G.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:return T.str`Only the administrator can change the conversion rate.`;case G.BANK_CONVERSION_RATE_CLASS_UNKNOWN:return T.str`The conversion rate class doesn't exist.`;case G.BANK_NON_ADMIN_SET_TAN_CHANNEL:return T.str`Only admin can create accounts with second factor authentication.`;case G.BANK_PASSWORD_TOO_SHORT:return T.str`The password is too short. Can't have less than 8 characters.`;case G.BANK_PASSWORD_TOO_LONG:return T.str`The password is too long. Can't have more than 64 characters.`;default:ue(v)}};let k=S.lambda(()=>{let v=NE(),_="12345678",g=`_${v.first}-${v.second}_`;return[{name:`${xE(v.first)} ${xE(v.second)}`,username:g,password:_}]},[]);return i(ae,null,i(yt,{notification:d}),i("div",{class:"flex min-h-full flex-col justify-center"},i("div",{class:"sm:mx-auto sm:w-full sm:max-w-sm"},i("h2",{class:"text-center text-2xl font-bold leading-9 tracking-tight text-gray-900"},T.str`Account registration`)),i("div",{class:"mt-10 sm:mx-auto sm:w-full sm:max-w-sm"},i("form",{class:"space-y-6",noValidate:!0,onSubmit:v=>{v.preventDefault()},autoCapitalize:"none",autoCorrect:"off"},i("div",null,i("label",{for:"username",class:"block text-sm font-medium leading-6 text-gray-900"},i(T.Translate,null,"Login username"),i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("input",{autoFocus:!0,type:"text",name:"username",id:"username",class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",value:r??"",enterkeyhint:"next",placeholder:T.str`account identification to login`,autocomplete:"username",required:!0,onInput:v=>{n(v.currentTarget.value)}}),i(nt,{message:A?.username,isDirty:r!==void 0}))),i("div",null,i("div",{class:"flex items-center justify-between"},i("label",{for:"password",class:"block text-sm font-medium leading-6 text-gray-900"},i(T.Translate,null,"Password"),i("b",{class:"text-[red]"}," *"))),i("div",{class:"mt-2"},i("input",{type:"password",name:"password",id:"password",autocomplete:"current-password",class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",enterkeyhint:"send",value:s??"",placeholder:T.str`Password`,required:!0,onInput:v=>{c(v.currentTarget.value)}}),i(nt,{message:A?.password,isDirty:s!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(T.Translate,null,"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers"))),i("div",null,i("div",{class:"flex items-center justify-between"},i("label",{for:"register-repeat",class:"block text-sm font-medium leading-6 text-gray-900"},i(T.Translate,null,"Repeat password"),i("b",{class:"text-[red]"}," *"))),i("div",{class:"mt-2"},i("input",{type:"password",name:"register-repeat",id:"register-repeat",autocomplete:"current-password",class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",enterkeyhint:"send",value:u??"",placeholder:T.str`Same password`,required:!0,onInput:v=>{f(v.currentTarget.value)}}),i(nt,{message:A?.repeatPassword,isDirty:u!==void 0}))),i("div",null,i("div",{class:"flex items-center justify-between"},i("label",{for:"name",class:"block text-sm font-medium leading-6 text-gray-900"},i(T.Translate,null,"Full name"),i("b",{class:"text-[red]"}," *"))),i("div",{class:"mt-2"},i("input",{autoFocus:!0,type:"text",name:"name",id:"name",class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",value:a??"",enterkeyhint:"next",placeholder:"John Doe",autocomplete:"name",required:!0,onInput:v=>{o(v.currentTarget.value)}}))),i("div",{class:"flex w-full justify-between"},i("a",{name:"cancel",href:t.url({}),class:"ring-1 ring-gray-600 rounded-md bg-white disabled:bg-gray-300 px-3 py-1.5 text-sm font-semibold leading-6 text-black shadow-sm hover:bg-white-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"},i(T.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"register",class:"rounded-md bg-indigo-600 disabled:bg-gray-300 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:S},i(T.Translate,null,"Register")))),R.allowRandomAccountCreation&&i("p",{class:"mt-10 text-center text-sm text-gray-500 border-t"},i(Ze,{type:"submit",name:"create random",class:"flex mt-4 w-full disabled:bg-gray-300 justify-center rounded-md bg-green-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600",onClick:k},i(T.Translate,null,"Create a random temporary user"))))))}function xE(e){return e.charAt(0).toUpperCase()+e.slice(1)}var RL=104,oo=rt.toTalerProtocolDuration(rt.fromSpec({minutes:30}));er.SCREEN_ID=RL;function er({currentUser:e,fixedUser:t,routeRegister:r}){let n=We(),a=n.state.status!=="loggedOut"?n.state.username:void 0,[o,s]=de(e??a),[c,u]=de(),{i18n:f}=Ne(),{lib:{bank:d}}=De(),[w,R]=ht(),h=br(),{config:p}=De(),T=Ht({username:o?mp.test(o)?void 0:f.str`Use letters, numbers or any of these characters: - . _ ~`:f.str`Missing username`,password:c?void 0:f.str`Missing password`}),A=R(f.str`logout`,async()=>(n.logOut(),ke()),[]);A.onSuccess=n.logOut,A.onFail=_=>{};let C={scope:"readwrite",duration:oo,refreshable:!0},S=R(f.str`login`,(_,g,O)=>d.createAccessToken(_,{type:"basic",username:_,password:g},C,{challengeIds:O}),T?void 0:[o,c,[]]);S.onSuccess=(_,g)=>{n.logIn({username:g,token:Ca(_.access_token),expiration:he.fromProtocolTimestamp(_.expiration)})},S.onFail=(_,g)=>{switch(_.case){case l.Accepted:return h.onChallengeRequired(_.body),f.str`A second factor authentication is required.`;case G.GENERIC_FORBIDDEN:return f.str`The account has no rights to login.`;case G.BANK_ACCOUNT_LOCKED:return f.str`The account is locked and cannot login. Contact administrator.`;case l.Unauthorized:return f.str`Wrong credentials for "${g}"`;case l.NotFound:return f.str`Account not found`;default:ue(_)}};let k=S.lambda(_=>[S.args[0],S.args[1],_]);if(h.pendingChallenge)return i(Er,{currentChallenge:h.pendingChallenge,description:f.str`Account login.`,onCancel:h.doCancelChallenge,username:o,onCompleted:k});let v=t||n.state.status!=="loggedOut";return i("div",{class:"flex min-h-full flex-col justify-center "},i(yt,{notification:w}),i("div",{class:"sm:mx-auto sm:w-full sm:max-w-sm"},n.state.status!=="expired"?void 0:i(Pe,{title:f.str`Session expired`,type:"warning"}),i("form",{class:"mt-10 space-y-6",noValidate:!0,onSubmit:_=>{_.preventDefault(),_.stopPropagation()},autoCapitalize:"none",autoCorrect:"off"},i("div",null,i("label",{for:"username",class:"block text-sm font-medium leading-6 text-gray-900"},i(f.Translate,null,"Username")),i("div",{class:"mt-2"},i("input",{ref:v?void 0:or,type:"text",name:"username",id:"username",class:"block w-full disabled:bg-gray-200 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",value:o??"",disabled:v,enterkeyhint:"next",placeholder:f.str`identification`,autocomplete:"username",title:f.str`Username of the account`,required:!0,onChange:_=>{s(_.currentTarget.value)}}),i(nt,{message:T?.username,isDirty:o!==void 0}))),i("div",null,i("div",{class:"flex items-center justify-between"},i("label",{for:"password",class:"block text-sm font-medium leading-6 text-gray-900"},i(f.Translate,null,"Password"))),i("div",{class:"mt-2"},i("input",{type:"password",name:"password",id:"password",autocomplete:"current-password",ref:v?or:void 0,class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",enterkeyhint:"send",value:c??"",placeholder:f.str`Password`,title:f.str`Password of the account`,required:!0,onChange:_=>{u(_.currentTarget.value)}}),i(nt,{message:T?.password,isDirty:c!==void 0}))),n.state.status!=="loggedOut"?i("div",{class:"flex justify-between"},i(Ze,{type:"button",name:"cancel",class:"rounded-md bg-white-600 px-3 py-1.5 text-sm font-semibold leading-6 text-black shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-600",onClick:A},i(f.Translate,null,"Forget")),i(Ze,{type:"submit",name:"check",class:"rounded-md bg-indigo-600 disabled:bg-gray-300 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:S},i(f.Translate,null,"Verify"))):i("div",null,i(Ze,{type:"submit",name:"login",class:"flex w-full justify-center rounded-md bg-indigo-600 disabled:bg-gray-300 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:S},i(f.Translate,null,"Log in")))),p.allow_registrations&&r&&i("a",{name:"register",href:r.url({}),class:"flex justify-center border-t mt-4 rounded-md bg-blue-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"},i(f.Translate,null,"Register"))))}Be();var xL=()=>W().property("status",X("loggedIn")).property("username",L()).property("expiration",Bt(Br,he.now())).property("token",L()).property("isUserAdministrator",Se()).build("SessionState.LoggedIn"),IL=()=>W().property("status",X("expired")).property("username",L()).property("expiration",Bt(Br,he.now())).property("isUserAdministrator",Se()).build("SessionState.Expired"),SL=()=>W().property("status",X("loggedOut")).build("SessionState.LoggedOut"),CL=()=>wt().discriminateOn("status").alternative("loggedIn",xL()).alternative("loggedOut",SL()).alternative("expired",IL()).build("SessionState"),CE={status:"loggedOut"},OL=Xn("bank-session",CL());function We(){let{value:e,update:t}=ga(OL,CE);return Ge(()=>{if(e.status==="loggedIn"&&he.isExpired(e.expiration)){let r={status:"expired",username:e.username,expiration:e.expiration,isUserAdministrator:e.username==="admin"};t(r)}}),{state:e,logOut(){t(CE)},expired(){if(e.status==="loggedOut")return;let r={status:"expired",username:e.username,expiration:e.expiration,isUserAdministrator:e.username==="admin"};t(r)},logIn(r){let n={status:"loggedIn",...r,isUserAdministrator:r.username==="admin"};t(n),DL()}}}function DL(){vr(()=>!0,void 0,{revalidate:!1})}function OE(){let e=We(),{lib:{bank:t}}=De(),r=e.state.status!=="loggedIn"||e.state.expiration.t_ms==="never"?void 0:e.state;Ge(()=>{if(!r)return;let n=rt.getRemaining(r.expiration),a=rt.multiply(rt.fromTalerProtocolDuration(oo),.2);if(n.d_ms==="forever"||a.d_ms==="forever")return;let o=Math.max(n.d_ms-a.d_ms,0),s=setTimeout(async()=>{let c=await t.createAccessToken(r.username,{type:"bearer",token:r.token},{scope:"readwrite",duration:oo,refreshable:!0});if(c.type==="fail"){console.log(`could not refresh session ${c.case}: ${JSON.stringify(c)}`);return}e.logIn({username:r.username,token:Ca(c.body.access_token),expiration:he.fromProtocolTimestamp(c.body.expiration)})},o);return()=>{clearTimeout(s)}},[r])}function DE({account:e,tab:t,routeChargeWallet:r,routeCreateWireTransfer:n,routePublicAccounts:a,routeOperationDetails:o,routeWireTransfer:s,routeCashout:c,onOperationCreated:u,onClose:f,routeClose:d}){let w=$r(e);if(!w)return{status:"loading",error:void 0};if(w instanceof Oe)return{status:"loading-error",error:w};if(w.type==="fail")switch(w.case){case l.Unauthorized:return{status:"login",reason:"forbidden"};case l.NotFound:return{status:"login",reason:"not-found"};default:ue(w)}let{body:R}=w,h=J.parseOrThrow(R.balance.amount),p=J.parseOrThrow(R.debit_threshold),T=$e.fromString(R.payto_uri);if(T.tag==="error"||!T.value.targetType||T.value.targetType!==Je.IBAN&&T.value.targetType!==Je.TalerBank)return{status:"invalid-iban",error:R};let A=R.balance.credit_debit_indicator=="debit",C=wn.toIntAmount(h,A).increment(p).result,S=A?J.zeroOfAmount(h):h;return{status:"ready",onOperationCreated:u,error:void 0,tab:t,routeCashout:c,routeOperationDetails:o,routeCreateWireTransfer:n,routePublicAccounts:a,onClose:f,routeClose:d,routeChargeWallet:r,routeWireTransfer:s,account:e,limit:C,balance:S}}Re();function PE({account:e,routeCreateWireTransfer:t}){let r=tE(e);if(!r)return{status:"loading",error:void 0};if(r instanceof Oe)return{status:"loading-error",error:r};if(r.type==="fail")return{status:"loading",error:void 0};let n=r.body.map(a=>{let o=a.direction==="debit",s=$e.fromString(o?a.creditor_payto_uri:a.debtor_payto_uri),c=fe.orUndefined(s)?.displayName,u=he.fromProtocolTimestamp(a.date),f=J.parse(a.amount),d=a.subject;return{negative:o,counterpart:c,when:u,amount:f,subject:d}}).filter(a=>a!==void 0);return{status:"ready",error:void 0,routeCreateWireTransfer:t,transactions:n,onGoNext:r.loadNext,onGoStart:r.loadFirst}}function Pt(e){if(e===null||e===!0||e===!1)return NaN;var t=Number(e);return isNaN(t)?t:t<0?Math.ceil(t):Math.floor(t)}function ft(e,t){if(t.length1?"s":"")+" required, but only "+t.length+" present")}function au(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?au=function(r){return typeof r}:au=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},au(e)}function Vt(e){ft(1,arguments);var t=Object.prototype.toString.call(e);return e instanceof Date||au(e)==="object"&&t==="[object Date]"?new Date(e.getTime()):typeof e=="number"||t==="[object Number]"?new Date(e):((typeof e=="string"||t==="[object String]")&&typeof console<"u"&&(console.warn("Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#string-arguments"),console.warn(new Error().stack)),new Date(NaN))}function gp(e,t){ft(2,arguments);var r=Vt(e),n=Pt(t);return isNaN(n)?new Date(NaN):(n&&r.setDate(r.getDate()+n),r)}function _p(e,t){ft(2,arguments);var r=Vt(e),n=Pt(t);if(isNaN(n))return new Date(NaN);if(!n)return r;var a=r.getDate(),o=new Date(r.getTime());o.setMonth(r.getMonth()+n+1,0);var s=o.getDate();return a>=s?o:(r.setFullYear(o.getFullYear(),o.getMonth(),a),r)}function yp(e,t){ft(2,arguments);var r=Vt(e).getTime(),n=Pt(t);return new Date(r+n)}var PL={};function Qn(){return PL}function bp(e){var t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()));return t.setUTCFullYear(e.getFullYear()),e.getTime()-t.getTime()}function ou(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?ou=function(r){return typeof r}:ou=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},ou(e)}function vp(e){return ft(1,arguments),e instanceof Date||ou(e)==="object"&&Object.prototype.toString.call(e)==="[object Date]"}function Ep(e){if(ft(1,arguments),!vp(e)&&typeof e!="number")return!1;var t=Vt(e);return!isNaN(Number(t))}function wp(e,t){ft(2,arguments);var r=Pt(t);return yp(e,-r)}var LL=864e5;function Ap(e){ft(1,arguments);var t=Vt(e),r=t.getTime();t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0);var n=t.getTime(),a=r-n;return Math.floor(a/LL)+1}function Zn(e){ft(1,arguments);var t=1,r=Vt(e),n=r.getUTCDay(),a=(n=a.getTime()?r+1:t.getTime()>=s.getTime()?r:r-1}function Tp(e){ft(1,arguments);var t=ai(e),r=new Date(0);r.setUTCFullYear(t,0,4),r.setUTCHours(0,0,0,0);var n=Zn(r);return n}var UL=6048e5;function Np(e){ft(1,arguments);var t=Vt(e),r=Zn(t).getTime()-Tp(t).getTime();return Math.round(r/UL)+1}function Jn(e,t){var r,n,a,o,s,c,u,f;ft(1,arguments);var d=Qn(),w=Pt((r=(n=(a=(o=t?.weekStartsOn)!==null&&o!==void 0?o:t==null||(s=t.locale)===null||s===void 0||(c=s.options)===null||c===void 0?void 0:c.weekStartsOn)!==null&&a!==void 0?a:d.weekStartsOn)!==null&&n!==void 0?n:(u=d.locale)===null||u===void 0||(f=u.options)===null||f===void 0?void 0:f.weekStartsOn)!==null&&r!==void 0?r:0);if(!(w>=0&&w<=6))throw new RangeError("weekStartsOn must be between 0 and 6 inclusively");var R=Vt(e),h=R.getUTCDay(),p=(h=1&&h<=7))throw new RangeError("firstWeekContainsDate must be between 1 and 7 inclusively");var p=new Date(0);p.setUTCFullYear(w+1,0,h),p.setUTCHours(0,0,0,0);var T=Jn(p,t),A=new Date(0);A.setUTCFullYear(w,0,h),A.setUTCHours(0,0,0,0);var C=Jn(A,t);return d.getTime()>=T.getTime()?w+1:d.getTime()>=C.getTime()?w:w-1}function Rp(e,t){var r,n,a,o,s,c,u,f;ft(1,arguments);var d=Qn(),w=Pt((r=(n=(a=(o=t?.firstWeekContainsDate)!==null&&o!==void 0?o:t==null||(s=t.locale)===null||s===void 0||(c=s.options)===null||c===void 0?void 0:c.firstWeekContainsDate)!==null&&a!==void 0?a:d.firstWeekContainsDate)!==null&&n!==void 0?n:(u=d.locale)===null||u===void 0||(f=u.options)===null||f===void 0?void 0:f.firstWeekContainsDate)!==null&&r!==void 0?r:1),R=oi(e,t),h=new Date(0);h.setUTCFullYear(R,0,w),h.setUTCHours(0,0,0,0);var p=Jn(h,t);return p}var ML=6048e5;function xp(e,t){ft(1,arguments);var r=Vt(e),n=Jn(r,t).getTime()-Rp(r,t).getTime();return Math.round(n/ML)+1}function It(e,t){for(var r=e<0?"-":"",n=Math.abs(e).toString();n.length0?n:1-n;return It(r==="yy"?a%100:a,r.length)},M:function(t,r){var n=t.getUTCMonth();return r==="M"?String(n+1):It(n+1,2)},d:function(t,r){return It(t.getUTCDate(),r.length)},a:function(t,r){var n=t.getUTCHours()/12>=1?"pm":"am";switch(r){case"a":case"aa":return n.toUpperCase();case"aaa":return n;case"aaaaa":return n[0];default:return n==="am"?"a.m.":"p.m."}},h:function(t,r){return It(t.getUTCHours()%12||12,r.length)},H:function(t,r){return It(t.getUTCHours(),r.length)},m:function(t,r){return It(t.getUTCMinutes(),r.length)},s:function(t,r){return It(t.getUTCSeconds(),r.length)},S:function(t,r){var n=r.length,a=t.getUTCMilliseconds(),o=Math.floor(a*Math.pow(10,n-3));return It(o,r.length)}},kn=kL;var io={am:"am",pm:"pm",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},FL={G:function(t,r,n){var a=t.getUTCFullYear()>0?1:0;switch(r){case"G":case"GG":case"GGG":return n.era(a,{width:"abbreviated"});case"GGGGG":return n.era(a,{width:"narrow"});default:return n.era(a,{width:"wide"})}},y:function(t,r,n){if(r==="yo"){var a=t.getUTCFullYear(),o=a>0?a:1-a;return n.ordinalNumber(o,{unit:"year"})}return kn.y(t,r)},Y:function(t,r,n,a){var o=oi(t,a),s=o>0?o:1-o;if(r==="YY"){var c=s%100;return It(c,2)}return r==="Yo"?n.ordinalNumber(s,{unit:"year"}):It(s,r.length)},R:function(t,r){var n=ai(t);return It(n,r.length)},u:function(t,r){var n=t.getUTCFullYear();return It(n,r.length)},Q:function(t,r,n){var a=Math.ceil((t.getUTCMonth()+1)/3);switch(r){case"Q":return String(a);case"QQ":return It(a,2);case"Qo":return n.ordinalNumber(a,{unit:"quarter"});case"QQQ":return n.quarter(a,{width:"abbreviated",context:"formatting"});case"QQQQQ":return n.quarter(a,{width:"narrow",context:"formatting"});default:return n.quarter(a,{width:"wide",context:"formatting"})}},q:function(t,r,n){var a=Math.ceil((t.getUTCMonth()+1)/3);switch(r){case"q":return String(a);case"qq":return It(a,2);case"qo":return n.ordinalNumber(a,{unit:"quarter"});case"qqq":return n.quarter(a,{width:"abbreviated",context:"standalone"});case"qqqqq":return n.quarter(a,{width:"narrow",context:"standalone"});default:return n.quarter(a,{width:"wide",context:"standalone"})}},M:function(t,r,n){var a=t.getUTCMonth();switch(r){case"M":case"MM":return kn.M(t,r);case"Mo":return n.ordinalNumber(a+1,{unit:"month"});case"MMM":return n.month(a,{width:"abbreviated",context:"formatting"});case"MMMMM":return n.month(a,{width:"narrow",context:"formatting"});default:return n.month(a,{width:"wide",context:"formatting"})}},L:function(t,r,n){var a=t.getUTCMonth();switch(r){case"L":return String(a+1);case"LL":return It(a+1,2);case"Lo":return n.ordinalNumber(a+1,{unit:"month"});case"LLL":return n.month(a,{width:"abbreviated",context:"standalone"});case"LLLLL":return n.month(a,{width:"narrow",context:"standalone"});default:return n.month(a,{width:"wide",context:"standalone"})}},w:function(t,r,n,a){var o=xp(t,a);return r==="wo"?n.ordinalNumber(o,{unit:"week"}):It(o,r.length)},I:function(t,r,n){var a=Np(t);return r==="Io"?n.ordinalNumber(a,{unit:"week"}):It(a,r.length)},d:function(t,r,n){return r==="do"?n.ordinalNumber(t.getUTCDate(),{unit:"date"}):kn.d(t,r)},D:function(t,r,n){var a=Ap(t);return r==="Do"?n.ordinalNumber(a,{unit:"dayOfYear"}):It(a,r.length)},E:function(t,r,n){var a=t.getUTCDay();switch(r){case"E":case"EE":case"EEE":return n.day(a,{width:"abbreviated",context:"formatting"});case"EEEEE":return n.day(a,{width:"narrow",context:"formatting"});case"EEEEEE":return n.day(a,{width:"short",context:"formatting"});default:return n.day(a,{width:"wide",context:"formatting"})}},e:function(t,r,n,a){var o=t.getUTCDay(),s=(o-a.weekStartsOn+8)%7||7;switch(r){case"e":return String(s);case"ee":return It(s,2);case"eo":return n.ordinalNumber(s,{unit:"day"});case"eee":return n.day(o,{width:"abbreviated",context:"formatting"});case"eeeee":return n.day(o,{width:"narrow",context:"formatting"});case"eeeeee":return n.day(o,{width:"short",context:"formatting"});default:return n.day(o,{width:"wide",context:"formatting"})}},c:function(t,r,n,a){var o=t.getUTCDay(),s=(o-a.weekStartsOn+8)%7||7;switch(r){case"c":return String(s);case"cc":return It(s,r.length);case"co":return n.ordinalNumber(s,{unit:"day"});case"ccc":return n.day(o,{width:"abbreviated",context:"standalone"});case"ccccc":return n.day(o,{width:"narrow",context:"standalone"});case"cccccc":return n.day(o,{width:"short",context:"standalone"});default:return n.day(o,{width:"wide",context:"standalone"})}},i:function(t,r,n){var a=t.getUTCDay(),o=a===0?7:a;switch(r){case"i":return String(o);case"ii":return It(o,r.length);case"io":return n.ordinalNumber(o,{unit:"day"});case"iii":return n.day(a,{width:"abbreviated",context:"formatting"});case"iiiii":return n.day(a,{width:"narrow",context:"formatting"});case"iiiiii":return n.day(a,{width:"short",context:"formatting"});default:return n.day(a,{width:"wide",context:"formatting"})}},a:function(t,r,n){var a=t.getUTCHours(),o=a/12>=1?"pm":"am";switch(r){case"a":case"aa":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"});case"aaa":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"}).toLowerCase();case"aaaaa":return n.dayPeriod(o,{width:"narrow",context:"formatting"});default:return n.dayPeriod(o,{width:"wide",context:"formatting"})}},b:function(t,r,n){var a=t.getUTCHours(),o;switch(a===12?o=io.noon:a===0?o=io.midnight:o=a/12>=1?"pm":"am",r){case"b":case"bb":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"});case"bbb":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"}).toLowerCase();case"bbbbb":return n.dayPeriod(o,{width:"narrow",context:"formatting"});default:return n.dayPeriod(o,{width:"wide",context:"formatting"})}},B:function(t,r,n){var a=t.getUTCHours(),o;switch(a>=17?o=io.evening:a>=12?o=io.afternoon:a>=4?o=io.morning:o=io.night,r){case"B":case"BB":case"BBB":return n.dayPeriod(o,{width:"abbreviated",context:"formatting"});case"BBBBB":return n.dayPeriod(o,{width:"narrow",context:"formatting"});default:return n.dayPeriod(o,{width:"wide",context:"formatting"})}},h:function(t,r,n){if(r==="ho"){var a=t.getUTCHours()%12;return a===0&&(a=12),n.ordinalNumber(a,{unit:"hour"})}return kn.h(t,r)},H:function(t,r,n){return r==="Ho"?n.ordinalNumber(t.getUTCHours(),{unit:"hour"}):kn.H(t,r)},K:function(t,r,n){var a=t.getUTCHours()%12;return r==="Ko"?n.ordinalNumber(a,{unit:"hour"}):It(a,r.length)},k:function(t,r,n){var a=t.getUTCHours();return a===0&&(a=24),r==="ko"?n.ordinalNumber(a,{unit:"hour"}):It(a,r.length)},m:function(t,r,n){return r==="mo"?n.ordinalNumber(t.getUTCMinutes(),{unit:"minute"}):kn.m(t,r)},s:function(t,r,n){return r==="so"?n.ordinalNumber(t.getUTCSeconds(),{unit:"second"}):kn.s(t,r)},S:function(t,r){return kn.S(t,r)},X:function(t,r,n,a){var o=a._originalDate||t,s=o.getTimezoneOffset();if(s===0)return"Z";switch(r){case"X":return UE(s);case"XXXX":case"XX":return _a(s);default:return _a(s,":")}},x:function(t,r,n,a){var o=a._originalDate||t,s=o.getTimezoneOffset();switch(r){case"x":return UE(s);case"xxxx":case"xx":return _a(s);default:return _a(s,":")}},O:function(t,r,n,a){var o=a._originalDate||t,s=o.getTimezoneOffset();switch(r){case"O":case"OO":case"OOO":return"GMT"+LE(s,":");default:return"GMT"+_a(s,":")}},z:function(t,r,n,a){var o=a._originalDate||t,s=o.getTimezoneOffset();switch(r){case"z":case"zz":case"zzz":return"GMT"+LE(s,":");default:return"GMT"+_a(s,":")}},t:function(t,r,n,a){var o=a._originalDate||t,s=Math.floor(o.getTime()/1e3);return It(s,r.length)},T:function(t,r,n,a){var o=a._originalDate||t,s=o.getTime();return It(s,r.length)}};function LE(e,t){var r=e>0?"-":"+",n=Math.abs(e),a=Math.floor(n/60),o=n%60;if(o===0)return r+String(a);var s=t||"";return r+String(a)+s+It(o,2)}function UE(e,t){if(e%60===0){var r=e>0?"-":"+";return r+It(Math.abs(e)/60,2)}return _a(e,t)}function _a(e,t){var r=t||"",n=e>0?"-":"+",a=Math.abs(e),o=It(Math.floor(a/60),2),s=It(a%60,2);return n+o+r+s}var ME=FL;var kE=function(t,r){switch(t){case"P":return r.date({width:"short"});case"PP":return r.date({width:"medium"});case"PPP":return r.date({width:"long"});default:return r.date({width:"full"})}},FE=function(t,r){switch(t){case"p":return r.time({width:"short"});case"pp":return r.time({width:"medium"});case"ppp":return r.time({width:"long"});default:return r.time({width:"full"})}},HL=function(t,r){var n=t.match(/(P+)(p+)?/)||[],a=n[1],o=n[2];if(!o)return kE(t,r);var s;switch(a){case"P":s=r.dateTime({width:"short"});break;case"PP":s=r.dateTime({width:"medium"});break;case"PPP":s=r.dateTime({width:"long"});break;default:s=r.dateTime({width:"full"});break}return s.replace("{{date}}",kE(a,r)).replace("{{time}}",FE(o,r))},GL={p:FE,P:HL},HE=GL;var BL=["D","DD"],WL=["YY","YYYY"];function GE(e){return BL.indexOf(e)!==-1}function BE(e){return WL.indexOf(e)!==-1}function Ip(e,t,r){if(e==="YYYY")throw new RangeError("Use `yyyy` instead of `YYYY` (in `".concat(t,"`) for formatting years to the input `").concat(r,"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"));if(e==="YY")throw new RangeError("Use `yy` instead of `YY` (in `".concat(t,"`) for formatting years to the input `").concat(r,"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"));if(e==="D")throw new RangeError("Use `d` instead of `D` (in `".concat(t,"`) for formatting days of the month to the input `").concat(r,"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"));if(e==="DD")throw new RangeError("Use `dd` instead of `DD` (in `".concat(t,"`) for formatting days of the month to the input `").concat(r,"`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"))}var VL={lessThanXSeconds:{one:"less than a second",other:"less than {{count}} seconds"},xSeconds:{one:"1 second",other:"{{count}} seconds"},halfAMinute:"half a minute",lessThanXMinutes:{one:"less than a minute",other:"less than {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"about 1 hour",other:"about {{count}} hours"},xHours:{one:"1 hour",other:"{{count}} hours"},xDays:{one:"1 day",other:"{{count}} days"},aboutXWeeks:{one:"about 1 week",other:"about {{count}} weeks"},xWeeks:{one:"1 week",other:"{{count}} weeks"},aboutXMonths:{one:"about 1 month",other:"about {{count}} months"},xMonths:{one:"1 month",other:"{{count}} months"},aboutXYears:{one:"about 1 year",other:"about {{count}} years"},xYears:{one:"1 year",other:"{{count}} years"},overXYears:{one:"over 1 year",other:"over {{count}} years"},almostXYears:{one:"almost 1 year",other:"almost {{count}} years"}},qL=function(t,r,n){var a,o=VL[t];return typeof o=="string"?a=o:r===1?a=o.one:a=o.other.replace("{{count}}",r.toString()),n!=null&&n.addSuffix?n.comparison&&n.comparison>0?"in "+a:a+" ago":a},WE=qL;function ii(e){return function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},r=t.width?String(t.width):e.defaultWidth,n=e.formats[r]||e.formats[e.defaultWidth];return n}}var KL={full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},YL={full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},zL={full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},$L={date:ii({formats:KL,defaultWidth:"full"}),time:ii({formats:YL,defaultWidth:"full"}),dateTime:ii({formats:zL,defaultWidth:"full"})},VE=$L;var XL={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"},jL=function(t,r,n,a){return XL[t]},qE=jL;function ya(e){return function(t,r){var n=r!=null&&r.context?String(r.context):"standalone",a;if(n==="formatting"&&e.formattingValues){var o=e.defaultFormattingWidth||e.defaultWidth,s=r!=null&&r.width?String(r.width):o;a=e.formattingValues[s]||e.formattingValues[o]}else{var c=e.defaultWidth,u=r!=null&&r.width?String(r.width):e.defaultWidth;a=e.values[u]||e.values[c]}var f=e.argumentCallback?e.argumentCallback(t):t;return a[f]}}var QL={narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},ZL={narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},JL={narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},eU={narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},tU={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},rU={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},nU=function(t,r){var n=Number(t),a=n%100;if(a>20||a<10)switch(a%10){case 1:return n+"st";case 2:return n+"nd";case 3:return n+"rd"}return n+"th"},aU={ordinalNumber:nU,era:ya({values:QL,defaultWidth:"wide"}),quarter:ya({values:ZL,defaultWidth:"wide",argumentCallback:function(t){return t-1}}),month:ya({values:JL,defaultWidth:"wide"}),day:ya({values:eU,defaultWidth:"wide"}),dayPeriod:ya({values:tU,defaultWidth:"wide",formattingValues:rU,defaultFormattingWidth:"wide"})},KE=aU;function ba(e){return function(t){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=r.width,a=n&&e.matchPatterns[n]||e.matchPatterns[e.defaultMatchWidth],o=t.match(a);if(!o)return null;var s=o[0],c=n&&e.parsePatterns[n]||e.parsePatterns[e.defaultParseWidth],u=Array.isArray(c)?iU(c,function(w){return w.test(s)}):oU(c,function(w){return w.test(s)}),f;f=e.valueCallback?e.valueCallback(u):u,f=r.valueCallback?r.valueCallback(f):f;var d=t.slice(s.length);return{value:f,rest:d}}}function oU(e,t){for(var r in e)if(e.hasOwnProperty(r)&&t(e[r]))return r}function iU(e,t){for(var r=0;r1&&arguments[1]!==void 0?arguments[1]:{},n=t.match(e.matchPattern);if(!n)return null;var a=n[0],o=t.match(e.parsePattern);if(!o)return null;var s=e.valueCallback?e.valueCallback(o[0]):o[0];s=r.valueCallback?r.valueCallback(s):s;var c=t.slice(a.length);return{value:s,rest:c}}}var sU=/^(\d+)(th|st|nd|rd)?/i,cU=/\d+/i,uU={narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},lU={any:[/^b/i,/^(a|c)/i]},dU={narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},fU={any:[/1/i,/2/i,/3/i,/4/i]},pU={narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},hU={narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},mU={narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},gU={narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},_U={narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},yU={any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},bU={ordinalNumber:Sp({matchPattern:sU,parsePattern:cU,valueCallback:function(t){return parseInt(t,10)}}),era:ba({matchPatterns:uU,defaultMatchWidth:"wide",parsePatterns:lU,defaultParseWidth:"any"}),quarter:ba({matchPatterns:dU,defaultMatchWidth:"wide",parsePatterns:fU,defaultParseWidth:"any",valueCallback:function(t){return t+1}}),month:ba({matchPatterns:pU,defaultMatchWidth:"wide",parsePatterns:hU,defaultParseWidth:"any"}),day:ba({matchPatterns:mU,defaultMatchWidth:"wide",parsePatterns:gU,defaultParseWidth:"any"}),dayPeriod:ba({matchPatterns:_U,defaultMatchWidth:"any",parsePatterns:yU,defaultParseWidth:"any"})},YE=bU;var vU={code:"en-US",formatDistance:WE,formatLong:VE,formatRelative:qE,localize:KE,match:YE,options:{weekStartsOn:0,firstWeekContainsDate:1}},zE=vU;var $E=zE;var EU=/[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g,wU=/P+p+|P+|p+|''|'(''|[^'])+('|$)|./g,AU=/^'([^]*?)'?$/,TU=/''/g,NU=/[a-zA-Z]/;function Rr(e,t,r){var n,a,o,s,c,u,f,d,w,R,h,p,T,A,C,S,k,v;ft(2,arguments);var _=String(t),g=Qn(),O=(n=(a=r?.locale)!==null&&a!==void 0?a:g.locale)!==null&&n!==void 0?n:$E,E=Pt((o=(s=(c=(u=r?.firstWeekContainsDate)!==null&&u!==void 0?u:r==null||(f=r.locale)===null||f===void 0||(d=f.options)===null||d===void 0?void 0:d.firstWeekContainsDate)!==null&&c!==void 0?c:g.firstWeekContainsDate)!==null&&s!==void 0?s:(w=g.locale)===null||w===void 0||(R=w.options)===null||R===void 0?void 0:R.firstWeekContainsDate)!==null&&o!==void 0?o:1);if(!(E>=1&&E<=7))throw new RangeError("firstWeekContainsDate must be between 1 and 7 inclusively");var m=Pt((h=(p=(T=(A=r?.weekStartsOn)!==null&&A!==void 0?A:r==null||(C=r.locale)===null||C===void 0||(S=C.options)===null||S===void 0?void 0:S.weekStartsOn)!==null&&T!==void 0?T:g.weekStartsOn)!==null&&p!==void 0?p:(k=g.locale)===null||k===void 0||(v=k.options)===null||v===void 0?void 0:v.weekStartsOn)!==null&&h!==void 0?h:0);if(!(m>=0&&m<=6))throw new RangeError("weekStartsOn must be between 0 and 6 inclusively");if(!O.localize)throw new RangeError("locale must contain localize property");if(!O.formatLong)throw new RangeError("locale must contain formatLong property");var y=Vt(e);if(!Ep(y))throw new RangeError("Invalid time value");var b=bp(y),x=wp(y,b),D={firstWeekContainsDate:E,weekStartsOn:m,locale:O,_originalDate:y},F=_.match(wU).map(function(B){var K=B[0];if(K==="p"||K==="P"){var Z=HE[K];return Z(B,O.formatLong)}return B}).join("").match(EU).map(function(B){if(B==="''")return"'";var K=B[0];if(K==="'")return RU(B);var Z=ME[K];if(Z)return!(r!=null&&r.useAdditionalWeekYearTokens)&&BE(B)&&Ip(B,t,String(e)),!(r!=null&&r.useAdditionalDayOfYearTokens)&&GE(B)&&Ip(B,t,String(e)),Z(x,B,O.localize,D);if(K.match(NU))throw new RangeError("Format string contains an unescaped latin alphabet character `"+K+"`");return B}).join("");return F}function RU(e){var t=e.match(AU);return t?t[1].replace(TU,"'"):e}function Cp(e,t){ft(2,arguments);var r=Pt(t);return gp(e,-r)}function Op(e,t){ft(2,arguments);var r=Pt(t);return _p(e,-r)}function iu(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?iu=function(r){return typeof r}:iu=function(r){return r&&typeof Symbol=="function"&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},iu(e)}function Xr(e,t){if(ft(2,arguments),!t||iu(t)!=="object")return new Date(NaN);var r=t.years?Pt(t.years):0,n=t.months?Pt(t.months):0,a=t.weeks?Pt(t.weeks):0,o=t.days?Pt(t.days):0,s=t.hours?Pt(t.hours):0,c=t.minutes?Pt(t.minutes):0,u=t.seconds?Pt(t.seconds):0,f=Op(e,n+r*12),d=Cp(f,o+a*7),w=c+s*60,R=u+w*60,h=R*1e3,p=new Date(d.getTime()-h);return p}Re();function XE({transactions:e,routeCreateWireTransfer:t,onGoNext:r,onGoStart:n}){let{i18n:a,dateLocale:o}=Ne(),{config:s}=De();if(!e.length)return i("div",{class:"px-4 mt-4"},i("div",{class:"sm:flex sm:items-center"},i("div",{class:"sm:flex-auto"},i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(a.Translate,null,"Transactions history")))),i(Pe,{type:"low",title:a.str`No transactions yet.`},i(a.Translate,null,"You can make a transfer or a withdrawal to your wallet.")));let c=e.reduce((u,f)=>{let d=f.when.t_ms==="never"?"":Rr(f.when.t_ms,"dd/MM/yyyy",{locale:o});return u[d]||(u[d]=[]),u[d].push(f),u},{});return i("div",{class:"px-4 mt-8"},i("div",{class:"sm:flex sm:items-center"},i("div",{class:"sm:flex-auto"},i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(a.Translate,null,"Transactions history")))),i("div",{class:"-mx-4 mt-5 ring-1 ring-gray-300 sm:mx-0 rounded-lg min-w-fit bg-white"},i("table",{class:"min-w-full divide-y divide-gray-300"},i("thead",null,i("tr",null,i("th",{scope:"col",class:"pl-2 py-3.5 text-left text-sm font-semibold text-gray-900 "},a.str`Date`),i("th",{scope:"col",class:"hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900 "},a.str`Amount`),i("th",{scope:"col",class:"hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900 "},a.str`Counterpart`),i("th",{scope:"col",class:"hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900 "},a.str`Subject`))),i("tbody",null,Object.entries(c).map(([u,f],d)=>i(ae,{key:d},i("tr",{class:"border-t border-gray-200"},i("th",{colSpan:4,scope:"colgroup",class:"bg-gray-50 py-2 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-3"},u)),f.map(w=>i("tr",{key:d,class:"border-b border-gray-200 last:border-none"},i("td",{class:"relative py-2 pl-2 pr-2 text-sm "},i("div",{class:"font-medium text-gray-900"},i(ln,{format:"HH:mm:ss",timestamp:w.when})),i("dl",{class:"font-normal sm:hidden"},i("dt",{class:"sr-only sm:hidden"},i(a.Translate,null,"Amount")),i("dd",{class:"mt-1 truncate text-gray-700"},w.negative?a.str`sent`:a.str`received`," ",w.amount?i("span",{"data-negative":w.negative?"true":"false",class:"data-[negative=false]:text-green-600 data-[negative=true]:text-red-600"},i(Xe,{value:w.amount,spec:s.currency_specification})):i("span",{class:"text-[grey]"},"<",a.str`Invalid value`,">")),i("dt",{class:"sr-only sm:hidden"},i(a.Translate,null,"Counterpart")),i("dd",{class:"mt-1 truncate text-gray-500 sm:hidden"},w.negative?a.str`to`:a.str`from`," ",t?i("a",{name:`transfer to ${w.counterpart}`,href:t.url({account:w.counterpart}),class:"text-indigo-600 hover:text-indigo-900"},w.counterpart):w.counterpart),i("dd",{class:"mt-1 text-gray-500 sm:hidden"},i("pre",{class:"break-words w-56 whitespace-break-spaces p-2 rounded-md mx-auto my-2 bg-gray-100"},w.subject)))),i("td",{"data-negative":w.negative?"true":"false",class:"hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 "},w.amount?i(Xe,{value:w.amount,negative:w.negative,withColor:!0,withSign:!0,spec:s.currency_specification}):i("span",{class:"text-[grey]"},"<",a.str`Invalid value`,">")),i("td",{class:"hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500"},t?i("a",{name:`wire transfer to ${w.counterpart}`,href:t.url({account:w.counterpart}),class:"text-indigo-600 hover:text-indigo-900"},w.counterpart):w.counterpart),i("td",{class:"hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 break-all min-w-md"},w.subject))))))),i("nav",{class:"flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg","aria-label":"Pagination"},i("div",{class:"flex flex-1 justify-between sm:justify-end"},i("button",{type:"button",name:"first page",class:"relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0",disabled:!n,onClick:n},i(a.Translate,null,"First page")),i("button",{type:"button",name:"next page",class:"relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0",disabled:!r,onClick:r},i(a.Translate,null,"Next"))))))}var xU={loading:st,"loading-error":_t,ready:XE},so=un.compose(e=>PE(e),xU);Re();Re();pa();Be();var IU=()=>W().property("operation",X("update-password")).property("id",L()).property("location",va()).property("sent",Br).property("request",He()).build("UpdatePasswordChallenge"),SU=()=>W().property("operation",X("delete-account")).property("id",L()).property("location",va()).property("sent",Br).property("request",L()).build("DeleteAccountChallenge"),CU=()=>W().property("operation",X("update-account")).property("id",L()).property("location",va()).property("sent",Br).property("request",He()).build("UpdateAccountChallenge"),OU=()=>W().property("operation",X("create-transaction")).property("id",L()).property("location",va()).property("sent",Br).property("request",He()).build("CreateTransactionChallenge"),DU=()=>W().property("operation",X("confirm-withdrawal")).property("id",L()).property("location",va()).property("sent",Br).property("request",He()).build("ConfirmWithdrawalChallenge"),va=L,PU=()=>W().property("operation",X("create-cashout")).property("id",L()).property("location",va()).property("sent",Br).property("request",He()).build("CashoutChallenge"),LU=()=>W().property("operation",X("login")).property("id",L()).property("location",U(va())).property("sent",Br).property("request",He()).build("LoginChallenge"),UU=()=>wt().discriminateOn("operation").alternative("confirm-withdrawal",DU()).alternative("create-cashout",PU()).alternative("create-transaction",OU()).alternative("delete-account",SU()).alternative("update-account",CU()).alternative("update-password",IU()).alternative("login",LU()).build("ChallengeInProgess"),MU=()=>W().property("currentWithdrawalOperationId",U(L())).property("currentChallenge",U(UU())).build("BankState"),jE={currentWithdrawalOperationId:void 0,currentChallenge:void 0},kU=Xn("bank-app-state",MU());function ea(){let{value:e,update:t}=ga(kU,jE);function r(a,o){let s={...e,[a]:o};t(s)}function n(){t(jE)}return[e,r,n]}Be();function QE({routeClose:e,onAbort:t,focus:r}){let[n]=Hr(),a=An(),[o,s]=ea(),{state:c}=We(),u=c.status!=="loggedIn"?void 0:c,{config:f,lib:{bank:d}}=De(),[w,R]=de(),h=a.defaultSuggestedAmount;async function p(){let S=J.parseOrThrow(`${f.currency}:${h}`);if(!u)return;let k=n.fastWithdrawalForm?{suggested_amount:J.stringify(S)}:{amount:J.stringify(S)},v=await d.createWithdrawal(u,k);if(v.type==="fail"){R(v);return}s("currentWithdrawalOperationId",v.body.withdrawal_id)}let T=o.currentWithdrawalOperationId;if(Ge(()=>{T===void 0&&p()},[n.fastWithdrawalForm,h]),w)return{status:"failed",error:w};if(!T)return{status:"loading",error:void 0};let A=_r.createTalerWithdraw(d.getIntegrationAPI().href,T),C=_r.toString(A);return A?()=>{let S=tu(T),k=S&&(S instanceof Oe||S.type==="fail"||S.body.status==="aborted"||S.body.status==="confirmed");if(Ge(()=>{k&&p()},[k]),!S)return{status:"loading",error:void 0};if(S instanceof Oe)return{status:"loading-error",error:S};if(S.type==="fail")switch(S.case){case l.BadRequest:case l.NotFound:return{status:"aborted",error:void 0,routeClose:e};default:ue(S)}let{body:v}=S;if(v.status==="aborted")return{status:"aborted",error:void 0,routeClose:e};if(v.status==="confirmed")return n.showWithdrawalSuccess||s("currentWithdrawalOperationId",void 0),{status:"confirmed",error:void 0,routeClose:e};if(v.status==="pending")return{status:"ready",error:void 0,uri:A,routeClose:e,focus:r,operationId:T,onAbort:t};if(!v.selected_reserve_pub)return{status:"invalid-reserve",error:void 0,reserve:v.selected_reserve_pub};let _=v.selected_exchange_account?$e.fromString(v.selected_exchange_account):void 0;return!_||_.tag==="error"||!_.value.targetType?{status:"invalid-payto",error:void 0,payto:v.selected_exchange_account}:{status:"need-confirmation",error:void 0,details:{account:_.value,reserve:v.selected_reserve_pub,username:v.username,amount:v.amount?J.parse(v.amount):void 0},account:v.username,operationId:T,onAbort:t}}:{status:"invalid-withdrawal",error:void 0,uri:C}}Re();Be();Re();Be();var r1=ui(t1(),1);function su({text:e}){let t=Yt(null);return Ge(()=>{let r=(0,r1.default)(0,"L");r.addData(e),r.make(),t.current&&(t.current.innerHTML=r.createSvgTag({scalable:!0}))}),i("div",{class:"flex flex-col "},i("div",{class:"mx-auto w-full",ref:t}))}Re();function FU(e){let{state:t}=We(),r=t.status!=="loggedIn"?void 0:t,[n,a]=ht(),{i18n:o}=Ne(),s=br(),{config:c,lib:{bank:u}}=De(),f=c.wire_transfer_fees===void 0?J.zeroOfCurrency(c.currency):J.parseOrThrow(c.wire_transfer_fees),d=a(o.str`confirm withdrawal`,(p,T)=>u.confirmWithdrawalById(p,{},e,{challengeIds:T}),r?[r,[]]:void 0);d.onSuccess=()=>{vr(()=>!0)},d.onFail=p=>{switch(p.case){case l.Accepted:case l.BadRequest:case l.NotFound:case G.BANK_UNALLOWED_DEBIT:case G.BANK_CONFIRM_ABORT_CONFLICT:case G.BANK_CONFIRM_INCOMPLETE:case G.BANK_AMOUNT_DIFFERS:case G.BANK_AMOUNT_REQUIRED:return o.str`cambiar`;default:ue(p)}};let w=d.lambda(p=>[d.args[0],p]),R=a(o.str`abort withdrawal`,u.abortWithdrawalById.bind(u),r?[r,e]:void 0);R.onSuccess=()=>{vr(()=>!0)},R.onFail=p=>{switch(p.case){case l.BadRequest:case l.NotFound:case l.Conflict:return o.str`cambiar`;default:ue(p)}};let h=c.currency_specification;return{notification:n,mfa:s,wireFee:f,spec:h,abort:R,confirm:d,repeat:w}}function n1({details:e,withdrawUri:t}){let{i18n:r}=Ne(),{notification:n,mfa:a,wireFee:o,spec:s,abort:c,confirm:u,repeat:f}=FU(t.withdrawalOperationId);return u.onFail=d=>{switch(d.case){case G.BANK_CONFIRM_ABORT_CONFLICT:return r.str`The withdrawal has been aborted previously and can't be confirmed`;case G.BANK_CONFIRM_INCOMPLETE:return r.str`The withdrawal operation can't be confirmed before a wallet accepted the transaction.`;case l.BadRequest:return r.str`The operation ID is invalid.`;case l.NotFound:return r.str`The operation was not found.`;case G.BANK_UNALLOWED_DEBIT:return r.str`Your balance is not sufficient for the operation.`;case G.BANK_AMOUNT_DIFFERS:return r.str`The starting withdrawal amount and the confirmation amount differs.`;case G.BANK_AMOUNT_REQUIRED:return r.str`The bank requires a bank account which has not been specified yet.`;case l.Accepted:return a.onChallengeRequired(d.body),r.str`A second factor authentication is required.`}},c.onFail=d=>{switch(d.case){case l.BadRequest:return r.str`Bad request`;case l.NotFound:return r.str`The withdrawal operation has been aborted.`;case l.Conflict:return r.str`The withdrawal operation has been confirmed previously and can’t be aborted.`}},a.pendingChallenge?i(Er,{currentChallenge:a.pendingChallenge,description:r.str`Complete withdrawal.`,onCancel:a.doCancelChallenge,onCompleted:f,username:e.username}):i(ae,null,i(yt,{notification:n}),i("div",{class:"bg-white shadow sm:rounded-lg"},i("div",{class:"px-4 py-5 sm:p-6"},i("h3",{class:"text-base font-semibold text-gray-900"},i(r.Translate,null,"Confirm the withdrawal operation")),i("div",{class:"mt-3 text-sm leading-6"},i(Dp,{username:e.username},i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-4 md:grid-cols-2 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:d=>{d.preventDefault()}},i("div",{class:"px-4 mt-4"},i("div",{class:"w-full"},i("div",{class:"px-4 sm:px-0 text-sm"},i("p",null,i(r.Translate,null,"Wire transfer details"))),i("div",{class:"mt-6 border-t border-gray-100"},i("dl",{class:"divide-y divide-gray-100"},(()=>{switch(e.account.targetType){case void 0:case Je.TalerReserveHttp:case Je.TalerReserve:return i("div",null,"not yet supported");case Je.IBAN:{let d=e.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's account number")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},e.account.iban)),d&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},d)))}case Je.TalerBank:{let d=e.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's account bank hostname")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},e.account.host)),i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's account id")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},e.account.account)),d&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},d)))}case Je.Bitcoin:{let d=e.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's account address")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},e.account.address)),d&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},d)))}case Je.Ethereum:{let d=e.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's account address")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},e.account.address)),d&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},d)))}case Je.Cyclos:{let d=e.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's account cyclos hostname")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},e.account.url)),i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's account id")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},e.account.account)),d&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},d)))}default:ue(e.account)}})(),i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Amount")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},e.amount!==void 0?i(Xe,{value:e.amount,spec:s}):i(r.Translate,null,"No amount has yet been determined."))),J.isZero(o)?void 0:i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(r.Translate,null,"Cost")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},i(Xe,{value:o,negative:!0,withColor:!0,spec:s})))))))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i(Ze,{type:"button",name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900",onClick:c},i(r.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"transfer",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:u},i(r.Translate,null,"Transfer"))))))))))}function Dp({username:e,children:t}){let{state:r}=We(),{i18n:n}=Ne();return r.status==="loggedOut"?i(ae,null,i(Pe,{type:"info",title:n.str`Authentication required`}),i(er,{currentUser:e,fixedUser:!0})):r.status==="expired"?i(er,{currentUser:e,fixedUser:!0}):r.username!==e?i(ae,null,i(Pe,{type:"warning",title:n.str`This operation was created with another username`},i("p",null,i(n.Translate,null,'You are currently logged in with user "',r.username,'" and the operation was made with user "',e,'"'))),i(er,{currentUser:e,fixedUser:!0})):i(ae,null,t)}function a1({payto:e}){return i("div",null,'Payto from server is not valid "',e,'"')}function o1({uri:e}){return i("div",null,'Withdrawal uri from server is not valid "',e,'"')}function i1({reserve:e}){return i("div",null,'Reserve from server is not valid "',e,'"')}function s1({onAbort:e,account:t,details:r,operationId:n}){let{i18n:a}=Ne(),[o]=Hr(),[s,c]=ht(),{state:u}=We(),f=u.status!=="loggedIn"?void 0:u,d=br(),{config:w,lib:{bank:R}}=De(),h=w.wire_transfer_fees===void 0?J.zeroOfCurrency(w.currency):J.parseOrThrow(w.wire_transfer_fees),p=c(a.str`abort withdrawal`,C=>R.abortWithdrawalById(C,n),f?[f]:void 0);p.onSuccess=e,p.onFail=C=>{switch(C.case){case l.Conflict:return a.str`The reserve operation has been confirmed previously and can't be aborted`;case l.BadRequest:return a.str`The operation ID is invalid.`;case l.NotFound:return a.str`The operation was not found.`;default:ue(C)}};let T=c(a.str`confirm withdrawal`,(C,S)=>R.confirmWithdrawalById(C,{},n,{challengeIds:S}),f?[f,[]]:void 0);T.onSuccess=()=>{o.showWithdrawalSuccess||pr(a.str`Wire transfer completed!`),e()},T.onFail=C=>{switch(C.case){case G.BANK_CONFIRM_ABORT_CONFLICT:return a.str`The withdrawal has been aborted previously and can't be confirmed`;case G.BANK_CONFIRM_INCOMPLETE:return a.str`The withdrawal operation can't be confirmed before a wallet accepted the transaction.`;case l.BadRequest:return a.str`The operation ID is invalid.`;case l.NotFound:return a.str`The operation was not found.`;case G.BANK_UNALLOWED_DEBIT:return a.str`Your balance is not sufficient for the operation.`;case l.Accepted:return d.onChallengeRequired(C.body),a.str`A second factor authentication is required.`;case G.BANK_AMOUNT_DIFFERS:return a.str`The starting withdrawal amount and the confirmation amount differs.`;case G.BANK_AMOUNT_REQUIRED:return a.str`The bank requires a bank account which has not been specified yet.`;default:ue(C)}};let A=T.lambda(C=>[T.args[0],C]);return d.pendingChallenge?i(Er,{currentChallenge:d.pendingChallenge,description:a.str`Confirm withdrawal.`,username:r.username,onCancel:d.doCancelChallenge,onCompleted:A}):i("div",{class:"bg-white shadow sm:rounded-lg"},i(yt,{notification:s}),i("div",{class:"px-4 py-5 sm:p-6"},i("h3",{class:"text-base font-semibold text-gray-900"},i(a.Translate,null,"Confirm the withdrawal operation")),i("div",{class:"mt-3 text-sm leading-6"},i(Dp,{username:t},i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:C=>{C.preventDefault()}},i("div",{class:"px-4 mt-4"},i("div",{class:"w-full"},i("dl",{class:""},(()=>{switch(r.account.targetType){case void 0:case Je.TalerReserveHttp:case Je.TalerReserve:return i("div",null,"not yet supported");case Je.IBAN:{let C=r.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's account number")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},r.account.iban)),C&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},C)))}case Je.TalerBank:{let C=r.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's account bank hostname")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},r.account.host)),i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's account id")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},r.account.account)),C&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},C)))}case Je.Bitcoin:{let C=r.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's account address")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},r.account.address)),C&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},C)))}case Je.Ethereum:{let C=r.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's account address")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},r.account.address)),C&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},C)))}case Je.Cyclos:{let C=r.account.params["receiver-name"];return i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's account cyclos hostname")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},r.account.url)),i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's account id")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},r.account.account)),C&&i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Payment Service Provider's name")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},C)))}default:ue(r.account)}})(),i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Amount")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},r.amount!==void 0?i(Xe,{value:r.amount,spec:w.currency_specification}):i(a.Translate,null,"No amount has yet been determined."))),J.isZero(h)?void 0:i(ae,null,i("div",{class:"px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"},i("dt",{class:"text-sm font-medium leading-6 text-gray-900"},i(a.Translate,null,"Cost")),i("dd",{class:"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"},i(Xe,{value:h,negative:!0,withColor:!0,spec:w.currency_specification}))))))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i(Ze,{type:"button",name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900",onClick:p},i(a.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"transfer",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:T},i(a.Translate,null,"Transfer"))))))))}function c1({error:e}){let{i18n:t}=Ne();switch(e.case){case l.Unauthorized:return i(Pe,{type:"danger",title:t.str`Unauthorized to make the operation, maybe the session has expired or the password changed.`},e.detail?i("div",{class:"mt-2 text-sm text-red-700"},e.detail.hint):void 0);case l.Conflict:return i(Pe,{type:"danger",title:t.str`The operation was rejected due to insufficient funds.`},e.detail?i("div",{class:"mt-2 text-sm text-red-700"},e.detail.hint):void 0);case l.NotFound:return i(Pe,{type:"danger",title:t.str`The operation was rejected due to insufficient funds.`},e.detail?i("div",{class:"mt-2 text-sm text-red-700"},e.detail.hint):void 0);default:ue(e)}}function u1(){return i("div",null,"aborted")}function l1({routeClose:e}){let{i18n:t}=Ne(),[r,n]=Hr();return i(ae,null,i("div",{class:"relative ml-auto mr-auto transform overflow-hidden rounded-lg bg-white p-4 text-left shadow-xl transition-all "},i("div",{class:"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100"},i("svg",{class:"h-6 w-6 text-green-600",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M4.5 12.75l6 6 9-13.5"}))),i("div",{class:"mt-3 text-center sm:mt-5"},i("h3",{class:"text-base font-semibold leading-6 text-gray-900",id:"modal-title"},i(t.Translate,null,"Withdrawal confirmed")),i("div",{class:"mt-2"},i("p",{class:"text-sm text-gray-500"},i(t.Translate,null,"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet."," "))))),i("div",{class:"mt-4"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(t.Translate,null,"Do not show this again"))),i("button",{type:"button",name:"toggle withdrawal","data-enabled":!r.showWithdrawalSuccess,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{n("showWithdrawalSuccess",!r.showWithdrawalSuccess)}},i("span",{"aria-hidden":"true","data-enabled":!r.showWithdrawalSuccess,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))),i("div",{class:"mt-5 sm:mt-6"},i("a",{href:e.url({}),type:"button",name:"close",class:"inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(t.Translate,null,"Close"))))}function d1({uri:e,focus:t,onAbort:r,operationId:n}){let{i18n:a}=Ne(),o=zc(),[s,c]=ht(),{state:u}=We(),f=u.status!=="loggedIn"?void 0:u,{config:d,lib:{bank:w}}=De(),R=_r.createTalerWithdraw(e.bankIntegrationApiBaseUrl,e.withdrawalOperationId),h=_r.toString(R);Ge(()=>{o.publishTalerAction(e)},[]);let p=c(a.str`abort withdrawal`,T=>w.abortWithdrawalById(T,n),f?[f]:void 0);return p.onSuccess=r,p.onFail=T=>{switch(T.case){case l.Conflict:return a.str`The reserve operation has been confirmed previously and can't be aborted`;case l.BadRequest:return a.str`The operation ID is invalid.`;case l.NotFound:return a.str`The operation was not found.`}},i(ae,null,i(yt,{notification:s}),i("div",{class:"bg-white shadow-xl sm:rounded-lg"},i("div",{class:"px-4 py-5 sm:p-6"},i("h3",{class:"text-base font-semibold leading-6 text-gray-900"},i(a.Translate,null,"If you have a Taler wallet installed on this device")),i("div",{class:"mt-4 mb-4 text-sm text-gray-500"},i("p",null,i(a.Translate,null,"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions")," ",i("a",{class:"font-semibold text-indigo-600 hover:text-indigo-900",name:"wallet page",href:"https://taler.net/en/wallet.html"},i(a.Translate,null,"on this page")),".")),i("div",{class:"flex items-center justify-between gap-x-6 pt-2 mt-2 "},i(Ze,{type:"button",name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900",onClick:p},i(a.Translate,null,"Cancel")),i("a",{href:h,name:"withdraw",class:"inline-flex items-center disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(a.Translate,null,"Withdraw"))))),i("div",{class:"bg-white shadow-xl sm:rounded-lg mt-8"},i("div",{class:"px-4 py-5 sm:p-6"},i("h3",{class:"text-base font-semibold leading-6 text-gray-900"},i(a.Translate,null,"In case you have a Taler wallet on another device")),i("div",{class:"mt-4 max-w-xl text-sm text-gray-500"},i(a.Translate,null,"Scan the QR below to start the withdrawal.")),i("div",{class:"mt-2 max-w-md ml-auto mr-auto"},i(su,{text:h}))),i("div",{class:"flex items-center justify-center gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i(Ze,{type:"button",class:"text-sm font-semibold leading-6 text-gray-900",onClick:p},i(a.Translate,null,"Cancel")))))}var HU={loading:st,failed:c1,"invalid-payto":a1,"invalid-withdrawal":o1,"invalid-reserve":i1,"need-confirmation":s1,aborted:u1,confirmed:l1,"loading-error":_t,ready:d1},f1=un.compose(e=>QE(e),HU);var GU=ws(Fr);function BU({onOperationCreated:e,limit:t,balance:r,routeCancel:n,focus:a}){let{i18n:o}=Ne(),s=An(),[c]=Hr(),[,u]=ea(),{lib:{bank:f},config:d}=De(),{state:w}=We(),R=w.status!=="loggedIn"?void 0:w,[h,p]=de(`${s.defaultSuggestedAmount??1}`),[T,A]=ht(),C=h?.trim(),S=C?J.parse(`${t.currency}:${C}`):void 0,k=Ht({amount:C==null?o.str`Required`:S?J.cmp(t,S)===-1?o.str`Balance is not enough`:void 0:o.str`Invalid`}),v=A(o.str`create withdrawal`,(_,g)=>f.createWithdrawal(_,c.fastWithdrawalForm?{suggested_amount:g}:{amount:g}),!S||!R?void 0:[R,J.stringify(S)]);return v.onSuccess=_=>{let g=_r.fromString(_.taler_withdraw_uri);if(g.tag==="error"||g.value.type!==Ee.Withdraw)return Kc(o.str`The server replied with an invalid taler://withdraw URI`,o.str`Withdraw URI: ${_.taler_withdraw_uri}`);u("currentWithdrawalOperationId",g.value.withdrawalOperationId),e(g.value.withdrawalOperationId)},v.onFail=_=>{switch(_.case){case l.Conflict:return o.str`The operation was rejected due to insufficient funds`;case l.Unauthorized:return o.str`The operation was rejected due to insufficient funds`;case l.NotFound:return o.str`Account not found`;default:ue(_)}},i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2 mt-4",autoCapitalize:"none",autoCorrect:"off",onSubmit:_=>{_.preventDefault()}},i(yt,{notification:T}),i("div",{class:"px-4 py-6 "},i("div",{class:"grid max-w-xs grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{for:"withdraw-amount"},o.str`Amount`),i(GU,{currency:t.currency,value:h,name:"withdraw-amount",onChange:_=>{p(_)},ref:a?or:void 0})),i(nt,{message:k?.amount,isDirty:h!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(o.Translate,null,"Current balance is"," ",i(Xe,{value:r,spec:d.currency_specification}))),J.cmp(t,r)>0?i("p",{class:"mt-2 text-sm text-gray-900"},i(o.Translate,null,"You can withdraw up to"," ",i(Xe,{value:t,spec:d.currency_specification}))):void 0,i("div",{class:"mt-4"},i("div",{class:"sm:inline"},i("button",{type:"button",name:"set 50",class:" inline-flex px-6 py-4 text-sm items-center rounded-l-md bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10",onClick:_=>{_.preventDefault(),p("50.00")}},"50.00"),i("button",{type:"button",name:"set 25",class:" -ml-px -mr-px inline-flex px-6 py-4 text-sm items-center rounded-r-md sm:rounded-none bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10",onClick:_=>{_.preventDefault(),p("25.00")}},"25.00")),i("div",{class:"mt-4 sm:inline"},i("button",{type:"button",name:"set 10",class:" -ml-px -mr-px inline-flex px-6 py-4 text-sm items-center rounded-l-md sm:rounded-none bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10",onClick:_=>{_.preventDefault(),p("10.00")}},"10.00"),i("button",{type:"button",name:"set 5",class:" inline-flex px-6 py-4 text-sm items-center rounded-r-md bg-white text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10",onClick:_=>{_.preventDefault(),p("5.00")}},"5.00")))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{href:n.url({}),name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900"},i(o.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"continue",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:v},i(o.Translate,null,"Continue"))))}function p1({focus:e,limit:t,balance:r,routeCancel:n,onOperationCreated:a,onOperationAborted:o}){let{i18n:s}=Ne(),[c,u]=Hr();return i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i(s.Translate,null,"Use your Taler wallet")),i("p",{class:"mt-1 text-sm text-gray-500"},i(s.Translate,null,"After using your wallet you will need to authorize or cancel the operation on this site."))),i("div",{class:"col-span-2"},c.showInstallWallet&&i(Pe,{title:s.str`You need a Taler wallet`,onClose:()=>{u("showInstallWallet",!1)}},i(s.Translate,null,"If you don't have one yet you can follow the instruction in")," ",i("a",{target:"_blank",name:"wallet page",rel:"noreferrer noopener",class:"font-semibold text-blue-700 hover:text-blue-600",href:"https://taler.net/en/wallet.html"},i(s.Translate,null,"this page"))),c.fastWithdrawalForm?i(f1,{focus:e,routeClose:n,onAbort:o}):i(BU,{focus:e,limit:t,balance:r,routeCancel:n,onOperationCreated:a})))}function h1({routeClose:e,routeCashout:t,routeChargeWallet:r,routeWireTransfer:n,tab:a,limit:o,balance:s,onOperationCreated:c,onClose:u,routeOperationDetails:f}){let{i18n:d}=Ne();return i("div",{class:"mt-4"},i("fieldset",null,i("legend",{class:"px-4 text-base font-semibold leading-6 text-gray-900"},i(d.Translate,null,"Send money")),i("div",{class:"px-4 mt-4 grid grid-cols-1 gap-y-6 sm:grid-cols-2 sm:gap-x-4"},i("a",{name:"charge wallet",href:r.url({})},i("label",{class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none"+(a==="charge-wallet"?"border-indigo-600 ring-2 ring-indigo-600":"border-gray-300")},i("div",{class:"flex flex-col"},i("span",{class:"flex"},i("div",{class:"text-4xl mr-4 my-auto"},"\u{1F4B5}"),i("span",{class:"grow self-center text-lg text-gray-900 align-middle text-center"},i(d.Translate,null,"to a Taler wallet")),i("svg",{"data-selection":a,class:"self-center flex-none h-5 w-5 text-indigo-600 invisible data-[selection=charge-wallet]:visible",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"}))),i("div",{class:"mt-1 flex items-center text-sm text-gray-500"},i(d.Translate,null,"Withdraw digital money into your mobile wallet or browser extension"))))),i("a",{name:"wire transfer",href:n.url({})},i("label",{class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none"+(a==="wire-transfer"?"border-indigo-600 ring-2 ring-indigo-600":"border-gray-300")},i("div",{class:"flex flex-col"},i("span",{class:"flex"},i("div",{class:"text-4xl mr-4 my-auto"},"\u2194"),i("span",{class:"grow self-center text-lg font-medium text-gray-900 align-middle text-center"},i(d.Translate,null,"to another bank account")),i("svg",{"data-selection":a,class:"self-center flex-none h-5 w-5 text-indigo-600 invisible data-[selection=wire-transfer]:visible",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"}))),i("div",{class:"mt-1 flex items-center text-sm text-gray-500"},i(d.Translate,null,"Make a wire transfer to an account with known bank account number.")))))),a==="charge-wallet"&&i(p1,{focus:!0,limit:o,balance:s,onOperationCreated:c,onOperationAborted:u,routeCancel:e}),a==="wire-transfer"&&i(nu,{focus:!0,limit:o,balance:s,onSuccess:u,routeCashout:t,routeCancel:e})))}function m1({error:e}){return i("div",null,'Payto from server is not valid "',e.payto_uri,'"')}var WU=!1;function VU({routePublicAccounts:e}){let{i18n:t}=Ne(),r=An(),[n,a]=Hr();return!r.showDemoDescription||n.hideDemo?i(ae,null):i(Pe,{title:t.str`This is a demo`,onClose:()=>{a("hideDemo",!0)}},WU?i(t.Translate,null,"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some"," ",i("a",{name:"public account",href:e.url({})},"Public Accounts"),"."):i(t.Translate,null,"Here you will be able to see how a bank that supports Taler directly would work."))}function g1({tab:e,account:t,routeChargeWallet:r,routeWireTransfer:n,limit:a,balance:o,routeCashout:s,routeCreateWireTransfer:c,routePublicAccounts:u,routeOperationDetails:f,onClose:d,routeClose:w,onOperationCreated:R}){return i(ae,null,i(VU,{routePublicAccounts:u}),i(h1,{tab:e,routeOperationDetails:f,routeCashout:s,routeChargeWallet:r,routeWireTransfer:n,limit:a,balance:o,routeClose:w,onClose:d,onOperationCreated:R}),i(so,{account:t,routeCreateWireTransfer:c}))}var qU={loading:st,login:er,"invalid-iban":m1,"loading-error":_t,ready:g1},cu=un.compose(e=>DE(e),qU);Re();Be();var uu=103,KU="b048d0ea9b9378b4802611de548129fbb1b996ac",YU="1.5.14";co.SCREEN_ID=uu;function co({children:e,account:t,routeAccountDetails:r,routeNotifications:n}){let{i18n:a}=Ne(),o=We(),s=An(),[{showDebugInfo:c},u]=Qo(),[f,d]=Hr(),[,,w]=ea(),R=De(),h=R===void 0?void 0:R.config,p=R===void 0?void 0:R.lib.bank,[T,A]=vs();return Ge(()=>{T&&(qf(T),T instanceof Error?vv(a.str`Internal error, please report. There should be more information in the console.`,T):Kc(a.str`Internal error, please report.`,String(T)),A())},[T]),i("div",{class:"min-h-full flex flex-col m-0 bg-slate-200",style:"min-height: 100vh;"},i("div",{class:"bg-indigo-600 pb-32"},i(j0,{title:h?.bank_name??"Bank",iconLinkURL:s.iconLinkURL??"#",profileURL:r?.url({}),notificationURL:c&&n?n.url({}):void 0,onLogout:o.state.status!=="loggedIn"?void 0:()=>{o.state.status==="loggedIn"&&p&&p.deleteAccessToken(o.state.username,o.state.token),o.logOut(),w()},sites:s.topNavSites?Object.entries(s.topNavSites):[]},i("li",null,i("div",{class:"text-xs font-semibold leading-6 text-gray-400"},i(a.Translate,null,"Preferences")),i("ul",{role:"list",class:"space-y-4"},EE(s).map(C=>{let S=!!f[C];return i("li",{key:C,class:"pl-2"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},wE(C,a))),i("button",{type:"button",name:`${C} switch`,"data-enabled":S,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{d(C,!S)}},i("span",{"aria-hidden":"true","data-enabled":S,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"}))))}),i("li",{class:"pl-2"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(a.Translate,null,"Show debug information"))),i("button",{type:"button",name:"debug switch","data-enabled":c,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{u("showDebugInfo",!c)}},i("span",{"aria-hidden":"true","data-enabled":c,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))))))),i("div",{class:"fixed z-20 top-14 w-full"},i("div",{class:"mx-auto w-4/5"},i(Z0,null))),i("main",{class:"-mt-32 flex-1"},t&&r&&i("header",{class:"py-6 bg-indigo-600"},i("div",{class:"mx-auto max-w-7xl px-4 sm:px-6 lg:px-8"},i("h1",{class:" flex flex-wrap items-center justify-between sm:flex-nowrap"},i("span",{class:"text-2xl font-bold tracking-tight text-white"},i(b1,{account:t,routeAccountDetails:r})),i("span",{class:"text-2xl font-bold tracking-tight text-white"},i(zU,{account:t}))))),i("div",{class:"mx-auto max-w-7xl px-4 pb-4 sm:px-6 lg:px-8"},i("div",{class:"rounded-lg bg-white px-5 py-6 shadow sm:px-6"},e))),i(y1,null),i(Q0,{testingUrlKey:"corebank-api-base-url",GIT_HASH:KU,VERSION:YU}))}_1.SCREEN_ID=uu;function _1({class:e}){return i(ae,null,i("style",null,` .animated-loader { display: inline-block; --b: 5px; border-radius: 50%; aspect-ratio: 1; padding: 1px; background: conic-gradient(#0000 10%,#4f46e5) content-box; -webkit-mask: repeating-conic-gradient(#0000 0deg,#000 1deg 20deg,#0000 21deg 36deg), radial-gradient(farthest-side,#0000 calc(100% - var(--b) - 1px),#000 calc(100% - var(--b))); -webkit-mask-composite: destination-in; mask-composite: intersect; animation:spinning-loader 1s infinite steps(10); } @keyframes spinning-loader {to{transform: rotate(1turn)}} `),i("div",{class:`animated-loader ${e}`}))}y1.SCREEN_ID=uu;function y1(){let[e,t]=de(),[r,n]=de(),a=De(),o=a?a.onActivity:void 0,s=a?a.cancelRequest:void 0,[{showDebugInfo:c}]=Qo();return Ge(()=>{if(c&&o)return o(u=>{switch(u.type){case vt.HttpFetchStart:{t(u),n(void 0);return}case vt.HttpFetchFinishError:{n("fail");return}case vt.HttpFetchFinishSuccess:{n("ok");return}case vt.DbQueryStart:case vt.DbQueryFinishSuccess:case vt.DbQueryFinishError:case vt.RequestStart:case vt.RequestFinishSuccess:case vt.RequestFinishError:case vt.TaskStart:case vt.TaskStop:case vt.TaskReset:case vt.ShepherdTaskResult:case vt.DeclareTaskDependency:case vt.CryptoStart:case vt.CryptoFinishSuccess:case vt.CryptoFinishError:case vt.Message:case vt.DeclareConcernsTransaction:return;default:ue(u)}})}),!c||!e?i(ae,null):i("div",{"data-status":r,class:"fixed z-20 bottom-0 w-full ease-in-out delay-1000 transition-transform data-[status=ok]:scale-y-0"},i("div",{"data-status":r,class:"mx-auto w-4/5 center flex p-1 bg-gray-300 m-1 data-[status=fail]:bg-red-200 data-[status=ok]:bg-green-200 "},r?i("div",{class:"w-6 h-6"}):i(_1,{class:"w-6 h-6"}),i("p",{class:"ml-2 my-auto text-sm text-gray-500"},e.url),r?void 0:i("button",{type:"button",onClick:()=>{s&&s(e.id)}},"cancel")))}b1.SCREEN_ID=uu;function b1({account:e,routeAccountDetails:t}){let{i18n:r}=Ne(),n=$r(e);return n?n instanceof Oe?i("div",null):n.type==="fail"?i("a",{name:"account details",href:t.url({}),class:"underline underline-offset-2"},i(r.Translate,null,"Welcome")):i("a",{name:"account details",href:t.url({}),class:"underline underline-offset-2"},i(r.Translate,null,"Welcome, ",i("span",{class:"whitespace-nowrap"},n.body.name))):i(st,null)}function zU({account:e}){let t=$r(e),{config:r}=De();return t?t instanceof Oe?i("div",null):t.type==="fail"?i("div",null):i(Xe,{value:J.parseOrThrow(t.body.balance.amount),negative:t.body.balance.credit_debit_indicator==="debit",spec:r.currency_specification,withSign:!0}):i(st,null)}Re();Be();Be();function v1(e,t,r){return Object.keys(e).reduce((o,s)=>{let c=e[s],u=r?r[s]:void 0;function f(w){t({...e,[s]:w})}if(typeof c=="object"){let w=v1(c,f,u);return o[s]=w,o}let d={error:u,value:c,onUpdate:f};return o[s]=d,o},{})}function lu(e,t){let[r,n]=de(e),a=t(r);return[v1(r,n,a.errors),a]}Re();function E1({routeCreate:e,routeShowDetails:t}){let r=hE(),{i18n:n}=Ne(),a=Lr(),o=!a||a instanceof Error||a.type==="fail"?void 0:a.body;if(!o)return i(ae,null,"-");if(!r)return i(st,null);if(r instanceof Oe)return i(_t,{error:r});if(r.type!=="ok")switch(r.case){case l.Forbidden:return i(Pe,{type:"warning",title:n.str`No enough permission to access the conversion rate list.`});case l.NotFound:return i(Pe,{type:"warning",title:n.str`Conversion list not found. Maybe conversion rate is not supported.`});case l.NotImplemented:return i(Pe,{type:"warning",title:n.str`Conversion list not implemented.`});case l.Unauthorized:return i(Pe,{type:"warning",title:n.str`No enough permission to access the conversion rate list.`});default:ue(r)}let s=r.body;return i(ae,null,i("div",{class:"px-4 sm:px-6 lg:px-8 mt-8"},i("div",{class:"sm:flex sm:items-center"},i("div",{class:"sm:flex-auto"},i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(n.Translate,null,"Conversion rate classes"))),i("div",{class:"mt-4 sm:ml-16 sm:mt-0 sm:flex-none"},i("a",{href:e.url({}),name:"create account",type:"button",class:"block rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(n.Translate,null,"Create conversion rate class")))),i("div",{class:"mt-4 flow-root"},i("div",{class:"-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"},i("div",{class:"inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"},s.length?i("table",{class:"min-w-full divide-y divide-gray-300"},i("thead",null,i("tr",null,i("th",{scope:"col",class:"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0"},n.str`Name`),i("th",{scope:"col",class:"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0"},n.str`Description`),i("th",{scope:"col",class:"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0"},n.str`Cashin`),i("th",{scope:"col",class:"px-3 py-3.5 text-left text-sm font-semibold text-gray-900"},n.str`Cashout`))),i("tbody",{class:"divide-y divide-gray-200"},s.map((c,u)=>i("tr",{key:u,class:""},i("td",{class:"whitespace-nowrap py-3 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-0"},i("a",{href:t.url({classId:String(c.conversion_rate_class_id)})},c.name)),i("td",{class:"whitespace-nowrap px-3 py-4 text-sm text-gray-500"},i("a",{href:t.url({classId:String(c.conversion_rate_class_id)})},c.description)),i("td",{class:"whitespace-nowrap px-3 py-2 text-sm text-gray-500"},i("a",{href:t.url({classId:String(c.conversion_rate_class_id)})},i(Tn,{ratio:c.cashin_ratio??o.conversion_rate.cashin_ratio,fee:c.cashin_fee??o.conversion_rate.cashin_fee,min:c.cashin_min_amount??o.conversion_rate.cashin_min_amount,rounding:c.cashin_rounding_mode??o.conversion_rate.cashin_rounding_mode,minSpec:o.fiat_currency_specification,feeSpec:o.regional_currency_specification}))),i("td",{class:"whitespace-nowrap px-3 py-2 text-sm text-gray-500"},i("a",{href:t.url({classId:String(c.conversion_rate_class_id)})},i(Tn,{ratio:c.cashout_ratio??o.conversion_rate.cashout_ratio,fee:c.cashout_fee??o.conversion_rate.cashout_fee,min:c.cashout_min_amount??o.conversion_rate.cashout_min_amount,rounding:c.cashout_rounding_mode??o.conversion_rate.cashout_rounding_mode,minSpec:o.regional_currency_specification,feeSpec:o.fiat_currency_specification}))))))):i("div",null,i(n.Translate,null,"No conversion rate class"))),i("nav",{class:"flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg","aria-label":"Pagination"},i("div",{class:"flex flex-1 justify-between sm:justify-end"},i("button",{type:"button",name:"first page",class:"relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0",disabled:!r.loadFirst,onClick:r.loadFirst},i(n.Translate,null,"First page")),i("button",{type:"button",name:"next page",class:"relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0",disabled:!r.loadNext,onClick:r.loadNext},i(n.Translate,null,"Next"))))))))}function Tn({fee:e,min:t,ratio:r,rounding:n,feeSpec:a,minSpec:o}){let{i18n:s}=Ne();return i(ae,null,"1:",r,J.isZero(t)?void 0:i(ae,null,i("br",null),i(s.Translate,null,"min:"),"\xA0",i(Xe,{spec:o,value:J.parseOrThrow(t)})),J.isZero(e)?void 0:i(ae,null,i("br",null),i(s.Translate,null,"fee:"),"\xA0",i(Xe,{spec:a,value:J.parseOrThrow(e)})))}Re();Be();Re();function ta({current:e,routeMyAccountCashout:t,routeMyAccountDelete:r,routeMyAccountDetails:n,routeMyAccountPassword:a,routeConversionConfig:o}){let{i18n:s}=Ne(),{config:c}=De(),{state:u}=We(),f=u.status!=="loggedIn"?!1:u.isUserAdministrator,d=!f,{navigateTo:w}=Qa();return i("div",null,i("div",{class:"sm:hidden"},i("label",{for:"tabs",class:"sr-only"},i(s.Translate,null,"Select a section")),i("select",{id:"tabs",name:"tabs",class:"block w-full rounded-md border-gray-300 focus:border-indigo-500 focus:ring-indigo-500",onChange:R=>{let h=R.currentTarget.value;switch(h){case"details":{w(n.url({}));return}case"delete":{w(r.url({}));return}case"credentials":{w(a.url({}));return}case"cashouts":{w(t.url({}));return}case"conversion":{w(o.url({}));return}default:ue(h)}}},i("option",{value:"details",selected:e=="details"},i(s.Translate,null,"Details")),c.allow_deletions?i("option",{value:"delete",selected:e=="delete"},i(s.Translate,null,"Delete")):void 0,i("option",{value:"credentials",selected:e=="credentials"},i(s.Translate,null,"Credentials")),c.allow_conversion?i(ae,null,i("option",{value:"cashouts",selected:e=="cashouts"},i(s.Translate,null,"Cashouts")),i("option",{value:"conversion",selected:e=="cashouts"},i(s.Translate,null,"Conversion"))):void 0)),i("div",{class:"hidden sm:block"},i("nav",{class:"isolate flex divide-x divide-gray-200 rounded-lg shadow","aria-label":"Tabs"},i("a",{name:"my account details",href:n.url({}),"data-selected":e=="details",class:"rounded-l-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(s.Translate,null,"Details")),i("span",{"aria-hidden":"true","data-selected":e=="details",class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})),c.allow_deletions?i("a",{name:"my account delete",href:r.url({}),"data-selected":e=="delete","aria-current":"page",class:" text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(s.Translate,null,"Delete")),i("span",{"aria-hidden":"true","data-selected":e=="delete",class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})):void 0,i("a",{name:"my account password",href:a.url({}),"data-selected":e=="credentials","aria-current":"page",class:" text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(s.Translate,null,"Credentials")),i("span",{"aria-hidden":"true","data-selected":e=="credentials",class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})),c.allow_conversion&&d?i("a",{name:"my account cashout",href:t.url({}),"data-selected":e=="cashouts",class:"rounded-r-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(s.Translate,null,"Cashouts")),i("span",{"aria-hidden":"true","data-selected":e=="cashouts",class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})):void 0,c.allow_conversion&&f?i("a",{name:"conversion config",href:o.url({}),"data-selected":e=="conversion",class:"rounded-r-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(s.Translate,null,"Conversion")),i("span",{"aria-hidden":"true","data-selected":e=="conversion",class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})):void 0)))}function $U({routeCancel:e,routeConversionConfig:t,routeMyAccountCashout:r,routeMyAccountDelete:n,routeMyAccountDetails:a,routeMyAccountPassword:o}){let{i18n:s}=Ne(),{state:c}=We(),u=c.status!=="loggedIn"||!c.isUserAdministrator?void 0:c;if(!u)return i(s.Translate,null,"only admin can setup conversion");let f=Lr();if(!f)return i(st,null);if(f instanceof Oe)return i(_t,{error:f});if(f.type!=="ok"){if(f.case===l.NotImplemented)return i(Pe,{type:"danger",title:s.str`Cashout is disabled`},i(s.Translate,null,"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));ue(f)}let d=f.body;return function(){let{lib:{conversion:R}}=De(),[h,p]=ht(),T={amount:"100",conv:{cashin_min_amount:d.conversion_rate.cashin_min_amount.split(":")[1],cashin_fee:d.conversion_rate.cashin_fee.split(":")[1],cashin_ratio:d.conversion_rate.cashin_ratio,cashin_rounding_mode:d.conversion_rate.cashin_rounding_mode,cashin_tiny_amount:d.conversion_rate.cashin_tiny_amount.split(":")[1],cashout_min_amount:d.conversion_rate.cashout_min_amount.split(":")[1],cashout_fee:d.conversion_rate.cashout_fee.split(":")[1],cashout_ratio:d.conversion_rate.cashout_ratio,cashout_rounding_mode:d.conversion_rate.cashout_rounding_mode,cashout_tiny_amount:d.conversion_rate.cashout_tiny_amount.split(":")[1]}},[A,C]=lu(T,XU(s,d.regional_currency,d.fiat_currency)),{estimateByDebit:S}=oE(),{estimateByDebit:k}=aE(),[v,_]=de(),g=A.amount?J.parseOrThrow(`${d.fiat_currency}:${A.amount.value}`):void 0,O=J.parseOrThrow(d.conversion_rate.cashin_fee),E=J.parseOrThrow(d.conversion_rate.cashout_fee),m=p(s.str`calculate cashout fee`,async Ie=>{let be=await k(Ie,O);if(be.type==="fail")return be;let xe=be.body,Le=await S(xe.credit,E);if(Le.type==="fail")return Le;let Ue=Le.body;return Ke({cashin:xe,cashout:Ue})},!g||C.status==="fail"?void 0:[g]);m.onSuccess=Ie=>_(Ie),m.onFail=Ie=>{switch(Ie.case){case l.BadRequest:return s.str`The server didn't understand the request.`;case l.Conflict:return s.str`The amount is too small`;case l.NotImplemented:return s.str`Conversion is not implemented.`;case G.GENERIC_PARAMETER_MISSING:return s.str`At least debit or credit needs to be provided`;case G.GENERIC_PARAMETER_MALFORMED:return s.str`The amount is malfored`;case G.GENERIC_CURRENCY_MISMATCH:return s.str`The currency is not supported`;default:ue(Ie)}},Ge(()=>{m.call()},[A.amount?.value,A.conv?.cashin_fee?.value,A.conv?.cashout_fee?.value]);let[y,b]=de("detail"),x=v?.cashin,D=v?.cashout,F=p(s.str`update conversion rate`,R.updateConversionRate.bind(R),!u||C.status==="fail"?void 0:[{type:"bearer",token:u.token},C.result.conv]);F.onSuccess=()=>{b("detail")},F.onFail=Ie=>{switch(Ie.case){case l.Unauthorized:return s.str`Wrong credentials`;case l.NotImplemented:return s.str`Conversion is disabled`;default:ue(Ie)}};let B=Number.parseFloat(d.conversion_rate.cashin_ratio),K=Number.parseFloat(d.conversion_rate.cashout_ratio),Z=B>1&&K>1,pe=B<1&&K<1;return i("div",null,i(ta,{current:"conversion",routeMyAccountCashout:r,routeMyAccountDelete:n,routeMyAccountDetails:a,routeMyAccountPassword:o,routeConversionConfig:t}),i(yt,{notification:h}),i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i(s.Translate,null,"Conversion")),i("div",{class:"px-2 mt-2 grid grid-cols-1 gap-y-4 sm:gap-x-4"},i("label",{"data-enabled":y==="detail",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Newsletter",class:"sr-only","aria-labelledby":"project-type-0-label","aria-describedby":"project-type-0-description-0 project-type-0-description-1",onChange:()=>{b("detail")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(s.Translate,null,"Details"))))),i("label",{"data-enabled":y==="cashout",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 -- data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Existing Customers",class:"sr-only","aria-labelledby":"project-type-1-label","aria-describedby":"project-type-1-description-0 project-type-1-description-1",onChange:()=>{b("cashout")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(s.Translate,null,"Config cashout"))))),i("label",{"data-enabled":y==="cashin",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 -- data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Existing Customers",class:"sr-only","aria-labelledby":"project-type-1-label","aria-describedby":"project-type-1-description-0 project-type-1-description-1",onChange:()=>{b("cashin")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(s.Translate,null,"Config cashin"))))))),i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:Ie=>{Ie.preventDefault()}},y=="cashin"&&i(si,{id:"cashin",inputCurrency:d.fiat_currency,outputCurrency:d.regional_currency,fee:A?.conv?.cashin_fee,minimum:A?.conv?.cashin_min_amount,ratio:A?.conv?.cashin_ratio,rounding:A?.conv?.cashin_rounding_mode,tiny:A?.conv?.cashin_tiny_amount}),y=="cashout"&&i(ae,null,i(si,{id:"cashout",inputCurrency:d.regional_currency,outputCurrency:d.fiat_currency,fee:A?.conv?.cashout_fee,minimum:A?.conv?.cashout_min_amount,ratio:A?.conv?.cashout_ratio,rounding:A?.conv?.cashout_rounding_mode,tiny:A?.conv?.cashout_tiny_amount})),y=="detail"&&i(ae,null,i("div",{class:"px-6 pt-6"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(s.Translate,null,"Cashin")),i("dd",{class:"text-sm text-gray-900"},i(Tn,{ratio:d.conversion_rate.cashin_ratio,fee:d.conversion_rate.cashin_fee,min:d.conversion_rate.cashin_min_amount,rounding:d.conversion_rate.cashin_rounding_mode,minSpec:d.fiat_currency_specification,feeSpec:d.regional_currency_specification})))),i("div",{class:"px-6 pt-6"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(s.Translate,null,"Cashout")),i("dd",{class:"text-sm text-gray-900"},i(Tn,{ratio:d.conversion_rate.cashout_ratio,fee:d.conversion_rate.cashout_fee,min:d.conversion_rate.cashout_min_amount,rounding:d.conversion_rate.cashout_rounding_mode,minSpec:d.regional_currency_specification,feeSpec:d.fiat_currency_specification})))),pe||Z?i("div",{class:"p-4"},i(Pe,{title:s.str`Bad ratios`,type:"warning"},i(s.Translate,null,"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1."))):void 0,i("div",{class:"px-6 pt-6"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{for:"amount",class:"block text-sm font-medium leading-6 text-gray-900"},s.str`Initial amount`),i(Fr,{name:"amount",left:!0,currency:d.fiat_currency,value:A.amount?.value??"",onChange:A.amount?.onUpdate}),i(nt,{message:A.amount?.error,isDirty:A.amount?.value!==void 0}),i("p",{class:"mt-2 text-sm text-gray-500"},i(s.Translate,null,"Use it to test how the conversion will affect the amount."))))),!D||!x?void 0:i("div",{class:"px-6 pt-6"},i("div",{class:"sm:col-span-5"},i("dl",{class:"mt-4 space-y-4"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(s.Translate,null,"Sending to this bank")),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:x.debit,negative:!0,withColor:!0,spec:d.fiat_currency_specification}))),J.isZero(x.beforeFee)?void 0:i("div",{class:"flex items-center justify-between afu "},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(s.Translate,null,"Converted"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:x.beforeFee,spec:d.regional_currency_specification}))),i("div",{class:"flex justify-between items-center border-t-2 afu pt-4"},i("dt",{class:"text-lg text-gray-900 font-medium"},i(s.Translate,null,"Cashin after fee")),i("dd",{class:"text-lg text-gray-900 font-medium"},i(Xe,{value:x.credit,withColor:!0,spec:d.regional_currency_specification}))))),i("div",{class:"sm:col-span-5"},i("dl",{class:"mt-4 space-y-4"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(s.Translate,null,"Sending from this bank")),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:D.debit,negative:!0,withColor:!0,spec:d.regional_currency_specification}))),J.isZero(D.beforeFee)?void 0:i("div",{class:"flex items-center justify-between afu"},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(s.Translate,null,"Converted"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:D.beforeFee,spec:d.fiat_currency_specification}))),i("div",{class:"flex justify-between items-center border-t-2 afu pt-4"},i("dt",{class:"text-lg text-gray-900 font-medium"},i(s.Translate,null,"Cashout after fee")),i("dd",{class:"text-lg text-gray-900 font-medium"},i(Xe,{value:D.credit,withColor:!0,spec:d.fiat_currency_specification}))))),D&&C.status==="ok"&&J.cmp(C.result.amount,D.credit)<0?i("div",{class:"p-4"},i(Pe,{title:s.str`Bad configuration`,type:"warning"},i(s.Translate,null,"This configuration allows users to cash out more of what has been cashed in."))):void 0)),i("div",{class:"flex items-center justify-between mt-4 gap-x-6 border-t border-gray-900/10 px-4 py-4"},i("a",{name:"cancel",href:e.url({}),class:"text-sm font-semibold leading-6 text-gray-900"},i(s.Translate,null,"Cancel")),y=="cashin"||y=="cashout"?i(Ze,{type:"submit",name:"update conversion",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:F},i(s.Translate,null,"Update")):i("div",null)))))}}var w1=un.recursive($U);function XU(e,t,r){return function(a){let o=J.parse(`${r}:${a.conv.cashin_min_amount}`),s=J.parse(`${t}:${a.conv.cashin_tiny_amount}`),c=J.parse(`${t}:${a.conv.cashin_fee}`),u=J.parse(`${t}:${a.conv.cashout_min_amount}`),f=J.parse(`${r}:${a.conv.cashout_tiny_amount}`),d=J.parse(`${r}:${a.conv.cashout_fee}`),w=J.parse(`${r}:${a.amount}`),R=Number.parseFloat(a.conv.cashin_ratio??""),h=Number.parseFloat(a.conv.cashout_ratio??""),p=Ht({conv:Ht({cashin_min_amount:a.conv.cashin_min_amount?o?void 0:e.str`Invalid`:e.str`Required`,cashin_fee:a.conv.cashin_fee?c?void 0:e.str`Invalid`:e.str`Required`,cashout_min_amount:a.conv.cashout_min_amount?u?void 0:e.str`Invalid`:e.str`Required`,cashout_fee:a.conv.cashin_fee?d?void 0:e.str`Invalid`:e.str`Required`,cashin_rounding_mode:a.conv.cashin_rounding_mode?void 0:e.str`Required`,cashout_rounding_mode:a.conv.cashout_rounding_mode?void 0:e.str`Required`,cashin_ratio:a.conv.cashin_ratio?Number.isNaN(R)?e.str`Invalid`:void 0:e.str`Required`,cashout_ratio:a.conv.cashout_ratio?Number.isNaN(h)?e.str`Rnvalid`:void 0:e.str`Required`,cashin_tiny_amount:a.conv.cashin_tiny_amount?s?+a.conv.cashin_tiny_amount==0?e.str`Must be > 0`:void 0:e.str`Invalid`:e.str`Required`,cashout_tiny_amount:a.conv.cashout_tiny_amount?f?+a.conv.cashout_tiny_amount==0?e.str`Must be > 0`:void 0:e.str`Invalid`:e.str`Required`}),amount:a.amount?w?void 0:e.str`Invalid`:e.str`Required`}),T={amount:w,conv:{cashin_fee:p?.conv?.cashin_fee?void 0:J.stringify(c),cashin_min_amount:p?.conv?.cashin_min_amount?void 0:J.stringify(o),cashin_tiny_amount:p?.conv?.cashin_tiny_amount?void 0:J.stringify(s),cashin_ratio:p?.conv?.cashin_ratio?void 0:String(R),cashin_rounding_mode:p?.conv?.cashin_rounding_mode?void 0:a.conv.cashin_rounding_mode,cashout_fee:p?.conv?.cashout_fee?void 0:J.stringify(d),cashout_min_amount:p?.conv?.cashout_min_amount?void 0:J.stringify(u),cashout_tiny_amount:p?.conv?.cashout_tiny_amount?void 0:J.stringify(f),cashout_ratio:p?.conv?.cashout_ratio?void 0:String(h),cashout_rounding_mode:p?.conv?.cashout_rounding_mode?void 0:a.conv.cashout_rounding_mode}};return p===void 0?{status:"ok",result:T,errors:p}:{status:"fail",result:T,errors:p}}}function si({id:e,inputCurrency:t,outputCurrency:r,fee:n,minimum:a,ratio:o,rounding:s,tiny:c,fallback_fee:u,fallback_minimum:f,fallback_ratio:d,fallback_rounding:w,fallback_tiny:R}){let{i18n:h}=Ne();return i(ae,null,i("div",{class:"px-6 pt-6"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{for:`${e}_min_amount`,class:"block text-sm font-medium leading-6 text-gray-900"},h.str`Minimum amount`),i(Fr,{name:`${e}_min_amount`,left:!0,currency:t,value:a?.value??"",onChange:a?.onUpdate,placeholder:f}),i(nt,{message:a?.error,isDirty:a?.value!==void 0}),i("p",{class:"mt-2 text-sm text-gray-500"},i(h.Translate,null,"Only cashout operation above this threshold will be allowed."),"\xA0")))),i("div",{class:"px-6 pt-6"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:`${e}_ratio`},h.str`Ratio`),i("div",{class:"mt-2"},i("input",{type:"number",class:"block rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"current",id:`${e}_ratio`,"data-error":!!o?.error&&o?.value!==void 0,value:o?.value??"",onChange:p=>{o?.onUpdate(p.currentTarget.value)},autocomplete:"off",placeholder:d??"1.0"}),i(nt,{message:o?.error,isDirty:o?.value!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(h.Translate,null,"Conversion ratio between currencies"))),i("div",{class:"px-6 pt-4"},i(Pe,{title:h.str`Example conversion`},i(h.Translate,null,"1 ",t," will be converted into"," ",o?.value??d," ",r))),i("div",{class:"px-6 pt-6"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:`${e}_tiny_amount`},h.str`Tiny amount`),i(Fr,{name:`${e}_tiny_amount`,left:!0,currency:t,value:c?.value??"",onChange:c?.onUpdate,placeholder:R??"0.01"}),i(nt,{message:c?.error,isDirty:c?.value!==void 0})))),i("div",{class:"px-6 pt-6"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:`${e}_channel`},h.str`Rounding mode`),i("div",{class:"mt-2 max-w-xl text-sm text-gray-500"},i("div",{class:"px-4 mt-4 grid grid-cols-1 gap-y-6"},i("label",{onClick:p=>{p.preventDefault(),s?.onUpdate("zero")},"data-selected":s?.value==="zero",class:"relative flex data-[disabled=false]:cursor-pointer rounded-lg border bg-white data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600"},i("input",{type:"radio",name:"channel",value:"Newsletter",class:"sr-only"}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900 "},i(h.Translate,null,"Zero")),i(h.Translate,null,"Amount will be round below to the largest possible value smaller than the input."))),i("svg",{"data-selected":s?.value==="zero",class:"h-5 w-5 text-indigo-600 data-[selected=false]:hidden",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"}))),i("label",{onClick:p=>{p.preventDefault(),s?.onUpdate("up")},"data-selected":s?.value==="up",class:"relative flex data-[disabled=false]:cursor-pointer rounded-lg border data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600"},i("input",{type:"radio",name:"channel",value:"Existing Customers",class:"sr-only"}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900 "},i(h.Translate,null,"Up")),i(h.Translate,null,"Amount will be round up to the smallest possible value larger than the input."))),i("svg",{"data-selected":s?.value==="up",class:"h-5 w-5 text-indigo-600 data-[selected=false]:hidden",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"}))),i("label",{onClick:p=>{p.preventDefault(),s?.onUpdate("nearest")},"data-selected":s?.value==="nearest",class:"relative flex data-[disabled=false]:cursor-pointer rounded-lg border data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600"},i("input",{type:"radio",name:"channel",value:"Existing Customers",class:"sr-only"}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900 "},i(h.Translate,null,"Nearest")),i(h.Translate,null,"Amount will be round to the closest possible value."))),i("svg",{"data-selected":s?.value==="nearest",class:"h-5 w-5 text-indigo-600 data-[selected=false]:hidden",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"})))),w?i("p",{class:"mt-2 text-sm text-gray-500"},i(h.Translate,null,'If none specified the fallback value is "',w,'".')):void 0)))),i("div",{class:"px-6 pt-4"},i(Pe,{title:h.str`Examples`},i("section",{class:"grid grid-cols-1 gap-y-3 text-gray-600"},i("details",{class:"group text-sm"},i("summary",{class:"flex cursor-pointer flex-row items-center justify-between "},i(h.Translate,null,"Rounding an amount of 1.24 with rounding value 0.1"),i("svg",{class:"h-6 w-6 rotate-0 transform group-open:rotate-180",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"2",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M19 9l-7 7-7-7"}))),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.")),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "zero" mode the value will be rounded to 1.2')),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "nearest" mode the value will be rounded to 1.2')),i("p",{class:"text-gray-900 mt-4"},i(h.Translate,null,'With the "up" mode the value will be rounded to 1.3'))),i("details",{class:"group "},i("summary",{class:"flex cursor-pointer flex-row items-center justify-between "},i(h.Translate,null,"Rounding an amount of 1.26 with rounding value 0.1"),i("svg",{class:"h-6 w-6 rotate-0 transform group-open:rotate-180",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"2",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M19 9l-7 7-7-7"}))),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.")),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "zero" mode the value will be rounded to 1.2')),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "nearest" mode the value will be rounded to 1.3')),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "up" mode the value will be rounded to 1.3'))),i("details",{class:"group "},i("summary",{class:"flex cursor-pointer flex-row items-center justify-between "},i(h.Translate,null,"Rounding an amount of 1.24 with rounding value 0.3"),i("svg",{class:"h-6 w-6 rotate-0 transform group-open:rotate-180",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"2",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M19 9l-7 7-7-7"}))),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.")),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "zero" mode the value will be rounded to 1.2')),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "nearest" mode the value will be rounded to 1.2')),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "up" mode the value will be rounded to 1.5'))),i("details",{class:"group "},i("summary",{class:"flex cursor-pointer flex-row items-center justify-between "},i(h.Translate,null,"Rounding an amount of 1.26 with rounding value 0.3"),i("svg",{class:"h-6 w-6 rotate-0 transform group-open:rotate-180",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"2",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M19 9l-7 7-7-7"}))),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.")),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "zero" mode the value will be rounded to 1.2')),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "nearest" mode the value will be rounded to 1.3')),i("p",{class:"text-gray-900 my-4"},i(h.Translate,null,'With the "up" mode the value will be rounded to 1.3'),".0"))))),i("div",{class:"px-6 pt-6"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{for:`${e}_fee`,class:"block text-sm font-medium leading-6 text-gray-900"},h.str`Fee`),i(Fr,{name:`${e}_fee`,left:!0,currency:r,value:n?.value??"",onChange:n?.onUpdate,placeholder:u}),i(nt,{message:n?.error,isDirty:n?.value!==void 0}),i("p",{class:"mt-2 text-sm text-gray-500"},i(h.Translate,null,"Amount to be deducted before amount is credited."))))))}function A1({routeCancel:e,classId:t,onClassDeleted:r}){let{i18n:n}=Ne(),a=mE(t),o=Lr(),s=o&&!(o instanceof Oe)&&o.type==="ok"?o.body:void 0;if(!a||!s)return i(st,null);if(a instanceof Oe)return i(_t,{error:a});if(a.type==="fail")switch(a.case){case l.Unauthorized:case l.Forbidden:case l.NotFound:case l.NotImplemented:return i(Pe,{type:"danger",title:n.str`Conversion is disabled`},i(n.Translate,null,"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));default:ue(a)}return i(jU,{conversionInfo:s,detailsResult:a.body,routeCancel:e,classId:t,onClassDeleted:r})}function jU({conversionInfo:e,detailsResult:t,routeCancel:r,classId:n,onClassDeleted:a}){let{i18n:o}=Ne(),{state:s}=We(),c=s.status!=="loggedIn"?void 0:s,{lib:u,config:f}=De(),[d,w]=ht(),[R,h]=de("detail"),p={name:t.name,description:t.description,conv:{cashin_min_amount:t.cashin_min_amount?.split(":")[1],cashin_fee:t.cashin_fee?.split(":")[1],cashin_ratio:t?.cashin_ratio,cashin_rounding_mode:t?.cashin_rounding_mode,cashout_min_amount:t.cashout_min_amount?.split(":")[1],cashout_fee:t.cashout_fee?.split(":")[1],cashout_ratio:t.cashout_ratio,cashout_rounding_mode:t.cashout_rounding_mode}},[T,A]=lu(p,QU(o,e.regional_currency,e.fiat_currency)),C=w(o.str`delete conversion rate class`,xe=>u.bank.deleteConversionRateClass(xe,n),!c||R!=="delete"||t.num_users>0?void 0:[c.token]);C.onSuccess=a,C.onFail=xe=>{switch(xe.case){case l.Unauthorized:return o.str`Unauthorized`;case l.Forbidden:return o.str`Forbidden`;case l.NotFound:return o.str`NotFound`;case l.NotImplemented:return o.str`NotImplemented`;default:ue(xe)}};let S=A.status==="fail"?void 0:{name:A.result.name,description:A.result.description,cashin_fee:A.result.conv.cashin_fee,cashin_min_amount:A.result.conv.cashin_min_amount,cashin_ratio:A.result.conv.cashin_ratio,cashin_rounding_mode:A.result.conv.cashin_rounding_mode,cashout_fee:A.result.conv.cashout_fee,cashout_min_amount:A.result.conv.cashout_min_amount,cashout_ratio:A.result.conv.cashout_ratio,cashout_rounding_mode:A.result.conv.cashout_rounding_mode},k=w(o.str`update conversion rate class`,u.bank.updateConversionRateClass.bind(u.bank),!c||!S?void 0:[c.token,n,S]);k.onSuccess=()=>{h("detail")},k.onFail=xe=>{switch(xe.case){case l.Unauthorized:return o.str`Unauthorized`;case l.Forbidden:return o.str`Forbidden`;case l.NotFound:return o.str`Not Found`;case l.NotImplemented:return o.str`Not implemented`;case G.BANK_NAME_REUSE:return o.str`The name of the conversion is already used.`;default:ue(xe)}};let v=A.status==="fail"?void 0:{name:A.result.name,description:A.result.description,cashin_fee:A.result.conv.cashin_fee,cashin_min_amount:A.result.conv.cashin_min_amount,cashin_ratio:A.result.conv.cashin_ratio,cashin_rounding_mode:A.result.conv.cashin_rounding_mode,cashout_fee:A.result.conv.cashout_fee,cashout_min_amount:A.result.conv.cashout_min_amount,cashout_ratio:A.result.conv.cashout_ratio,cashout_rounding_mode:A.result.conv.cashout_rounding_mode},_=k.lambda((xe,Le,Ue)=>[xe,Le,Ue],!c||!v||R!=="detail"||A.errors?.name||A.errors?.description||A.result.name===p.name&&A.result.description===p.description?void 0:[c.token,n,v]),g=k.lambda((xe,Le,Ue)=>[xe,Le,Ue],!c||!v||R!=="cashin"||A.errors?.conv?.cashin_fee||A.errors?.conv?.cashin_min_amount||A.errors?.conv?.cashin_ratio||A.errors?.conv?.cashin_rounding_mode?void 0:[c.token,n,v]),O=k.lambda((xe,Le,Ue)=>[xe,Le,Ue],!c||!v||R!=="cashout"||A.errors?.conv?.cashout_fee||A.errors?.conv?.cashout_min_amount||A.errors?.conv?.cashout_ratio||A.errors?.conv?.cashout_rounding_mode||A.result?.conv?.cashout_fee===p.conv.cashout_fee&&A.result?.conv?.cashout_min_amount===p.conv.cashout_min_amount&&A.result?.conv?.cashout_ratio===p.conv.cashout_ratio&&A.result?.conv?.cashout_rounding_mode===p.conv.cashout_rounding_mode?void 0:[c.token,n,v]),E=e.conversion_rate,m=t.cashin_ratio??E.cashin_ratio,y=t.cashin_fee??E.cashin_fee,b=t.cashin_min_amount??E.cashin_min_amount,x=t.cashin_rounding_mode??E.cashin_rounding_mode,D=t.cashout_ratio??E.cashout_ratio,F=t.cashout_fee??E.cashout_fee,B=t.cashout_min_amount??E.cashout_min_amount,K=t.cashout_rounding_mode??E.cashout_rounding_mode,Z=Number.parseFloat(m),pe=Number.parseFloat(D),Ie=Z>1&&pe>1,be=Z<1&&pe<1;return i("div",null,i(yt,{notification:d}),i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i(o.Translate,null,"Conversion rate class")),i("div",{class:"px-2 mt-2 grid grid-cols-1 gap-y-4 sm:gap-x-4"},i("label",{"data-enabled":R==="detail",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Newsletter",class:"sr-only","aria-labelledby":"project-type-0-label","aria-describedby":"project-type-0-description-0 project-type-0-description-1",onChange:()=>{h("detail")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(o.Translate,null,"Details"))))),i("label",{"data-enabled":R==="cashout",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 -- data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Existing Customers",class:"sr-only","aria-labelledby":"project-type-1-label","aria-describedby":"project-type-1-description-0 project-type-1-description-1",onChange:()=>{h("cashout")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(o.Translate,null,"Config cashout"))))),i("label",{"data-enabled":R==="cashin",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 -- data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Existing Customers",class:"sr-only","aria-labelledby":"project-type-1-label","aria-describedby":"project-type-1-description-0 project-type-1-description-1",onChange:()=>{h("cashin")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(o.Translate,null,"Config cashin"))))),i("label",{"data-enabled":R==="users",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Newsletter",class:"sr-only","aria-labelledby":"project-type-0-label","aria-describedby":"project-type-0-description-0 project-type-0-description-1",onChange:()=>{h("users")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(o.Translate,null,"Accounts"))))),i("label",{"data-enabled":R==="test",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Newsletter",class:"sr-only","aria-labelledby":"project-type-0-label","aria-describedby":"project-type-0-description-0 project-type-0-description-1",onChange:()=>{h("test")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(o.Translate,null,"Test")))))," ",i("label",{"data-enabled":R==="delete",class:"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none border-gray-300 data-[enabled=true]:border-indigo-600 data-[enabled=true]:ring-2 data-[enabled=true]:ring-indigo-600"},i("input",{type:"radio",name:"project-type",value:"Newsletter",class:"sr-only","aria-labelledby":"project-type-0-label","aria-describedby":"project-type-0-description-0 project-type-0-description-1",onChange:()=>{h("delete")}}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{class:"block text-sm font-medium text-gray-900"},i(o.Translate,null,"Delete"))))))),i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:xe=>{xe.preventDefault()}},R=="cashin"&&i(si,{id:"cashin",inputCurrency:e.fiat_currency,outputCurrency:e.regional_currency,fee:T?.conv?.cashin_fee,minimum:T?.conv?.cashin_min_amount,ratio:T?.conv?.cashin_ratio,rounding:T?.conv?.cashin_rounding_mode,tiny:void 0,fallback_fee:E.cashin_fee.split(":")[1],fallback_minimum:E.cashin_min_amount.split(":")[1],fallback_ratio:E.cashin_ratio,fallback_rounding:E.cashin_rounding_mode,fallback_tiny:E.cashin_tiny_amount}),R=="cashout"&&i(ae,null,i(si,{id:"cashout",inputCurrency:e.regional_currency,outputCurrency:e.fiat_currency,fee:T?.conv?.cashout_fee,minimum:T?.conv?.cashout_min_amount,ratio:T?.conv?.cashout_ratio,rounding:T?.conv?.cashout_rounding_mode,tiny:void 0,fallback_fee:E.cashout_fee.split(":")[1],fallback_minimum:E.cashout_min_amount.split(":")[1],fallback_ratio:E.cashout_ratio,fallback_rounding:E.cashout_rounding_mode,fallback_tiny:E.cashout_tiny_amount})),R=="detail"&&i(ae,null,i("div",{class:"px-6 pt-6"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(o.Translate,null,"Name")),i("dd",{class:"text-sm text-gray-900"},i("input",{ref:or,type:"text",name:"name",id:"name",class:"block w-full disabled:bg-gray-200 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",value:T?.name?.value??"",enterkeyhint:"next",placeholder:o.str`identification`,autocomplete:"username",title:o.str`Username of the account`,required:!0,onInput:xe=>{T?.name?.onUpdate(xe.currentTarget.value)}}),i(nt,{message:T?.name?.error,isDirty:T?.name?.value!==void 0})))),i("div",{class:"px-6 pt-6"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(o.Translate,null,"Description")),i("dd",{class:"text-sm text-gray-900"},i("input",{type:"text",name:"description",id:"description",class:"block w-full disabled:bg-gray-200 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",value:T?.description?.value??"",enterkeyhint:"next",autocomplete:"username",title:o.str`Username of the account`,onInput:xe=>{T?.description?.onUpdate(xe.currentTarget.value)}}),i(nt,{message:T?.description?.error,isDirty:T?.description?.value!==void 0})))),i("div",{class:"px-6 pt-6"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(o.Translate,null,"Cashin")),i("dd",{class:"text-sm text-gray-900"},i(Tn,{ratio:m,fee:y,min:b,rounding:x,minSpec:e.fiat_currency_specification,feeSpec:e.regional_currency_specification})))),i("div",{class:"px-6 pt-6"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(o.Translate,null,"Cashout")),i("dd",{class:"text-sm text-gray-900"},i(Tn,{ratio:D,fee:F,min:B,rounding:K,minSpec:e.regional_currency_specification,feeSpec:e.fiat_currency_specification})))),i("div",{class:"px-6 pt-6"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(o.Translate,null,"Users")),i("dd",{class:"text-sm text-gray-900"},t.num_users))),be||Ie?i("div",{class:"p-4"},i(Pe,{title:o.str`Bad ratios`,type:"warning"},i(o.Translate,null,"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1."))):void 0),R=="users"&&i(eM,{classId:n}),R=="delete"&&i(JU,{classId:n,userCount:t.num_users}),R=="test"&&i(ZU,{classId:n,info:e}),i("div",{class:"flex items-center justify-between mt-4 gap-x-6 border-t border-gray-900/10 px-4 py-4"},i("a",{name:"cancel",href:r.url({}),class:"text-sm font-semibold leading-6 text-gray-900"},i(o.Translate,null,"Cancel")),R=="cashin"?i(ae,null,i(Ze,{type:"submit",name:"update conversion",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:g},i(o.Translate,null,"Update"))):void 0,R=="cashout"?i(ae,null,i(Ze,{type:"submit",name:"update conversion",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:O},i(o.Translate,null,"Update"))):void 0,R=="detail"?i(ae,null,i(Ze,{type:"submit",name:"update conversion",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:_},i(o.Translate,null,"Update"))):void 0,R=="delete"?i(ae,null,i(Ze,{type:"submit",name:"update conversion",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600",onClick:C},i(o.Translate,null,"Delete"))):void 0))))}function QU(e,t,r){return function(a){let o=J.parse(`${r}:${a.conv.cashin_min_amount}`),s=J.parse(`${t}:${a.conv.cashin_fee}`),c=J.parse(`${t}:${a.conv.cashout_min_amount}`),u=J.parse(`${r}:${a.conv.cashout_fee}`),f=Number.parseFloat(a.conv.cashin_ratio??""),d=Number.parseFloat(a.conv.cashout_ratio??""),w=Number.isNaN(f)?void 0:f,R=Number.isNaN(d)?void 0:d,h=Ht({conv:Ht({cashin_min_amount:a.conv.cashin_min_amount?o?void 0:e.str`Invalid`:void 0,cashin_fee:a.conv.cashin_fee?s?void 0:e.str`Invalid`:void 0,cashout_min_amount:a.conv.cashout_min_amount?c?void 0:e.str`Invalid`:void 0,cashout_fee:a.conv.cashin_fee?u?void 0:e.str`Invalid`:void 0,cashin_rounding_mode:(a.conv.cashin_rounding_mode,void 0),cashout_rounding_mode:(a.conv.cashout_rounding_mode,void 0),cashin_ratio:a.conv.cashin_ratio&&Number.isNaN(w)?e.str`Invalid`:void 0,cashout_ratio:a.conv.cashout_ratio&&Number.isNaN(R)?e.str`Invalid`:void 0}),description:void 0,name:a.name?void 0:e.str`Required`}),p={name:h?.name?void 0:a.name,description:a.description,conv:{cashin_fee:!h?.conv?.cashin_fee&&s?J.stringify(s):void 0,cashin_min_amount:!h?.conv?.cashin_min_amount&&o?J.stringify(o):void 0,cashin_ratio:!h?.conv?.cashin_ratio&&w?String(w):void 0,cashin_rounding_mode:h?.conv?.cashin_rounding_mode?void 0:a.conv.cashin_rounding_mode,cashout_fee:!h?.conv?.cashout_fee&&u?J.stringify(u):void 0,cashout_min_amount:!h?.conv?.cashout_min_amount&&c?J.stringify(c):void 0,cashout_ratio:!h?.conv?.cashout_ratio&&R?String(R):void 0,cashout_rounding_mode:h?.conv?.cashout_rounding_mode?void 0:a.conv.cashout_rounding_mode}};return h===void 0?{status:"ok",result:p,errors:h}:{status:"fail",result:p,errors:h}}}function ZU({classId:e,info:t}){let{i18n:r}=Ne(),[n,a]=ht(),{estimateByDebit:o}=sE(e),{estimateByDebit:s}=iE(e),[c,u]=de("100"),[f,d]=de(),[w,R]=de(),h=c?J.parseOrThrow(`${t.fiat_currency}:${c}`):void 0,p=J.parseOrThrow(t.conversion_rate.cashin_fee),T=J.parseOrThrow(t.conversion_rate.cashout_fee),A=a(r.str`calculate cashout fee`,async k=>{let v=await s(k,p);if(v.type==="fail")return v;let _=v.body,g=await o(_.credit,T);if(g.type==="fail")return g;let O=g.body;return Ke({cashin:_,cashout:O})},!h||f?void 0:[h]);A.onSuccess=k=>R(k),A.onFail=k=>{switch(k.case){case l.BadRequest:return r.str`The server didn't understand the request.`;case l.Conflict:return r.str`The amount is too small`;case l.NotImplemented:return r.str`Conversion is not implemented.`;case G.GENERIC_PARAMETER_MISSING:return r.str`At least debit or credit needs to be provided`;case G.GENERIC_PARAMETER_MALFORMED:return r.str`The amount is malfored`;case G.GENERIC_CURRENCY_MISMATCH:return r.str`The currency is not supported`;default:ue(k)}},Ge(()=>{A.call()},[c]);let C=w?.cashin,S=w?.cashout;return i(ae,null,i("div",{class:"px-6 pt-6"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{for:"amount",class:"block text-sm font-medium leading-6 text-gray-900"},r.str`Initial amount`),i(Fr,{name:"amount",left:!0,currency:t.fiat_currency,value:c??"",onChange:k=>{u(k)}}),i(nt,{message:f,isDirty:c!==void 0}),i("p",{class:"mt-2 text-sm text-gray-500"},i(r.Translate,null,"Use it to test how the conversion will affect the amount."))))),!S||!C?void 0:i("div",{class:"px-6 pt-6"},i("div",{class:"sm:col-span-5"},i("dl",{class:"mt-4 space-y-4"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(r.Translate,null,"Sending to this bank")),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:C.debit,negative:!0,withColor:!0,spec:t.fiat_currency_specification}))),J.isZero(C.beforeFee)?void 0:i("div",{class:"flex items-center justify-between afu "},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(r.Translate,null,"Converted"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:C.beforeFee,spec:t.regional_currency_specification}))),i("div",{class:"flex justify-between items-center border-t-2 afu pt-4"},i("dt",{class:"text-lg text-gray-900 font-medium"},i(r.Translate,null,"Cashin after fee")),i("dd",{class:"text-lg text-gray-900 font-medium"},i(Xe,{value:C.credit,withColor:!0,spec:t.regional_currency_specification}))))),i("div",{class:"sm:col-span-5"},i("dl",{class:"mt-4 space-y-4"},i("div",{class:"justify-between items-center flex "},i("dt",{class:"text-sm text-gray-600"},i(r.Translate,null,"Sending from this bank")),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:S.debit,negative:!0,withColor:!0,spec:t.regional_currency_specification}))),J.isZero(S.beforeFee)?void 0:i("div",{class:"flex items-center justify-between afu"},i("dt",{class:"flex items-center text-sm text-gray-600"},i("span",null,i(r.Translate,null,"Converted"))),i("dd",{class:"text-sm text-gray-900"},i(Xe,{value:S.beforeFee,spec:t.fiat_currency_specification}))),i("div",{class:"flex justify-between items-center border-t-2 afu pt-4"},i("dt",{class:"text-lg text-gray-900 font-medium"},i(r.Translate,null,"Cashout after fee")),i("dd",{class:"text-lg text-gray-900 font-medium"},i(Xe,{value:S.credit,withColor:!0,spec:t.fiat_currency_specification})))))))}function JU({classId:e,userCount:t}){let{i18n:r}=Ne();return i(ae,null,i("div",{class:"px-4 mt-4"},t>0?i(Pe,{type:"danger",title:r.str`Can't remove the conversion rate class`},i(r.Translate,null,"There are some user associated to this class. You need to remove them first.")):i(Pe,{type:"warning",title:r.str`You are going to remove the conversion rate class`},i(r.Translate,null,"This step can't be undone."))))}function eM({classId:e}){let{i18n:t}=Ne(),{lib:{bank:r},config:n}=De(),{state:a}=We(),o=Lr(),s=!o||o instanceof Error||o.type==="fail"?void 0:o.body,c=a.status==="loggedIn"?a.token:void 0,[u,f]=de({showAll:e===void 0,classId:e}),d=gE(u.classId,u.account);if(!d)return i(st,null);if(d instanceof Oe)return i(_t,{error:d});if(d.type==="fail"){if(d.case===l.Unauthorized)return i(Pe,{type:"danger",title:t.str`Conversion is disabled`},i(t.Translate,null,"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));ue(d)}return i(ae,null,i("div",{class:"px-4 mt-4"},i("div",{class:"sm:flex sm:items-center"},i("div",{class:"sm:flex-auto"},i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(t.Translate,null,"Filters"))))),i("div",{class:"px-4 mt-2"},i(Pv,{label:t.str`Show from other classes`,name:"show_all",threeState:!1,handler:{value:u.showAll,onChange(w){u.showAll=!!w,w?u.classId=void 0:u.classId=e,f(structuredClone(u))},name:"show_all"}}),i(Yf,{label:t.str`Account`,name:"account",handler:{value:u.account,onChange(w){u.account=w,f(structuredClone(u))},name:"account"}}),u.showAll?i(Yf,{label:t.str`Group ID`,name:"crcid",handler:{value:String(u.classId),onChange(w){let R=w?Number.parseInt(w,10):void 0;u.classId=R,f(structuredClone(u))},name:"crcid"}}):void 0),i("div",{class:"mt-4 flow-root"},i("div",{class:"overflow-x-auto"},i("div",{class:"inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"},d.body.length?i("table",{class:"min-w-full divide-y divide-gray-300"},i("thead",null,i("tr",null,i("th",{scope:"col",class:"px-3 py-3.5 text-left text-sm font-semibold text-gray-900"},t.str`Name`),i("th",{scope:"col",class:"px-3 py-3.5 text-left text-sm font-semibold text-gray-900"},t.str`Class`),i("th",{scope:"col",class:"px-3 py-3.5 text-left text-sm font-semibold text-gray-900"},t.str`Cashin`),i("th",{scope:"col",class:"px-3 py-3.5 text-left text-sm font-semibold text-gray-900"},t.str`Cashout`),i("th",{scope:"col",class:"px-3 py-3.5 text-left text-sm font-semibold text-gray-900"},t.str`Action`))),i("tbody",{class:"divide-y divide-gray-200"},d.body.map((w,R)=>i("tr",{key:R,class:"data-[status=deleted]:bg-gray-100","data-status":w.status},i("td",{class:"whitespace-nowrap px-3 py-4 text-sm text-gray-500"},w.name),i("td",{class:"whitespace-nowrap px-3 py-4 text-sm text-gray-500"},w.conversion_rate_class_id),i("td",{class:"whitespace-nowrap px-3 py-4 text-sm text-gray-500"},i(Tn,{ratio:w.conversion_rate.cashin_ratio,fee:w.conversion_rate.cashin_fee,min:w.conversion_rate.cashin_min_amount,rounding:w.conversion_rate.cashin_rounding_mode,minSpec:s.fiat_currency_specification,feeSpec:s.regional_currency_specification})),i("td",{class:"whitespace-nowrap px-3 py-4 text-sm text-gray-500"},i(Tn,{ratio:w.conversion_rate.cashout_ratio,fee:w.conversion_rate.cashout_fee,min:w.conversion_rate.cashout_min_amount,rounding:w.conversion_rate.cashout_rounding_mode,minSpec:s.fiat_currency_specification,feeSpec:s.regional_currency_specification})),i("td",{class:"whitespace-nowrap px-3 py-4 text-sm text-gray-500"},e===w.conversion_rate_class_id?i("button",{type:"button",class:"disabled:opacity-50 disabled:bg-gray-600 disabled:hover:bg-gray-600 disabled:cursor-default cursor-pointer rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600",onClick:async()=>{c&&(await r.updateAccount({username:w.username,token:c},{conversion_rate_class_id:null}),await pp(),await ri())}},i(t.Translate,null,"Remove")):i("button",{type:"button",class:"disabled:opacity-50 disabled:bg-gray-600 disabled:hover:bg-gray-600 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:async()=>{c&&(await r.updateAccount({username:w.username,token:c},{conversion_rate_class_id:e}),await pp(),await ri())}},i(t.Translate,null,"Add"))))))):i("div",{class:"py-3.5 pl-4 pr-3 "},i(t.Translate,null,"No users in this conversion rate class"))),!d.loadFirst&&!d.loadNext?void 0:i("nav",{class:"flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg","aria-label":"Pagination"},i("div",{class:"flex flex-1 justify-between sm:justify-end"},i("button",{type:"button",name:"first page",class:"relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0",disabled:!d.loadFirst,onClick:d.loadFirst},i(t.Translate,null,"First page")),i("button",{type:"button",name:"next page",class:"relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0",disabled:!d.loadNext,onClick:d.loadNext},i(t.Translate,null,"Next")))))))}Re();Be();Re();Be();function T1({onChange:e,focus:t,children:r}){let{i18n:n}=Ne(),{state:a}=We(),[o,s]=de({}),[c,u]=de(void 0),d=a.status!=="loggedIn"?!1:a.isUserAdministrator;function w(R){let h=Ht({name:d?R.name?void 0:n.str`Required`:void 0});if(u(h),s(R),!!e)if(h)e(void 0);else{let p={name:R.name,description:R.description};e(p)}}return i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:R=>{R.preventDefault()}},i("div",{class:"px-4 py-6 sm:p-8"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"username"},n.str`Name`,d&&i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("input",{ref:t?or:void 0,type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"username",id:"username","data-error":!!c?.name&&o.name!==void 0,disabled:!d,value:o.name??"",onChange:R=>{o.name=R.currentTarget.value,w(structuredClone(o))},autocomplete:"off"}),i(nt,{message:c?.name,isDirty:o.name!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(n.Translate,null,"Conversion rate name"))),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"username"},n.str`Description`),i("div",{class:"mt-2"},i("input",{ref:t?or:void 0,type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"username",id:"username","data-error":!!c?.description&&o.description!==void 0,disabled:!d,value:o.description??"",onChange:R=>{o.description=R.currentTarget.value,w(structuredClone(o))},autocomplete:"off"}),i(nt,{message:c?.description,isDirty:o.description!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(n.Translate,null,"Short description of the class"))))),r)}function N1({routeCancel:e,onCreated:t}){let{i18n:r}=Ne(),{state:n}=We(),a=n.status!=="loggedIn"?void 0:n.token,{lib:{bank:o}}=De(),[s,c]=ht(),[u,f]=de(),d=c(r.str`create conversion rate class`,(w,R)=>o.createConversionRateClass(w,R),!u||!a?void 0:[a,u]);return d.onSuccess=w=>{pr(r.str`Conversion rate class created.`),t(w.conversion_rate_class_id)},d.onFail=w=>{switch(w.case){case l.Unauthorized:return r.str`The rights to change the account are not sufficient`;case l.Forbidden:return r.str`Wrong credentials`;case l.NotFound:return r.str`Account not found`;case l.NotImplemented:return r.str`Not implemented`;case G.BANK_NAME_REUSE:return r.str`The name of the conversion is already used.`;default:ue(w)}},i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i(yt,{notification:s}),i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i(r.Translate,null,"New conversion rate class"))),i(T1,{onChange:f},i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{href:e.url({}),name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900"},i(r.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"create",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:d},i(r.Translate,null,"Create")))))}Re();Be();function Pp(){let{i18n:e}=Ne(),t=eE(void 0),r=t&&!(t instanceof Oe)&&t.body.length>0?t.body[0].username:void 0,[n,a]=de(r);if(!t)return i(st,null);if(t instanceof Oe)return i(st,null);let{body:o}=t,s={},c=[];for(let u of o){let f=u.username==n;c.push(i("li",{class:f?"pure-menu-selected pure-menu-item":"pure-menu-item pure-menu"},i("a",{href:"#",name:`show account ${u.username}`,class:"pure-menu-link",onClick:()=>a(u.username)},u.username))),s[u.username]=i(so,{account:u.username,routeCreateWireTransfer:void 0})}return i(ae,null,i("h1",{class:"nav"},e.str`History of public accounts`),i("section",{id:"main"},i("article",null,i("div",{class:"pure-menu pure-menu-horizontal",name:"accountMenu"},i("ul",{class:"pure-menu-list"},c),typeof n<"u"?s[n]:i("p",null,"No public transactions found."),i("br",null)))))}Re();function R1(){let e=Yc();return e.length?i("div",null,i("p",null,"Notifications"),i("table",null,i("thead",null),i("tbody",null,e.map((t,r)=>i("tr",{key:r},i("td",null,i(ln,{timestamp:t.message.when,format:"dd/MM/yyyy HH:mm:ss"})),i("td",null,t.message.title),i("td",null,t.message.type==="error"?t.message.description:void 0)))))):i("div",null,"no notifications")}Re();function du({toAccount:e,withSubject:t,withAmount:r,routeCancel:n,onSuccess:a}){let{i18n:o}=Ne(),s=We(),c=s.state.status!=="loggedOut"?s.state.username:"admin",u=$r(c);if(!u)return i(st,null);if(u instanceof Oe)return i(ae,null,i(_t,{error:u}),i(er,{currentUser:c}));if(u.type==="fail")switch(u.case){case l.Unauthorized:return i(er,{currentUser:c});case l.NotFound:return i(er,{currentUser:c});default:ue(u)}let{body:f}=u,d=J.parseOrThrow(f.balance.amount),w=f.balance.credit_debit_indicator=="debit",R=J.parseOrThrow(f.debit_threshold),h=wn.toIntAmount(d,w),p=h.increment(R).result,T=h.getResultZeroIfNegative();return i("div",{class:"px-4 mt-8"},i("div",{class:"sm:flex sm:items-center mb-4"},i("div",{class:"sm:flex-auto"},i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(o.Translate,null,"Make a wire transfer")))),i(nu,{withAccount:e,withAmount:r,balance:T,withSubject:t,limit:p,onSuccess:()=>{pr(o.str`The wire transfer was successfully completed!`),a&&a()},routeCancel:n}))}Re();Re();Re();Be();function x1({withdrawUri:e,onAborted:t}){let{i18n:r}=Ne(),n=zc(),a=_r.toString(e),{state:o}=We(),s=o.status!=="loggedIn"?void 0:o;Ge(()=>{n.publishTalerAction(e)},[]);let[c,u]=ht(),{lib:{bank:f}}=De(),d=u(r.str`abort withdrawal`,w=>f.abortWithdrawalById(w,e.withdrawalOperationId),s?[s]:void 0);return d.onSuccess=t,d.onFail=w=>{switch(w.case){case l.BadRequest:return r.str`The operation ID is invalid.`;case l.NotFound:return r.str`The operation was not found.`;case l.Conflict:return r.str`The reserve operation has been confirmed previously and can't be aborted`;default:ue(w)}},i(ae,null,i(yt,{notification:c}),i("div",{class:"bg-white shadow-xl sm:rounded-lg"},i("div",{class:"px-4 py-5 sm:p-6"},i("h3",{class:"text-base font-semibold leading-6 text-gray-900"},i(r.Translate,null,"If you have a Taler wallet installed on this device")),i("div",{class:"mt-4 mb-4 text-sm text-gray-500"},i("p",null,i(r.Translate,null,"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions")," ",i("a",{class:"font-semibold text-indigo-600 hover:text-indigo-900",name:"wallet page",href:"https://taler.net/en/wallet.html"},i(r.Translate,null,"on this page")),".")),i("div",{class:"flex items-center justify-between gap-x-6 pt-2 mt-2 "},i(Ze,{type:"button",name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900",onClick:d},i(r.Translate,null,"Cancel")),i("a",{href:a,name:"withdraw",class:"inline-flex items-center disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(r.Translate,null,"Withdraw"))))),i("div",{class:"bg-white shadow-xl sm:rounded-lg mt-8"},i("div",{class:"px-4 py-5 sm:p-6"},i("h3",{class:"text-base font-semibold leading-6 text-gray-900"},i(r.Translate,null,"In case you have a Taler wallet on another device")),i("div",{class:"mt-4 max-w-xl text-sm text-gray-500"},i(r.Translate,null,"Scan the QR code below to start the withdrawal.")),i("div",{class:"mt-2 max-w-md ml-auto mr-auto"},i(su,{text:a}))),i("div",{class:"flex items-center justify-center gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i(Ze,{type:"button",class:"text-sm font-semibold leading-6 text-gray-900",onClick:d},i(r.Translate,null,"Cancel")))))}function I1({withdrawUri:e,onOperationAborted:t,routeClose:r,origin:n}){let{i18n:a}=Ne(),o=tu(e.withdrawalOperationId);if(!o)return i(st,null);if(o instanceof Oe)return i(_t,{error:o});if(o.type==="fail")switch(o.case){case l.BadRequest:case l.NotFound:return i(tM,{routeClose:r});default:ue(o)}let{body:s}=o;if(s.status==="aborted")return i("div",{class:"relative ml-auto mr-auto transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6"},i("div",null,i("div",{class:"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-yellow-100"},i("svg",{class:"h-5 w-5 text-yellow-400",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z","clip-rule":"evenodd"}))),i("div",{class:"mt-3 text-center sm:mt-5"},i("h3",{class:"text-base font-semibold leading-6 text-gray-900",id:"modal-title"},i(a.Translate,null,"Operation aborted")),i("div",{class:"mt-2"},i("p",{class:"text-sm text-gray-500"},i(a.Translate,null,"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected."))))),i("div",{class:"mt-5 sm:mt-6"},i("a",{href:r.url({}),name:"continue",class:"inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(a.Translate,null,"Continue"))));let c=_r.toString(e);if(s.status==="confirmed")return i("div",{class:"relative ml-auto mr-auto transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6"},i("div",null,i("div",{class:"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100"},i("svg",{class:"h-6 w-6 text-green-600",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M4.5 12.75l6 6 9-13.5"}))),i("div",{class:"mt-3 text-center sm:mt-5"},i("h3",{class:"text-base font-semibold leading-6 text-gray-900",id:"modal-title"},i(a.Translate,null,"Withdrawal confirmed")),i("div",{class:"mt-2"},i("p",{class:"text-sm text-gray-500"},i(a.Translate,null,"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet."," "))))),i("div",{class:"mt-5 sm:mt-6 items-center justify-between gap-x-2 flex"},i("a",{href:r.url({}),name:"done",class:"inline-flex justify-center rounded-md bg-white-600 px-3 py-2 text-sm font-semibold text-black shadow-sm "},i(a.Translate,null,"Close")),void 0));if(s.status==="pending")return i(x1,{withdrawUri:e,onAborted:()=>{pr(a.str`Operation aborted`),t()}});let u=s.selected_exchange_account?$e.fromString(s.selected_exchange_account):void 0;return!u||u.tag==="error"?s.selected_reserve_pub?i(Pe,{type:"danger",title:a.str`The operation is marked as selected, but a process during the withdrawal failed`},i(a.Translate,null,"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.")):i(Pe,{type:"danger",title:a.str`The operation is marked as selected, but a process during the withdrawal failed`},i(a.Translate,null,"A withdrawal reserve ID was not found and no account has been selected.")):s.selected_reserve_pub?i(n1,{withdrawUri:e,details:{username:s.username,account:u.value,reserve:s.selected_reserve_pub,amount:s.amount?J.parseOrThrow(s.amount):void 0}}):i(Pe,{type:"danger",title:a.str`The operation is marked as selected, but a process during the withdrawal failed`},i(a.Translate,null,"The account was selected, but no withdrawal reserve ID was found."))}function tM({routeClose:e}){let{i18n:t}=Ne();return i("div",{class:"relative ml-auto mr-auto transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6"},i("div",null,i("div",{class:"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100 "},i("svg",{class:"h-6 w-6 text-red-600",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"}))),i("div",{class:"mt-3 text-center sm:mt-5"},i("h3",{class:"text-base font-semibold leading-6 text-gray-900",id:"modal-title"},i(t.Translate,null,"Operation not found")),i("div",{class:"mt-2"},i("p",{class:"text-sm text-gray-500"},i(t.Translate,null,"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here."))))),e&&i("div",{class:"mt-5 sm:mt-6"},i("a",{href:e.url({}),name:"continue to dashboard",class:"inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(t.Translate,null,"Continue to dashboard"))))}function fu({operationId:e,onOperationAborted:t,routeClose:r,origin:n}){let{lib:{bank:a}}=De(),o=_r.createTalerWithdraw(a.getIntegrationAPI().href,e),s=_r.toString(o),{i18n:c}=Ne(),[,u]=ea();return o?i(I1,{withdrawUri:o,origin:n,onOperationAborted:()=>{u("currentWithdrawalOperationId",void 0),t()},routeClose:r}):i(Pe,{type:"danger",title:c.str`The Withdrawal URI is not valid`},s)}Re();function S1({account:e,routeCashoutDetails:t}){let r=lE(e);return r?r instanceof Oe?{status:"loading-error",error:r}:r.type==="fail"?{status:"failed",error:r}:{status:"ready",error:void 0,cashouts:r.body.cashouts,routeCashoutDetails:t}:{status:"loading",error:void 0}}Re();function C1({error:e}){let{i18n:t}=Ne();if(e.case===l.NotImplemented)return i(Pe,{type:"danger",title:t.str`Cashout is disabled`},i(t.Translate,null,"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode."));ue(e.case)}function O1({cashouts:e,routeCashoutDetails:t}){let{i18n:r,dateLocale:n}=Ne();if(!e.length)return i("div",null);let a=e.reduce((u,f)=>{let d=f.creation_time.t_s==="never"?"":Rr(f.creation_time.t_s*1e3,"dd/MM/yyyy",{locale:n});return u[d]||(u[d]=[]),u[d].push(f),u},{}),o=Lr();if(o){if(o instanceof Oe)return i(_t,{error:o});if(o.type==="fail"){if(o.case===l.NotImplemented)return i(Pe,{type:"danger",title:r.str`Cashout is disabled`},i(r.Translate,null,"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));ue(o)}}else return i(st,null);let{fiat_currency_specification:s,regional_currency_specification:c}=o.body;return i("div",{class:"px-4 mt-4"},i("div",{class:"sm:flex sm:items-center"},i("div",{class:"sm:flex-auto"},i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(r.Translate,null,"Latest cashouts")))),i("div",{class:"-mx-4 mt-5 ring-1 ring-gray-300 sm:mx-0 rounded-lg min-w-fit bg-white"},i("table",{class:"min-w-full divide-y divide-gray-300"},i("thead",null,i("tr",null,i("th",{scope:"col",class:" pl-2 py-3.5 text-left text-sm font-semibold text-gray-900"},r.str`Created`),i("th",{scope:"col",class:"hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900"},r.str`Total debit`),i("th",{scope:"col",class:"hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900"},r.str`Total credit`),i("th",{scope:"col",class:"hidden sm:table-cell pl-2 py-3.5 text-left text-sm font-semibold text-gray-900"},r.str`Subject`))),i("tbody",null,Object.entries(a).map(([u,f],d)=>i(ae,{key:d},i("tr",{class:"border-t border-gray-200"},i("th",{colSpan:6,scope:"colgroup",class:"bg-gray-50 py-2 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-3"},u)),f.map(w=>i("a",{name:"cashout details",key:d,class:"table-row border-b border-gray-200 hover:bg-gray-200 last:border-none",href:t.url({cid:String(w.id)})},i("td",{class:"relative py-2 pl-2 pr-2 text-sm "},i("div",{class:"font-medium text-gray-900"},i(ln,{format:"HH:mm:ss",timestamp:he.fromProtocolTimestamp(w.creation_time)}))),i("td",{class:"hidden sm:table-cell px-3 py-3.5 text-sm text-red-600 cursor-pointer"},i(Xe,{value:J.parseOrThrow(w.amount_debit),spec:c})),i("td",{class:"hidden sm:table-cell px-3 py-3.5 text-sm text-green-600 cursor-pointer"},i(Xe,{value:J.parseOrThrow(w.amount_credit),spec:s})),i("td",{class:"hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 break-all min-w-md"},w.subject)))))))))}var rM={loading:st,"loading-error":_t,failed:C1,ready:O1},D1=un.compose(e=>S1(e),rM);function Lp({account:e,onCashout:t,routeCashoutDetails:r,routeMyAccountCashout:n,routeMyAccountDelete:a,routeMyAccountDetails:o,routeConversionConfig:s,routeMyAccountPassword:c,routeClose:u}){let{i18n:f}=Ne(),{state:d}=We(),w=d.status==="loggedIn"?d.username===e:!1;return i(ae,null,w?i(ta,{current:"cashouts",routeMyAccountCashout:n,routeMyAccountDelete:a,routeMyAccountDetails:o,routeMyAccountPassword:c,routeConversionConfig:s}):i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(f.Translate,null,"Cashout for account ",e)),i(ru,{focus:!0,routeClose:u,onCashout:t,account:e}),i(D1,{account:e,routeCashoutDetails:r}))}Re();Be();Re();Be();var nM=/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,aM=/^\+[0-9 ]*$/;function pu({template:e,username:t,purpose:r,onChange:n,focus:a,children:o}){let{config:s,url:c}=De(),{i18n:u}=Ne(),{state:f}=We(),[d,w]=de({}),[R,h]=de(void 0),p=s.wire_type==="X_TALER_BANK"?"x-taler-bank":"iban",T="iban",A={debit_threshold:J.stringifyValue(e?.debit_threshold??s.default_debit_threshold??`${s.currency}:0`),isExchange:e?.is_taler_exchange,isPublic:e?.is_public,name:e?.name??"",cashout_payto_uri:P1(T,e?.cashout_payto_uri)??"",payto_uri:P1(p,e?.payto_uri)??"",email:e?.contact_data?.email??"",phone:e?.contact_data?.phone??"",username:t??"",tan_channel:e?.tan_channel},C=f.status!=="loggedIn"?!1:f.isUserAdministrator,S=r==="create",k=r==="create"||r==="update"&&(s.allow_edit_name||C),v=s.allow_conversion,_=r==="create"||r==="update"&&(s.allow_edit_cashout_payto_uri||C),g=C&&(r==="create"||r==="update"),O=r==="create"&&C,E=!!A.phone||!!d.phone,m=!!A.email||!!d.email;function y(b){let x=b.debit_threshold?.trim(),D=J.parse(`${s.currency}:${x}`),F=Ht({cashout_payto_uri:b.cashout_payto_uri&&_&&b.cashout_payto_uri?T==="iban"?eo(b.cashout_payto_uri,u):T==="x-taler-bank"?to(b.cashout_payto_uri,u):void 0:void 0,payto_uri:b.payto_uri&&O&&b.payto_uri?p==="iban"?eo(b.payto_uri,u):p==="x-taler-bank"?to(b.payto_uri,u):void 0:void 0,email:b.email?nM.test(b.email)?void 0:u.str`Invalid email format`:void 0,phone:b.phone?b.phone.startsWith("+")?aM.test(b.phone)?void 0:u.str`A phone number consists of numbers only`:u.str`Should start with +`:void 0,debit_threshold:g&&x?D?void 0:u.str`Not valid`:void 0,name:k?r==="update"&&b.name===void 0||b.name?void 0:u.str`Required`:void 0,username:S?b.username?void 0:u.str`Required`:void 0});if(h(F),w(b),!!n)if(F)n(void 0);else{let B;if(b.cashout_payto_uri)switch(T){case"x-taler-bank":{B=$e.createTalerBank(c.href,b.cashout_payto_uri);break}case"iban":{B=$e.createIban(b.cashout_payto_uri,void 0);break}default:ue(T)}let K=B?$e.toFullString(B):null,Z;if(b.payto_uri)switch(p){case"x-taler-bank":{Z=$e.createTalerBank(c.href,b.payto_uri);break}case"iban":{Z=$e.createIban(b.payto_uri,void 0);break}default:ue(p)}let pe=Z?$e.toFullString(Z):void 0,Ie=D?J.stringify(D):void 0;switch(r){case"create":{let be=n,xe={name:b.name,password:RE(),username:b.username,contact_data:Ht({email:b.email?b.email:void 0,phone:b.phone?b.phone:void 0}),debit_threshold:Ie??s.default_debit_threshold,cashout_payto_uri:K===null?void 0:K,payto_uri:pe,is_public:b.isPublic,is_taler_exchange:b.isExchange,tan_channel:b.tan_channel==="remove"?void 0:b.tan_channel};be(xe);return}case"update":{let be=n,xe={cashout_payto_uri:K,contact_data:Ht({email:b.email?b.email:void 0,phone:b.phone?b.phone:void 0}),debit_threshold:Ie,is_public:b.isPublic,name:b.name,tan_channel:b.tan_channel==="remove"?null:b.tan_channel};be(xe);return}case"show":return;default:ue(r)}}}return i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:b=>{b.preventDefault()}},i("div",{class:"px-4 py-6 sm:p-8"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"username"},u.str`Login username`,S&&i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("input",{ref:a&&r==="create"?or:void 0,type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"username",id:"username","data-error":!!R?.username&&d.username!==void 0,disabled:!S,value:d.username??A.username,onChange:b=>{d.username=b.currentTarget.value,y(structuredClone(d))},autocomplete:"off"}),i(nt,{message:R?.username,isDirty:d.username!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"Account ID for authentication"))),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"name"},u.str`Full name`,k&&i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"name","data-error":!!R?.name&&d.name!==void 0,id:"name",disabled:!k,value:d.name??A.name,onChange:b=>{d.name=b.currentTarget.value,y(structuredClone(d))},autocomplete:"off"}),i(nt,{message:R?.name,isDirty:d.name!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"Name of the account holder"))),r==="create"?void 0:i(ni,{id:"internal-account",label:u.str`Internal account`,help:r==="create"?u.str`If this field is empty, a random account ID will be assigned`:u.str`You can copy and share this IBAN number in order to receive wire transfers to your bank account`,error:R?.payto_uri,onChange:b=>{d.payto_uri=b,y(structuredClone(d))},rightIcons:i(Ln,{class:"p-2 rounded-full text-black shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ",getContent:()=>d.payto_uri??A.payto_uri??""}),value:d.payto_uri??A.payto_uri,disabled:!O}),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"email"},u.str`Email`),i("div",{class:"mt-2"},i("input",{type:"email",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"email",id:"email","data-error":!!R?.email&&d.email!==void 0,disabled:r==="show",value:d.email??A.email,onChange:b=>{d.email=b.currentTarget.value,y(structuredClone(d))},autocomplete:"off"}),i(nt,{message:R?.email,isDirty:d.email!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"To be used when second factor authentication is enabled"))),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"phone"},u.str`Phone`),i("div",{class:"mt-2"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"phone",id:"phone",disabled:r==="show",value:d.phone??A.phone,"data-error":!!R?.phone&&d.phone!==void 0,onChange:b=>{d.phone=b.currentTarget.value,y(structuredClone(d))},autocomplete:"off"}),i(nt,{message:R?.phone,isDirty:d.phone!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"To be used when second factor authentication is enabled"))),!s.supported_tan_channels||s.supported_tan_channels.length===0?void 0:i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"channel"},u.str`Enable second factor authentication`),i("div",{class:"mt-2 max-w-xl text-sm text-gray-500"},i("div",{class:"px-4 mt-4 grid grid-cols-1 gap-y-6"},s.supported_tan_channels.indexOf("email")===-1?void 0:i("label",{onClick:b=>{m&&(d.tan_channel==="email"?d.tan_channel="remove":d.tan_channel="email",y(structuredClone(d)),b.preventDefault())},"data-disabled":r==="show"||!m,"data-selected":(d.tan_channel??A.tan_channel)==="email",class:"relative flex data-[disabled=false]:cursor-pointer rounded-lg border bg-white data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600"},i("input",{type:"radio",name:"channel",value:"Newsletter",class:"sr-only"}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{id:"project-type-0-label",class:"block text-sm font-medium text-gray-900 "},i(u.Translate,null,"Using email")),r!=="show"&&!m&&u.str`Add an email in your profile to enable this option`)),i("svg",{"data-selected":(d.tan_channel??A.tan_channel)==="email",class:"h-5 w-5 text-indigo-600 data-[selected=false]:hidden",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"}))),s.supported_tan_channels.indexOf("sms")===-1?void 0:i("label",{onClick:b=>{E&&(d.tan_channel==="sms"?d.tan_channel="remove":d.tan_channel="sms",y(structuredClone(d)),b.preventDefault())},"data-disabled":r==="show"||!E,"data-selected":(d.tan_channel??A.tan_channel)==="sms",class:"relative flex data-[disabled=false]:cursor-pointer rounded-lg border data-[disabled=true]:bg-gray-200 p-4 shadow-sm focus:outline-none border-gray-300 data-[selected=true]:ring-2 data-[selected=true]:ring-indigo-600"},i("input",{type:"radio",name:"channel",value:"Existing Customers",class:"sr-only"}),i("span",{class:"flex flex-1"},i("span",{class:"flex flex-col"},i("span",{id:"project-type-1-label",class:"block text-sm font-medium text-gray-900"},i(u.Translate,null,"Using SMS")),r!=="show"&&!E&&u.str`Add a phone number in your profile to enable this option`)),i("svg",{"data-selected":(d.tan_channel??A.tan_channel)==="sms",class:"h-5 w-5 text-indigo-600 data-[selected=false]:hidden",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},i("path",{"fill-rule":"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z","clip-rule":"evenodd"})))))),v&&i(ni,{id:"cashout-account",label:u.str`Cashout account`,help:u.str`External account number where the money is going to be sent when doing cashouts`,error:R?.cashout_payto_uri,onChange:b=>{d.cashout_payto_uri=b,y(structuredClone(d))},value:d.cashout_payto_uri??A.cashout_payto_uri,disabled:!_}),i("div",{class:"sm:col-span-5"},i("label",{for:"debit",class:"block text-sm font-medium leading-6 text-gray-900"},u.str`Max debt`),i(Fr,{name:"debit",left:!0,currency:s.currency,value:d.debit_threshold??A.debit_threshold,onChange:g?b=>{d.debit_threshold=b,y(structuredClone(d))}:void 0}),i(nt,{message:R?.debit_threshold?String(R?.debit_threshold):void 0,isDirty:d.debit_threshold!==void 0}),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"How much the balance can go below zero."))),i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(u.Translate,null,"Is this account public?"))),i("button",{type:"button",name:"is public","data-enabled":d.isPublic??A.isPublic?"true":"false",class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{d.isPublic=!(d.isPublic??A.isPublic),y(structuredClone(d))}},i("span",{"aria-hidden":"true","data-enabled":d.isPublic??A.isPublic?"true":"false",class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"}))),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"Public accounts have their balance publicly accessible"))),r!=="create"||!C?void 0:i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(u.Translate,null,"Does this account belong to a Payment Service Provider?"))),i("button",{type:"button",name:"is exchange","data-enabled":d.isExchange??A.isExchange?"true":"false",class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{d.isExchange=!d.isExchange,y(structuredClone(d))}},i("span",{"aria-hidden":"true","data-enabled":d.isExchange??A.isExchange?"true":"false",class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))))),o)}function P1(e,t){if(t===void 0)return;let r=$e.fromString(t);if(r.tag!=="error")return e==="iban"&&r.value.targetType===Je.IBAN?r.value.iban:e==="x-taler-bank"&&r.value.targetType===Je.TalerBank?r.value.account:""}function Up({account:e,routeClose:t,onUpdateSuccess:r,routeMyAccountCashout:n,routeMyAccountDelete:a,routeMyAccountDetails:o,routeMyAccountPassword:s,routeConversionConfig:c}){let{i18n:u}=Ne(),{state:f}=We(),d=f.status!=="loggedIn"?void 0:f.token,{lib:{bank:w}}=De(),R=f.status==="loggedIn"?f.username===e:!1,[h,p]=de(),[T,A]=ht(),C=br(),S=$r(e);if(!S)return i(st,null);if(S instanceof Oe)return i(ae,null,i(_t,{error:S}),i(er,{currentUser:e}));if(S.type==="fail")switch(S.case){case l.Unauthorized:case l.NotFound:return i(er,{currentUser:e});default:ue(S)}let k=A(u.str`update account`,(y,b,x,D)=>w.updateAccount({username:y,token:b},x,{challengeIds:D}),!d||!h?void 0:[e,d,h,[]]);k.onSuccess=y=>{pr(u.str`Account updated`),r()},k.onFail=y=>{switch(y.case){case l.Unauthorized:return u.str`The rights to change the account are not sufficient`;case l.NotFound:return u.str`The username was not found`;case G.BANK_NON_ADMIN_PATCH_LEGAL_NAME:return u.str`You can't change the legal name, please contact the your account administrator.`;case G.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:return u.str`You can't change the debt limit, please contact the your account administrator.`;case G.BANK_NON_ADMIN_PATCH_CASHOUT:return u.str`You can't change the cashout address, please contact the your account administrator.`;case G.BANK_MISSING_TAN_INFO:return u.str`No information for the selected authentication channel.`;case l.Accepted:return C.onChallengeRequired(y.body),u.str`A second factor authentication is required.`;case G.BANK_TAN_CHANNEL_NOT_SUPPORTED:return u.str`Authentication channel is not supported.`;case G.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:return u.str`Only the administrator can change the conversion rate.`;case G.BANK_CONVERSION_RATE_CLASS_UNKNOWN:return u.str`The conversion rate class doesn't exist.`;case G.BANK_PASSWORD_TOO_SHORT:return u.str`The password is too short. Can't have less than 8 characters.`;case G.BANK_PASSWORD_TOO_LONG:return u.str`The password is too long. Can't have more than 64 characters.`;default:ue(y)}};let v=k.lambda(y=>[k.args[0],k.args[1],k.args[2],y]),g=w.getRevenueAPI(e).href,O=new URL(g);O.username=e,O.password;let E=$e.fromString(S.body.payto_uri),m=E.tag==="error"||!E.value.targetType?void 0:E.value;return C.pendingChallenge?i(Er,{currentChallenge:C.pendingChallenge,description:u.str`Update account information.`,onCancel:C.doCancelChallenge,username:e,onCompleted:v}):i(ae,null,i(yt,{notification:T}),R?i(ta,{current:"details",routeMyAccountCashout:n,routeMyAccountDelete:a,routeConversionConfig:c,routeMyAccountDetails:o,routeMyAccountPassword:s}):i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(u.Translate,null,'Account "',e,'"')),S.body.status!=="deleted"?void 0:i(Pe,{title:u.str`Removed`,type:"info"},i(u.Translate,null,"This account can't be used.")),i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-semibold leading-6 ",id:"availability-label"},i(u.Translate,null,"Change details")))))),i(pu,{focus:!0,username:e,template:S.body,purpose:"update",onChange:y=>p(y)},i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{href:t.url({}),name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900"},i(u.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"update",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:k},i(u.Translate,null,"Update"))))),S.body.is_taler_exchange||e==="admin"?void 0:i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-semibold leading-6 ",id:"availability-label"},i(u.Translate,null,"Merchant integration"))))),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.'))),m!==void 0&&i("div",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"},i("div",{class:"px-4 py-6 sm:p-8"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"account-type"},u.str`Account type`),i("div",{class:"mt-2"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"account-type",id:"account-type",disabled:!0,value:m.targetType,autocomplete:"off"})),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"Method to use for wire transfer."))),(y=>{switch(y.targetType){case"iban":return i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"iban"},u.str`IBAN`),i("div",{class:"mt-2"},i("div",{class:"flex justify-between"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"iban",id:"iban",disabled:!0,value:y.iban,autocomplete:"off"}),i(Ln,{class:"p-2 rounded-full text-black shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ",getContent:()=>y.iban}))),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"International Bank Account Number.")));case"x-taler-bank":return i(ae,null,i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"account-host"},u.str`Account name`),i("div",{class:"mt-2"},i("div",{class:"flex justify-between"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"account-host",id:"account-host",disabled:!0,value:y.host,autocomplete:"off"})),i(Ln,{class:"p-2 rounded-full text-black shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ",getContent:()=>y.host})),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"Bank host where the service is located."))),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"account-name"},u.str`Account name`),i("div",{class:"mt-2"},i("div",{class:"flex justify-between"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"account-name",id:"account-name",disabled:!0,value:y.account,autocomplete:"off"})),i(Ln,{class:"p-2 rounded-full text-black shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ",getContent:()=>y.account})),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"Bank account identifier for wire transfers."))));case"bitcoin":return i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"iban"},u.str`Address`),i("div",{class:"mt-2"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"iban",id:"iban",disabled:!0,value:"asd",autocomplete:"off"}),i(Ln,{class:"p-2 rounded-full text-black shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ",getContent:()=>"Asd"})),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"International Bank Account Number.")));default:return`unsupported account type ${y.targetType}`}})(m),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"iban"},u.str`Owner's name`),i("div",{class:"mt-2"},i("div",{class:"flex justify-between"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"iban",id:"iban",disabled:!0,value:S.body.name,autocomplete:"off"}),i(Ln,{class:"p-2 rounded-full text-black shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ",getContent:()=>S.body.name}))),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"Legal name of the person holding the account."))),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"iban"},u.str`Account info URL`),i("div",{class:"mt-2"},i("div",{class:"flex justify-between"},i("input",{type:"text",class:"block w-full disabled:bg-gray-100 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"iban",id:"iban",disabled:!0,value:g,autocomplete:"off"}),i(Ln,{class:"p-2 rounded-full text-black shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ",getContent:()=>g}))),i("p",{class:"mt-2 text-sm text-gray-500"},i(u.Translate,null,"From where the merchant can download information about incoming wire transfers to this account."))))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{href:t.url({}),name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900"},i(u.Translate,null,"Cancel")),i("span",null)))))}Re();Be();function Mp({account:e,routeClose:t,onUpdateSuccess:r,routeMyAccountCashout:n,routeMyAccountDelete:a,routeMyAccountDetails:o,routeMyAccountPassword:s,routeConversionConfig:c,focus:u}){let{i18n:f}=Ne(),{state:d}=We(),w=d.status!=="loggedIn"?void 0:d.token,{lib:{bank:R}}=De(),[h,p]=de(),[T,A]=de(),[C,S]=de(),k=d.status==="loggedIn"?d.username===e:!1,v=Ht({current:k?h?void 0:f.str`Required`:void 0,password:T?void 0:f.str`Required`,repeat:C?T!==C?f.str`Repeated password doesn't match`:void 0:f.str`Required`}),[_,g]=ht(),O=br(),E=g(f.str`update password`,(y,b,x)=>R.updatePassword({username:e,token:y},b,{challengeIds:x}),!T||!w?void 0:[w,{old_password:h,new_password:T},[]]);E.onSuccess=y=>{pr(f.str`Password changed`),r()},E.onFail=y=>{switch(y.case){case l.Unauthorized:return f.str`Not authorized to change the password, maybe the session is invalid.`;case l.NotFound:return f.str`Account not found`;case G.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD:return f.str`You need to provide the old password. If you don't have it contact your account administrator.`;case G.BANK_PATCH_BAD_OLD_PASSWORD:return f.str`Your current password doesn't match, can't change to a new password.`;case l.Accepted:return O.onChallengeRequired(y.body),f.str`A second factor authentication is required.`;case l.Forbidden:return f.str`You don't have the rights to change the password.`;case G.BANK_PASSWORD_TOO_SHORT:return f.str`The password is too short. Can't have less than 8 characters.`;case G.BANK_PASSWORD_TOO_LONG:return f.str`The password is too long. Can't have more than 64 characters.`;default:ue(y)}};let m=E.lambda(y=>[E.args[0],E.args[1],y]);return O.pendingChallenge?i(Er,{currentChallenge:O.pendingChallenge,description:f.str`Update account password.`,username:e,onCancel:O.doCancelChallenge,onCompleted:m}):i(ae,null,i(yt,{notification:_}),k?i(ta,{current:"credentials",routeMyAccountCashout:n,routeMyAccountDelete:a,routeMyAccountDetails:o,routeMyAccountPassword:s,routeConversionConfig:c}):i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(f.Translate,null,'Account "',e,'"')),i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i(f.Translate,null,"Update password"))),i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:y=>{y.preventDefault()}},i("div",{class:"px-4 py-6 sm:p-8"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},k?i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"password"},f.str`Current password`,i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("input",{type:"password",ref:u?or:void 0,class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"current",id:"current-password","data-error":!!v?.current&&h!==void 0,value:h??"",onChange:y=>{p(y.currentTarget.value)},autocomplete:"off"}),i(nt,{message:v?.current,isDirty:h!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(f.Translate,null,"Your current password, for security"))):void 0,i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"password"},f.str`New password`,i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("input",{type:"password",class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"password",id:"password","data-error":!!v?.password&&T!==void 0,value:T??"",onChange:y=>{A(y.currentTarget.value)},autocomplete:"off"}),i(nt,{message:v?.password,isDirty:T!==void 0}))),i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"repeat"},f.str`Type it again`,i("b",{class:"text-[red]"}," *")),i("div",{class:"mt-2"},i("input",{type:"password",class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"repeat",id:"repeat","data-error":!!v?.repeat&&C!==void 0,value:C??"",onChange:y=>{S(y.currentTarget.value)},autocomplete:"off"}),i(nt,{message:v?.repeat,isDirty:C!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(f.Translate,null,"Repeat the same password"))))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{href:t.url({}),name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900"},i(f.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"change",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:E},i(f.Translate,null,"Change"))))))}Re();Be();Re();function L1({routeCreate:e,routeRemoveAccount:t,routeShowAccount:r,routeUpdatePasswordAccount:n}){let a=uE(),{i18n:o}=Ne(),{config:s}=De();if(!a)return i(st,null);if(a instanceof Oe)return i(_t,{error:a});switch(a.case){case"ok":break;case l.Unauthorized:return i(ae,null);default:ue(a)}let c=a.body;return i(ae,null,i("div",{class:"px-4 sm:px-6 lg:px-8 mt-8"},i("div",{class:"sm:flex sm:items-center"},i("div",{class:"sm:flex-auto"},i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(o.Translate,null,"Accounts"))),i("div",{class:"mt-4 sm:ml-16 sm:mt-0 sm:flex-none"},i("a",{href:e.url({}),name:"create account",type:"button",class:"block rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(o.Translate,null,"Create account")))),i("div",{class:"mt-4 flow-root"},i("div",{class:"-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"},i("div",{class:"inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"},c.length?i("table",{class:"min-w-full divide-y divide-gray-300"},i("thead",null,i("tr",null,i("th",{scope:"col",class:"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0"},o.str`Username`),i("th",{scope:"col",class:"px-3 py-3.5 text-left text-sm font-semibold text-gray-900"},o.str`Name`),i("th",{scope:"col",class:"px-3 py-3.5 text-left text-sm font-semibold text-gray-900"},o.str`Balance`),i("th",{scope:"col",class:"relative py-3.5 pl-3 pr-4 sm:pr-0"},i("span",{class:"sr-only"},o.str`Actions`)))),i("tbody",{class:"divide-y divide-gray-200"},c.map((u,f)=>{let d=u.balance?J.parse(u.balance.amount):void 0,w=J.isZero(u.balance.amount),R=u.balance&&u.balance.credit_debit_indicator=="debit";return i("tr",{key:f,class:"data-[status=deleted]:bg-gray-100","data-status":u.status},i("td",{class:"whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-0"},i("a",{name:`show account ${u.username}`,href:r.url({account:u.username}),class:"text-indigo-600 hover:text-indigo-900"},u.username)),i("td",{class:"whitespace-nowrap px-3 py-4 text-sm text-gray-500"},u.name),i("td",{"data-negative":w?void 0:R?"true":"false",class:"whitespace-nowrap px-3 py-4 text-sm text-gray-500 data-[negative=false]:text-green-600 data-[negative=true]:text-red-600 "},d?i("span",{class:"amount"},i(Xe,{value:d,negative:R,withSign:!0,spec:s.currency_specification})):o.str`Unknown`),i("td",{class:"relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-0"},u.status==="deleted"?i("p",{class:"text-gray-600"},"removed"):i(ae,null,i("a",{name:`update password ${u.username}`,href:n.url({account:u.username}),class:"text-indigo-600 hover:text-indigo-900"},i(o.Translate,null,"Change password")),i("br",null),w?i("a",{name:`remove account ${u.username}`,href:t.url({account:u.username}),class:"text-indigo-600 hover:text-indigo-900"},i(o.Translate,null,"Remove")):void 0)))}))):i("div",null)),i("nav",{class:"flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 rounded-lg","aria-label":"Pagination"},i("div",{class:"flex flex-1 justify-between sm:justify-end"},i("button",{type:"button",name:"first page",class:"relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0",disabled:!a.loadFirst,onClick:a.loadFirst},i(o.Translate,null,"First page")),i("button",{type:"button",name:"next page",class:"relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0",disabled:!a.loadNext,onClick:a.loadNext},i(o.Translate,null,"Next"))))))))}function M1({routeCreateAccount:e,routeRemoveAccount:t,routeShowAccount:r,routeUpdatePasswordAccount:n,routeDownloadStats:a,routeCreateWireTransfer:o,routeCreateConversionRateClass:s,routeShowConversionRateClass:c}){let{config:u}=De();return i(ae,null,i(sM,{routeDownloadStats:a}),i(du,null),i(so,{account:"admin",routeCreateWireTransfer:o}),i(L1,{routeCreate:e,routeRemoveAccount:t,routeShowAccount:r,routeUpdatePasswordAccount:n}),u.allow_conversion?i(E1,{routeCreate:s,routeShowDetails:c}):void 0)}function oM(e,t,r){if(e.t_ms==="never")return"--";switch(t){case tt.MonitorTimeframeParam.hour:return`${Rr(e.t_ms,"HH:00",{locale:r})}hs`;case tt.MonitorTimeframeParam.day:return Rr(e.t_ms,"EEEE",{locale:r});case tt.MonitorTimeframeParam.month:return Rr(e.t_ms,"MMMM",{locale:r});case tt.MonitorTimeframeParam.year:return Rr(e.t_ms,"yyyy",{locale:r});case tt.MonitorTimeframeParam.decade:return Rr(e.t_ms,"yyyy",{locale:r})}ue(t)}function iM(e,t,r){if(e.t_ms==="never")return"--";switch(t){case tt.MonitorTimeframeParam.hour:{let n=he.addDuration(e,rt.fromSpec({hours:1}));if(n.t_ms==="never")throw Error("abs time plus 1 hour duration can't be 'never'");return`${Rr(n.t_ms,"HH:00",{locale:r})}hs`}case tt.MonitorTimeframeParam.day:{let n=he.addDuration(e,rt.fromSpec({days:1}));if(n.t_ms==="never")throw Error("abs time plus 1 day duration can't be 'never'");return Rr(n.t_ms,"EEEE",{locale:r})}case tt.MonitorTimeframeParam.month:{let n=he.addDuration(e,rt.fromSpec({months:1}));if(n.t_ms==="never")throw Error("abs time plus 1 month duration can't be 'never'");return Rr(n.t_ms,"MMMM",{locale:r})}case tt.MonitorTimeframeParam.year:{let n=he.addDuration(e,rt.fromSpec({years:1}));if(n.t_ms==="never")throw Error("abs time plus 1 year duration can't be 'never'");return Rr(n.t_ms,"yyyy",{locale:r})}case tt.MonitorTimeframeParam.decade:{let n=he.addDuration(e,rt.fromSpec({years:10}));if(n.t_ms==="never")throw Error("abs time plus 10 years duration can't be 'never'");return Rr(n.t_ms,"yyyy",{locale:r})}}ue(t)}function kp(e,t){switch(t){case tt.MonitorTimeframeParam.hour:return{current:he.fromMilliseconds(Xr(e,{hours:1}).getTime()),previous:he.fromMilliseconds(Xr(e,{hours:2}).getTime())};case tt.MonitorTimeframeParam.day:return{current:he.fromMilliseconds(Xr(e,{days:1}).getTime()),previous:he.fromMilliseconds(Xr(e,{days:2}).getTime())};case tt.MonitorTimeframeParam.month:return{current:he.fromMilliseconds(Xr(e,{months:1}).getTime()),previous:he.fromMilliseconds(Xr(e,{months:2}).getTime())};case tt.MonitorTimeframeParam.year:return{current:he.fromMilliseconds(Xr(e,{years:1}).getTime()),previous:he.fromMilliseconds(Xr(e,{years:2}).getTime())};case tt.MonitorTimeframeParam.decade:return{current:he.fromMilliseconds(Xr(e,{years:10}).getTime()),previous:he.fromMilliseconds(Xr(e,{years:20}).getTime())};default:ue(t)}}function sM({routeDownloadStats:e}){let{i18n:t,dateLocale:r}=Ne(),[n,a]=de(tt.MonitorTimeframeParam.hour),{config:o}=De(),s=Lr(),c=kp(new Date,n),u=fE(c.current,c.previous,n);if(!u)return i(ae,null);if(u instanceof Oe)return i(_t,{error:u});if(s&&s instanceof Oe)return i(_t,{error:s});if(s&&s.type==="fail"){if(s.case===l.NotImplemented)return i(Pe,{type:"danger",title:t.str`Cashout is disabled`},i(t.Translate,null,"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));ue(s)}if(u.current.type!=="ok")switch(u.current.case){case l.BadRequest:return i(Pe,{type:"warning",title:t.str`Querying for the current stats failed`},i(t.Translate,null,"The request parameters are wrong"));case l.Unauthorized:return i(Pe,{type:"warning",title:t.str`Querying for the current stats failed`},i(t.Translate,null,"The user is unauthorized"));default:ue(u.current)}if(u.previous.type!=="ok")switch(u.previous.case){case l.BadRequest:return i(Pe,{type:"warning",title:t.str`Querying for the previous stats failed`},i(t.Translate,null,"The request parameters are wrong"));case l.Unauthorized:return i(Pe,{type:"warning",title:t.str`Querying for the previous stats failed`},i(t.Translate,null,"The user is unauthorized"));default:ue(u.previous)}return i("div",{class:"px-4 mt-4"},i("div",{class:"sm:flex sm:items-center mb-4"},i("div",{class:"sm:flex-auto"},i("h1",{class:"text-base font-semibold leading-6 text-gray-900"},i(t.Translate,null,"Transaction volume report")))),i("div",{class:"sm:hidden"},i("label",{for:"tabs",class:"sr-only"},i(t.Translate,null,"Select a section")),i("select",{id:"tabs",name:"tabs",class:"block w-full rounded-md border-gray-300 focus:border-indigo-500 focus:ring-indigo-500",onChange:f=>{a(parseInt(f.currentTarget.value,10))}},i("option",{value:tt.MonitorTimeframeParam.hour,selected:n==tt.MonitorTimeframeParam.hour},i(t.Translate,null,"Last hour")),i("option",{value:tt.MonitorTimeframeParam.day,selected:n==tt.MonitorTimeframeParam.day},i(t.Translate,null,"Previous day")),i("option",{value:tt.MonitorTimeframeParam.month,selected:n==tt.MonitorTimeframeParam.month},i(t.Translate,null,"Last month")),i("option",{value:tt.MonitorTimeframeParam.year,selected:n==tt.MonitorTimeframeParam.year},i(t.Translate,null,"Last year")))),i("div",{class:"hidden sm:block"},i("nav",{class:"isolate flex divide-x divide-gray-200 rounded-lg shadow","aria-label":"Tabs"},i("button",{type:"button",name:"set last hour",onClick:f=>{f.preventDefault(),a(tt.MonitorTimeframeParam.hour)},"data-selected":n==tt.MonitorTimeframeParam.hour,class:"rounded-l-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(t.Translate,null,"Last hour")),i("span",{"aria-hidden":"true","data-selected":n==tt.MonitorTimeframeParam.hour,class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})),i("button",{type:"button",name:"set previous day",onClick:f=>{f.preventDefault(),a(tt.MonitorTimeframeParam.day)},"data-selected":n==tt.MonitorTimeframeParam.day,class:" text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(t.Translate,null,"Previous day")),i("span",{"aria-hidden":"true","data-selected":n==tt.MonitorTimeframeParam.day,class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})),i("button",{type:"button",name:"set last month",onClick:f=>{f.preventDefault(),a(tt.MonitorTimeframeParam.month)},"data-selected":n==tt.MonitorTimeframeParam.month,class:"rounded-r-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(t.Translate,null,"Last month")),i("span",{"aria-hidden":"true","data-selected":n==tt.MonitorTimeframeParam.month,class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})),i("button",{type:"button",name:"set last year",onClick:f=>{f.preventDefault(),a(tt.MonitorTimeframeParam.year)},"data-selected":n==tt.MonitorTimeframeParam.year,class:"rounded-r-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10"},i("span",null,i(t.Translate,null,"Last Year")),i("span",{"aria-hidden":"true","data-selected":n==tt.MonitorTimeframeParam.year,class:"bg-transparent data-[selected=true]:bg-indigo-500 absolute inset-x-0 bottom-0 h-0.5"})))),i("div",{class:"w-full flex justify-between"},i("h1",{class:"text-base text-gray-900 mt-5"},t.str`Trading volume from ${oM(c.current,n,r)} to ${iM(c.current,n,r)}`)),i("dl",{class:"mt-5 grid grid-cols-1 md:grid-cols-2 divide-y divide-gray-200 overflow-hidden rounded-lg bg-white shadow-lg md:divide-x md:divide-y-0"},!s||u.current.body.type!=="with-conversions"||u.previous.body.type!=="with-conversions"?void 0:i(ae,null,i("div",{class:"px-4 py-5 sm:p-6"},i("dt",{class:"text-base font-normal text-gray-900"},i(t.Translate,null,"Cashin"),i("div",{class:"text-xs text-gray-500"},i(t.Translate,null,"Transferred from an external account to an account in this bank."))),i(hu,{current:u.current.body.cashinFiatVolume,previous:u.previous.body.cashinFiatVolume,spec:s.body.fiat_currency_specification})),i("div",{class:"px-4 py-5 sm:p-6"},i("dt",{class:"text-base font-normal text-gray-900"},i(t.Translate,null,"Cashout")),i("div",{class:"text-xs text-gray-500"},i(t.Translate,null,"Transferred from an account in this bank to an external account.")),i(hu,{current:u.current.body.cashoutFiatVolume,previous:u.previous.body.cashoutFiatVolume,spec:s.body.fiat_currency_specification}))),i("div",{class:"px-4 py-5 sm:p-6"},i("dt",{class:"text-base font-normal text-gray-900"},i(t.Translate,null,"Payin"),i("div",{class:"text-xs text-gray-500"},i(t.Translate,null,"Transferred from an account to a Taler exchange."))),i(hu,{current:u.current.body.talerInVolume,previous:u.previous.body.talerInVolume,spec:o.currency_specification})),i("div",{class:"px-4 py-5 sm:p-6"},i("dt",{class:"text-base font-normal text-gray-900"},i(t.Translate,null,"Payout"),i("div",{class:"text-xs text-gray-500"},i(t.Translate,null,"Transferred from a Taler exchange to another account."))),i(hu,{current:u.current.body.talerOutVolume,previous:u.previous.body.talerOutVolume,spec:o.currency_specification})),i("div",{class:"px-4 py-5 sm:p-6"},i("dt",{class:"text-base font-normal text-gray-900"},i(t.Translate,null,"Payin"),i("div",{class:"text-xs text-gray-500"},i(t.Translate,null,"Transferred from an account to a Taler exchange."))),i(U1,{current:u.current.body.talerInCount,previous:u.previous.body.talerInCount})),i("div",{class:"px-4 py-5 sm:p-6"},i("dt",{class:"text-base font-normal text-gray-900"},i(t.Translate,null,"Payout"),i("div",{class:"text-xs text-gray-500"},i(t.Translate,null,"Transferred from a Taler exchange to another account."))),i(U1,{current:u.current.body.talerOutCount,previous:u.previous.body.talerOutCount}))),i("div",{class:"flex justify-end mt-4"},i("a",{href:e.url({}),name:"download stats",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(t.Translate,null,"Download stats as CSV"))))}function hu({current:e,previous:t,spec:r}){let{i18n:n}=Ne(),a=e&&t?J.cmp(e,t):0,o=e?J.stringifyValue(e):void 0,s=o?Number.parseFloat(o):void 0,c=t?Number.parseFloat(J.stringifyValue(t)):void 0,u=!s||Number.isNaN(s)||!c||Number.isNaN(c)?0:a===-1?1-Math.round(s)/Math.round(c):a===1?Math.round(s)/Math.round(c)-1:0,f=a===0?void 0:a===-1,d=`${(Math.abs(u)*100).toFixed(2)}%`;return i(ae,null,i("dd",{class:"mt-1 block "},i("div",{class:"flex justify-start text-2xl items-baseline font-semibold text-indigo-600"},e?i(Xe,{value:J.parseOrThrow(e),spec:r,hideSmall:!0}):"-"),i("div",{class:"flex flex-col"},i("div",{class:"flex justify-end items-baseline text-2xl font-semibold text-indigo-600"},i("small",{class:"ml-2 text-sm font-medium text-gray-500"},i(n.Translate,null,"previous")," ",t?i(Xe,{value:J.parseOrThrow(t),spec:r,hideSmall:!0}):"-")),!!u&&i("span",{"data-negative":f,class:"flex items-center gap-x-1.5 w-fit rounded-md bg-green-100 text-green-800 data-[negative=true]:bg-red-100 px-2 py-1 text-xs font-medium data-[negative=true]:text-red-700 whitespace-pre"},f?i("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"w-6 h-6"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75"})):i("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"w-6 h-6"},i("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M12 19.5v-15m0 0l-6.75 6.75M12 4.5l6.75 6.75"})),f?i("span",{class:"sr-only"},i(n.Translate,null,"Decreased by")):i("span",{class:"sr-only"},i(n.Translate,null,"Increased by")),d))))}function U1({current:e,previous:t}){let{i18n:r}=Ne(),n=e&&t?e{pr(r.str`Account created with password "${h.password}".`),t()},d.onFail=w=>{switch(w.case){case l.BadRequest:return r.str`Server replied that phone or email is invalid`;case l.Unauthorized:return r.str`The rights to perform the operation are not sufficient`;case G.BANK_REGISTER_USERNAME_REUSE:return r.str`Account username is already taken`;case G.BANK_REGISTER_PAYTO_URI_REUSE:return r.str`Account ID is already taken`;case G.BANK_UNALLOWED_DEBIT:return r.str`Bank ran out of bonus credit.`;case G.BANK_RESERVED_USERNAME_CONFLICT:return r.str`Account username can't be used because is reserved`;case G.BANK_NON_ADMIN_PATCH_DEBT_LIMIT:return r.str`Only an administrator is allowed to set the debt limit.`;case G.BANK_MISSING_TAN_INFO:return r.str`No information for the selected authentication channel.`;case G.BANK_TAN_CHANNEL_NOT_SUPPORTED:return r.str`Authentication channel is not supported.`;case G.BANK_NON_ADMIN_SET_TAN_CHANNEL:return r.str`Only admin can create accounts with second factor authentication.`;case G.BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS:return r.str`Only the administrator can change the conversion rate.`;case G.BANK_CONVERSION_RATE_CLASS_UNKNOWN:return r.str`The conversion rate class doesn't exist.`;case G.BANK_PASSWORD_TOO_SHORT:return r.str`The password is too short. Can't have less than 8 characters.`;case G.BANK_PASSWORD_TOO_LONG:return r.str`The password is too long. Can't have more than 64 characters.`;default:ue(w)}},n.status==="loggedIn"&&n.isUserAdministrator?i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i(yt,{notification:u}),i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i(r.Translate,null,"New bank account"))),i(pu,{template:void 0,purpose:"create",onChange:w=>{c(w)}},i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{href:e.url({}),name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900"},i(r.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"create",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:d},i(r.Translate,null,"Create"))))):i(ae,null,i(Pe,{type:"warning",title:r.str`Can't create accounts`},i(r.Translate,null,"Only system admin can create accounts.")),i("div",{class:"mt-5 sm:mt-6"},i("a",{href:e.url({}),name:"close",class:"inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(r.Translate,null,"Close"))))}Re();Be();function H1({routeCancel:e}){let{i18n:t}=Ne(),{state:r}=We(),n=r.status!=="loggedIn"||!r.isUserAdministrator?void 0:r,{lib:{bank:a}}=De(),[o,s]=de({compareWithPrevious:!0,dayMetric:!0,endOnFirstFail:!1,hourMetric:!0,includeHeader:!0,monthMetric:!0,yearMetric:!0}),[c,u]=de(),[f,d]=de(),w=[new Date],[R,h]=ht(),p=h(t.str`download statistics`,async T=>(d(void 0),cM(a,T,o,w,(A,C)=>{u({step:A,total:C})})),c!==void 0||!n?void 0:[n.token]);return p.onSuccess=T=>{d(T),u(void 0)},p.onFail=T=>{},n?i("div",null,i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i(yt,{notification:R}),i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i(t.Translate,null,"Download bank stats"))),i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:T=>{T.preventDefault()}},i("div",{class:"px-4 py-6 sm:p-8"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(t.Translate,null,"Include hour metric"))),i("button",{type:"button",name:"hour switch","data-enabled":o.hourMetric,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{s({...o,hourMetric:!o.hourMetric})}},i("span",{"aria-hidden":"true","data-enabled":o.hourMetric,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))),i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(t.Translate,null,"Include day metric"))),i("button",{type:"button",name:"day switch","data-enabled":!!o.dayMetric,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{s({...o,dayMetric:!o.dayMetric})}},i("span",{"aria-hidden":"true","data-enabled":o.dayMetric,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))),i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(t.Translate,null,"Include month metric"))),i("button",{type:"button",name:"month switch","data-enabled":!!o.monthMetric,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{s({...o,monthMetric:!o.monthMetric})}},i("span",{"aria-hidden":"true","data-enabled":o.monthMetric,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))),i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(t.Translate,null,"Include year metric"))),i("button",{type:"button",name:"year switch","data-enabled":!!o.yearMetric,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{s({...o,yearMetric:!o.yearMetric})}},i("span",{"aria-hidden":"true","data-enabled":o.yearMetric,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))),i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(t.Translate,null,"Include table header"))),i("button",{type:"button",name:"header switch","data-enabled":!!o.includeHeader,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{s({...o,includeHeader:!o.includeHeader})}},i("span",{"aria-hidden":"true","data-enabled":o.includeHeader,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))),i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(t.Translate,null,"Add previous metric for compare"))),i("button",{type:"button",name:"compare switch","data-enabled":!!o.compareWithPrevious,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{s({...o,compareWithPrevious:!o.compareWithPrevious})}},i("span",{"aria-hidden":"true","data-enabled":o.compareWithPrevious,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))),i("div",{class:"sm:col-span-5"},i("div",{class:"flex items-center justify-between"},i("span",{class:"flex flex-grow flex-col"},i("span",{class:"text-sm text-black font-medium leading-6 ",id:"availability-label"},i(t.Translate,null,"Fail on first error"))),i("button",{type:"button",name:"fail switch","data-enabled":!!o.endOnFirstFail,class:"bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2",role:"switch","aria-checked":"false","aria-labelledby":"availability-label","aria-describedby":"availability-description",onClick:()=>{s({...o,endOnFirstFail:!o.endOnFirstFail})}},i("span",{"aria-hidden":"true","data-enabled":o.endOnFirstFail,class:"translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"})))))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{name:"cancel",href:e.url({}),class:"text-sm font-semibold leading-6 text-gray-900"},i(t.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"download",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600",onClick:p},i(t.Translate,null,"Download"))))),!c||c.step===c.total?i("div",{class:"h-5 mb-5"}):i("div",null,i("div",{class:"relative mb-5 h-5 rounded-full bg-gray-200"},i("div",{class:`h-full animate-pulse rounded-full bg-blue-500 w-[${Math.round(c.step/c.total*100)}%]`},i("span",{class:"absolute inset-0 flex items-center justify-center text-xs font-semibold text-white"},i(t.Translate,null,"downloading..."," ",Math.round(c.step/c.total*100)))))),f?i("a",{href:"data:text/plain;charset=utf-8,"+encodeURIComponent(f),name:"save file",download:"bank-stats.csv"},i(Pe,{title:t.str`Download completed`},i(t.Translate,null,"Click here to save the file in your computer."))):i("div",{class:"h-5 mb-5"})):i(t.Translate,null,"only admin can download stats")}async function cM(e,t,r,n,a){let o=[];r.hourMetric&&o.push(tt.MonitorTimeframeParam.hour),r.dayMetric&&o.push(tt.MonitorTimeframeParam.day),r.monthMetric&&o.push(tt.MonitorTimeframeParam.month),r.yearMetric&&o.push(tt.MonitorTimeframeParam.year);let s=o.flatMap(w=>n.map(R=>({reference:R,timeframe:w,moment:kp(R,w)}))),c=s.length,u=await s.reduce(async(w,R,h)=>{let p=await w;a(h,c);let T=r.compareWithPrevious?await e.getMonitor(t,{timeframe:R.timeframe,date:R.moment.previous}):void 0;if(T&&T.type==="fail"&&r.endOnFirstFail)return p;let A=await e.getMonitor(t,{timeframe:R.timeframe,date:R.moment.current});if(A.type==="fail"&&r.endOnFirstFail)return p;let C=tt.MonitorTimeframeParam[o[h]];return p[C]={reference:R.reference,current:A.type!=="ok"?void 0:A.body,previous:!T||T.type!=="ok"?void 0:T.body},p},Promise.resolve({}));a(c,c);let f=[];r.includeHeader&&f.push(["date","metric","reference","talerInCount","talerInVolume","talerOutCount","talerOutVolume","cashinCount","cashinFiatVolume","cashinRegionalVolume","cashoutCount","cashoutFiatVolume","cashoutRegionalVolume"]),Object.entries(u).forEach(([w,R])=>{if(R.current){let h={date:R.reference.getTime(),metric:w,reference:"current",...F1(R.current)};f.push(Object.values(h))}if(R.previous){let h={date:R.reference.getTime(),metric:w,reference:"previous",...F1(R.previous)};f.push(Object.values(h))}});let d=f.reduce((w,R)=>w+R.join(",")+` `,"");return Ke(d)}function F1(e){return{talerInCount:e.talerInCount,talerInVolume:e.talerInVolume,talerOutCount:e.talerOutCount,talerOutVolume:e.talerOutVolume,cashinCount:e.type==="no-conversions"?void 0:e.cashinCount,cashinFiatVolume:e.type==="no-conversions"?void 0:e.cashinFiatVolume,cashinRegionalVolume:e.type==="no-conversions"?void 0:e.cashinRegionalVolume,cashoutCount:e.type==="no-conversions"?void 0:e.cashoutCount,cashoutFiatVolume:e.type==="no-conversions"?void 0:e.cashoutFiatVolume,cashoutRegionalVolume:e.type==="no-conversions"?void 0:e.cashoutRegionalVolume}}Re();Be();function Fp({account:e,routeCancel:t,onUpdateSuccess:r,focus:n}){let{i18n:a}=Ne(),o=$r(e),[s,c]=de(),{state:u}=We(),f=u.status!=="loggedIn"?void 0:u.token,{lib:{bank:d}}=De(),[w,R]=ht(),h=br();if(!o)return i(st,null);if(o instanceof Oe)return i(ae,null,i(_t,{error:o}),i(er,{currentUser:e}));if(o.type==="fail")switch(o.case){case l.Unauthorized:return i(er,{currentUser:e});case l.NotFound:return i(er,{currentUser:e});default:ue(o)}let p=J.parse(o.body.balance.amount);if(!p)return i(a.Translate,null,"there was an error reading the balance");if(!J.isZero(p))return i(ae,null,i(Pe,{type:"warning",title:a.str`Can't delete the account`},i(a.Translate,null,"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.")),i("div",{class:"mt-5 sm:mt-6"},i("a",{href:t.url({}),name:"close",class:"inline-flex w-full justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},i(a.Translate,null,"Close"))));let A=Ht({accountName:s?e!==s?a.str`Name doesn't match`:void 0:a.str`Required`}),C=R(a.str`delete account`,(k,v)=>d.deleteAccount(k,{challengeIds:v}),A||!f?void 0:[{username:e,token:f},[]]);C.onSuccess=k=>{pr(a.str`Account removed`),r()},C.onFail=k=>{switch(k.case){case l.Unauthorized:return a.str`No enough permission to delete the account.`;case l.NotFound:return a.str`The username was not found.`;case G.BANK_RESERVED_USERNAME_CONFLICT:return a.str`Can't delete a reserved username.`;case G.BANK_ACCOUNT_BALANCE_NOT_ZERO:return a.str`Can't delete an account with balance different than zero.`;case l.Accepted:return h.onChallengeRequired(k.body),a.str`A second factor authentication is required.`;default:ue(k)}};let S=C.lambda(k=>[C.args[0],k]);return h.pendingChallenge?i(Er,{currentChallenge:h.pendingChallenge,description:a.str`Remove account.`,username:e,onCancel:h.doCancelChallenge,onCompleted:S}):i("div",null,i(yt,{notification:w}),i(Pe,{type:"warning",title:a.str`You are going to remove the account`},i(a.Translate,null,"This step can't be undone.")),i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("div",{class:"px-4 sm:px-0"},i("h2",{class:"text-base font-semibold leading-7 text-gray-900"},i(a.Translate,null,'Deleting account "',e,'"'))),i("form",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2",autoCapitalize:"none",autoCorrect:"off",onSubmit:k=>{k.preventDefault()}},i("div",{class:"px-4 py-6 sm:p-8"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"},i("div",{class:"sm:col-span-5"},i("label",{class:"block text-sm font-medium leading-6 text-gray-900",for:"password"},a.str`Verification`),i("div",{class:"mt-2"},i("input",{ref:n?or:void 0,type:"text",class:"block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 data-[error=true]:ring-red-500 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6",name:"password",id:"password","data-error":!!A?.accountName&&s!==void 0,value:s??"",onChange:k=>{c(k.currentTarget.value)},placeholder:e,autocomplete:"off"}),i(nt,{message:A?.accountName,isDirty:s!==void 0})),i("p",{class:"mt-2 text-sm text-gray-500"},i(a.Translate,null,"Enter the account name that is going to be deleted"))))),i("div",{class:"flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8"},i("a",{href:t.url({}),name:"cancel",class:"text-sm font-semibold leading-6 text-gray-900"},i(a.Translate,null,"Cancel")),i(Ze,{type:"submit",name:"delete",class:"disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600",onClick:C},i(a.Translate,null,"Delete"))))))}Re();var uM=128;Hp.SCREEN_ID=uM;function Hp({id:e,routeClose:t}){let{i18n:r}=Ne(),n=Number.parseInt(e,10),a=dE(Number.isNaN(n)?void 0:n),o=Lr();if(Number.isNaN(n))return i(Pe,{type:"danger",title:r.str`Cashout id should be a number`});if(!a)return i(st,null);if(a instanceof Oe)return i(_t,{error:a});if(a.type==="fail")switch(a.case){case l.NotFound:return i(Pe,{type:"warning",title:r.str`This cashout not found. Maybe already aborted.`});case l.NotImplemented:return i(Pe,{type:"warning",title:r.str`Cashout is disabled`},i(r.Translate,null,"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));default:ue(a)}if(!o)return i(st,null);if(o instanceof Oe)return i(_t,{error:o});if(o.type==="fail"){if(o.case===l.NotImplemented)return i(Pe,{type:"danger",title:r.str`Cashout is disabled`},i(r.Translate,null,"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode."));ue(o)}let{fiat_currency_specification:s,regional_currency_specification:c}=o.body;return i("div",null,i("div",{class:"grid grid-cols-1 gap-x-8 gap-y-8 pt-6 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"},i("section",{class:"rounded-sm px-4"},i("h2",{id:"summary-heading",class:"font-medium text-lg"},i(r.Translate,null,"Cashout detail")),i("dl",{class:"mt-8 space-y-4"},i("div",{class:"justify-between items-center flex"},i("dt",{class:"text-sm text-gray-600"},i(r.Translate,null,"Subject")),i("dd",{class:"text-sm "},a.body.subject)))),i("div",{class:"bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"},i("div",{class:"px-4 py-6 sm:p-8"},i("div",{class:"grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 "},i("div",{class:"sm:col-span-5"},i("dl",{class:"space-y-4"},a.body.creation_time.t_s!=="never"?i("div",{class:"justify-between items-center flex "},i("dt",{class:" text-gray-600"},i(r.Translate,null,"Date")),i("dd",{class:"text-sm "},i(ln,{format:"dd/MM/yyyy HH:mm:ss",timestamp:he.fromProtocolTimestamp(a.body.creation_time)}))):void 0,i("div",{class:"flex justify-between items-center border-t-2 afu pt-4"},i("dt",{class:"text-gray-600"},i(r.Translate,null,"Debited")),i("dd",{class:" font-medium"},i(Xe,{value:J.parseOrThrow(a.body.amount_debit),negative:!0,withColor:!0,spec:c}))),i("div",{class:"flex items-center justify-between border-t-2 afu pt-4"},i("dt",{class:"flex items-center text-gray-600"},i("span",null,i(r.Translate,null,"Transferred"))),i("dd",{class:"text-sm "},i(Xe,{value:J.parseOrThrow(a.body.amount_credit),withColor:!0,spec:s}))))))))),i("div",null,i("a",{href:t.url({}),name:"close",class:"text-sm font-semibold leading-6 text-gray-900"},i(r.Translate,null,"Close"))))}var lM=100;Gp.SCREEN_ID=lM;function Gp(){let e=We();if(OE(),e.state.status==="loggedIn"){let{isUserAdministrator:t,username:r}=e.state;return i(co,{account:r,routeNotifications:ge.notifications,routeAccountDetails:ge.myAccountDetails},i(fM,{username:r,isAdmin:t}))}return i(co,{routeNotifications:ge.notifications},i(dM,{onLoggedUser:(t,r,n)=>{e.logIn({username:t,token:r,expiration:n})}}))}var uo={login:Ut(/\/login/,()=>"#/login"),register:Ut(/\/register/,()=>"#/register"),publicAccounts:Ut(/\/public-accounts/,()=>"#/public-accounts"),operationDetails:Ut(/\/operation\/(?[a-zA-Z0-9-]+)/,({wopid:e})=>`#/operation/${e}`)};function dM({onLoggedUser:e}){let{i18n:t}=Ne(),r=Kf(uo),{navigateTo:n}=Qa(),{config:a,lib:o}=De(),[s,c]=ht(),u=br();Ge(()=>{r===void 0&&n(uo.login.url({}))},[r]);let f={scope:"readwrite",duration:oo,refreshable:!0},d=c(t.str`login`,(R,h,p)=>o.bank.createAccessToken(R,{type:"basic",username:R,password:h},f,{challengeIds:p}));d.onSuccess=(R,h)=>e(h,Ca(R.access_token),he.fromProtocolTimestamp(R.expiration)),d.onFail=(R,h)=>{switch(R.case){case l.Accepted:return u.onChallengeRequired(R.body),t.str`A second factor authentication is required.`;case l.Unauthorized:return t.str`Wrong credentials for "${h}"`;case G.GENERIC_FORBIDDEN:return t.str`You have no permission to this account.`;case G.BANK_ACCOUNT_LOCKED:return t.str`This account is locked. If you have a active session you can change the password or contact the administrator.`;case l.NotFound:return t.str`Account not found`;default:ue(R)}};let w=d.lambda(R=>[d.args[0],d.args[1],R]);if(u.pendingChallenge)return i(Er,{currentChallenge:u.pendingChallenge,description:t.str`New web session`,onCancel:u.doCancelChallenge,username:d.args[0],onCompleted:w});switch(r.name){case void 0:case"login":return i(ae,null,i("div",{class:"sm:mx-auto sm:w-full sm:max-w-sm"},i("h2",{class:"text-center text-2xl font-bold leading-9 tracking-tight text-gray-900"},t.str`Welcome to ${a.bank_name}!`)),i(er,{routeRegister:uo.register}));case"publicAccounts":return i(Pp,null);case"operationDetails":return i(fu,{operationId:r.values.wopid,origin:"from-wallet-ui",onOperationAborted:()=>n(uo.login.url({})),routeClose:uo.login});case"register":return i(ae,null,i(yt,{notification:s}),i(hp,{onRegistrationSuccesful:(R,h)=>{d.withArgs(R,h,[]).call()},routeCancel:uo.login}));default:ue(r)}}var ge={homeChargeWallet:Ut(/\/account\/charge-wallet/,()=>"#/account/charge-wallet"),homeWireTransfer:Ut(/\/account\/wire-transfer/,()=>"#/account/wire-transfer"),home:Ut(/\/account/,()=>"#/account"),notifications:Ut(/\/notifications/,()=>"#/notifications"),cashoutCreate:Ut(/\/new-cashout/,()=>"#/new-cashout"),cashoutDetails:Ut(/\/cashout\/(?[a-zA-Z0-9]+)/,({cid:e})=>`#/cashout/${e}`),wireTranserCreate:Ut(/\/wire-transfer\/(?[a-zA-Z0-9]+)/,({account:e})=>`#/wire-transfer/${e}`),publicAccountList:Ut(/\/public-accounts/,()=>"#/public-accounts"),statsDownload:Ut(/\/download-stats/,()=>"#/download-stats"),accountCreate:Ut(/\/new-account/,()=>"#/new-account"),myAccountDelete:Ut(/\/delete-my-account/,()=>"#/delete-my-account"),myAccountDetails:Ut(/\/my-profile/,()=>"#/my-profile"),myAccountPassword:Ut(/\/my-password/,()=>"#/my-password"),myAccountCashouts:Ut(/\/my-cashouts/,()=>"#/my-cashouts"),conversionConfig:Ut(/\/conversion$/,()=>"#/conversion"),accountDetails:Ut(/\/profile\/(?[a-zA-Z0-9_-]+)\/details/,({account:e})=>`#/profile/${e}/details`),accountChangePassword:Ut(/\/profile\/(?[a-zA-Z0-9_-]+)\/change-password/,({account:e})=>`#/profile/${e}/change-password`),accountDelete:Ut(/\/profile\/(?[a-zA-Z0-9_-]+)\/delete/,({account:e})=>`#/profile/${e}/delete`),accountCashouts:Ut(/\/profile\/(?[a-zA-Z0-9_-]+)\/cashouts/,({account:e})=>`#/profile/${e}/cashouts`),startOperation:Ut(/\/start-operation\/(?[a-zA-Z0-9-]+)/,({wopid:e})=>`#/start-operation/${e}`),operationDetails:Ut(/\/operation\/(?[a-zA-Z0-9-]+)/,({wopid:e})=>`#/operation/${e}`),conversionRateClassCreate:Ut(/\/new-conversion-rate-class/,()=>"#/new-conversion-rate-class"),conversionRateClassDetails:Ut(/\/conversion-rate-class\/(?[0-9]+)\/details/,({classId:e})=>`#/conversion-rate-class/${e}/details`)};function fM({username:e,isAdmin:t}){let{navigateTo:r}=Qa(),n=Kf(ge);switch(Ge(()=>{n===void 0&&r(ge.home.url({}))},[n]),n.name){case"operationDetails":return i(fu,{operationId:n.values.wopid,origin:"from-wallet-ui",onOperationAborted:()=>r(ge.home.url({})),routeClose:ge.home});case"startOperation":return i(fu,{operationId:n.values.wopid,origin:"from-bank-ui",onOperationAborted:()=>r(ge.home.url({})),routeClose:ge.home});case"publicAccountList":return i(Pp,null);case"statsDownload":return i(H1,{routeCancel:ge.home});case"accountCreate":return i(k1,{routeCancel:ge.home,onCreateSuccess:()=>r(ge.home.url({}))});case"accountDetails":return i(Up,{account:n.values.account,onUpdateSuccess:()=>r(ge.home.url({})),routeMyAccountCashout:ge.myAccountCashouts,routeMyAccountDelete:ge.myAccountDelete,routeMyAccountDetails:ge.myAccountDetails,routeMyAccountPassword:ge.myAccountPassword,routeConversionConfig:ge.conversionConfig,routeClose:ge.home});case"accountChangePassword":return i(Mp,{focus:!0,account:n.values.account,onUpdateSuccess:()=>r(ge.home.url({})),routeMyAccountCashout:ge.myAccountCashouts,routeMyAccountDelete:ge.myAccountDelete,routeMyAccountDetails:ge.myAccountDetails,routeMyAccountPassword:ge.myAccountPassword,routeConversionConfig:ge.conversionConfig,routeClose:ge.home});case"accountDelete":return i(Fp,{account:n.values.account,onUpdateSuccess:()=>r(ge.home.url({})),routeCancel:ge.home});case"accountCashouts":return i(Lp,{account:n.values.account,routeCashoutDetails:ge.cashoutDetails,routeClose:ge.home,routeMyAccountCashout:ge.myAccountCashouts,routeMyAccountDelete:ge.myAccountDelete,routeMyAccountDetails:ge.myAccountDetails,routeMyAccountPassword:ge.myAccountPassword,routeConversionConfig:ge.conversionConfig,onCashout:()=>r(ge.home.url({}))});case"myAccountDelete":return i(Fp,{account:e,onUpdateSuccess:()=>r(ge.home.url({})),routeCancel:ge.home});case"myAccountDetails":return i(Up,{account:e,onUpdateSuccess:()=>r(ge.home.url({})),routeMyAccountCashout:ge.myAccountCashouts,routeConversionConfig:ge.conversionConfig,routeMyAccountDelete:ge.myAccountDelete,routeMyAccountDetails:ge.myAccountDetails,routeMyAccountPassword:ge.myAccountPassword,routeClose:ge.home});case"myAccountPassword":return i(Mp,{focus:!0,account:e,onUpdateSuccess:()=>r(ge.home.url({})),routeMyAccountCashout:ge.myAccountCashouts,routeMyAccountDelete:ge.myAccountDelete,routeMyAccountDetails:ge.myAccountDetails,routeMyAccountPassword:ge.myAccountPassword,routeConversionConfig:ge.conversionConfig,routeClose:ge.home});case"myAccountCashouts":return i(Lp,{account:e,routeCashoutDetails:ge.cashoutDetails,routeMyAccountCashout:ge.myAccountCashouts,routeMyAccountDelete:ge.myAccountDelete,routeMyAccountDetails:ge.myAccountDetails,routeMyAccountPassword:ge.myAccountPassword,routeConversionConfig:ge.conversionConfig,onCashout:()=>r(ge.home.url({})),routeClose:ge.home});case void 0:case"home":return t?i(M1,{routeCreateAccount:ge.accountCreate,routeRemoveAccount:ge.accountDelete,routeShowAccount:ge.accountDetails,routeShowCashoutsAccount:ge.accountCashouts,routeUpdatePasswordAccount:ge.accountChangePassword,routeCreateWireTransfer:ge.wireTranserCreate,routeDownloadStats:ge.statsDownload,routeCreateConversionRateClass:ge.conversionRateClassCreate,routeShowConversionRateClass:ge.conversionRateClassDetails}):i(cu,{account:e,tab:void 0,routeCreateWireTransfer:ge.wireTranserCreate,routePublicAccounts:ge.publicAccountList,routeOperationDetails:ge.startOperation,routeChargeWallet:ge.homeChargeWallet,routeWireTransfer:ge.homeWireTransfer,routeCashout:ge.myAccountCashouts,routeClose:ge.home,onClose:()=>r(ge.home.url({})),onOperationCreated:a=>r(ge.startOperation.url({wopid:a}))});case"cashoutCreate":return i(ru,{account:e,onCashout:()=>r(ge.home.url({})),routeClose:ge.home});case"cashoutDetails":return i(Hp,{id:n.values.cid,routeClose:ge.myAccountCashouts});case"wireTranserCreate":return i(du,{toAccount:n.values.account,withAmount:n.values.amount,withSubject:n.values.subject,routeCancel:ge.home,onSuccess:()=>r(ge.home.url({}))});case"homeChargeWallet":return i(cu,{account:e,tab:"charge-wallet",routeChargeWallet:ge.homeChargeWallet,routeWireTransfer:ge.homeWireTransfer,routeCreateWireTransfer:ge.wireTranserCreate,routePublicAccounts:ge.publicAccountList,routeOperationDetails:ge.startOperation,routeCashout:ge.myAccountCashouts,routeClose:ge.home,onClose:()=>r(ge.home.url({})),onOperationCreated:a=>r(ge.startOperation.url({wopid:a}))});case"conversionConfig":return i(w1,{routeMyAccountCashout:ge.myAccountCashouts,routeMyAccountDelete:ge.myAccountDelete,routeMyAccountDetails:ge.myAccountDetails,routeMyAccountPassword:ge.myAccountPassword,routeConversionConfig:ge.conversionConfig,routeCancel:ge.home,onUpdateSuccess:()=>{r(ge.home.url({}))}});case"homeWireTransfer":return i(cu,{account:e,tab:"wire-transfer",routeChargeWallet:ge.homeChargeWallet,routeWireTransfer:ge.homeWireTransfer,routeCreateWireTransfer:ge.wireTranserCreate,routePublicAccounts:ge.publicAccountList,routeOperationDetails:ge.startOperation,routeCashout:ge.myAccountCashouts,routeClose:ge.home,onClose:()=>r(ge.home.url({})),onOperationCreated:a=>r(ge.startOperation.url({wopid:a}))});case"conversionRateClassCreate":return i(N1,{onCreated:a=>r(ge.conversionRateClassDetails.url({classId:String(a)})),routeCancel:ge.home});case"conversionRateClassDetails":{let a=Number.parseInt(n.values.classId,10);return Number.isNaN(a)?i("div",null,'class id is not a number "',n.values.classId,'"'):i(A1,{classId:a,routeCancel:ge.home,onClassDeleted:()=>{r(ge.home.url({}))}})}case"notifications":return i(R1,null);default:ue(n)}}var Nn={};Nn.uk={locale_data:{messages:{"":{domain:"messages",plural_forms:"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;",lang:"uk"},"An IBAN consists of capital letters and numbers only":["IBAN \u043F\u043E\u0432\u0438\u043D\u0435\u043D \u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u043B\u0438\u0448\u0435 \u0432\u0435\u043B\u0438\u043A\u0456 \u043B\u0456\u0442\u0435\u0440\u0438 \u0442\u0430 \u0446\u0438\u0444\u0440\u0438"],"IBAN numbers have more that 4 digits":["\u041D\u043E\u043C\u0435\u0440\u0430 IBAN \u0437\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u043C\u0430\u044E\u0442\u044C \u0431\u0456\u043B\u044C\u0448\u0435 4-\u044C\u043E\u0445 \u0446\u0438\u0444\u0440"],"IBAN numbers have less that 34 digits":["\u041D\u043E\u043C\u0435\u0440\u0430 IBAN \u0437\u0430\u0437\u0432\u0438\u0447\u0430\u0439 \u043C\u0430\u044E\u0442\u044C \u043C\u0435\u043D\u0448\u0435 34-\u044C\u043E\u0445 \u0446\u0438\u0444\u0440"],"IBAN country code not found":["\u041A\u043E\u0434 \u043A\u0440\u0430\u0457\u043D\u0438 IBAN \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E"],"IBAN number is not valid, checksum is wrong":["\u041D\u043E\u043C\u0435\u0440 IBAN \u043D\u0435 \u043A\u043E\u0440\u0435\u043A\u0442\u043D\u0438\u0439, \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430 \u0441\u0443\u043C\u0430 \u043D\u0435 \u0441\u0445\u043E\u0434\u0438\u0442\u044C\u0441\u044F"],"Use letters, numbers or any of these characters: - . _ ~":[""],Required:["\u043E\u0431\u043E\u0432\u02BC\u044F\u0437\u043A\u043E\u0432\u043E"],"confirm MFA challenge":[""],"Unknown challenge.":[""],"Failed to validate the verification code.":[""],"Too many challenges are active right now, you must wait or confirm current challenges.":[""],"Wrong authentication number.":["\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0438\u0439 \u043D\u043E\u043C\u0435\u0440 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0457."],"Expired challenge.":[""],"Submit the transmitted code number.":[""],"The verification code sent to the email address starting with %1$s":[""],"The verification code sent to the phone number ending with %1$s":[""],Code:[""],"Username of the account":["\u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],"It will expired at %1$s":[""],"The challenge is expired and can't be solved but you can go back and create a new challenge.":[""],Back:[""],Verify:[""],"send MFA challenge":[""],"Failed to send the verification code.":[""],"The request was valid, but the server is refusing action.":[""],"The backend is not aware of the specified MFA challenge.":[""],"It is too early to request another transmission of the challenge.":[""],"Code transmission failed.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u043D\u0435 \u0432\u0434\u0430\u043B\u0430\u0441\u044F."],"select challenge":[""],"Multi-factor authentication required":["\u041F\u043E\u0442\u0440\u0456\u0431\u043D\u0430 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F"],"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.":[""],"The next challenge needs to be completed to confirm the operation.":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457."],"All the next challenges need to be completed to confirm the operation.":[""],"One of the next challenges need to be completed to confirm the operation.":[""],'To an phone ending with "%1$s"':[""],'To an email starting with " %1$s"':[""],"I have a code":[""],"Send me a message":[""],"You have to wait until %1$s to send a new code.":[""],Cancel:[""],Complete:[""],"Unable to create a cashout":["\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0441\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438"],"The bank configuration does not support cashout operations.":["\u041A\u043E\u043D\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044F \u0431\u0430\u043D\u043A\u0443 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0437\u0456 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438."],Close:["\u0417\u0430\u043A\u0440\u0438\u0442\u0438"],"Cashout is disabled":["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043E"],"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"calculate conversion fee":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"The server didn't understand the request.":["\u0426\u0435\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E."],"The amount is too small":["\u041F\u0430\u0440\u043E\u043B\u0456 \u043D\u0435 \u0437\u0431\u0456\u0433\u0430\u044E\u0442\u044C\u0441\u044F"],"Conversion is not implemented.":["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0440\u0435\u0430\u043B\u0456\u0437\u043E\u0432\u0430\u043D\u043E"],"At least debit or credit needs to be provided":[""],"The amount is malfored":["\u0426\u0435\u0439 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u0438\u0439."],"The currency is not supported":["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454\u0442\u044C\u0441\u044F"],Invalid:["\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u043E"],"Amount needs to be higher":["\u043F\u043E\u0432\u0438\u043D\u043D\u0430 \u0431\u0443\u0442\u0438 \u0432\u0438\u0449\u043E\u044E \u0447\u0435\u0440\u0435\u0437 \u043A\u043E\u043C\u0456\u0441\u0456\u0457"],"Balance is not enough":["\u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u0456\u0439 \u0431\u0430\u043B\u0430\u043D\u0441"],"It is not possible to cashout less than %1$s: %2$s":[""],"The total transfer to the destination will be zero":["\u0437\u0430\u0433\u0430\u043B\u044C\u043D\u0430 \u0441\u0443\u043C\u0430 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443 \u043D\u0430 \u043C\u0456\u0441\u0446\u0456 \u043F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u0431\u0443\u0434\u0435 \u043D\u0443\u043B\u044C\u043E\u0432\u043E\u044E"],"create cashout":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],"Cashout created":["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043E"],"Second factor authentication required.":["\u041F\u043E\u0442\u0440\u0456\u0431\u043D\u0430 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F"],"Account not found":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E"],"Duplicated request detected, check if the operation succeeded or try again.":["\u0412\u0438\u044F\u0432\u043B\u0435\u043D\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u043D\u0438\u0439 \u0437\u0430\u043F\u0438\u0442, \u043F\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435, \u0447\u0438 \u0431\u0443\u043B\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0443\u0441\u043F\u0456\u0448\u043D\u043E\u044E, \u0430\u0431\u043E \u0441\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u0449\u0435 \u0440\u0430\u0437."],"The conversion rate was applied incorrectly":["\u041A\u0443\u0440\u0441 \u043E\u0431\u043C\u0456\u043D\u0443 \u0431\u0443\u043B\u043E \u0437\u0430\u0441\u0442\u043E\u0441\u043E\u0432\u0430\u043D\u043E \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E"],"The account does not have sufficient funds":["\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043A\u043E\u0448\u0442\u0456\u0432"],"Missing cashout URI in the profile":["\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0456\u0439 URI \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0432 \u043F\u0440\u043E\u0444\u0456\u043B\u0456"],"The amount is below the minimum amount permitted.":[""],"Sending the confirmation message failed, retry later or contact the administrator.":["\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u043D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u043B\u0435\u043D\u043D\u044F \u0437 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F\u043C, \u0441\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043F\u0456\u0437\u043D\u0456\u0448\u0435 \u0430\u0431\u043E \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430."],"The server doesn't support the current TAN channel.":["\u0426\u0435\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E."],"Create cashout.":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],Cashout:["\u0412\u0438\u043F\u043B\u0430\u0442\u0438 \u0433\u043E\u0442\u0456\u0432\u043A\u043E\u044E"],"Conversion rate":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],Balance:["\u0411\u0430\u043B\u0430\u043D\u0441"],Fee:["\u041A\u043E\u043C\u0456\u0441\u0456\u044F"],"To account":["\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A"],"Legal name":[""],"If this name doesn't match the account holder's name, your transaction may fail.":[""],"Unable to cashout":["\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0441\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438"],"Before being able to cashout to a bank account, you need to complete your profile":["\u041F\u0435\u0440\u0448 \u043D\u0456\u0436 \u0437\u0434\u0456\u0439\u0441\u043D\u0438\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438, \u0432\u0430\u043C \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0437\u0430\u043F\u043E\u0432\u043D\u0438\u0442\u0438 \u0441\u0432\u0456\u0439 \u043F\u0440\u043E\u0444\u0456\u043B\u044C"],"Transfer subject":["\u041F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443"],Currency:[""],"Send %1$s":[""],"Receive %1$s":["\u0412\u0456\u0442\u0430\u0454\u043C\u043E, %1$s"],Amount:["\u0421\u0443\u043C\u0430"],"Total cost":["\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0430 \u0432\u0430\u0440\u0442\u0456\u0441\u0442\u044C"],"Balance left":["\u0417\u0430\u043B\u0438\u0448\u043E\u043A \u0431\u0430\u043B\u0430\u043D\u0441\u0443"],"Before fee":["\u041A\u043E\u043C\u0456\u0441\u0456\u044F \u0434\u043E"],"Total cashout transfer":["\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0430 \u0441\u0443\u043C\u0430 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438"],"Not valid":["\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439"],"Does not follow the pattern":["\u043D\u0435 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u0430\u0454 \u0448\u0430\u0431\u043B\u043E\u043D\u0443"],"send transaction":["\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0456\u0439 \u043F\u043E\u043A\u0438 \u0449\u043E \u043D\u0435\u043C\u0430\u0454."],"The wire transfer was successfully completed!":["\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E!"],"The request was invalid or the payto://-URI used unacceptable features.":["\u0417\u0430\u043F\u0438\u0442 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439 \u0430\u0431\u043E payto://-URI \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0454 \u043D\u0435\u043F\u0440\u0438\u043F\u0443\u0441\u0442\u0438\u043C\u0456 \u0444\u0443\u043D\u043A\u0446\u0456\u0457."],"Not enough permission to complete the operation.":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457."],"The bank administrator cannot be the transfer creditor.":[""],'The destination account "%1$s" was not found.':['\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F "%1$s" \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E.'],"The origin and the destination of the transfer can't be the same.":["\u0414\u0436\u0435\u0440\u0435\u043B\u043E \u0442\u0430 \u043C\u0456\u0441\u0446\u0435 \u043F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443 \u043D\u0435 \u043C\u043E\u0436\u0443\u0442\u044C \u0431\u0443\u0442\u0438 \u043E\u0434\u043D\u0430\u043A\u043E\u0432\u0438\u043C\u0438."],"Your balance is not sufficient for the operation.":["\u0412\u0430\u0448 \u0431\u0430\u043B\u0430\u043D\u0441 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u0456\u0439 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457."],'The origin account "%1$s" was not found.':['\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0434\u0436\u0435\u0440\u0435\u043B\u0430 "%1$s" \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E.'],"The attempt to create the transaction has failed. Please try again.":[""],"A second factor authentication is required.":["\u0423\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E"],"Confirm wire transfer.":["\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437"],"Input wire transfer detail":["\u0414\u0435\u0442\u0430\u043B\u0456 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443"],"Using a form":["\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0447\u0438 \u0444\u043E\u0440\u043C\u0443"],"A special URI that specifies the amount to be transferred and the destination account.":[""],"QR code":["\u0412\u0456\u0434\u043F\u0440\u0430\u0432\u0438\u0442\u0438 \u043A\u043E\u0434"],"If your device has a camera, you can import a payto:// URI from a QR code.":[""],Recipient:["\u041E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447"],"ID of the recipient's account":["IBAN \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430"],username:["\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"],"IBAN of the recipient's account":["IBAN \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430"],Subject:["\u041F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F"],"Some text to identify the transfer":["\u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0457 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443"],"Amount to transfer":["\u0441\u0443\u043C\u0430 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443"],"Payto URI:":["payto URI:"],"Uniform resource identifier of the target account":["\u0443\u043D\u0456\u0444\u0456\u043A\u043E\u0432\u0430\u043D\u0438\u0439 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0440\u0435\u0441\u0443\u0440\u0441\u0443 \u0446\u0456\u043B\u044C\u043E\u0432\u043E\u0433\u043E \u0440\u0430\u0445\u0443\u043D\u043A\u0443"],"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]":["payto://x-taler-bank/[o\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u0431\u0430\u043D\u043A\u0443]/[p\u0430\u0445\u0443\u043D\u043E\u043A \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430]?message=[\u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u043B\u0430\u0442\u0435\u0436\u0443]&amount=[%1$s:X.Y]"],"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]":["payto://iban/[iban \u043E\u0434\u0435\u0440\u0436\u0443\u0432\u0430\u0447\u0430]?message=[\u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u043B\u0430\u0442\u0435\u0436\u0443]&amount=[%1$s:X.Y]"],"The maximum amount for a wire transfer is %1$s":[""],Cost:[""],Send:["\u0417\u0434\u0456\u0439\u0441\u043D\u0438\u0442\u0438 \u043F\u0435\u0440\u0435\u043A\u0430\u0437"],'Only "x-taler-bank" target are supported':['\u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u044E\u0442\u044C\u0441\u044F \u043B\u0438\u0448\u0435 \u0446\u0456\u043B\u0456 "IBAN"'],'Only this host is allowed. Use "%1$s"':[""],"Account name is missing":["\u041E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],'Only "IBAN" target are supported':['\u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u044E\u0442\u044C\u0441\u044F \u043B\u0438\u0448\u0435 \u0446\u0456\u043B\u0456 "IBAN"'],'Missing "amount" parameter to specify the amount to be transferred':['\u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 "amount", \u0449\u043E\u0431 \u0432\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u0443\u043C\u0443 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443'],'The "amount" parameter is not valid':["\u0441\u0443\u043C\u0430 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0430"],'"message" parameters to specify a reference text for the transfer are missing':['\u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 "message", \u0449\u043E\u0431 \u0432\u043A\u0430\u0437\u0430\u0442\u0438 \u0434\u043E\u0432\u0456\u0434\u043A\u043E\u0432\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443'],'The only currency allowed is "%1$s"':[""],"You cannot transfer an amount of zero.":["\u0412\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u0443\u043C\u0443, \u0449\u043E \u0434\u043E\u0440\u0456\u0432\u043D\u044E\u0454 \u043D\u0443\u043B\u044E."],"The balance is not sufficient":["\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043A\u0443 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043A\u043E\u0448\u0442\u0456\u0432"],"Please enter a longer subject":["\u041F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443"],"Show withdrawal confirmation":["\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"Withdraw without setting amount":[""],"Hide demo hint.":[""],"Show install wallet first":["\u0421\u043F\u043E\u0447\u0430\u0442\u043A\u0443 \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u0438, \u044F\u043A \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C"],"Currently, the bank is not accepting new registrations!":["\u041D\u0430\u0440\u0430\u0437\u0456 \u0431\u0430\u043D\u043A \u043D\u0435 \u043F\u0440\u0438\u0439\u043C\u0430\u0454 \u043D\u043E\u0432\u0456 \u0440\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u0457!"],"The name is missing":[""],"Missing username":["\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0454 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"],"Missing password":["\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0456\u0439 \u043F\u0430\u0440\u043E\u043B\u044C"],"The password should be longer than 8 letters":["\u043C\u0430\u0454 \u0431\u0443\u0442\u0438 \u0431\u0456\u043B\u044C\u0448\u0438\u043C \u0437\u0430 0"],"The passwords do not match":["\u041F\u0430\u0440\u043E\u043B\u0456 \u043D\u0435 \u0437\u0431\u0456\u0433\u0430\u044E\u0442\u044C\u0441\u044F"],"register new account":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],"Server replied with invalid phone or email.":["\u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0432, \u0449\u043E \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u0430\u0431\u043E \u0435\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0430 \u043F\u043E\u0448\u0442\u0430 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0456."],"You are not authorised to create this account.":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043D\u044F \u0446\u044C\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443."],"Registration is disabled because the bank ran out of bonus credit.":["\u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F \u0432\u0456\u0434\u043A\u043B\u044E\u0447\u0435\u043D\u0430, \u043E\u0441\u043A\u0456\u043B\u044C\u043A\u0438 \u0431\u0430\u043D\u043A \u0432\u0438\u0447\u0435\u0440\u043F\u0430\u0432 \u0431\u043E\u043D\u0443\u0441\u043D\u0438\u0439 \u043A\u0440\u0435\u0434\u0438\u0442."],"That username can't be used because is reserved.":["\u0426\u0435 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438, \u043E\u0441\u043A\u0456\u043B\u044C\u043A\u0438 \u0432\u043E\u043D\u043E \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043E\u0432\u0430\u043D\u0435."],"That username is already taken.":["\u0426\u0435 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u0435."],"That account ID is already taken.":["\u0426\u0435\u0439 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u0438\u0439."],"No information for the selected authentication channel.":["\u041D\u0435\u043C\u0430\u0454 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u0457 \u043F\u0440\u043E \u043E\u0431\u0440\u0430\u043D\u0438\u0439 \u043A\u0430\u043D\u0430\u043B \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0457."],"Authentication channel is not supported.":["\u041A\u0430\u043D\u0430\u043B \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0457 \u043D\u0435 \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454\u0442\u044C\u0441\u044F."],"Only an administrator is allowed to set the debt limit.":["\u041B\u0438\u0448\u0435 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0443 \u0434\u043E\u0437\u0432\u043E\u043B\u0435\u043D\u043E \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u044E\u0432\u0430\u0442\u0438 \u043B\u0456\u043C\u0456\u0442 \u0431\u043E\u0440\u0433\u0443."],"Only the administrator can change the conversion rate.":["\u041B\u0438\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0439 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438."],"The conversion rate class doesn't exist.":["\u041A\u0443\u0440\u0441 \u043E\u0431\u043C\u0456\u043D\u0443 \u0431\u0443\u043B\u043E \u0437\u0430\u0441\u0442\u043E\u0441\u043E\u0432\u0430\u043D\u043E \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E"],"Only admin can create accounts with second factor authentication.":["\u041B\u0438\u0448\u0435 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0437\u0430\u043F\u0438\u0441\u0438 \u0437 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u043E\u044E \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u0454\u044E."],"The password is too short. Can't have less than 8 characters.":["\u043C\u0430\u0454 \u0431\u0443\u0442\u0438 \u0431\u0456\u043B\u044C\u0448\u0438\u043C \u0437\u0430 0"],"The password is too long. Can't have more than 64 characters.":["\u043C\u0430\u0454 \u0431\u0443\u0442\u0438 \u0431\u0456\u043B\u044C\u0448\u0438\u043C \u0437\u0430 0"],"Account registration":["\u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],"Login username":["\u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"],"account identification to login":["\u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432 \u0431\u0430\u043D\u043A\u0443"],Password:["\u041F\u0430\u0440\u043E\u043B\u044C"],"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers":[""],"Repeat password":["\u041F\u043E\u0432\u0442\u043E\u0440\u0456\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C"],"Same password":["\u041D\u043E\u0432\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C"],"Full name":[""],Register:["\u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F"],"Create a random temporary user":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0432\u0438\u043F\u0430\u0434\u043A\u043E\u0432\u043E\u0433\u043E \u0442\u0438\u043C\u0447\u0430\u0441\u043E\u0432\u043E\u0433\u043E \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"],logout:[""],login:[""],"The account has no rights to login.":[""],"The account is locked and cannot login. Contact administrator.":[""],'Wrong credentials for "%1$s"':['\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0434\u0430\u043D\u0456 \u0434\u043B\u044F "%1$s"'],"Account login.":["\u041E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],"Session expired":["\u0422\u0435\u0440\u043C\u0456\u043D \u0434\u0456\u0457 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0437\u0430\u043A\u0456\u043D\u0447\u0438\u0432\u0441\u044F."],Username:["\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"],identification:["\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F"],"Password of the account":["\u043F\u0430\u0440\u043E\u043B\u044C \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],Forget:[""],"Log in":["\u0423\u0432\u0456\u0439\u0442\u0438"],"Transactions history":[""],"No transactions yet.":["\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0456\u0439 \u043F\u043E\u043A\u0438 \u0449\u043E \u043D\u0435\u043C\u0430\u0454."],"You can make a transfer or a withdrawal to your wallet.":[""],Date:["\u0414\u0430\u0442\u0430"],Counterpart:["\u041A\u043E\u043D\u0442\u0440\u0440\u0430\u0445\u0443\u043D\u043E\u043A"],sent:["\u0432\u0456\u0434\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E"],received:["\u043E\u0442\u0440\u0438\u043C\u0430\u043D\u043E"],"Invalid value":["\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F"],to:["\u0434\u043E"],from:["\u0432\u0456\u0434"],"First page":["\u041F\u0435\u0440\u0448\u0430 \u0441\u0442\u043E\u0440\u0456\u043D\u043A\u0430"],Next:["\u0414\u0430\u043B\u0456"],"confirm withdrawal":["\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],cambiar:[""],"abort withdrawal":["\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"The withdrawal has been aborted previously and can't be confirmed":["\u0412\u0438\u0432\u0435\u0434\u0435\u043D\u043D\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u0431\u0443\u043B\u043E \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E \u0440\u0430\u043D\u0456\u0448\u0435 \u0456 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043E"],"The withdrawal operation can't be confirmed before a wallet accepted the transaction.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438, \u0434\u043E\u043A\u0438 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C \u043D\u0435 \u043F\u0440\u0438\u0439\u043C\u0435 \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0456\u044E."],"The operation ID is invalid.":["\u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439."],"The operation was not found.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E."],"The starting withdrawal amount and the confirmation amount differs.":[""],"The bank requires a bank account which has not been specified yet.":[""],"Bad request":[""],"The withdrawal operation has been aborted.":["\u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"The withdrawal operation has been confirmed previously and can\u2019t be aborted.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043D\u043D\u044F \u0431\u0443\u043B\u0430 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u0430 \u0440\u0430\u043D\u0456\u0448\u0435 \u0456 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u0430"],"Complete withdrawal.":["\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"Confirm the withdrawal operation":["\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"Wire transfer details":["\u0414\u0435\u0442\u0430\u043B\u0456 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443"],"Payment Service Provider's account number":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler"],"Payment Service Provider's name":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler"],"Payment Service Provider's account bank hostname":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler"],"Payment Service Provider's account id":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler"],"Payment Service Provider's account address":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler"],"Payment Service Provider's account cyclos hostname":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler"],"No amount has yet been determined.":[""],Transfer:["\u041F\u0435\u0440\u0435\u043A\u0430\u0437\u0430\u0442\u0438"],"Authentication required":["\u041F\u043E\u0442\u0440\u0456\u0431\u043D\u0430 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F"],"This operation was created with another username":["\u0426\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0431\u0443\u043B\u0430 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u0430 \u0437 \u0456\u043D\u0448\u0438\u043C \u0456\u043C\u0435\u043D\u0435\u043C \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"],'You are currently logged in with user "%1$s" and the operation was made with user "%2$s"':[""],"The reserve operation has been confirmed previously and can't be aborted":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0440\u0435\u0437\u0435\u0440\u0432\u0443\u0432\u0430\u043D\u043D\u044F \u0431\u0443\u043B\u0430 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u0430 \u0440\u0430\u043D\u0456\u0448\u0435 \u0456 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u0430"],"Wire transfer completed!":["\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E!"],"Confirm withdrawal.":["\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"Unauthorized to make the operation, maybe the session has expired or the password changed.":["\u041D\u0435 \u0430\u0432\u0442\u043E\u0440\u0438\u0437\u043E\u0432\u0430\u043D\u043E \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457, \u043C\u043E\u0436\u043B\u0438\u0432\u043E, \u0441\u0435\u0441\u0456\u044F \u0437\u0430\u043A\u0456\u043D\u0447\u0438\u043B\u0430\u0441\u044F \u0430\u0431\u043E \u043F\u0430\u0440\u043E\u043B\u044C \u0431\u0443\u043B\u043E \u0437\u043C\u0456\u043D\u0435\u043D\u043E."],"The operation was rejected due to insufficient funds.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0431\u0443\u043B\u043E \u0432\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u043E \u0447\u0435\u0440\u0435\u0437 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u0456\u0441\u0442\u044C \u043A\u043E\u0448\u0442\u0456\u0432."],"Withdrawal confirmed":["\u0417\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043E"],"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.":["\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u0434\u043E \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 Taler \u0431\u0443\u043B\u043E \u0456\u043D\u0456\u0446\u0456\u0439\u043E\u0432\u0430\u043D\u043E. \u041D\u0435\u0437\u0430\u0431\u0430\u0440\u043E\u043C \u0432\u0438 \u043E\u0442\u0440\u0438\u043C\u0430\u0454\u0442\u0435 \u0437\u0430\u043F\u0438\u0442\u0430\u043D\u0443 \u0441\u0443\u043C\u0443 \u0443 \u0432\u0430\u0448 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C Taler."],"Do not show this again":["\u0411\u0456\u043B\u044C\u0448\u0435 \u043D\u0435 \u043F\u043E\u043A\u0430\u0437\u0443\u0432\u0430\u0442\u0438 \u0446\u0435"],"If you have a Taler wallet installed on this device":["\u042F\u043A\u0449\u043E \u043D\u0430 \u0446\u044C\u043E\u043C\u0443 \u043F\u0440\u0438\u0441\u0442\u0440\u043E\u0457 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C Taler"],"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions":["\u0412\u0438 \u043F\u043E\u0431\u0430\u0447\u0438\u0442\u0435 \u0434\u0435\u0442\u0430\u043B\u0456 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0443 \u0432\u0430\u0448\u043E\u043C\u0443\u0433\u0430\u043C\u0430\u043D\u0446\u0456, \u0432\u043A\u043B\u044E\u0447\u0430\u044E\u0447\u0438 \u043A\u043E\u043C\u0456\u0441\u0456\u0457 (\u044F\u043A\u0449\u043E \u0454). \u042F\u043A\u0449\u043E \u0443 \u0432\u0430\u0441 \u0439\u043E\u0433\u043E \u0449\u0435 \u043D\u0435\u043C\u0430\u0454, \u0432\u0438 \u043C\u043E\u0436\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u0438 \u0439\u043E\u0433\u043E, \u0434\u043E\u0442\u0440\u0438\u043C\u0443\u044E\u0447\u0438\u0441\u044C \u0456\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0456\u0439 \u0443"],"on this page":["\u0446\u0456\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u0446\u0456"],Withdraw:["\u0417\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"In case you have a Taler wallet on another device":["\u0410\u0431\u043E \u044F\u043A\u0449\u043E \u0443 \u0432\u0430\u0441 \u0454 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C \u043D\u0430 \u0456\u043D\u0448\u043E\u043C\u0443 \u043F\u0440\u0438\u0441\u0442\u0440\u043E\u0457"],"Scan the QR below to start the withdrawal.":["\u0421\u043A\u0430\u043D\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434 \u043D\u0438\u0436\u0447\u0435, \u0449\u043E\u0431 \u0440\u043E\u0437\u043F\u043E\u0447\u0430\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432."],"create withdrawal":["\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"The server replied with an invalid taler://withdraw URI":["\u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0432 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u043C URI \u0434\u043B\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"Withdraw URI: %1$s":["URI \u0434\u043B\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432: %1$s"],"The operation was rejected due to insufficient funds":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0431\u0443\u043B\u043E \u0432\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u043E \u0447\u0435\u0440\u0435\u0437 \u0431\u0440\u0430\u043A \u043A\u043E\u0448\u0442\u0456\u0432"],"Current balance is %1$s":[""],"You can withdraw up to %1$s":[""],Continue:["\u041F\u0440\u043E\u0434\u043E\u0432\u0436\u0438\u0442\u0438"],"Use your Taler wallet":["\u041F\u0456\u0434\u0433\u043E\u0442\u0443\u0439\u0442\u0435 \u0441\u0432\u0456\u0439 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C"],"After using your wallet you will need to authorize or cancel the operation on this site.":["\u041F\u0456\u0441\u043B\u044F \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F \u0432\u0430\u0448\u043E\u0433\u043E \u0433\u0430\u043C\u0430\u043D\u0446\u044F \u0412\u0430\u043C \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u0431\u0443\u0434\u0435 \u043F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0438 \u0430\u0431\u043E \u0441\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u043D\u0430 \u0446\u044C\u043E\u043C\u0443 \u0441\u0430\u0439\u0442\u0456."],"You need a Taler wallet":["\u0412\u0430\u043C \u043F\u043E\u0442\u0440\u0456\u0431\u0435\u043D \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C GNU Taler"],"If you don't have one yet you can follow the instruction in":["\u042F\u043A\u0449\u043E \u0443 \u0432\u0430\u0441 \u0439\u043E\u0433\u043E \u0449\u0435 \u043D\u0435\u043C\u0430\u0454, \u0432\u0438 \u043C\u043E\u0436\u0435\u0442\u0435 \u0434\u043E\u0442\u0440\u0438\u043C\u0443\u0432\u0430\u0442\u0438\u0441\u044F \u0456\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0456\u0439 \u0443"],"this page":["\u0446\u0456\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u0446\u0456"],"Send money":["\u041D\u0430\u0434\u0456\u0441\u043B\u0430\u0442\u0438 \u0433\u0440\u043E\u0448\u0456"],"to a Taler wallet":["\u0434\u043E \u0433\u0430\u043C\u0430\u043D\u0446\u044F %1$s"],"Withdraw digital money into your mobile wallet or browser extension":["\u0417\u043D\u0456\u043C\u0456\u0442\u044C \u0446\u0438\u0444\u0440\u043E\u0432\u0456 \u0433\u0440\u043E\u0448\u0456 \u0443 \u0412\u0430\u0448 \u043C\u043E\u0431\u0456\u043B\u044C\u043D\u0438\u0439 \u0433\u0430\u043C\u0430\u043D\u0435\u0446\u044C \u0430\u0431\u043E \u0440\u043E\u0437\u0448\u0438\u0440\u0435\u043D\u043D\u044F \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430"],"to another bank account":["\u043D\u0430 \u0456\u043D\u0448\u0438\u0439 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u0440\u0430\u0445\u0443\u043D\u043E\u043A"],"Make a wire transfer to an account with known bank account number.":["\u0417\u0434\u0456\u0439\u0441\u043D\u0456\u0442\u044C \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u043D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A \u0456\u0437 \u0432\u0456\u0434\u043E\u043C\u0438\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u0440\u0430\u0445\u0443\u043D\u043A\u0443."],"This is a demo":["\u0426\u0435 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0456\u0439\u043D\u0438\u0439 \u0431\u0430\u043D\u043A"],"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .":["\u0426\u044F \u0447\u0430\u0441\u0442\u0438\u043D\u0430 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0456\u0457 \u043F\u043E\u043A\u0430\u0437\u0443\u0454, \u044F\u043A \u043F\u0440\u0430\u0446\u044E\u0432\u0430\u0432 \u0431\u0438 \u0431\u0430\u043D\u043A, \u0449\u043E \u0431\u0435\u0437\u043F\u043E\u0441\u0435\u0440\u0435\u0434\u043D\u044C\u043E \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 Taler. \u041E\u043A\u0440\u0456\u043C \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F \u0432\u0430\u0448\u043E\u0433\u043E \u0432\u043B\u0430\u0441\u043D\u043E\u0433\u043E \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u0440\u0430\u0445\u0443\u043D\u043A\u0443, \u0432\u0438 \u0442\u0430\u043A\u043E\u0436 \u043C\u043E\u0436\u0435\u0442\u0435 \u043F\u0435\u0440\u0435\u0433\u043B\u044F\u043D\u0443\u0442\u0438 \u0456\u0441\u0442\u043E\u0440\u0456\u044E \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0456\u0439 \u0434\u0435\u044F\u043A\u0438\u0445 %1$s."],"Here you will be able to see how a bank that supports Taler directly would work.":["\u0426\u044F \u0447\u0430\u0441\u0442\u0438\u043D\u0430 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0456\u0457 \u043F\u043E\u043A\u0430\u0437\u0443\u0454, \u044F\u043A \u043F\u0440\u0430\u0446\u044E\u0432\u0430\u0432 \u0431\u0438 \u0431\u0430\u043D\u043A, \u0449\u043E \u0431\u0435\u0437\u043F\u043E\u0441\u0435\u0440\u0435\u0434\u043D\u044C\u043E \u043F\u0456\u0434\u0442\u0440\u0438\u043C\u0443\u0454 Taler."],"Internal error, please report. There should be more information in the console.":[""],"Internal error, please report.":["\u0412\u043D\u0443\u0442\u0440\u0456\u0448\u043D\u044F \u043F\u043E\u043C\u0438\u043B\u043A\u0430, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u043F\u043E\u0432\u0456\u0434\u043E\u043C\u0442\u0435 \u043F\u0440\u043E \u0446\u0435."],Preferences:["\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F"],"Show debug information":["\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044E \u0434\u043B\u044F \u0432\u0456\u0434\u043B\u0430\u0434\u043A\u0438"],Welcome:["\u0412\u0456\u0442\u0430\u0454\u043C\u043E"],"Welcome, %1$s":["\u0412\u0456\u0442\u0430\u0454\u043C\u043E, %1$s"],"No enough permission to access the conversion rate list.":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457."],"Conversion list not found. Maybe conversion rate is not supported.":[""],"Conversion list not implemented.":["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0440\u0435\u0430\u043B\u0456\u0437\u043E\u0432\u0430\u043D\u043E"],"Conversion rate classes":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"Create conversion rate class":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"No conversion rate class":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],Name:["\u041D\u0430\u0437\u0432\u0430"],Description:["\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0434\u0435\u043C\u043E \u043E\u043F\u0438\u0441"],Cashin:["\u041F\u043E\u043F\u043E\u0432\u043D\u0435\u043D\u043D\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u043E\u044E"],"min:":[""],"fee:":[""],"Select a section":["\u041E\u0431\u0435\u0440\u0456\u0442\u044C \u0440\u043E\u0437\u0434\u0456\u043B"],Details:["\u0414\u0435\u0442\u0430\u043B\u0456"],Delete:["\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438"],Credentials:["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0434\u0430\u043D\u0456"],Cashouts:["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438"],Conversion:["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"only admin can setup conversion":["\u041B\u0438\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0439 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438."],"calculate cashout fee":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],"update conversion rate":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"Wrong credentials":['\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0434\u0430\u043D\u0456 \u0434\u043B\u044F "%1$s"'],"Conversion is disabled":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"Config cashout":["\u0412\u0438\u043F\u043B\u0430\u0442\u0438 \u0433\u043E\u0442\u0456\u0432\u043A\u043E\u044E"],"Config cashin":["\u041F\u043E\u043F\u043E\u0432\u043D\u0435\u043D\u043D\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u043E\u044E"],"Bad ratios":[""],"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.":[""],"Initial amount":["\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430 \u0441\u0443\u043C\u0430 \u0437\u043D\u044F\u0442\u0442\u044F"],"Use it to test how the conversion will affect the amount.":[""],"Sending to this bank":[""],Converted:["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"Cashin after fee":[""],"Sending from this bank":[""],"Cashout after fee":["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0441\u0442\u0432\u043E\u0440\u0435\u043D\u043E"],"Bad configuration":[""],"This configuration allows users to cash out more of what has been cashed in.":[""],Update:["\u041E\u043D\u043E\u0432\u0438\u0442\u0438"],Rnvalid:["\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u043E"],"Must be > 0":[""],"Minimum amount":[""],"Only cashout operation above this threshold will be allowed.":[""],Ratio:[""],"Conversion ratio between currencies":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"Example conversion":[""],"1 %1$s will be converted into %2$s %3$s":[""],"Tiny amount":["\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A"],"Rounding mode":[""],Zero:[""],"Amount will be round below to the largest possible value smaller than the input.":[""],Up:[""],"Amount will be round up to the smallest possible value larger than the input.":[""],Nearest:[""],"Amount will be round to the closest possible value.":[""],'If none specified the fallback value is "%1$s ".':[""],Examples:[""],"Rounding an amount of 1.24 with rounding value 0.1":[""],"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.":[""],'With the "zero" mode the value will be rounded to 1.2':[""],'With the "nearest" mode the value will be rounded to 1.2':[""],'With the "up" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.26 with rounding value 0.1":[""],'With the "nearest" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.24 with rounding value 0.3":[""],"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.":[""],'With the "up" mode the value will be rounded to 1.5':[""],"Rounding an amount of 1.26 with rounding value 0.3":[""],"Amount to be deducted before amount is credited.":[""],"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"delete conversion rate class":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],Unauthorized:["\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E"],Forbidden:[""],NotFound:[""],NotImplemented:["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0440\u0435\u0430\u043B\u0456\u0437\u043E\u0432\u0430\u043D\u043E"],"update conversion rate class":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"Not Found":[""],"Not implemented":["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0440\u0435\u0430\u043B\u0456\u0437\u043E\u0432\u0430\u043D\u043E"],"The name of the conversion is already used.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u0432\u0436\u0435 \u0456\u0441\u043D\u0443\u0454"],"Conversion rate class":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],Accounts:["\u0420\u0430\u0445\u0443\u043D\u043A\u0438"],Test:[""],Users:["\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"],"Can't remove the conversion rate class":[""],"There are some user associated to this class. You need to remove them first.":[""],"You are going to remove the conversion rate class":["\u0412\u0438 \u0437\u0431\u0438\u0440\u0430\u0454\u0442\u0435\u0441\u044F \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],"This step can't be undone.":["\u0426\u0435\u0439 \u043A\u0440\u043E\u043A \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0441\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438."],Filters:[""],"Show from other classes":[""],Account:["\u0420\u0430\u0445\u0443\u043D\u043E\u043A"],"Group ID":[""],"No users in this conversion rate class":[""],Class:[""],Action:["\u0414\u0456\u0457"],Remove:["\u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438"],Add:[""],"Conversion rate name":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"Short description of the class":[""],"create conversion rate class":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"Conversion rate class created.":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],"The rights to change the account are not sufficient":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0437\u043C\u0456\u043D\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],"New conversion rate class":["\u041E\u0431\u043C\u0456\u043D\u043D\u0438\u0439 \u043A\u0443\u0440\u0441"],Create:["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438"],"History of public accounts":["\u0406\u0441\u0442\u043E\u0440\u0456\u044F \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0438\u0445 \u0440\u0430\u0445\u0443\u043D\u043A\u0456\u0432"],"Make a wire transfer":["\u0417\u0434\u0456\u0439\u0441\u043D\u0438\u0442\u0438 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437"],"Scan the QR code below to start the withdrawal.":["\u0421\u043A\u0430\u043D\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434 \u043D\u0438\u0436\u0447\u0435, \u0449\u043E\u0431 \u0440\u043E\u0437\u043F\u043E\u0447\u0430\u0442\u0438 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432."],"Operation aborted":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E"],"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.":["\u0411\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u043D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 Taler Exchange \u0431\u0443\u043B\u043E \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E, \u0432\u0430\u0448 \u0431\u0430\u043B\u0430\u043D\u0441 \u043D\u0435 \u043F\u043E\u0441\u0442\u0440\u0430\u0436\u0434\u0430\u0432."],"Go to your wallet now":["\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0434\u043E \u0433\u0430\u043C\u0430\u043D\u0446\u044F \u0437\u0430\u0440\u0430\u0437"],"The operation is marked as selected, but a process during the withdrawal failed":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u043F\u043E\u0437\u043D\u0430\u0447\u0435\u043D\u0430 \u044F\u043A '\u0432\u0438\u0431\u0440\u0430\u043D\u0430', \u0430\u043B\u0435 \u0434\u0435\u044F\u043A\u0438\u0439 \u043A\u0440\u043E\u043A \u0443 \u043F\u0440\u043E\u0446\u0435\u0441\u0456 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u0442\u0438"],"A withdrawal reserve ID was not found and no account has been selected.":["\u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E, \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u0432\u0438\u0431\u0440\u0430\u043D\u043E \u0430\u0431\u043E \u0432\u0438\u0431\u0440\u0430\u043D\u0438\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439."],"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.":["\u0404 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432, \u0430\u043B\u0435 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u0432\u0438\u0431\u0440\u0430\u043D\u043E \u0430\u0431\u043E \u0432\u0438\u0431\u0440\u0430\u043D\u0438\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439."],"The account was selected, but no withdrawal reserve ID was found.":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0432\u0438\u0431\u0440\u0430\u043D\u043E, \u0430\u043B\u0435 \u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E."],"Operation not found":["\u041E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E"],"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.":["\u0426\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044F \u043D\u0435\u0432\u0456\u0434\u043E\u043C\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0443. \u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0438\u0439 \u0430\u0431\u043E \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0438\u0434\u0430\u043B\u0438\u0432 \u0456\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0456\u044E \u043F\u0440\u043E \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u044E \u0434\u043E \u0457\u0457 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043D\u044F."],"Continue to dashboard":["\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0434\u043E \u043F\u0430\u043D\u0435\u043B\u0456 \u043A\u0435\u0440\u0443\u0432\u0430\u043D\u043D\u044F"],"The Withdrawal URI is not valid":["URI \u0434\u043B\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439"],"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.":[""],"Latest cashouts":["\u041E\u0441\u0442\u0430\u043D\u043D\u0456 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438"],Created:["\u0421\u0442\u0432\u043E\u0440\u0435\u043D\u043E"],"Total debit":["\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0438\u0439 \u0434\u0435\u0431\u0435\u0442"],"Total credit":["\u0417\u0430\u0433\u0430\u043B\u044C\u043D\u0438\u0439 \u043A\u0440\u0435\u0434\u0438\u0442"],"Cashout for account %1$s":["\u0417\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u0434\u043B\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 %1$s"],"Invalid email format":["\u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u043D\u044F"],"Should start with +":["\u043F\u043E\u0432\u0438\u043D\u0435\u043D \u043F\u043E\u0447\u0438\u043D\u0430\u0442\u0438\u0441\u044F \u0437 +"],"A phone number consists of numbers only":["\u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u043F\u043E\u0432\u0438\u043D\u0435\u043D \u043C\u0456\u0441\u0442\u0438\u0442\u0438 \u043B\u0438\u0448\u0435 \u0446\u0438\u0444\u0440\u0438"],"Account ID for authentication":["\u0414\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0430 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F"],"Name of the account holder":["\u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],"Internal account":["\u043D\u0430 \u0456\u043D\u0448\u0438\u0439 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u0440\u0430\u0445\u0443\u043D\u043E\u043A"],"If this field is empty, a random account ID will be assigned":["\u044F\u043A\u0449\u043E \u043F\u043E\u0440\u043E\u0436\u043D\u044C\u043E, \u0431\u0443\u0434\u0435 \u043F\u0440\u0438\u0437\u043D\u0430\u0447\u0435\u043D\u043E \u0432\u0438\u043F\u0430\u0434\u043A\u043E\u0432\u0438\u0439 \u043D\u043E\u043C\u0435\u0440 \u0440\u0430\u0445\u0443\u043D\u043A\u0443"],"You can copy and share this IBAN number in order to receive wire transfers to your bank account":[""],Email:["Email"],"To be used when second factor authentication is enabled":["\u0423\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E"],Phone:["\u0422\u0435\u043B\u0435\u0444\u043E\u043D"],"Enable second factor authentication":["\u0423\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0434\u0432\u043E\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443 \u0430\u0432\u0442\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044E"],"Using email":["\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0447\u0438 email"],"Add an email in your profile to enable this option":["\u0434\u043E\u0434\u0430\u0439\u0442\u0435 \u0435\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0443 \u043F\u043E\u0448\u0442\u0443 \u0443 \u0432\u0430\u0448\u043E\u043C\u0443 \u043F\u0440\u043E\u0444\u0456\u043B\u0456, \u0449\u043E\u0431 \u0443\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0446\u044E \u043E\u043F\u0446\u0456\u044E"],"Using SMS":["\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u044E\u0447\u0438 SMS"],"Add a phone number in your profile to enable this option":["\u0434\u043E\u0434\u0430\u0439\u0442\u0435 \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u0443 \u0432\u0430\u0448\u043E\u043C\u0443 \u043F\u0440\u043E\u0444\u0456\u043B\u0456, \u0449\u043E\u0431 \u0443\u0432\u0456\u043C\u043A\u043D\u0443\u0442\u0438 \u0446\u044E \u043E\u043F\u0446\u0456\u044E"],"Cashout account":["\u0412\u0456\u0434\u0441\u0443\u0442\u043D\u0456\u0439 \u0440\u0430\u0445\u0443\u043D\u043E\u043A \u0434\u043B\u044F \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438"],"External account number where the money is going to be sent when doing cashouts":["\u043D\u043E\u043C\u0435\u0440 \u0440\u0430\u0445\u0443\u043D\u043A\u0443, \u043D\u0430 \u044F\u043A\u0438\u0439 \u0431\u0443\u0434\u0443\u0442\u044C \u0432\u0456\u0434\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0456 \u0433\u0440\u043E\u0448\u0456 \u043F\u0440\u0438 \u0437\u043D\u044F\u0442\u0442\u0456 \u0433\u043E\u0442\u0456\u0432\u043A\u0438"],"Max debt":["\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0438\u0439 \u0431\u043E\u0440\u0433"],"How much the balance can go below zero.":[""],"Is this account public?":["\u0426\u0435\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0454 \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0438\u043C?"],"Public accounts have their balance publicly accessible":["\u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0456 \u0440\u0430\u0445\u0443\u043D\u043A\u0438 \u043C\u0430\u044E\u0442\u044C \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u043E \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u0431\u0430\u043B\u0430\u043D\u0441"],"Does this account belong to a Payment Service Provider?":["\u0426\u0435\u0439 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0454 \u043F\u0443\u0431\u043B\u0456\u0447\u043D\u0438\u043C?"],"update account":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],"Account updated":["\u0420\u0430\u0445\u0443\u043D\u043E\u043A \u043E\u043D\u043E\u0432\u043B\u0435\u043D\u043E"],"The username was not found":["\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E"],"You can't change the legal name, please contact the your account administrator.":["\u0412\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u044E\u0440\u0438\u0434\u0438\u0447\u043D\u0435 \u0456\u043C'\u044F, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0430\u0448\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443."],"You can't change the debt limit, please contact the your account administrator.":["\u0412\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043B\u0456\u043C\u0456\u0442 \u0431\u043E\u0440\u0433\u0443, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0430\u0448\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443."],"You can't change the cashout address, please contact the your account administrator.":["\u0412\u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0443 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438, \u0431\u0443\u0434\u044C \u043B\u0430\u0441\u043A\u0430, \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0430\u0448\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443."],"Update account information.":["\u041E\u0447\u0456\u043A\u0443\u0432\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457 \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],'Account "%1$s"':['\u0420\u0430\u0445\u0443\u043D\u043E\u043A "%1$s"'],Removed:["\u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438"],"This account can't be used.":["\u0426\u0435\u0439 \u043A\u0440\u043E\u043A \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0441\u043A\u0430\u0441\u0443\u0432\u0430\u0442\u0438."],"Change details":["\u0417\u043C\u0456\u043D\u0430 \u0440\u0435\u043A\u0432\u0456\u0437\u0438\u0442\u0456\u0432"],"Merchant integration":["\u0420\u0435\u0454\u0441\u0442\u0440\u0430\u0446\u0456\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.':[""],"Account type":["\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],"Method to use for wire transfer.":["\u0417\u0434\u0456\u0439\u0441\u043D\u0438\u0442\u0438 \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437"],IBAN:[""],"International Bank Account Number.":[""],"Account name":["\u041E\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443"],"Bank host where the service is located.":[""],"Bank account identifier for wire transfers.":["\u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0446\u0456\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0434\u043B\u044F \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u043A\u0430\u0437\u0443"],Address:[""],"Owner's name":["\u0406\u043C\u02BC\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"],"Legal name of the person holding the account.":["\u0456\u043C'\u044F \u043E\u0441\u043E\u0431\u0438, \u044F\u043A\u0456\u0439 \u043D\u0430\u043B\u0435\u0436\u0438\u0442\u044C \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],"Account info URL":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E"],"From where the merchant can download information about incoming wire transfers to this account.":[""],"Repeated password doesn't match":["\u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0441\u043F\u0456\u0432\u043F\u0430\u0434\u0430\u0454"],"update password":["\u041E\u043D\u043E\u0432\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C"],"Password changed":["\u041F\u0430\u0440\u043E\u043B\u044C \u0437\u043C\u0456\u043D\u0435\u043D\u043E"],"Not authorized to change the password, maybe the session is invalid.":["\u041D\u0435\u043C\u0430\u0454 \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0437\u043C\u0456\u043D\u0438 \u043F\u0430\u0440\u043E\u043B\u044F, \u043C\u043E\u0436\u043B\u0438\u0432\u043E, \u0441\u0435\u0430\u043D\u0441 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0438\u0439."],"You need to provide the old password. If you don't have it contact your account administrator.":["\u0412\u0430\u043C \u043F\u043E\u0442\u0440\u0456\u0431\u043D\u043E \u043D\u0430\u0434\u0430\u0442\u0438 \u0441\u0442\u0430\u0440\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C. \u042F\u043A\u0449\u043E \u0443 \u0432\u0430\u0441 \u0439\u043E\u0433\u043E \u043D\u0435\u043C\u0430\u0454, \u0437\u0432\u0435\u0440\u043D\u0456\u0442\u044C\u0441\u044F \u0434\u043E \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0430 \u0432\u0430\u0448\u043E\u0433\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443."],"Your current password doesn't match, can't change to a new password.":["\u0412\u0430\u0448 \u043F\u043E\u0442\u043E\u0447\u043D\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0437\u0431\u0456\u0433\u0430\u0454\u0442\u044C\u0441\u044F, \u043D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043D\u0430 \u043D\u043E\u0432\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C."],"You don't have the rights to change the password.":[""],"Update account password.":["\u041E\u043D\u043E\u0432\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C"],"Update password":["\u041E\u043D\u043E\u0432\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C"],"Current password":["\u041F\u043E\u0442\u043E\u0447\u043D\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C"],"Your current password, for security":["\u0432\u0430\u0448 \u043F\u043E\u0442\u043E\u0447\u043D\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C, \u0434\u043B\u044F \u0431\u0435\u0437\u043F\u0435\u043A\u0438"],"New password":["\u041D\u043E\u0432\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C"],"Type it again":["\u0412\u0432\u0435\u0434\u0456\u0442\u044C \u0439\u043E\u0433\u043E \u0449\u0435 \u0440\u0430\u0437"],"Repeat the same password":["\u043F\u043E\u0432\u0442\u043E\u0440\u0456\u0442\u044C \u0442\u043E\u0439 \u0441\u0430\u043C\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C"],Change:["\u0417\u043C\u0456\u043D\u0438\u0442\u0438"],"Create account":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],Actions:["\u0414\u0456\u0457"],Unknown:["\u043D\u0435\u0432\u0456\u0434\u043E\u043C\u043E"],"Change password":["\u0437\u043C\u0456\u043D\u0438\u0442\u0438 \u043F\u0430\u0440\u043E\u043B\u044C"],"Querying for the current stats failed":[""],"The request parameters are wrong":[""],"The user is unauthorized":["\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E"],"Querying for the previous stats failed":[""],"Transaction volume report":[""],"Last hour":["\u041E\u0441\u0442\u0430\u043D\u043D\u044F \u0433\u043E\u0434\u0438\u043D\u0430"],"Previous day":[""],"Last month":["\u041E\u0441\u0442\u0430\u043D\u043D\u0456\u0439 \u043C\u0456\u0441\u044F\u0446\u044C"],"Last year":["\u041E\u0441\u0442\u0430\u043D\u043D\u0456\u0439 \u0440\u0456\u043A"],"Last Year":["\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u0440\u0456\u043A"],"Trading volume from %1$s to %2$s":["\u041E\u0431\u0441\u044F\u0433 \u0442\u043E\u0440\u0433\u0456\u0432 \u043D\u0430 %1$s \u043F\u043E\u0440\u0456\u0432\u043D\u044F\u043D\u043E \u0437 %2$s"],"Transferred from an external account to an account in this bank.":[""],"Transferred from an account in this bank to an external account.":["\u0417\u0434\u0456\u0439\u0441\u043D\u0456\u0442\u044C \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u043A\u0430\u0437 \u043D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A \u0456\u0437 \u0432\u0456\u0434\u043E\u043C\u0438\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0431\u0430\u043D\u043A\u0456\u0432\u0441\u044C\u043A\u043E\u0433\u043E \u0440\u0430\u0445\u0443\u043D\u043A\u0443."],Payin:["\u0412\u043D\u0435\u0441\u0435\u043D\u043D\u044F \u043A\u043E\u0448\u0442\u0456\u0432"],"Transferred from an account to a Taler exchange.":[""],Payout:["\u0412\u0438\u043F\u043B\u0430\u0442\u0430"],"Transferred from a Taler exchange to another account.":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u043E\u0431\u043C\u0456\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u043D\u043A\u0442\u0443 Taler"],"Download stats as CSV":["\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0443 \u0444\u043E\u0440\u043C\u0430\u0442\u0456 CSV"],previous:[""],"Decreased by":["\u0417\u043C\u0435\u043D\u0448\u0438\u043B\u043E\u0441\u044C \u043D\u0430"],"Increased by":["\u0417\u0431\u0456\u043B\u044C\u0448\u0438\u043B\u043E\u0441\u044C \u043D\u0430"],"create account":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],'Account created with password "%1$s".':[""],"Server replied that phone or email is invalid":["\u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0432, \u0449\u043E \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0443 \u0430\u0431\u043E \u0435\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0430 \u043F\u043E\u0448\u0442\u0430 \u043D\u0435\u0434\u0456\u0439\u0441\u043D\u0456"],"The rights to perform the operation are not sufficient":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u043A\u043E\u043D\u0430\u043D\u043D\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0456\u0457"],"Account username is already taken":["\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u043E"],"Account ID is already taken":["\u0406\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u0432\u0436\u0435 \u0437\u0430\u0439\u043D\u044F\u0442\u0438\u0439"],"Bank ran out of bonus credit.":["\u0423 \u0431\u0430\u043D\u043A\u0443 \u0437\u0430\u043A\u0456\u043D\u0447\u0438\u0432\u0441\u044F \u0431\u043E\u043D\u0443\u0441\u043D\u0438\u0439 \u043A\u0440\u0435\u0434\u0438\u0442."],"Account username can't be used because is reserved":["\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438, \u043E\u0441\u043A\u0456\u043B\u044C\u043A\u0438 \u0432\u043E\u043D\u043E \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043E\u0432\u0430\u043D\u0435"],"Can't create accounts":["\u041D\u0435 \u0432\u0434\u0430\u0454\u0442\u044C\u0441\u044F \u0441\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438"],"Only system admin can create accounts.":["\u041B\u0438\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0439 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438."],"New bank account":["\u041D\u043E\u0432\u0438\u0439 \u0431\u0456\u0437\u043D\u0435\u0441 \u0440\u0430\u0445\u0443\u043D\u043E\u043A"],"download statistics":["\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0443 \u0444\u043E\u0440\u043C\u0430\u0442\u0456 CSV"],"only admin can download stats":["\u041B\u0438\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0438\u0439 \u0430\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435 \u0441\u0442\u0432\u043E\u0440\u044E\u0432\u0430\u0442\u0438 \u0440\u0430\u0445\u0443\u043D\u043A\u0438."],"Download bank stats":["\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0431\u0430\u043D\u043A\u0443"],"Include hour metric":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u0447\u0430\u0441\u043E\u0432\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443"],"Include day metric":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u0434\u043E\u0431\u043E\u0432\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443"],"Include month metric":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u043C\u0456\u0441\u044F\u0447\u043D\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443"],"Include year metric":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u0440\u0456\u0447\u043D\u0443 \u043C\u0435\u0442\u0440\u0438\u043A\u0443"],"Include table header":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0438 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0442\u0430\u0431\u043B\u0438\u0446\u0456"],"Add previous metric for compare":["\u0414\u043E\u0434\u0430\u0442\u0438 \u043F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443 \u0434\u043B\u044F \u043F\u043E\u0440\u0456\u0432\u043D\u044F\u043D\u043D\u044F"],"Fail on first error":["\u0417\u0431\u0456\u0439 \u043D\u0430 \u043F\u0435\u0440\u0448\u0456\u0439 \u043F\u043E\u043C\u0438\u043B\u0446\u0456"],Download:["\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438"],"downloading... %1$s":["\u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F...%1$s"],"Download completed":["\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E"],"Click here to save the file in your computer.":["\u043D\u0430\u0442\u0438\u0441\u043D\u0456\u0442\u044C \u0442\u0443\u0442, \u0449\u043E\u0431 \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0444\u0430\u0439\u043B \u043D\u0430 \u0432\u0430\u0448\u043E\u043C\u0443 \u043A\u043E\u043C\u043F'\u044E\u0442\u0435\u0440\u0456"],"there was an error reading the balance":[""],"Can't delete the account":["\u041D\u0435 \u0432\u0434\u0430\u0454\u0442\u044C\u0441\u044F \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u043D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438, \u043F\u043E\u043A\u0438 \u043D\u0430 \u043D\u044C\u043E\u043C\u0443 \u0454 \u0431\u0430\u043B\u0430\u043D\u0441. \u0421\u043F\u043E\u0447\u0430\u0442\u043A\u0443 \u043F\u0435\u0440\u0435\u043A\u043E\u043D\u0430\u0439\u0442\u0435\u0441\u044F, \u0449\u043E \u0432\u043B\u0430\u0441\u043D\u0438\u043A \u0437\u0440\u043E\u0431\u0438\u0432 \u043F\u043E\u0432\u043D\u0435 \u0437\u043D\u044F\u0442\u0442\u044F \u043A\u043E\u0448\u0442\u0456\u0432."],"Name doesn't match":["\u0456\u043C'\u044F \u043D\u0435 \u0437\u0431\u0456\u0433\u0430\u0454\u0442\u044C\u0441\u044F"],"delete account":["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],"Account removed":["\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043E"],"No enough permission to delete the account.":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443."],"The username was not found.":["\u0406\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E."],"Can't delete a reserved username.":["\u041D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u043E\u0432\u0430\u043D\u0435 \u0456\u043C'\u044F \u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430."],"Can't delete an account with balance different than zero.":["\u041D\u0435 \u043C\u043E\u0436\u043D\u0430 \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 \u0437 \u0431\u0430\u043B\u0430\u043D\u0441\u043E\u043C, \u0432\u0456\u0434\u043C\u0456\u043D\u043D\u0438\u043C \u0432\u0456\u0434 \u043D\u0443\u043B\u044F."],"Remove account.":["\u041D\u0430 \u0440\u0430\u0445\u0443\u043D\u043E\u043A"],"You are going to remove the account":["\u0412\u0438 \u0437\u0431\u0438\u0440\u0430\u0454\u0442\u0435\u0441\u044F \u0432\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441"],'Deleting account "%1$s"':['\u0412\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u0440\u0430\u0445\u0443\u043D\u043A\u0443 "%1$s"'],Verification:["\u041F\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043D\u043D\u044F"],"Enter the account name that is going to be deleted":["\u0432\u0432\u0435\u0434\u0456\u0442\u044C \u0456\u043C'\u044F \u0440\u0430\u0445\u0443\u043D\u043A\u0443, \u044F\u043A\u0438\u0439 \u0431\u0443\u0434\u0435 \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043E"],"Cashout id should be a number":["\u0456\u0434\u0435\u043D\u0442\u0438\u0444\u0456\u043A\u0430\u0442\u043E\u0440 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043F\u043E\u0432\u0438\u043D\u0435\u043D \u0431\u0443\u0442\u0438 \u0447\u0438\u0441\u043B\u043E\u043C"],"This cashout not found. Maybe already aborted.":["\u0426\u0435 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438 \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E. \u041C\u043E\u0436\u043B\u0438\u0432\u043E, \u0439\u043E\u0433\u043E \u0432\u0436\u0435 \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E."],"Cashout detail":["\u0414\u0435\u0442\u0430\u043B\u0456 \u0437\u043D\u044F\u0442\u0442\u044F \u0433\u043E\u0442\u0456\u0432\u043A\u0438"],Debited:["\u0414\u0435\u0431\u0435\u0442\u043E\u0432\u0430\u043D\u043E"],Transferred:["\u041F\u0435\u0440\u0435\u043A\u0430\u0437\u0430\u0442\u0438"],"You have no permission to this account.":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043D\u044C\u043E \u043F\u0440\u0430\u0432 \u0434\u043B\u044F \u0432\u0438\u0434\u0430\u043B\u0435\u043D\u043D\u044F \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u043E\u0433\u043E \u0437\u0430\u043F\u0438\u0441\u0443."],"This account is locked. If you have a active session you can change the password or contact the administrator.":[""],"New web session":[""],"Welcome to %1$s!":["\u041B\u0430\u0441\u043A\u0430\u0432\u043E \u043F\u0440\u043E\u0441\u0438\u043C\u043E \u0434\u043E %1$s!"]}},domain:"messages",plural_forms:"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;",lang:"uk",completeness:72};Nn.ru={locale_data:{messages:{"":{domain:"messages",plural_forms:"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;",lang:"ru"},"An IBAN consists of capital letters and numbers only":["IBAN \u0434\u043E\u043B\u0436\u0435\u043D \u0441\u043E\u0441\u0442\u043E\u044F\u0442\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u0438\u0437 \u043F\u0440\u043E\u043F\u0438\u0441\u043D\u044B\u0445 \u0431\u0443\u043A\u0432 \u0438 \u0446\u0438\u0444\u0440"],"IBAN numbers have more that 4 digits":["\u041D\u043E\u043C\u0435\u0440\u0430 IBAN \u043E\u0431\u044B\u0447\u043D\u043E \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442 \u0431\u043E\u043B\u0435\u0435 4 \u0446\u0438\u0444\u0440"],"IBAN numbers have less that 34 digits":["\u041D\u043E\u043C\u0435\u0440\u0430 IBAN \u043E\u0431\u044B\u0447\u043D\u043E \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442 \u043C\u0435\u043D\u0435\u0435 34 \u0446\u0438\u0444\u0440"],"IBAN country code not found":["\u041A\u043E\u0434 \u0441\u0442\u0440\u0430\u043D\u044B IBAN \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D"],"IBAN number is not valid, checksum is wrong":["\u041D\u043E\u043C\u0435\u0440 IBAN \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D, \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u044C\u043D\u0430\u044F \u0441\u0443\u043C\u043C\u0430 \u043D\u0435\u0432\u0435\u0440\u043D\u0430"],"Use letters, numbers or any of these characters: - . _ ~":[""],Required:["\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E"],"confirm MFA challenge":[""],"Unknown challenge.":[""],"Failed to validate the verification code.":[""],"Too many challenges are active right now, you must wait or confirm current challenges.":[""],"Wrong authentication number.":["\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 \u043D\u043E\u043C\u0435\u0440 \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438."],"Expired challenge.":[""],"Submit the transmitted code number.":[""],"The verification code sent to the email address starting with %1$s":[""],"The verification code sent to the phone number ending with %1$s":[""],Code:[""],"Username of the account":["\u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u0441\u0447\u0451\u0442\u0430"],"It will expired at %1$s":[""],"The challenge is expired and can't be solved but you can go back and create a new challenge.":[""],Back:[""],Verify:[""],"send MFA challenge":[""],"Failed to send the verification code.":[""],"The request was valid, but the server is refusing action.":[""],"The backend is not aware of the specified MFA challenge.":[""],"It is too early to request another transmission of the challenge.":[""],"Code transmission failed.":[""],"select challenge":[""],"Multi-factor authentication required":["\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F"],"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.":[""],"The next challenge needs to be completed to confirm the operation.":["\u041D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u0434\u043B\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438."],"All the next challenges need to be completed to confirm the operation.":[""],"One of the next challenges need to be completed to confirm the operation.":[""],'To an phone ending with "%1$s"':[""],'To an email starting with " %1$s"':[""],"I have a code":[""],"Send me a message":[""],"You have to wait until %1$s to send a new code.":[""],Cancel:["\u041E\u0442\u043C\u0435\u043D\u0430"],Complete:[""],"Unable to create a cashout":["\u041D\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044F \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u0432\u044B\u043F\u043B\u0430\u0442\u0443"],"The bank configuration does not support cashout operations.":["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F \u0431\u0430\u043D\u043A\u0430 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u044B\u043F\u043B\u0430\u0442\u044B."],Close:["\u0417\u0430\u043A\u0440\u044B\u0442\u044C"],"Cashout is disabled":["\u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0430"],"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"calculate conversion fee":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"The server didn't understand the request.":["\u042D\u0442\u043E\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E."],"The amount is too small":["\u041F\u0430\u0440\u043E\u043B\u044C \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u044B\u0439."],"Conversion is not implemented.":["\u041E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0430 \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u0430"],"At least debit or credit needs to be provided":[""],"The amount is malfored":["\u042D\u0442\u043E\u0442 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0441\u0447\u0451\u0442\u0430 \u0443\u0436\u0435 \u0437\u0430\u043D\u044F\u0442."],"The currency is not supported":["\u0412\u044B\u043F\u043B\u0430\u0442\u044B \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F"],Invalid:["\u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E"],"Amount needs to be higher":["\u0434\u043E\u043B\u0436\u043D\u0430 \u0431\u044B\u0442\u044C \u0432\u044B\u0448\u0435 \u0438\u0437-\u0437\u0430 \u043A\u043E\u043C\u0438\u0441\u0441\u0438\u0439"],"Balance is not enough":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043D\u0430 \u0431\u0430\u043B\u0430\u043D\u0441\u0435"],"It is not possible to cashout less than %1$s: %2$s":[""],"The total transfer to the destination will be zero":["\u043E\u0431\u0449\u0430\u044F \u0441\u0443\u043C\u043C\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0432 \u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0432\u043D\u0430 \u043D\u0443\u043B\u044E"],"create cashout":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C"],"Cashout created":["\u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0430"],"Second factor authentication required.":["\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F"],"Account not found":["\u0423\u0447\u0451\u0442\u043D\u0430\u044F \u0437\u0430\u043F\u0438\u0441\u044C \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430"],"Duplicated request detected, check if the operation succeeded or try again.":["\u041E\u0431\u043D\u0430\u0440\u0443\u0436\u0435\u043D \u0434\u0443\u0431\u043B\u0438\u043A\u0430\u0442 \u0437\u0430\u043F\u0440\u043E\u0441\u0430, \u043F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435, \u0443\u0441\u043F\u0435\u0448\u043D\u043E \u043B\u0438 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F, \u0438\u043B\u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u043F\u044B\u0442\u043A\u0443."],"The conversion rate was applied incorrectly":["\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D \u043A\u0443\u0440\u0441 \u043A\u043E\u043D\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438"],"The account does not have sufficient funds":["\u041D\u0430 \u0441\u0447\u0435\u0442\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0441\u0440\u0435\u0434\u0441\u0442\u0432"],"Missing cashout URI in the profile":["\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044E\u0449\u0438\u0439 URI \u0432\u044B\u043B\u0430\u0442 \u0432 \u043F\u0440\u043E\u0444\u0438\u043B\u0435"],"The amount is below the minimum amount permitted.":[""],"Sending the confirmation message failed, retry later or contact the administrator.":["\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0441 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0435\u043C, \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u043F\u043E\u043F\u044B\u0442\u043A\u0443 \u043F\u043E\u0437\u0436\u0435 \u0438\u043B\u0438 \u043E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0443."],"The server doesn't support the current TAN channel.":["\u042D\u0442\u043E\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E."],"Create cashout.":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C"],Cashout:["\u0412\u044B\u043F\u043B\u0430\u0442\u0430"],"Conversion rate":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],Balance:["\u0411\u0430\u043B\u0430\u043D\u0441"],Fee:["\u041A\u043E\u043C\u0438\u0441\u0441\u0438\u044F"],"To account":["\u041D\u0430 \u0441\u0447\u0451\u0442"],"Legal name":[""],"If this name doesn't match the account holder's name, your transaction may fail.":[""],"Unable to cashout":["\u041D\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044F \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u0432\u044B\u043F\u043B\u0430\u0442\u0443"],"Before being able to cashout to a bank account, you need to complete your profile":["\u041F\u0435\u0440\u0435\u0434 \u0442\u0435\u043C, \u043A\u0430\u043A \u0441\u0434\u0435\u043B\u0430\u0442\u044C \u0432\u044B\u043F\u043B\u0430\u0442\u0443, \u0432\u0430\u043C \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u0437\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u0441\u0432\u043E\u0439 \u043F\u0440\u043E\u0444\u0438\u043B\u044C"],"Transfer subject":["\u041F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430"],Currency:[""],"Send %1$s":["\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C %1$s"],"Receive %1$s":["\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C %1$s"],Amount:["\u0421\u0443\u043C\u043C\u0430"],"Total cost":["\u041E\u0431\u0449\u0430\u044F \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C"],"Balance left":["\u041E\u0441\u0442\u0430\u0442\u043E\u043A \u0431\u0430\u043B\u0430\u043D\u0441\u0430"],"Before fee":["\u041A\u043E\u043C\u0438\u0441\u0441\u0438\u044F \u0434\u043E"],"Total cashout transfer":["\u041E\u0431\u0449\u0438\u0439 \u0441\u0443\u043C\u043C\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0432\u044B\u043F\u043B\u0430\u0442\u044B"],"Not valid":["\u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439"],"Does not follow the pattern":["\u043D\u0435 \u0441\u043B\u0435\u0434\u0443\u0435\u0442 \u0448\u0430\u0431\u043B\u043E\u043D\u0443"],"send transaction":["\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u0439 \u043F\u043E\u043A\u0430 \u043D\u0435\u0442."],"The wire transfer was successfully completed!":["\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430!"],"The request was invalid or the payto://-URI used unacceptable features.":["\u0417\u0430\u043F\u0440\u043E\u0441 \u0431\u044B\u043B \u043D\u0435\u0432\u0435\u0440\u043D\u044B\u043C \u0438\u043B\u0438 payto://-URI \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043B \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u0443\u044E \u0444\u0443\u043D\u043A\u0446\u0438\u043E\u043D\u0430\u043B\u044C\u043D\u043E\u0441\u0442\u044C."],"Not enough permission to complete the operation.":["\u041D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u0434\u043B\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438."],"The bank administrator cannot be the transfer creditor.":[""],'The destination account "%1$s" was not found.':['\u0426\u0435\u043B\u0435\u0432\u043E\u0439 \u0441\u0447\u0435\u0442 "%1$s" \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.'],"The origin and the destination of the transfer can't be the same.":["\u041F\u0443\u043D\u043A\u0442 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u044F \u0438 \u043F\u0443\u043D\u043A\u0442 \u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u043D\u0435 \u043C\u043E\u0433\u0443\u0442 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0442\u044C."],"Your balance is not sufficient for the operation.":["\u0412\u0430\u0448\u0435\u0433\u043E \u0431\u0430\u043B\u0430\u043D\u0441\u0430 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0434\u0435\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438."],'The origin account "%1$s" was not found.':['\u0418\u0441\u0445\u043E\u0434\u043D\u044B\u0439 \u0430\u043A\u043A\u0430\u0443\u043D\u0442 "%1$s" \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.'],"The attempt to create the transaction has failed. Please try again.":[""],"A second factor authentication is required.":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E"],"Confirm wire transfer.":["\u041F\u0435\u0440\u0435\u0432\u043E\u0434"],"Input wire transfer detail":["\u0414\u0435\u0442\u0430\u043B\u0438 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430"],"Using a form":["\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F \u0444\u043E\u0440\u043C\u0443"],"A special URI that specifies the amount to be transferred and the destination account.":[""],"QR code":["\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u043A\u043E\u0434"],"If your device has a camera, you can import a payto:// URI from a QR code.":[""],Recipient:["\u041F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044C"],"ID of the recipient's account":["IBAN \u0441\u0447\u0435\u0442\u0430 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F"],username:["\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F"],"IBAN of the recipient's account":["IBAN \u0441\u0447\u0435\u0442\u0430 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F"],Subject:["\u041F\u0440\u0438\u0447\u0438\u043D\u0430"],"Some text to identify the transfer":["\u043A\u0430\u043A\u043E\u0439-\u0442\u043E \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430"],"Amount to transfer":["\u0441\u0443\u043C\u043C\u0430 \u0434\u043B\u044F \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430"],"Payto URI:":["payto URI:"],"Uniform resource identifier of the target account":["\u0443\u043D\u0438\u0444\u0438\u0446\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0446\u0435\u043B\u0435\u0432\u043E\u0439 \u0443\u0447\u0435\u0442\u043D\u043E\u0439 \u0437\u0430\u043F\u0438\u0441\u0438"],"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]":["payto://x-taler-bank/[o\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u0431\u0430\u043D\u043A\u0430]/[c\u0447\u0435\u0442 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F]?message=[\u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u043B\u0430\u0442\u0435\u0436\u0430]&amount=[%1$s:X.Y]"],"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]":["payto://iban/[iban \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F]?message=[\u043F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u043B\u0430\u0442\u0435\u0436\u0430]&amount=[%1$s:X.Y]"],"The maximum amount for a wire transfer is %1$s":[""],Cost:[""],Send:["\u041E\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044C \u043F\u0435\u0440\u0435\u0432\u043E\u0434"],'Only "x-taler-bank" target are supported':['\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E "IBAN"'],'Only this host is allowed. Use "%1$s"':[""],"Account name is missing":["\u041E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430"],'Only "IBAN" target are supported':['\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E "IBAN"'],'Missing "amount" parameter to specify the amount to be transferred':['\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 "\u0421\u0443\u043C\u043C\u0430" \u0434\u043B\u044F \u0443\u043A\u0430\u0437\u0430\u043D\u0438\u044F \u0441\u0443\u043C\u043C\u044B \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430'],'The "amount" parameter is not valid':["\u0441\u0443\u043C\u043C\u0430 \u043D\u0435 \u044F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0439"],'"message" parameters to specify a reference text for the transfer are missing':['\u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 "message" \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u0430 \u043F\u0440\u0438\u0447\u0438\u043D\u044B \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430'],'The only currency allowed is "%1$s"':[""],"You cannot transfer an amount of zero.":[""],"The balance is not sufficient":["\u041D\u0430 \u0441\u0447\u0435\u0442\u0435 \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0441\u0440\u0435\u0434\u0441\u0442\u0432"],"Please enter a longer subject":["\u041F\u0440\u0438\u0447\u0438\u043D\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430"],"Show withdrawal confirmation":["\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0435 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432"],"Withdraw without setting amount":[""],"Hide demo hint.":[""],"Show install wallet first":["\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043A\u0430\u043A \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043A\u043E\u0448\u0435\u043B\u0451\u043A"],"Currently, the bank is not accepting new registrations!":["\u0412 \u043D\u0430\u0441\u0442\u043E\u044F\u0449\u0435\u0435 \u0432\u0440\u0435\u043C\u044F \u0431\u0430\u043D\u043A \u043D\u0435 \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442 \u043D\u043E\u0432\u044B\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438!"],"The name is missing":[""],"Missing username":["\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F"],"Missing password":["\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043F\u0430\u0440\u043E\u043B\u044C"],"The password should be longer than 8 letters":["\u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 0"],"The passwords do not match":["\u041F\u0430\u0440\u043E\u043B\u0438 \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u044E\u0442"],"register new account":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C"],"Server replied with invalid phone or email.":["\u0421\u0435\u0440\u0432\u0435\u0440 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0447\u0442\u043E \u0442\u0435\u043B\u0435\u0444\u043E\u043D \u0438\u043B\u0438 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u0430 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B."],"You are not authorised to create this account.":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u0439 \u0434\u043B\u044F \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u044D\u0442\u043E\u0433\u043E \u0441\u0447\u0451\u0442\u0430."],"Registration is disabled because the bank ran out of bonus credit.":["\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F \u043E\u0442\u043A\u043B\u044E\u0447\u0435\u043D\u0430, \u0442\u0430\u043A \u043A\u0430\u043A \u0432 \u0431\u0430\u043D\u043A\u0435 \u0437\u0430\u043A\u043E\u043D\u0447\u0438\u043B\u0441\u044F \u0431\u043E\u043D\u0443\u0441\u043D\u044B\u0439 \u043A\u0440\u0435\u0434\u0438\u0442."],"That username can't be used because is reserved.":["\u042D\u0442\u043E \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u043E, \u0442\u0430\u043A \u043A\u0430\u043A \u043E\u043D\u043E \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u043E."],"That username is already taken.":["\u042D\u0442\u043E \u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u0443\u0436\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F."],"That account ID is already taken.":["\u042D\u0442\u043E\u0442 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0441\u0447\u0451\u0442\u0430 \u0443\u0436\u0435 \u0437\u0430\u043D\u044F\u0442."],"No information for the selected authentication channel.":["\u041D\u0435\u0442 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u0438 \u043E \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u043E\u043C \u043A\u0430\u043D\u0430\u043B\u0435 \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438."],"Authentication channel is not supported.":["\u041A\u0430\u043D\u0430\u043B \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0438 \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F."],"Only an administrator is allowed to set the debt limit.":["\u0422\u043E\u043B\u044C\u043A\u043E \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435\u0442 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043B\u0438\u043C\u0438\u0442 \u0437\u0430\u0434\u043E\u043B\u0436\u0435\u043D\u043D\u043E\u0441\u0442\u0438."],"Only the administrator can change the conversion rate.":[""],"The conversion rate class doesn't exist.":["\u041D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D \u043A\u0443\u0440\u0441 \u043A\u043E\u043D\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438"],"Only admin can create accounts with second factor authentication.":["\u0422\u043E\u043B\u044C\u043A\u043E \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440 \u043C\u043E\u0436\u0435\u0442 \u0441\u043E\u0437\u0434\u0430\u0432\u0430\u0442\u044C \u0443\u0447\u0435\u0442\u043D\u044B\u0435 \u0437\u0430\u043F\u0438\u0441\u0438 \u0441\u043E \u0432\u0442\u043E\u0440\u043E\u0439 \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u0435\u0439."],"The password is too short. Can't have less than 8 characters.":["\u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 0"],"The password is too long. Can't have more than 64 characters.":["\u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 0"],"Account registration":["\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F \u0441\u0447\u0451\u0442\u0430"],"Login username":["\u0418\u043C\u044F \u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F"],"account identification to login":["\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F \u0441\u0447\u0435\u0442\u0430 \u0432 \u0431\u0430\u043D\u043A\u0435"],Password:["\u041F\u0430\u0440\u043E\u043B\u044C"],"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers":[""],"Repeat password":["\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u041F\u0430\u0440\u043E\u043B\u044C"],"Same password":["\u041D\u043E\u0432\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C"],"Full name":[""],Register:["\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F"],"Create a random temporary user":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u043E\u0433\u043E \u0432\u0440\u0435\u043C\u0435\u043D\u043D\u043E\u0433\u043E \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F"],logout:[""],login:[""],"The account has no rights to login.":[""],"The account is locked and cannot login. Contact administrator.":[""],'Wrong credentials for "%1$s"':["\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0435 \u0443\u0447\u0435\u0442\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0434\u043B\u044F \xAB%1$s\xBB \u200E"],"Account login.":["\u041E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430"],"Session expired":[""],Username:["\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F"],identification:["\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430"],"Password of the account":["\u043F\u0430\u0440\u043E\u043B\u044C \u043E\u0442 \u0441\u0447\u0451\u0442\u0430"],Forget:[""],"Log in":["\u0412\u043E\u0439\u0442\u0438"],"Transactions history":[""],"No transactions yet.":["\u0422\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u0439 \u043F\u043E\u043A\u0430 \u043D\u0435\u0442."],"You can make a transfer or a withdrawal to your wallet.":[""],Date:["\u0414\u0430\u0442\u0430"],Counterpart:["\u041A\u043E\u043D\u0442\u0440\u0430\u0441\u0447\u0435\u0442"],sent:["\u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E"],received:["\u043F\u043E\u043B\u0443\u0447\u0435\u043D\u043E"],"Invalid value":["\u041D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435"],to:["\u043A"],from:["\u043E\u0442"],"First page":["\u041F\u0435\u0440\u0432\u0430\u044F \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430"],Next:["\u0414\u0430\u043B\u0435\u0435"],"confirm withdrawal":["\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430"],cambiar:[""],"abort withdrawal":["\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430"],"The withdrawal has been aborted previously and can't be confirmed":["\u0412\u044B\u0432\u043E\u0434 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u0431\u044B\u043B \u043F\u0440\u0435\u0440\u0432\u0430\u043D \u0440\u0430\u043D\u0435\u0435 \u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D"],"The withdrawal operation can't be confirmed before a wallet accepted the transaction.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043F\u043E \u0432\u044B\u0432\u043E\u0434\u0443 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0430 \u0434\u043E \u0442\u043E\u0433\u043E \u043A\u0430\u043A \u043A\u043E\u0448\u0451\u043B\u0435\u043A \u043F\u0440\u0438\u043C\u0435\u0442 \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u044E."],"The operation ID is invalid.":["\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D."],"The operation was not found.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430."],"The starting withdrawal amount and the confirmation amount differs.":[""],"The bank requires a bank account which has not been specified yet.":[""],"Bad request":[""],"The withdrawal operation has been aborted.":["\u041E\u0436\u0438\u0434\u0430\u043D\u0438\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432"],"The withdrawal operation has been confirmed previously and can\u2019t be aborted.":["\u0420\u0435\u0437\u0435\u0440\u0432\u043D\u0430\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0431\u044B\u043B\u0430 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0430 \u0440\u0430\u043D\u0435\u0435 \u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430"],"Complete withdrawal.":["\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430"],"Confirm the withdrawal operation":["\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430"],"Wire transfer details":["\u0414\u0435\u0442\u0430\u043B\u0438 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430"],"Payment Service Provider's account number":["\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler"],"Payment Service Provider's name":["\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler"],"Payment Service Provider's account bank hostname":["\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler"],"Payment Service Provider's account id":["\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler"],"Payment Service Provider's account address":["\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler"],"Payment Service Provider's account cyclos hostname":["\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler"],"No amount has yet been determined.":[""],Transfer:["\u041F\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438"],"Authentication required":["\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F"],"This operation was created with another username":["\u042D\u0442\u0430 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0431\u044B\u043B\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0430 \u0441 \u0434\u0440\u0443\u0433\u0438\u043C \u0438\u043C\u0435\u043D\u0435\u043C \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F"],'You are currently logged in with user "%1$s" and the operation was made with user "%2$s"':[""],"The reserve operation has been confirmed previously and can't be aborted":["\u0420\u0435\u0437\u0435\u0440\u0432\u043D\u0430\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0431\u044B\u043B\u0430 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0430 \u0440\u0430\u043D\u0435\u0435 \u0438 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430"],"Wire transfer completed!":["\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0430!"],"Confirm withdrawal.":["\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430"],"Unauthorized to make the operation, maybe the session has expired or the password changed.":["\u041D\u0435\u0430\u0432\u0442\u043E\u0440\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438, \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0438\u0441\u0442\u0435\u043A \u0441\u0435\u0430\u043D\u0441 \u0438\u043B\u0438 \u0438\u0437\u043C\u0435\u043D\u0451\u043D \u043F\u0430\u0440\u043E\u043B\u044C."],"The operation was rejected due to insufficient funds.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043E\u0442\u043A\u043B\u043E\u043D\u0435\u043D\u0430 \u0438\u0437-\u0437\u0430 \u043D\u0435\u0445\u0432\u0430\u0442\u043A\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432."],"Withdrawal confirmed":["\u0412\u044B\u0432\u043E\u0434 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D"],"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.":["\u0418\u043D\u0438\u0446\u0438\u0438\u0440\u043E\u0432\u0430\u043D \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0443 Taler. \u0412\u0441\u043A\u043E\u0440\u0435 \u0432\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u0435 \u0437\u0430\u043F\u0440\u043E\u0448\u0435\u043D\u043D\u0443\u044E \u0441\u0443\u043C\u043C\u0443 \u043D\u0430 \u0441\u0432\u043E\u0439 \u043A\u043E\u0448\u0435\u043B\u0451\u043A Taler."],"Do not show this again":["\u041D\u0435 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u0441\u043D\u043E\u0432\u0430"],"If you have a Taler wallet installed on this device":["\u0415\u0441\u043B\u0438 \u0432 \u044D\u0442\u043E\u043C \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D \u043A\u043E\u0448\u0435\u043B\u0451\u043A Taler"],"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions":["\u0412\u044B \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043F\u043E\u0434\u0440\u043E\u0431\u043D\u043E\u0441\u0442\u0438 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0432 \u0441\u0432\u043E\u0435\u043C \u043A\u043E\u0448\u0435\u043B\u044C\u043A\u0435, \u0432\u043A\u043B\u044E\u0447\u0430\u044F \u043A\u043E\u043C\u0438\u0441\u0441\u0438\u044E (\u0435\u0441\u043B\u0438 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u043C\u043E). \u0415\u0441\u043B\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0433\u043E \u0435\u0449\u0435 \u043D\u0435\u0442, \u0432\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u0435\u0433\u043E \u0441\u043B\u0435\u0434\u0443\u044F \u0438\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u044F\u043C \u043D\u0430"],"on this page":["\u044D\u0442\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435"],Withdraw:["\u0421\u043D\u044F\u0442\u044C \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430"],"In case you have a Taler wallet on another device":["\u0418\u043B\u0438 \u0435\u0441\u043B\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044C \u043A\u043E\u0448\u0435\u043B\u0451\u043A \u0432 \u0434\u0440\u0443\u0433\u043E\u043C \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0435"],"Scan the QR below to start the withdrawal.":["\u041E\u0442\u0441\u043A\u0430\u043D\u0438\u0440\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434 \u043D\u0438\u0436\u0435 \u0447\u0442\u043E\u0431\u044B \u043D\u0430\u0447\u0430\u0442\u044C \u0432\u044B\u0432\u043E\u0434 \u0441\u0440\u0435\u0434\u0441\u0442\u0432."],"create withdrawal":["\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u0432\u044B\u0432\u043E\u0434\u0430"],"The server replied with an invalid taler://withdraw URI":["\u0421\u0435\u0440\u0432\u0435\u0440 \u043E\u0442\u0432\u0435\u0442\u0438\u043B \u0441 \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u043C URI \u0432\u044B\u0432\u043E\u0434\u0430"],"Withdraw URI: %1$s":["URI \u0432\u044B\u0432\u043E\u0434\u0430: %1$s"],"The operation was rejected due to insufficient funds":["\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043E\u0442\u043A\u043B\u043E\u043D\u0435\u043D\u0430 \u0438\u0437-\u0437\u0430 \u043D\u0435\u0445\u0432\u0430\u0442\u043A\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432."],"Current balance is %1$s":[""],"You can withdraw up to %1$s":[""],Continue:["\u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C"],"Use your Taler wallet":["\u041F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u044C\u0442\u0435 \u0441\u0432\u043E\u0439 \u043A\u043E\u0448\u0435\u043B\u0451\u043A"],"After using your wallet you will need to authorize or cancel the operation on this site.":["\u041F\u043E\u0441\u043B\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u043A\u043E\u0448\u0435\u043B\u044C\u043A\u0430 \u0432\u0430\u043C \u043D\u0443\u0436\u043D\u043E \u0431\u0443\u0434\u0435\u0442 \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u0438\u043B\u0438 \u043E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E \u043D\u0430 \u044D\u0442\u043E\u043C \u0441\u0430\u0439\u0442\u0435."],"You need a Taler wallet":["\u0412\u0430\u043C \u043D\u0443\u0436\u0435\u043D \u043A\u043E\u0448\u0435\u043B\u0451\u043A Taler"],"If you don't have one yet you can follow the instruction in":["\u0415\u0441\u043B\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0433\u043E \u0435\u0449\u0435 \u043D\u0435\u0442, \u0432\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0441\u043B\u0435\u0434\u043E\u0432\u0430\u0442\u044C \u0438\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u044F\u043C \u043D\u0430"],"this page":["\u044D\u0442\u043E\u0439 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0435"],"Send money":["\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0434\u0435\u043D\u044C\u0433\u0438"],"to a Taler wallet":["\u043D\u0430 \u043A\u043E\u0448\u0435\u043B\u0435\u043A Taler"],"Withdraw digital money into your mobile wallet or browser extension":["\u0412\u044B\u0432\u043E\u0434\u0438\u0442\u0435 \u0446\u0438\u0444\u0440\u043E\u0432\u044B\u0435 \u0434\u0435\u043D\u044C\u0433\u0438 \u043D\u0430 \u0441\u0432\u043E\u0439 \u043C\u043E\u0431\u0438\u043B\u044C\u043D\u044B\u0439 \u043A\u043E\u0448\u0435\u043B\u0451\u043A \u0438\u043B\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430"],"to another bank account":["\u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u0439 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u0441\u0447\u0435\u0442"],"Make a wire transfer to an account with known bank account number.":["\u0421\u0434\u0435\u043B\u0430\u0439\u0442\u0435 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u043D\u0430 \u0441\u0447\u0435\u0442 \u0441 \u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u0441\u0447\u0435\u0442\u0430."],"This is a demo":["\u042D\u0442\u043E \u0434\u0435\u043C\u043E-\u0431\u0430\u043D\u043A"],"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .":["\u0412 \u044D\u0442\u043E\u0439 \u0447\u0430\u0441\u0442\u0438 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043F\u043E\u043A\u0430\u0437\u0430\u043D\u043E \u043A\u0430\u043A \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C \u0431\u0430\u043D\u043A \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0449\u0438\u0439 Taler \u043D\u0430\u043F\u0440\u044F\u043C\u0443\u044E. \u041F\u043E\u043C\u0438\u043C\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u0441\u043E\u0431\u0441\u0442\u0432\u0435\u043D\u043D\u043E\u0433\u043E \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u0441\u0447\u0451\u0442\u0430, \u0432\u044B \u0442\u0430\u043A\u0436\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C \u0438\u0441\u0442\u043E\u0440\u0438\u044E \u0442\u0440\u0430\u043D\u0437\u0430\u043A\u0446\u0438\u0439 \u043D\u0435\u043A\u043E\u0442\u043E\u0440\u044B\u0445 %1$s."],"Here you will be able to see how a bank that supports Taler directly would work.":["\u0412 \u044D\u0442\u043E\u0439 \u0447\u0430\u0441\u0442\u0438 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043F\u043E\u043A\u0430\u0437\u0430\u043D\u043E \u043A\u0430\u043A \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C \u0431\u0430\u043D\u043A \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0449\u0438\u0439 Taler \u043D\u0430\u043F\u0440\u044F\u043C\u0443\u044E."],"Internal error, please report. There should be more information in the console.":[""],"Internal error, please report.":["\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u043E\u0448\u0438\u0431\u043A\u0430, \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0441\u043E\u043E\u0431\u0449\u0438\u0442\u0435."],Preferences:["\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438"],"Show debug information":["\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044E \u0434\u043B\u044F \u043E\u0442\u043B\u0430\u0434\u043A\u0438"],Welcome:["\u0414\u043E\u0431\u0440\u043E \u043F\u043E\u0436\u0430\u043B\u043E\u0432\u0430\u0442\u044C"],"Welcome, %1$s":["\u0414\u043E\u0431\u0440\u043E \u043F\u043E\u0436\u0430\u043B\u043E\u0432\u0430\u0442\u044C, %1$s"],"No enough permission to access the conversion rate list.":["\u041D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u044F \u0434\u043B\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438."],"Conversion list not found. Maybe conversion rate is not supported.":[""],"Conversion list not implemented.":["\u041E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0430 \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u0430"],"Conversion rate classes":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"Create conversion rate class":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"No conversion rate class":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],Name:["\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435"],Description:["\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0434\u0435\u043C\u043E"],Cashin:["\u0412\u043D\u0435\u0441\u0435\u043D\u0438\u044F"],"min:":[""],"fee:":[""],"Select a section":["\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0440\u0430\u0437\u0434\u0435\u043B"],Details:["\u041F\u043E\u0434\u0440\u043E\u0431\u043D\u043E\u0441\u0442\u0438"],Delete:["\u0423\u0434\u0430\u043B\u0438\u0442\u044C"],Credentials:["\u0423\u0447\u0435\u0442\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435"],Cashouts:["\u0412\u044B\u043F\u043B\u0430\u0442\u044B"],Conversion:["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"only admin can setup conversion":[""],"calculate cashout fee":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C"],"update conversion rate":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"Wrong credentials":["\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0435 \u0443\u0447\u0435\u0442\u043D\u044B\u0435 \u0434\u0430\u043D\u043D\u044B\u0435 \u0434\u043B\u044F \xAB%1$s\xBB \u200E"],"Conversion is disabled":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"Config cashout":["\u0412\u044B\u043F\u043B\u0430\u0442\u0430"],"Config cashin":["\u0412\u043D\u0435\u0441\u0435\u043D\u0438\u044F"],"Bad ratios":[""],"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.":[""],"Initial amount":["\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0441\u0443\u043C\u043C\u0430 \u0432\u044B\u0432\u043E\u0434\u0430"],"Use it to test how the conversion will affect the amount.":[""],"Sending to this bank":[""],Converted:["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"Cashin after fee":[""],"Sending from this bank":[""],"Cashout after fee":["\u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0430"],"Bad configuration":[""],"This configuration allows users to cash out more of what has been cashed in.":[""],Update:["\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C"],Rnvalid:["\u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E"],"Must be > 0":[""],"Minimum amount":[""],"Only cashout operation above this threshold will be allowed.":[""],Ratio:[""],"Conversion ratio between currencies":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"Example conversion":[""],"1 %1$s will be converted into %2$s %3$s":[""],"Tiny amount":["\u041D\u0430 \u0441\u0447\u0451\u0442"],"Rounding mode":[""],Zero:[""],"Amount will be round below to the largest possible value smaller than the input.":[""],Up:[""],"Amount will be round up to the smallest possible value larger than the input.":[""],Nearest:[""],"Amount will be round to the closest possible value.":[""],'If none specified the fallback value is "%1$s ".':[""],Examples:[""],"Rounding an amount of 1.24 with rounding value 0.1":[""],"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.":[""],'With the "zero" mode the value will be rounded to 1.2':[""],'With the "nearest" mode the value will be rounded to 1.2':[""],'With the "up" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.26 with rounding value 0.1":[""],'With the "nearest" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.24 with rounding value 0.3":[""],"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.":[""],'With the "up" mode the value will be rounded to 1.5':[""],"Rounding an amount of 1.26 with rounding value 0.3":[""],"Amount to be deducted before amount is credited.":[""],"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"delete conversion rate class":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],Unauthorized:["\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E"],Forbidden:[""],NotFound:[""],NotImplemented:["\u041E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0430 \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u0430"],"update conversion rate class":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"Not Found":[""],"Not implemented":["\u041E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0430 \u043D\u0435 \u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u043D\u0430"],"The name of the conversion is already used.":["\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u0443\u0436\u0435 \u0438\u0434\u0435\u0442"],"Conversion rate class":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],Accounts:["\u0421\u0447\u0435\u0442\u0430"],Test:[""],Users:["\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F"],"Can't remove the conversion rate class":[""],"There are some user associated to this class. You need to remove them first.":[""],"You are going to remove the conversion rate class":[""],"This step can't be undone.":[""],Filters:[""],"Show from other classes":[""],Account:["\u0421\u0447\u0451\u0442"],"Group ID":[""],"No users in this conversion rate class":[""],Class:[""],Action:["\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F"],Remove:["\u0443\u0434\u0430\u043B\u0438\u0442\u044C"],Add:[""],"Conversion rate name":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"Short description of the class":[""],"create conversion rate class":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"Conversion rate class created.":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],"The rights to change the account are not sufficient":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u043F\u0440\u0430\u0432 \u043D\u0430 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430"],"New conversion rate class":["\u041E\u0431\u043C\u0435\u043D\u043D\u044B\u0439 \u043A\u0443\u0440\u0441"],Create:["\u0421\u043E\u0437\u0434\u0430\u0442\u044C"],"History of public accounts":["\u0418\u0441\u0442\u043E\u0440\u0438\u044F \u043F\u0443\u0431\u043B\u0438\u0447\u043D\u044B\u0445 \u0441\u0447\u0435\u0442\u043E\u0432"],"Make a wire transfer":["\u0421\u0434\u0435\u043B\u0430\u0442\u044C \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434"],"Scan the QR code below to start the withdrawal.":["\u041E\u0442\u0441\u043A\u0430\u043D\u0438\u0440\u0443\u0439\u0442\u0435 QR-\u043A\u043E\u0434 \u043D\u0438\u0436\u0435 \u0447\u0442\u043E\u0431\u044B \u043D\u0430\u0447\u0430\u0442\u044C \u0432\u044B\u0432\u043E\u0434 \u0441\u0440\u0435\u0434\u0441\u0442\u0432."],"Operation aborted":["\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043F\u0440\u0435\u0440\u0432\u0430\u043D\u0430"],"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.":["\u0411\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u043D\u0430 \u0441\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler \u0431\u044B\u043B \u043F\u0440\u0435\u0440\u0432\u0430\u043D, \u0432\u0430\u0448 \u0431\u0430\u043B\u0430\u043D\u0441 \u043D\u0435 \u043F\u043E\u0441\u0442\u0440\u0430\u0434\u0430\u043B."],"Go to your wallet now":["\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043A\u043E\u0448\u0435\u043B\u0435\u043A"],"The operation is marked as selected, but a process during the withdrawal failed":["\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043F\u043E\u043C\u0435\u0447\u0435\u043D\u0430 \u043A\u0430\u043A \xAB\u0432\u044B\u0431\u0440\u0430\u043D\u043D\u0430\u044F\xBB, \u043D\u043E \u043A\u0430\u043A\u043E\u0439-\u0442\u043E \u0448\u0430\u0433 \u0432 \u0432\u044B\u0432\u043E\u0434\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043D\u0435 \u0443\u0434\u0430\u043B\u0441\u044F"],"A withdrawal reserve ID was not found and no account has been selected.":["\u0415\u0441\u0442\u044C \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432, \u043D\u043E \u0441\u0447\u0451\u0442 \u043D\u0435 \u0431\u044B\u043B \u0432\u044B\u0431\u0440\u0430\u043D \u0438\u043B\u0438 \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u0441\u0447\u0451\u0442 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D."],"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.":["\u0415\u0441\u0442\u044C \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432, \u043D\u043E \u0441\u0447\u0451\u0442 \u043D\u0435 \u0431\u044B\u043B \u0432\u044B\u0431\u0440\u0430\u043D \u0438\u043B\u0438 \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u0441\u0447\u0451\u0442 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D."],"The account was selected, but no withdrawal reserve ID was found.":["\u0421\u0447\u0451\u0442 \u0432\u044B\u0431\u0440\u0430\u043D, \u043D\u043E \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D."],"Operation not found":[""],"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.":[""],"Continue to dashboard":[""],"The Withdrawal URI is not valid":["URI \u0432\u044B\u0432\u043E\u0434\u0430 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u0435\u043D"],"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.":[""],"Latest cashouts":["\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u043E\u0431\u043D\u0430\u043B\u0438\u0447\u043A\u0438"],Created:["\u0421\u043E\u0437\u0434\u0430\u043D\u043E"],"Total debit":["\u0412\u0441\u0435\u0433\u043E \u0434\u0435\u0431\u0435\u0442"],"Total credit":["\u0418\u0442\u043E\u0433\u043E \u043A\u0440\u0435\u0434\u0438\u0442"],"Cashout for account %1$s":["\u0412\u044B\u043F\u043B\u0430\u0442\u0430 \u0434\u043B\u044F \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u0430 %1$s"],"Invalid email format":["\u041D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435"],"Should start with +":["\u0434\u043E\u043B\u0436\u0435\u043D \u043D\u0430\u0447\u0438\u043D\u0430\u0442\u044C\u0441\u044F \u0441 +"],"A phone number consists of numbers only":["\u041D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430 \u043D\u0435 \u043C\u043E\u0436\u0435\u0442 \u0438\u043C\u0435\u0442\u044C \u043D\u0438\u0447\u0435\u0433\u043E, \u043A\u0440\u043E\u043C\u0435 \u0446\u0438\u0444\u0440"],"Account ID for authentication":["\u0414\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0430\u044F \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F"],"Name of the account holder":["\u0438\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u0441\u0447\u0451\u0442\u0430"],"Internal account":["\u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u0439 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u0441\u0447\u0435\u0442"],"If this field is empty, a random account ID will be assigned":["\u0415\u0441\u043B\u0438 \u043F\u0443\u0441\u0442\u043E, \u0431\u0443\u0434\u0435\u0442 \u043F\u0440\u0438\u0441\u0432\u043E\u0435\u043D \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u044B\u0439 \u043D\u043E\u043C\u0435\u0440 \u0441\u0447\u0435\u0442\u0430"],"You can copy and share this IBAN number in order to receive wire transfers to your bank account":[""],Email:["Email"],"To be used when second factor authentication is enabled":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E"],Phone:["\u0422\u0435\u043B\u0435\u0444\u043E\u043D"],"Enable second factor authentication":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u0434\u0432\u0443\u0445\u0444\u0430\u043A\u0442\u043E\u0440\u043D\u0443\u044E \u0430\u0443\u0442\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044E"],"Using email":["\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F email"],"Add an email in your profile to enable this option":["\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0430\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B \u0432 \u0441\u0432\u043E\u0439 \u043F\u0440\u043E\u0444\u0438\u043B\u044C, \u0447\u0442\u043E\u0431\u044B \u0432\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u044D\u0442\u0443 \u043E\u043F\u0446\u0438\u044E"],"Using SMS":["\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F SMS"],"Add a phone number in your profile to enable this option":["\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430 \u0432 \u0441\u0432\u043E\u0439 \u043F\u0440\u043E\u0444\u0438\u043B\u044C, \u0447\u0442\u043E\u0431\u044B \u0432\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u044D\u0442\u0443 \u043E\u043F\u0446\u0438\u044E"],"Cashout account":["\u041D\u0435\u0442 \u0441\u0447\u0451\u0442\u0430 \u0434\u043B\u044F \u0432\u044B\u043F\u043B\u0430\u0442"],"External account number where the money is going to be sent when doing cashouts":["\u043D\u043E\u043C\u0435\u0440 \u0441\u0447\u0435\u0442\u0430, \u043D\u0430 \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0431\u0443\u0434\u0443\u0442 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u044B \u0434\u0435\u043D\u044C\u0433\u0438 \u043F\u0440\u0438 \u0432\u044B\u0432\u043E\u0434\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432"],"Max debt":["\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u0430\u044F \u0437\u0430\u0434\u043E\u043B\u0436\u0435\u043D\u043D\u043E\u0441\u0442\u044C"],"How much the balance can go below zero.":[""],"Is this account public?":["\u042F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u043B\u0438 \u044D\u0442\u043E\u0442 \u0441\u0447\u0451\u0442 \u043E\u0431\u0449\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u043C?"],"Public accounts have their balance publicly accessible":["\u0411\u0430\u043B\u0430\u043D\u0441 \u043F\u0443\u0431\u043B\u0438\u0447\u043D\u044B\u0445 \u0441\u0447\u0451\u0442\u043E\u0432 \u043D\u0430\u0445\u043E\u0434\u0438\u0442\u0441\u044F \u0432 \u043E\u0442\u043A\u0440\u044B\u0442\u043E\u043C \u0434\u043E\u0441\u0442\u0443\u043F\u0435"],"Does this account belong to a Payment Service Provider?":["\u042F\u0432\u043B\u044F\u0435\u0442\u0441\u044F \u043B\u0438 \u044D\u0442\u043E\u0442 \u0441\u0447\u0451\u0442 \u043E\u0431\u0449\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u043C?"],"update account":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C"],"Account updated":["\u0421\u0447\u0451\u0442 \u043E\u0431\u043D\u043E\u0432\u043B\u0451\u043D"],"The username was not found":["\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E"],"You can't change the legal name, please contact the your account administrator.":["\u0412\u044B \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043E\u0444\u0438\u0446\u0438\u0430\u043B\u044C\u043D\u043E\u0435 \u0438\u043C\u044F, \u043E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0443 \u0432\u0430\u0448\u0435\u0439 \u0443\u0447\u0435\u0442\u043D\u043E\u0439 \u0437\u0430\u043F\u0438\u0441\u0438."],"You can't change the debt limit, please contact the your account administrator.":["\u0412\u044B \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043B\u0438\u043C\u0438\u0442 \u0437\u0430\u0434\u043E\u043B\u0436\u0435\u043D\u043D\u043E\u0441\u0442\u0438, \u043E\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044C \u043A \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u0443 \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u0430."],"You can't change the cashout address, please contact the your account administrator.":["\u0412\u044B \u043D\u0435 \u043C\u043E\u0436\u0435\u0442\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0430\u0434\u0440\u0435\u0441 \u0434\u043B\u044F \u0432\u044B\u0432\u043E\u0434\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432, \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u044F\u0436\u0438\u0442\u0435\u0441\u044C \u0441 \u0430\u0434\u043C\u0438\u043D\u0438\u0441\u0442\u0440\u0430\u0442\u043E\u0440\u043E\u043C \u0432\u0430\u0448\u0435\u0433\u043E \u0430\u043A\u043A\u0430\u0443\u043D\u0442\u0430."],"Update account information.":["\u041E\u0436\u0438\u0434\u0430\u043D\u0438\u0435 \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u0441\u0447\u0451\u0442\u0430"],'Account "%1$s"':['\u0421\u0447\u0435\u0442 "%1$s"'],Removed:["\u0443\u0434\u0430\u043B\u0438\u0442\u044C"],"This account can't be used.":[""],"Change details":["\u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0435 \u0440\u0435\u043A\u0432\u0438\u0437\u0438\u0442\u043E\u0432"],"Merchant integration":["\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044F \u0441\u0447\u0451\u0442\u0430"],'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.':[""],"Account type":["\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430"],"Method to use for wire transfer.":["\u0421\u0434\u0435\u043B\u0430\u0442\u044C \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434"],IBAN:[""],"International Bank Account Number.":[""],"Account name":["\u041E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430"],"Bank host where the service is located.":[""],"Bank account identifier for wire transfers.":["\u0418\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F \u0441\u0447\u0435\u0442\u0430 \u0434\u043B\u044F \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u043F\u0435\u0440\u0435\u0432\u043E\u0434\u0430"],Address:[""],"Owner's name":["\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F"],"Legal name of the person holding the account.":["\u0438\u043C\u044F \u0432\u043B\u0430\u0434\u0435\u043B\u044C\u0446\u0430 \u0441\u0447\u0451\u0442\u0430"],"Account info URL":["\u0423\u0447\u0451\u0442\u043D\u0430\u044F \u0437\u0430\u043F\u0438\u0441\u044C \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430"],"From where the merchant can download information about incoming wire transfers to this account.":[""],"Repeated password doesn't match":["\u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0435\u0442"],"update password":["\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C"],"Password changed":["\u041F\u0430\u0440\u043E\u043B\u044C \u0438\u0437\u043C\u0435\u043D\u0435\u043D"],"Not authorized to change the password, maybe the session is invalid.":[""],"You need to provide the old password. If you don't have it contact your account administrator.":[""],"Your current password doesn't match, can't change to a new password.":[""],"You don't have the rights to change the password.":[""],"Update account password.":["\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C"],"Update password":["\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C"],"Current password":["\u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u043F\u0430\u0440\u043E\u043B\u044C"],"Your current password, for security":[""],"New password":["\u041D\u043E\u0432\u044B\u0439 \u043F\u0430\u0440\u043E\u043B\u044C"],"Type it again":["\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043E \u0435\u0449\u0451 \u0440\u0430\u0437"],"Repeat the same password":["\u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435 \u044D\u0442\u043E\u0442 \u0436\u0435 \u043F\u0430\u0440\u043E\u043B\u044C"],Change:["\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C"],"Create account":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C"],Actions:["\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F"],Unknown:["\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u043E"],"Change password":["\u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u0430\u0440\u043E\u043B\u044C"],"Querying for the current stats failed":[""],"The request parameters are wrong":[""],"The user is unauthorized":["\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E"],"Querying for the previous stats failed":[""],"Transaction volume report":[""],"Last hour":["\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u0447\u0430\u0441"],"Previous day":[""],"Last month":["\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u043C\u0435\u0441\u044F\u0446"],"Last year":["\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u0433\u043E\u0434"],"Last Year":["\u041F\u0440\u043E\u0448\u043B\u044B\u0439 \u0433\u043E\u0434"],"Trading volume from %1$s to %2$s":["\u041E\u0431\u044A\u0435\u043C \u0442\u043E\u0440\u0433\u043E\u0432 \u043D\u0430 %1$s \u043F\u043E \u0441\u0440\u0430\u0432\u043D\u0435\u043D\u0438\u044E \u0441 %2$s"],"Transferred from an external account to an account in this bank.":[""],"Transferred from an account in this bank to an external account.":["\u0421\u0434\u0435\u043B\u0430\u0439\u0442\u0435 \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u0438\u0439 \u043F\u0435\u0440\u0435\u0432\u043E\u0434 \u043D\u0430 \u0441\u0447\u0435\u0442 \u0441 \u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u043C \u043D\u043E\u043C\u0435\u0440\u043E\u043C \u0431\u0430\u043D\u043A\u043E\u0432\u0441\u043A\u043E\u0433\u043E \u0441\u0447\u0435\u0442\u0430."],Payin:["\u041E\u0442\u043F\u043B\u0430\u0442\u0430"],"Transferred from an account to a Taler exchange.":[""],Payout:["\u0412\u044B\u043F\u043B\u0430\u0442\u0430"],"Transferred from a Taler exchange to another account.":["\u0421\u0447\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u041E\u0431\u043C\u0435\u043D\u043D\u0438\u043A\u0430 Taler"],"Download stats as CSV":["\u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435 CSV"],previous:[""],"Decreased by":["\u0423\u043C\u0435\u043D\u044C\u0448\u0438\u043B\u043E\u0441\u044C \u043D\u0430"],"Increased by":["\u0423\u0432\u0435\u043B\u0438\u0447\u0435\u043D\u0438\u0435 \u043D\u0430"],"create account":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C"],'Account created with password "%1$s".':[""],"Server replied that phone or email is invalid":[""],"The rights to perform the operation are not sufficient":[""],"Account username is already taken":[""],"Account ID is already taken":["\u042D\u0442\u043E\u0442 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u0441\u0447\u0451\u0442\u0430 \u0443\u0436\u0435 \u0437\u0430\u043D\u044F\u0442."],"Bank ran out of bonus credit.":[""],"Account username can't be used because is reserved":[""],"Can't create accounts":[""],"Only system admin can create accounts.":[""],"New bank account":["\u041D\u043E\u0432\u044B\u0439 \u0431\u0438\u0437\u043D\u0435\u0441 \u0441\u0447\u0451\u0442"],"download statistics":["\u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435 CSV"],"only admin can download stats":[""],"Download bank stats":["\u0421\u043A\u0430\u0447\u0438\u0432\u0430\u0442\u044C \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0431\u0430\u043D\u043A\u0430"],"Include hour metric":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0447\u0430\u0441\u043E\u0432\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443"],"Include day metric":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0434\u043D\u0435\u0432\u043D\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443"],"Include month metric":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043C\u0435\u0441\u044F\u0447\u043D\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443"],"Include year metric":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0433\u043E\u0434\u043E\u0432\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443"],"Include table header":["\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0442\u0430\u0431\u043B\u0438\u0446\u044B"],"Add previous metric for compare":["\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0443\u044E \u043C\u0435\u0442\u0440\u0438\u043A\u0443 \u0434\u043B\u044F \u0441\u0440\u0430\u0432\u043D\u0435\u043D\u0438\u044F"],"Fail on first error":["\u0421\u0431\u043E\u0439 \u043F\u0440\u0438 \u043F\u0435\u0440\u0432\u043E\u0439 \u043E\u0448\u0438\u0431\u043A\u0435"],Download:["\u0421\u043A\u0430\u0447\u0438\u0432\u0430\u0442\u044C"],"downloading... %1$s":["\u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u0435... %1$s"],"Download completed":["\u0421\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E"],"Click here to save the file in your computer.":["\u041D\u0430\u0436\u043C\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044C, \u0447\u0442\u043E\u0431\u044B \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u043D\u0430 \u0441\u0432\u043E\u0435\u043C \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0435"],"there was an error reading the balance":[""],"Can't delete the account":[""],"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.":[""],"Name doesn't match":["\u043F\u0430\u0440\u043E\u043B\u044C \u043D\u0435 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u0435\u0442"],"delete account":["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0443\u0447\u0451\u0442\u043D\u0443\u044E \u0437\u0430\u043F\u0438\u0441\u044C"],"Account removed":[""],"No enough permission to delete the account.":[""],"The username was not found.":[""],"Can't delete a reserved username.":[""],"Can't delete an account with balance different than zero.":[""],"Remove account.":["\u041D\u0430 \u0441\u0447\u0451\u0442"],"You are going to remove the account":[""],'Deleting account "%1$s"':['\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u0441\u0447\u0451\u0442\u0430 "%1$s"'],Verification:["\u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430"],"Enter the account name that is going to be deleted":[""],"Cashout id should be a number":[""],"This cashout not found. Maybe already aborted.":[""],"Cashout detail":["\u041F\u043E\u0434\u0440\u043E\u0431\u043D\u043E\u0441\u0442\u0438 \u043E\u0431\u043D\u0430\u043B\u0438\u0447\u0438\u0432\u0430\u043D\u0438\u044F"],Debited:["\u0414\u0435\u0431\u0435\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u043E"],Transferred:["\u041F\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438"],"You have no permission to this account.":["\u041D\u0435\u0434\u043E\u0441\u0442\u0430\u0442\u043E\u0447\u043D\u043E \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u0439 \u0434\u043B\u044F \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u044D\u0442\u043E\u0433\u043E \u0441\u0447\u0451\u0442\u0430."],"This account is locked. If you have a active session you can change the password or contact the administrator.":[""],"New web session":[""],"Welcome to %1$s!":["\u0414\u043E\u0431\u0440\u043E \u043F\u043E\u0436\u0430\u043B\u043E\u0432\u0430\u0442\u044C \u0432 %1$s!"]}},domain:"messages",plural_forms:"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;",lang:"ru",completeness:66};Nn.it={locale_data:{messages:{"":{domain:"messages",plural_forms:"nplurals=2; plural=n != 1;",lang:"it"},"An IBAN consists of capital letters and numbers only":[""],"IBAN numbers have more that 4 digits":[""],"IBAN numbers have less that 34 digits":[""],"IBAN country code not found":[""],"IBAN number is not valid, checksum is wrong":[""],"Use letters, numbers or any of these characters: - . _ ~":[""],Required:[""],"confirm MFA challenge":[""],"Unknown challenge.":[""],"Failed to validate the verification code.":[""],"Too many challenges are active right now, you must wait or confirm current challenges.":[""],"Wrong authentication number.":[""],"Expired challenge.":[""],"Submit the transmitted code number.":[""],"The verification code sent to the email address starting with %1$s":[""],"The verification code sent to the phone number ending with %1$s":[""],Code:[""],"Username of the account":["Trasferisci fondi a un altro conto di questa banca:"],"It will expired at %1$s":[""],"The challenge is expired and can't be solved but you can go back and create a new challenge.":[""],Back:[""],Verify:[""],"send MFA challenge":[""],"Failed to send the verification code.":[""],"The request was valid, but the server is refusing action.":[""],"The backend is not aware of the specified MFA challenge.":[""],"It is too early to request another transmission of the challenge.":[""],"Code transmission failed.":["Operazione non riuscita."],"select challenge":[""],"Multi-factor authentication required":[""],"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.":[""],"The next challenge needs to be completed to confirm the operation.":["La banca sta creando l'operazione..."],"All the next challenges need to be completed to confirm the operation.":[""],"One of the next challenges need to be completed to confirm the operation.":[""],'To an phone ending with "%1$s"':[""],'To an email starting with " %1$s"':[""],"I have a code":[""],"Send me a message":[""],"You have to wait until %1$s to send a new code.":[""],Cancel:[""],Complete:[""],"Unable to create a cashout":[""],"The bank configuration does not support cashout operations.":[""],Close:[""],"Cashout is disabled":[""],"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"calculate conversion fee":[""],"The server didn't understand the request.":[""],"The amount is too small":["Questo ritiro \xE8 stato annullato!"],"Conversion is not implemented.":[""],"At least debit or credit needs to be provided":[""],"The amount is malfored":[""],"The currency is not supported":[""],Invalid:[""],"Amount needs to be higher":["Somma da ritirare"],"Balance is not enough":[""],"It is not possible to cashout less than %1$s: %2$s":[""],"The total transfer to the destination will be zero":[""],"create cashout":["Ultime transazioni:"],"Cashout created":[""],"Second factor authentication required.":[""],"Account not found":[""],"Duplicated request detected, check if the operation succeeded or try again.":[""],"The conversion rate was applied incorrectly":[""],"The account does not have sufficient funds":[""],"Missing cashout URI in the profile":[""],"The amount is below the minimum amount permitted.":[""],"Sending the confirmation message failed, retry later or contact the administrator.":[""],"The server doesn't support the current TAN channel.":[""],"Create cashout.":["Ultime transazioni:"],Cashout:[""],"Conversion rate":[""],Balance:[""],Fee:[""],"To account":["Al conto"],"Legal name":[""],"If this name doesn't match the account holder's name, your transaction may fail.":[""],"Unable to cashout":["Ultime transazioni:"],"Before being able to cashout to a bank account, you need to complete your profile":[""],"Transfer subject":["Trasferisci fondi a un altro conto di questa banca:"],Currency:[""],"Send %1$s":[""],"Receive %1$s":[""],Amount:["Importo"],"Total cost":[""],"Balance left":[""],"Before fee":[""],"Total cashout transfer":[""],"Not valid":[""],"Does not follow the pattern":[""],"send transaction":["Ancora nessuna transazione."],"The wire transfer was successfully completed!":["Il bonifico bancario \xE8 stato completato con successo!"],"The request was invalid or the payto://-URI used unacceptable features.":[""],"Not enough permission to complete the operation.":["La banca sta creando l'operazione..."],"The bank administrator cannot be the transfer creditor.":[""],'The destination account "%1$s" was not found.':["Lista conti pubblici non trovata."],"The origin and the destination of the transfer can't be the same.":[""],"Your balance is not sufficient for the operation.":[""],'The origin account "%1$s" was not found.':["Lista conti pubblici non trovata."],"The attempt to create the transaction has failed. Please try again.":[""],"A second factor authentication is required.":[""],"Confirm wire transfer.":["Bonifico"],"Input wire transfer detail":["Inserite qui i dettagli del bonifico"],"Using a form":[""],"A special URI that specifies the amount to be transferred and the destination account.":[""],"QR code":[""],"If your device has a camera, you can import a payto:// URI from a QR code.":[""],Recipient:[""],"ID of the recipient's account":["Storico dei conti pubblici"],username:[""],"IBAN of the recipient's account":[""],Subject:["Soggetto"],"Some text to identify the transfer":[""],"Amount to transfer":["Somma da trasferire"],"Payto URI:":[""],"Uniform resource identifier of the target account":[""],"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]":[""],"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]":[""],"The maximum amount for a wire transfer is %1$s":[""],Cost:[""],Send:[""],'Only "x-taler-bank" target are supported':[""],'Only this host is allowed. Use "%1$s"':[""],"Account name is missing":["Importo"],'Only "IBAN" target are supported':[""],'Missing "amount" parameter to specify the amount to be transferred':[""],'The "amount" parameter is not valid':["Questo ritiro \xE8 stato annullato!"],'"message" parameters to specify a reference text for the transfer are missing':[""],'The only currency allowed is "%1$s"':[""],"You cannot transfer an amount of zero.":[""],"The balance is not sufficient":[""],"Please enter a longer subject":["Trasferisci fondi a un altro conto di questa banca:"],"Show withdrawal confirmation":["Questo ritiro \xE8 stato annullato!"],"Withdraw without setting amount":[""],"Hide demo hint.":[""],"Show install wallet first":[""],"Currently, the bank is not accepting new registrations!":[""],"The name is missing":[""],"Missing username":[""],"Missing password":[""],"The password should be longer than 8 letters":[""],"The passwords do not match":[""],"register new account":["Conto interno"],"Server replied with invalid phone or email.":[""],"You are not authorised to create this account.":[""],"Registration is disabled because the bank ran out of bonus credit.":[""],"That username can't be used because is reserved.":[""],"That username is already taken.":[""],"That account ID is already taken.":[""],"No information for the selected authentication channel.":[""],"Authentication channel is not supported.":[""],"Only an administrator is allowed to set the debt limit.":[""],"Only the administrator can change the conversion rate.":[""],"The conversion rate class doesn't exist.":[""],"Only admin can create accounts with second factor authentication.":[""],"The password is too short. Can't have less than 8 characters.":[""],"The password is too long. Can't have more than 64 characters.":[""],"Account registration":[""],"Login username":[""],"account identification to login":[""],Password:[""],"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers":[""],"Repeat password":[""],"Same password":[""],"Full name":[""],Register:["Registrati"],"Create a random temporary user":[""],logout:[""],login:["Accedi"],"The account has no rights to login.":[""],"The account is locked and cannot login. Contact administrator.":[""],'Wrong credentials for "%1$s"':["Credenziali invalide."],"Account login.":["Importo"],"Session expired":[""],Username:[""],identification:[""],"Password of the account":["Password dell'account"],Forget:[""],"Log in":[""],"Transactions history":[""],"No transactions yet.":["Ancora nessuna transazione."],"You can make a transfer or a withdrawal to your wallet.":[""],Date:["Data"],Counterpart:["Conto corrente"],sent:[""],received:[""],"Invalid value":[""],to:[""],from:[""],"First page":[""],Next:[""],"confirm withdrawal":["Conferma il ritiro"],cambiar:[""],"abort withdrawal":["Conferma il ritiro"],"The withdrawal has been aborted previously and can't be confirmed":[""],"The withdrawal operation can't be confirmed before a wallet accepted the transaction.":[""],"The operation ID is invalid.":["L'ID dell'operazione non \xE8 valido."],"The operation was not found.":["L'operazione non \xE8 stata trovata."],"The starting withdrawal amount and the confirmation amount differs.":[""],"The bank requires a bank account which has not been specified yet.":[""],"Bad request":[""],"The withdrawal operation has been aborted.":["L'operazione non \xE8 stata trovata."],"The withdrawal operation has been confirmed previously and can\u2019t be aborted.":[""],"Complete withdrawal.":["Conferma il ritiro"],"Confirm the withdrawal operation":["Conferma il ritiro"],"Wire transfer details":["Bonifico"],"Payment Service Provider's account number":[""],"Payment Service Provider's name":[""],"Payment Service Provider's account bank hostname":[""],"Payment Service Provider's account id":[""],"Payment Service Provider's account address":[""],"Payment Service Provider's account cyclos hostname":[""],"No amount has yet been determined.":[""],Transfer:[""],"Authentication required":[""],"This operation was created with another username":["Lista conti pubblici non trovata."],'You are currently logged in with user "%1$s" and the operation was made with user "%2$s"':[""],"The reserve operation has been confirmed previously and can't be aborted":[""],"Wire transfer completed!":["Bonifico"],"Confirm withdrawal.":["Conferma il ritiro"],"Unauthorized to make the operation, maybe the session has expired or the password changed.":[""],"The operation was rejected due to insufficient funds.":[""],"Withdrawal confirmed":["Questo ritiro \xE8 stato annullato!"],"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.":[""],"Do not show this again":[""],"If you have a Taler wallet installed on this device":[""],"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions":[""],"on this page":[""],Withdraw:["Prelevare"],"In case you have a Taler wallet on another device":[""],"Scan the QR below to start the withdrawal.":["Chiudi il ritiro Taler"],"create withdrawal":["Conferma il ritiro"],"The server replied with an invalid taler://withdraw URI":[""],"Withdraw URI: %1$s":["Withdraw URI: %1$s"],"The operation was rejected due to insufficient funds":[""],"Current balance is %1$s":[""],"You can withdraw up to %1$s":[""],Continue:[""],"Use your Taler wallet":[""],"After using your wallet you will need to authorize or cancel the operation on this site.":[""],"You need a Taler wallet":["Ritira contante nel portafoglio Taler"],"If you don't have one yet you can follow the instruction in":[""],"this page":[""],"Send money":[""],"to a Taler wallet":["Ritira contante nel portafoglio Taler"],"Withdraw digital money into your mobile wallet or browser extension":[""],"to another bank account":["Trasferisci fondi a un altro conto di questa banca:"],"Make a wire transfer to an account with known bank account number.":[""],"This is a demo":[""],"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .":[""],"Here you will be able to see how a bank that supports Taler directly would work.":[""],"Internal error, please report. There should be more information in the console.":[""],"Internal error, please report.":["Registrazione"],Preferences:[""],"Show debug information":["Questo ritiro \xE8 stato annullato!"],Welcome:[""],"Welcome, %1$s":[""],"No enough permission to access the conversion rate list.":["La banca sta creando l'operazione..."],"Conversion list not found. Maybe conversion rate is not supported.":[""],"Conversion list not implemented.":[""],"Conversion rate classes":["Cambio"],"Create conversion rate class":[""],"No conversion rate class":[""],Name:[""],Description:[""],Cashin:[""],"min:":[""],"fee:":[""],"Select a section":[""],Details:[""],Delete:[""],Credentials:["Credenziali"],Cashouts:["Incassi (Cashout)"],Conversion:["Cambio"],"only admin can setup conversion":[""],"calculate cashout fee":["Ultime transazioni:"],"update conversion rate":["Cambio"],"Wrong credentials":["Credenziali invalide."],"Conversion is disabled":[""],"Config cashout":["Ultime transazioni:"],"Config cashin":[""],"Bad ratios":[""],"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.":[""],"Initial amount":["Questo ritiro \xE8 stato annullato!"],"Use it to test how the conversion will affect the amount.":[""],"Sending to this bank":[""],Converted:[""],"Cashin after fee":[""],"Sending from this bank":[""],"Cashout after fee":[""],"Bad configuration":[""],"This configuration allows users to cash out more of what has been cashed in.":[""],Update:[""],Rnvalid:[""],"Must be > 0":[""],"Minimum amount":[""],"Only cashout operation above this threshold will be allowed.":[""],Ratio:[""],"Conversion ratio between currencies":[""],"Example conversion":[""],"1 %1$s will be converted into %2$s %3$s":[""],"Tiny amount":["Al conto"],"Rounding mode":[""],Zero:[""],"Amount will be round below to the largest possible value smaller than the input.":[""],Up:[""],"Amount will be round up to the smallest possible value larger than the input.":[""],Nearest:[""],"Amount will be round to the closest possible value.":[""],'If none specified the fallback value is "%1$s ".':[""],Examples:[""],"Rounding an amount of 1.24 with rounding value 0.1":[""],"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.":[""],'With the "zero" mode the value will be rounded to 1.2':[""],'With the "nearest" mode the value will be rounded to 1.2':[""],'With the "up" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.26 with rounding value 0.1":[""],'With the "nearest" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.24 with rounding value 0.3":[""],"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.":[""],'With the "up" mode the value will be rounded to 1.5':[""],"Rounding an amount of 1.26 with rounding value 0.3":[""],"Amount to be deducted before amount is credited.":[""],"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"delete conversion rate class":["Cambio"],Unauthorized:[""],Forbidden:[""],NotFound:[""],NotImplemented:[""],"update conversion rate class":["Cambio"],"Not Found":[""],"Not implemented":[""],"The name of the conversion is already used.":["Questo ritiro \xE8 stato annullato!"],"Conversion rate class":["Cambio"],Accounts:["Importo"],Test:[""],Users:[""],"Can't remove the conversion rate class":[""],"There are some user associated to this class. You need to remove them first.":[""],"You are going to remove the conversion rate class":[""],"This step can't be undone.":[""],Filters:[""],"Show from other classes":[""],Account:["Conto"],"Group ID":[""],"No users in this conversion rate class":[""],Class:[""],Action:[""],Remove:[""],Add:["indirizzo Payto"],"Conversion rate name":["Cambio"],"Short description of the class":[""],"create conversion rate class":["Cambio"],"Conversion rate class created.":[""],"The rights to change the account are not sufficient":[""],"New conversion rate class":[""],Create:[""],"History of public accounts":["Storico dei conti pubblici"],"Make a wire transfer":["Chiudi il bonifico"],"Scan the QR code below to start the withdrawal.":["Chiudi il ritiro Taler"],"Operation aborted":[""],"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.":[""],"Go to your wallet now":[""],"The operation is marked as selected, but a process during the withdrawal failed":[""],"A withdrawal reserve ID was not found and no account has been selected.":[""],"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.":[""],"The account was selected, but no withdrawal reserve ID was found.":[""],"Operation not found":[""],"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.":[""],"Continue to dashboard":[""],"The Withdrawal URI is not valid":["Questo ritiro \xE8 stato annullato!"],"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.":[""],"Latest cashouts":["Ultime transazioni:"],Created:[""],"Total debit":[""],"Total credit":[""],"Cashout for account %1$s":[""],"Invalid email format":[""],"Should start with +":[""],"A phone number consists of numbers only":[""],"Account ID for authentication":[""],"Name of the account holder":["Nome del titolare del conto corrente bancario"],"Internal account":["Conto interno"],"If this field is empty, a random account ID will be assigned":[""],"You can copy and share this IBAN number in order to receive wire transfers to your bank account":[""],Email:[""],"To be used when second factor authentication is enabled":[""],Phone:[""],"Enable second factor authentication":[""],"Using email":[""],"Add an email in your profile to enable this option":[""],"Using SMS":[""],"Add a phone number in your profile to enable this option":[""],"Cashout account":["Conto di incasso"],"External account number where the money is going to be sent when doing cashouts":[""],"Max debt":[""],"How much the balance can go below zero.":[""],"Is this account public?":[""],"Public accounts have their balance publicly accessible":[""],"Does this account belong to a Payment Service Provider?":[""],"update account":["Conto di incasso"],"Account updated":[""],"The username was not found":[""],"You can't change the legal name, please contact the your account administrator.":[""],"You can't change the debt limit, please contact the your account administrator.":[""],"You can't change the cashout address, please contact the your account administrator.":[""],"Update account information.":["Aggiornamento dei valori del conto"],'Account "%1$s"':[""],Removed:[""],"This account can't be used.":[""],"Change details":[""],"Merchant integration":[""],'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.':[""],"Account type":["Importo"],"Method to use for wire transfer.":["Chiudi il bonifico"],IBAN:[""],"International Bank Account Number.":[""],"Account name":["Importo"],"Bank host where the service is located.":[""],"Bank account identifier for wire transfers.":[""],Address:["indirizzo Payto"],"Owner's name":[""],"Legal name of the person holding the account.":[""],"Account info URL":["Lista conti pubblici non trovata."],"From where the merchant can download information about incoming wire transfers to this account.":[""],"Repeated password doesn't match":[""],"update password":["Aggiornamento dei valori del conto"],"Password changed":[""],"Not authorized to change the password, maybe the session is invalid.":[""],"You need to provide the old password. If you don't have it contact your account administrator.":[""],"Your current password doesn't match, can't change to a new password.":[""],"You don't have the rights to change the password.":[""],"Update account password.":["Aggiornamento dei valori del conto"],"Update password":[""],"Current password":[""],"Your current password, for security":[""],"New password":[""],"Type it again":[""],"Repeat the same password":[""],Change:[""],"Create account":[""],Actions:[""],Unknown:[""],"Change password":[""],"Querying for the current stats failed":[""],"The request parameters are wrong":[""],"The user is unauthorized":[""],"Querying for the previous stats failed":[""],"Transaction volume report":[""],"Last hour":[""],"Previous day":[""],"Last month":[""],"Last year":[""],"Last Year":[""],"Trading volume from %1$s to %2$s":[""],"Transferred from an external account to an account in this bank.":[""],"Transferred from an account in this bank to an external account.":[""],Payin:[""],"Transferred from an account to a Taler exchange.":[""],Payout:[""],"Transferred from a Taler exchange to another account.":[""],"Download stats as CSV":[""],previous:[""],"Decreased by":[""],"Increased by":[""],"create account":["Al conto"],'Account created with password "%1$s".':[""],"Server replied that phone or email is invalid":[""],"The rights to perform the operation are not sufficient":[""],"Account username is already taken":[""],"Account ID is already taken":[""],"Bank ran out of bonus credit.":[""],"Account username can't be used because is reserved":[""],"Can't create accounts":[""],"Only system admin can create accounts.":[""],"New bank account":["Trasferisci fondi a un altro conto di questa banca:"],"download statistics":[""],"only admin can download stats":[""],"Download bank stats":[""],"Include hour metric":[""],"Include day metric":[""],"Include month metric":[""],"Include year metric":[""],"Include table header":[""],"Add previous metric for compare":[""],"Fail on first error":[""],Download:[""],"downloading... %1$s":[""],"Download completed":[""],"Click here to save the file in your computer.":[""],"there was an error reading the balance":[""],"Can't delete the account":[""],"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.":[""],"Name doesn't match":[""],"delete account":["Al conto"],"Account removed":[""],"No enough permission to delete the account.":[""],"The username was not found.":[""],"Can't delete a reserved username.":[""],"Can't delete an account with balance different than zero.":[""],"Remove account.":["Al conto"],"You are going to remove the account":[""],'Deleting account "%1$s"':[""],Verification:[""],"Enter the account name that is going to be deleted":[""],"Cashout id should be a number":[""],"This cashout not found. Maybe already aborted.":[""],"Cashout detail":[""],Debited:[""],Transferred:["Trasferisci fondi a un altro conto di questa banca:"],"You have no permission to this account.":["La banca sta creando l'operazione..."],"This account is locked. If you have a active session you can change the password or contact the administrator.":[""],"New web session":[""],"Welcome to %1$s!":[""]}},domain:"messages",plural_forms:"nplurals=2; plural=n != 1;",lang:"it",completeness:19};Nn.he={locale_data:{messages:{"":{domain:"messages",plural_forms:"nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && n % 10 == 0) ? 2 : 3));",lang:"he"},"An IBAN consists of capital letters and numbers only":[""],"IBAN numbers have more that 4 digits":[""],"IBAN numbers have less that 34 digits":[""],"IBAN country code not found":[""],"IBAN number is not valid, checksum is wrong":[""],"Use letters, numbers or any of these characters: - . _ ~":[""],Required:[""],"confirm MFA challenge":[""],"Unknown challenge.":[""],"Failed to validate the verification code.":[""],"Too many challenges are active right now, you must wait or confirm current challenges.":[""],"Wrong authentication number.":[""],"Expired challenge.":[""],"Submit the transmitted code number.":[""],"The verification code sent to the email address starting with %1$s":[""],"The verification code sent to the phone number ending with %1$s":[""],Code:[""],"Username of the account":[""],"It will expired at %1$s":[""],"The challenge is expired and can't be solved but you can go back and create a new challenge.":[""],Back:[""],Verify:[""],"send MFA challenge":[""],"Failed to send the verification code.":[""],"The request was valid, but the server is refusing action.":[""],"The backend is not aware of the specified MFA challenge.":[""],"It is too early to request another transmission of the challenge.":[""],"Code transmission failed.":[""],"select challenge":[""],"Multi-factor authentication required":[""],"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.":[""],"The next challenge needs to be completed to confirm the operation.":[""],"All the next challenges need to be completed to confirm the operation.":[""],"One of the next challenges need to be completed to confirm the operation.":[""],'To an phone ending with "%1$s"':[""],'To an email starting with " %1$s"':[""],"I have a code":[""],"Send me a message":[""],"You have to wait until %1$s to send a new code.":[""],Cancel:[""],Complete:[""],"Unable to create a cashout":[""],"The bank configuration does not support cashout operations.":[""],Close:[""],"Cashout is disabled":[""],"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"calculate conversion fee":[""],"The server didn't understand the request.":[""],"The amount is too small":[""],"Conversion is not implemented.":[""],"At least debit or credit needs to be provided":[""],"The amount is malfored":[""],"The currency is not supported":[""],Invalid:[""],"Amount needs to be higher":[""],"Balance is not enough":[""],"It is not possible to cashout less than %1$s: %2$s":[""],"The total transfer to the destination will be zero":[""],"create cashout":[""],"Cashout created":[""],"Second factor authentication required.":[""],"Account not found":[""],"Duplicated request detected, check if the operation succeeded or try again.":[""],"The conversion rate was applied incorrectly":[""],"The account does not have sufficient funds":[""],"Missing cashout URI in the profile":[""],"The amount is below the minimum amount permitted.":[""],"Sending the confirmation message failed, retry later or contact the administrator.":[""],"The server doesn't support the current TAN channel.":[""],"Create cashout.":[""],Cashout:[""],"Conversion rate":[""],Balance:[""],Fee:[""],"To account":[""],"Legal name":[""],"If this name doesn't match the account holder's name, your transaction may fail.":[""],"Unable to cashout":[""],"Before being able to cashout to a bank account, you need to complete your profile":[""],"Transfer subject":[""],Currency:[""],"Send %1$s":[""],"Receive %1$s":[""],Amount:[""],"Total cost":[""],"Balance left":[""],"Before fee":[""],"Total cashout transfer":[""],"Not valid":[""],"Does not follow the pattern":[""],"send transaction":[""],"The wire transfer was successfully completed!":[""],"The request was invalid or the payto://-URI used unacceptable features.":[""],"Not enough permission to complete the operation.":[""],"The bank administrator cannot be the transfer creditor.":[""],'The destination account "%1$s" was not found.':[""],"The origin and the destination of the transfer can't be the same.":[""],"Your balance is not sufficient for the operation.":[""],'The origin account "%1$s" was not found.':[""],"The attempt to create the transaction has failed. Please try again.":[""],"A second factor authentication is required.":[""],"Confirm wire transfer.":[""],"Input wire transfer detail":[""],"Using a form":[""],"A special URI that specifies the amount to be transferred and the destination account.":[""],"QR code":[""],"If your device has a camera, you can import a payto:// URI from a QR code.":[""],Recipient:[""],"ID of the recipient's account":[""],username:[""],"IBAN of the recipient's account":[""],Subject:[""],"Some text to identify the transfer":[""],"Amount to transfer":[""],"Payto URI:":[""],"Uniform resource identifier of the target account":[""],"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]":[""],"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]":[""],"The maximum amount for a wire transfer is %1$s":[""],Cost:[""],Send:[""],'Only "x-taler-bank" target are supported':[""],'Only this host is allowed. Use "%1$s"':[""],"Account name is missing":[""],'Only "IBAN" target are supported':[""],'Missing "amount" parameter to specify the amount to be transferred':[""],'The "amount" parameter is not valid':[""],'"message" parameters to specify a reference text for the transfer are missing':[""],'The only currency allowed is "%1$s"':[""],"You cannot transfer an amount of zero.":[""],"The balance is not sufficient":[""],"Please enter a longer subject":[""],"Show withdrawal confirmation":[""],"Withdraw without setting amount":[""],"Hide demo hint.":[""],"Show install wallet first":[""],"Currently, the bank is not accepting new registrations!":[""],"The name is missing":[""],"Missing username":[""],"Missing password":[""],"The password should be longer than 8 letters":[""],"The passwords do not match":[""],"register new account":[""],"Server replied with invalid phone or email.":[""],"You are not authorised to create this account.":[""],"Registration is disabled because the bank ran out of bonus credit.":[""],"That username can't be used because is reserved.":[""],"That username is already taken.":[""],"That account ID is already taken.":[""],"No information for the selected authentication channel.":[""],"Authentication channel is not supported.":[""],"Only an administrator is allowed to set the debt limit.":[""],"Only the administrator can change the conversion rate.":[""],"The conversion rate class doesn't exist.":[""],"Only admin can create accounts with second factor authentication.":[""],"The password is too short. Can't have less than 8 characters.":[""],"The password is too long. Can't have more than 64 characters.":[""],"Account registration":[""],"Login username":[""],"account identification to login":[""],Password:[""],"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers":[""],"Repeat password":[""],"Same password":[""],"Full name":[""],Register:[""],"Create a random temporary user":[""],logout:[""],login:[""],"The account has no rights to login.":[""],"The account is locked and cannot login. Contact administrator.":[""],'Wrong credentials for "%1$s"':[""],"Account login.":[""],"Session expired":[""],Username:[""],identification:[""],"Password of the account":[""],Forget:[""],"Log in":[""],"Transactions history":[""],"No transactions yet.":[""],"You can make a transfer or a withdrawal to your wallet.":[""],Date:[""],Counterpart:[""],sent:[""],received:[""],"Invalid value":[""],to:[""],from:[""],"First page":[""],Next:[""],"confirm withdrawal":[""],cambiar:[""],"abort withdrawal":[""],"The withdrawal has been aborted previously and can't be confirmed":[""],"The withdrawal operation can't be confirmed before a wallet accepted the transaction.":[""],"The operation ID is invalid.":[""],"The operation was not found.":[""],"The starting withdrawal amount and the confirmation amount differs.":[""],"The bank requires a bank account which has not been specified yet.":[""],"Bad request":[""],"The withdrawal operation has been aborted.":[""],"The withdrawal operation has been confirmed previously and can\u2019t be aborted.":[""],"Complete withdrawal.":[""],"Confirm the withdrawal operation":[""],"Wire transfer details":[""],"Payment Service Provider's account number":[""],"Payment Service Provider's name":[""],"Payment Service Provider's account bank hostname":[""],"Payment Service Provider's account id":[""],"Payment Service Provider's account address":[""],"Payment Service Provider's account cyclos hostname":[""],"No amount has yet been determined.":[""],Transfer:[""],"Authentication required":[""],"This operation was created with another username":[""],'You are currently logged in with user "%1$s" and the operation was made with user "%2$s"':[""],"The reserve operation has been confirmed previously and can't be aborted":[""],"Wire transfer completed!":[""],"Confirm withdrawal.":[""],"Unauthorized to make the operation, maybe the session has expired or the password changed.":[""],"The operation was rejected due to insufficient funds.":[""],"Withdrawal confirmed":[""],"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.":[""],"Do not show this again":[""],"If you have a Taler wallet installed on this device":[""],"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions":[""],"on this page":[""],Withdraw:[""],"In case you have a Taler wallet on another device":[""],"Scan the QR below to start the withdrawal.":[""],"create withdrawal":[""],"The server replied with an invalid taler://withdraw URI":[""],"Withdraw URI: %1$s":[""],"The operation was rejected due to insufficient funds":[""],"Current balance is %1$s":[""],"You can withdraw up to %1$s":[""],Continue:[""],"Use your Taler wallet":[""],"After using your wallet you will need to authorize or cancel the operation on this site.":[""],"You need a Taler wallet":[""],"If you don't have one yet you can follow the instruction in":[""],"this page":[""],"Send money":[""],"to a Taler wallet":[""],"Withdraw digital money into your mobile wallet or browser extension":[""],"to another bank account":[""],"Make a wire transfer to an account with known bank account number.":[""],"This is a demo":[""],"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .":[""],"Here you will be able to see how a bank that supports Taler directly would work.":[""],"Internal error, please report. There should be more information in the console.":[""],"Internal error, please report.":[""],Preferences:[""],"Show debug information":[""],Welcome:[""],"Welcome, %1$s":[""],"No enough permission to access the conversion rate list.":[""],"Conversion list not found. Maybe conversion rate is not supported.":[""],"Conversion list not implemented.":[""],"Conversion rate classes":[""],"Create conversion rate class":[""],"No conversion rate class":[""],Name:[""],Description:[""],Cashin:[""],"min:":[""],"fee:":[""],"Select a section":[""],Details:[""],Delete:[""],Credentials:[""],Cashouts:[""],Conversion:[""],"only admin can setup conversion":[""],"calculate cashout fee":[""],"update conversion rate":[""],"Wrong credentials":[""],"Conversion is disabled":[""],"Config cashout":[""],"Config cashin":[""],"Bad ratios":[""],"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.":[""],"Initial amount":[""],"Use it to test how the conversion will affect the amount.":[""],"Sending to this bank":[""],Converted:[""],"Cashin after fee":[""],"Sending from this bank":[""],"Cashout after fee":[""],"Bad configuration":[""],"This configuration allows users to cash out more of what has been cashed in.":[""],Update:[""],Rnvalid:[""],"Must be > 0":[""],"Minimum amount":[""],"Only cashout operation above this threshold will be allowed.":[""],Ratio:[""],"Conversion ratio between currencies":[""],"Example conversion":[""],"1 %1$s will be converted into %2$s %3$s":[""],"Tiny amount":[""],"Rounding mode":[""],Zero:[""],"Amount will be round below to the largest possible value smaller than the input.":[""],Up:[""],"Amount will be round up to the smallest possible value larger than the input.":[""],Nearest:[""],"Amount will be round to the closest possible value.":[""],'If none specified the fallback value is "%1$s ".':[""],Examples:[""],"Rounding an amount of 1.24 with rounding value 0.1":[""],"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.":[""],'With the "zero" mode the value will be rounded to 1.2':[""],'With the "nearest" mode the value will be rounded to 1.2':[""],'With the "up" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.26 with rounding value 0.1":[""],'With the "nearest" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.24 with rounding value 0.3":[""],"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.":[""],'With the "up" mode the value will be rounded to 1.5':[""],"Rounding an amount of 1.26 with rounding value 0.3":[""],"Amount to be deducted before amount is credited.":[""],"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"delete conversion rate class":[""],Unauthorized:[""],Forbidden:[""],NotFound:[""],NotImplemented:[""],"update conversion rate class":[""],"Not Found":[""],"Not implemented":[""],"The name of the conversion is already used.":[""],"Conversion rate class":[""],Accounts:[""],Test:[""],Users:[""],"Can't remove the conversion rate class":[""],"There are some user associated to this class. You need to remove them first.":[""],"You are going to remove the conversion rate class":[""],"This step can't be undone.":[""],Filters:[""],"Show from other classes":[""],Account:[""],"Group ID":[""],"No users in this conversion rate class":[""],Class:[""],Action:[""],Remove:[""],Add:[""],"Conversion rate name":[""],"Short description of the class":[""],"create conversion rate class":[""],"Conversion rate class created.":[""],"The rights to change the account are not sufficient":[""],"New conversion rate class":[""],Create:[""],"History of public accounts":[""],"Make a wire transfer":[""],"Scan the QR code below to start the withdrawal.":[""],"Operation aborted":[""],"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.":[""],"Go to your wallet now":[""],"The operation is marked as selected, but a process during the withdrawal failed":[""],"A withdrawal reserve ID was not found and no account has been selected.":[""],"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.":[""],"The account was selected, but no withdrawal reserve ID was found.":[""],"Operation not found":[""],"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.":[""],"Continue to dashboard":[""],"The Withdrawal URI is not valid":[""],"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.":[""],"Latest cashouts":[""],Created:[""],"Total debit":[""],"Total credit":[""],"Cashout for account %1$s":[""],"Invalid email format":[""],"Should start with +":[""],"A phone number consists of numbers only":[""],"Account ID for authentication":[""],"Name of the account holder":[""],"Internal account":[""],"If this field is empty, a random account ID will be assigned":[""],"You can copy and share this IBAN number in order to receive wire transfers to your bank account":[""],Email:[""],"To be used when second factor authentication is enabled":[""],Phone:[""],"Enable second factor authentication":[""],"Using email":[""],"Add an email in your profile to enable this option":[""],"Using SMS":[""],"Add a phone number in your profile to enable this option":[""],"Cashout account":[""],"External account number where the money is going to be sent when doing cashouts":[""],"Max debt":[""],"How much the balance can go below zero.":[""],"Is this account public?":[""],"Public accounts have their balance publicly accessible":[""],"Does this account belong to a Payment Service Provider?":[""],"update account":[""],"Account updated":[""],"The username was not found":[""],"You can't change the legal name, please contact the your account administrator.":[""],"You can't change the debt limit, please contact the your account administrator.":[""],"You can't change the cashout address, please contact the your account administrator.":[""],"Update account information.":[""],'Account "%1$s"':[""],Removed:[""],"This account can't be used.":[""],"Change details":[""],"Merchant integration":[""],'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.':[""],"Account type":[""],"Method to use for wire transfer.":[""],IBAN:[""],"International Bank Account Number.":[""],"Account name":[""],"Bank host where the service is located.":[""],"Bank account identifier for wire transfers.":[""],Address:[""],"Owner's name":[""],"Legal name of the person holding the account.":[""],"Account info URL":[""],"From where the merchant can download information about incoming wire transfers to this account.":[""],"Repeated password doesn't match":[""],"update password":[""],"Password changed":[""],"Not authorized to change the password, maybe the session is invalid.":[""],"You need to provide the old password. If you don't have it contact your account administrator.":[""],"Your current password doesn't match, can't change to a new password.":[""],"You don't have the rights to change the password.":[""],"Update account password.":[""],"Update password":[""],"Current password":[""],"Your current password, for security":[""],"New password":[""],"Type it again":[""],"Repeat the same password":[""],Change:[""],"Create account":[""],Actions:[""],Unknown:[""],"Change password":[""],"Querying for the current stats failed":[""],"The request parameters are wrong":[""],"The user is unauthorized":[""],"Querying for the previous stats failed":[""],"Transaction volume report":[""],"Last hour":[""],"Previous day":[""],"Last month":[""],"Last year":[""],"Last Year":[""],"Trading volume from %1$s to %2$s":[""],"Transferred from an external account to an account in this bank.":[""],"Transferred from an account in this bank to an external account.":[""],Payin:[""],"Transferred from an account to a Taler exchange.":[""],Payout:[""],"Transferred from a Taler exchange to another account.":[""],"Download stats as CSV":[""],previous:[""],"Decreased by":[""],"Increased by":[""],"create account":[""],'Account created with password "%1$s".':[""],"Server replied that phone or email is invalid":[""],"The rights to perform the operation are not sufficient":[""],"Account username is already taken":[""],"Account ID is already taken":[""],"Bank ran out of bonus credit.":[""],"Account username can't be used because is reserved":[""],"Can't create accounts":[""],"Only system admin can create accounts.":[""],"New bank account":[""],"download statistics":[""],"only admin can download stats":[""],"Download bank stats":[""],"Include hour metric":[""],"Include day metric":[""],"Include month metric":[""],"Include year metric":[""],"Include table header":[""],"Add previous metric for compare":[""],"Fail on first error":[""],Download:[""],"downloading... %1$s":[""],"Download completed":[""],"Click here to save the file in your computer.":[""],"there was an error reading the balance":[""],"Can't delete the account":[""],"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.":[""],"Name doesn't match":[""],"delete account":[""],"Account removed":[""],"No enough permission to delete the account.":[""],"The username was not found.":[""],"Can't delete a reserved username.":[""],"Can't delete an account with balance different than zero.":[""],"Remove account.":[""],"You are going to remove the account":[""],'Deleting account "%1$s"':[""],Verification:[""],"Enter the account name that is going to be deleted":[""],"Cashout id should be a number":[""],"This cashout not found. Maybe already aborted.":[""],"Cashout detail":[""],Debited:[""],Transferred:[""],"You have no permission to this account.":[""],"This account is locked. If you have a active session you can change the password or contact the administrator.":[""],"New web session":[""],"Welcome to %1$s!":[""]}},domain:"messages",plural_forms:"nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && n % 10 == 0) ? 2 : 3));",lang:"he",completeness:0};Nn.fr={locale_data:{messages:{"":{domain:"messages",plural_forms:"nplurals=2; plural=n > 1;",lang:"fr"},"An IBAN consists of capital letters and numbers only":["Un IBAN se compose uniquement de lettres majuscules et de chiffres"],"IBAN numbers have more that 4 digits":["Les num\xE9ros IBAN ont plus de 4 chiffres"],"IBAN numbers have less that 34 digits":["Les num\xE9ros IBAN ont moins de 34 chiffres"],"IBAN country code not found":["Le code pays de l'IBAN n'a pas \xE9t\xE9 trouv\xE9"],"IBAN number is not valid, checksum is wrong":["Le num\xE9ro IBAN n'est pas valide, la somme de contr\xF4le est incorrecte"],"Use letters, numbers or any of these characters: - . _ ~":["Utilisez des lettres, des chiffres ou l'un de ces caract\xE8res\u202F: - . _ ~"],Required:["Obligatoire"],"confirm MFA challenge":[""],"Unknown challenge.":[""],"Failed to validate the verification code.":[""],"Too many challenges are active right now, you must wait or confirm current challenges.":[""],"Wrong authentication number.":["Num\xE9ro d'authentification erron\xE9."],"Expired challenge.":[""],"Submit the transmitted code number.":[""],"The verification code sent to the email address starting with %1$s":[""],"The verification code sent to the phone number ending with %1$s":[""],Code:[""],"Username of the account":["Nom d'utilisateur du compte"],"It will expired at %1$s":["Date d'expiration %1$s"],"The challenge is expired and can't be solved but you can go back and create a new challenge.":[""],Back:[""],Verify:[""],"send MFA challenge":[""],"Failed to send the verification code.":[""],"The request was valid, but the server is refusing action.":[""],"The backend is not aware of the specified MFA challenge.":[""],"It is too early to request another transmission of the challenge.":[""],"Code transmission failed.":["L\u2019op\xE9ration a \xE9chou\xE9."],"select challenge":[""],"Multi-factor authentication required":["Authentification obligatoire"],"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.":["Cette op\xE9ration est prot\xE9g\xE9e par une authentification \xE0 deuxi\xE8me facteur. Pour la mener \xE0 bien, nous devons v\xE9rifier votre identit\xE9 \xE0 l'aide du canal d'authentification que vous avez fourni."],"The next challenge needs to be completed to confirm the operation.":["Autorisation insuffisante pour terminer l'op\xE9ration."],"All the next challenges need to be completed to confirm the operation.":[""],"One of the next challenges need to be completed to confirm the operation.":[""],'To an phone ending with "%1$s"':[""],'To an email starting with " %1$s"':[""],"I have a code":[""],"Send me a message":[""],"You have to wait until %1$s to send a new code.":[""],Cancel:["Annuler"],Complete:[""],"Unable to create a cashout":["Impossible de cr\xE9er un encaissement"],"The bank configuration does not support cashout operations.":["La configuration bancaire ne prend pas en charge les op\xE9rations d'encaissement."],Close:["Fermer"],"Cashout is disabled":["L'encaissement est d\xE9sactiv\xE9"],"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":["Le retrait doit \xEAtre activ\xE9 dans la configuration, le taux de conversion doit \xEAtre initialis\xE9 avec des frais, des taux et un mode d'arrondi."],"calculate conversion fee":["Taux de conversion"],"The server didn't understand the request.":["Le serveur ne prend pas en charge le canal TAN actuel."],"The amount is too small":["Le mot de passe est trop long."],"Conversion is not implemented.":[""],"At least debit or credit needs to be provided":[""],"The amount is malfored":["D\xE9sol\xE9, cet identifiant de compte est d\xE9j\xE0 pris."],"The currency is not supported":["Le canal d'authentification n'est pas pris en charge."],Invalid:["Invalide"],"Amount needs to be higher":["Le montant doit \xEAtre plus \xE9lev\xE9"],"Balance is not enough":["Le solde n'est pas suffisant"],"It is not possible to cashout less than %1$s: %2$s":["Il n'est pas possible d'encaisser moins de %1$s"],"The total transfer to the destination will be zero":["Le montant total transf\xE9r\xE9 vers la destination sera nul"],"create cashout":["Cr\xE9er un compte"],"Cashout created":["Encaissement cr\xE9\xE9"],"Second factor authentication required.":["Authentification obligatoire"],"Account not found":["Compte non trouv\xE9"],"Duplicated request detected, check if the operation succeeded or try again.":["Requ\xEAte dupliqu\xE9e d\xE9tect\xE9e, v\xE9rifiez si l'op\xE9ration a r\xE9ussi ou r\xE9essayez."],"The conversion rate was applied incorrectly":["Le taux de conversion a \xE9t\xE9 appliqu\xE9 de mani\xE8re incorrecte"],"The account does not have sufficient funds":["Le compte ne dispose pas de fonds suffisants"],"Missing cashout URI in the profile":["URI d'encaissement manquante dans le profil"],"The amount is below the minimum amount permitted.":["Le montant est inf\xE9rieur au montant minimum autoris\xE9."],"Sending the confirmation message failed, retry later or contact the administrator.":["L'envoi du message de confirmation a \xE9chou\xE9, r\xE9essayez plus tard ou contactez l'administrateur."],"The server doesn't support the current TAN channel.":["Le serveur ne prend pas en charge le canal TAN actuel."],"Create cashout.":["Cr\xE9er un compte"],Cashout:["Retrait"],"Conversion rate":["Taux de conversion"],Balance:["Solde"],Fee:["Frais"],"To account":["Compte de destination"],"Legal name":["Nom l\xE9gal du b\xE9n\xE9ficiaire du compte bancaire"],"If this name doesn't match the account holder's name, your transaction may fail.":["Si ce nom ne correspond pas au nom du titulaire du compte, votre transaction peut \xE9chouer."],"Unable to cashout":["Impossible de cr\xE9er un encaissement"],"Before being able to cashout to a bank account, you need to complete your profile":["Avant de pouvoir effectuer un encaissement vers un compte bancaire, vous devez compl\xE9ter votre profil"],"Transfer subject":["R\xE9f\xE9rence du transfert"],Currency:["Devise"],"Send %1$s":["Envoyer %1$s"],"Receive %1$s":["Recevoir %1$s"],Amount:["Montant"],"Total cost":["Montant total des frais"],"Balance left":["Solde restant"],"Before fee":["Avant les frais"],"Total cashout transfer":["Transfert d'encaissement total"],"Not valid":["Non valide"],"Does not follow the pattern":["Ne suit pas le mod\xE8le"],"send transaction":["Aucune transaction n'a encore \xE9t\xE9 effectu\xE9e."],"The wire transfer was successfully completed!":["Le virement bancaire a \xE9t\xE9 effectu\xE9 avec succ\xE8s\u202F!"],"The request was invalid or the payto://-URI used unacceptable features.":["La requ\xEAte n'\xE9tait pas valide ou l'URI payto:// a utilis\xE9 des fonctionnalit\xE9s inacceptables."],"Not enough permission to complete the operation.":["Autorisation insuffisante pour terminer l'op\xE9ration."],"The bank administrator cannot be the transfer creditor.":["L'administrateur de la banque ne peut pas \xEAtre le destinataire du transfert."],'The destination account "%1$s" was not found.':[`Le compte de destination "%1$s" n'a pas \xE9t\xE9 trouv\xE9.`],"The origin and the destination of the transfer can't be the same.":["L'origine et la destination du transfert ne peuvent pas \xEAtre les m\xEAmes."],"Your balance is not sufficient for the operation.":["Votre solde n'est pas suffisant pour l'op\xE9ration."],'The origin account "%1$s" was not found.':[`Le compte d'origine "%1$s" est introuvable.`],"The attempt to create the transaction has failed. Please try again.":["La tentative de cr\xE9ation de la transaction a \xE9chou\xE9. Essayez \xE0 nouveau."],"A second factor authentication is required.":["\xC0 utiliser lorsque l'authentification par deuxi\xE8me facteur est activ\xE9e"],"Confirm wire transfer.":["Effectuer un virement bancaire"],"Input wire transfer detail":["D\xE9tail du virement d'entr\xE9e"],"Using a form":["Utilisation d'un formulaire"],"A special URI that specifies the amount to be transferred and the destination account.":["Un URI sp\xE9cial qui sp\xE9cifie le montant \xE0 transf\xE9rer et le compte de destination."],"QR code":["Code QR"],"If your device has a camera, you can import a payto:// URI from a QR code.":["Si votre appareil dispose d'une cam\xE9ra, vous pouvez importer un URI-payto:// \xE0 partir d'un code QR."],Recipient:["Destinataire"],"ID of the recipient's account":["Identifiant du compte du destinataire"],username:["nom d'utilisateur"],"IBAN of the recipient's account":["IBAN du compte du destinataire"],Subject:["R\xE9f\xE9rence"],"Some text to identify the transfer":["Texte permettant d'identifier le transfert"],"Amount to transfer":["Montant \xE0 transf\xE9rer"],"Payto URI:":["URI Payto\u202F:"],"Uniform resource identifier of the target account":["Identifiant de ressource uniforme (URI en anglais) du compte cible"],"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]":["payto://x-taler-bank/[serveur-de-la-banque]/[compte-destinataire]?message=[reference]&amount=[%1$s:X.Y]"],"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]":["payto://iban/[IBAN du destinataire]?message=[r\xE9f\xE9rence]&amount=[%1$s:X.Y]"],"The maximum amount for a wire transfer is %1$s":["Le montant maximum pour un virement bancaire est de %1$s"],Cost:["Co\xFBt"],Send:["Envoyer"],'Only "x-taler-bank" target are supported':['Seule la destination "x-taler-bank" est prise en charge'],'Only this host is allowed. Use "%1$s"':['Seul cet h\xF4te est autoris\xE9. Utilisez "%1$s"'],"Account name is missing":["Le nom du compte est manquant"],'Only "IBAN" target are supported':['"IBAN" est la seule destination support\xE9e'],'Missing "amount" parameter to specify the amount to be transferred':['Param\xE8tre "montant" manquant pour sp\xE9cifier le montant \xE0 transf\xE9rer'],'The "amount" parameter is not valid':[`Le param\xE8tre "montant" n'est pas valide`],'"message" parameters to specify a reference text for the transfer are missing':['Les param\xE8tres "message" pour sp\xE9cifier un texte de r\xE9f\xE9rence pour le transfert sont manquants'],'The only currency allowed is "%1$s"':['La seule devise autoris\xE9e est "%1$s"'],"You cannot transfer an amount of zero.":["Vous ne pouvez pas transf\xE9rer un montant \xE9gal \xE0 z\xE9ro."],"The balance is not sufficient":["Le solde n'est pas suffisant"],"Please enter a longer subject":["Veuillez saisir une r\xE9f\xE9rence plus longue"],"Show withdrawal confirmation":["Afficher la confirmation de retrait"],"Withdraw without setting amount":["Retirer sans fixer le montant"],"Hide demo hint.":[""],"Show install wallet first":["Afficher d'abord le portefeuille d'installation"],"Currently, the bank is not accepting new registrations!":["Actuellement, la banque n'accepte pas de nouvelles inscriptions\u202F!"],"The name is missing":["Nom manquant"],"Missing username":["Identifiant manquant"],"Missing password":["Mot de passe manquant"],"The password should be longer than 8 letters":["Le mot de passe doit comporter plus de 8 caract\xE8res"],"The passwords do not match":["Les mots de passe ne correspondent pas"],"register new account":["Cr\xE9er un compte"],"Server replied with invalid phone or email.":["Le serveur a r\xE9pondu avec un t\xE9l\xE9phone ou un e-mail invalide."],"You are not authorised to create this account.":["Vous n'\xEAtes pas autoris\xE9 \xE0 cr\xE9er ce compte."],"Registration is disabled because the bank ran out of bonus credit.":["L'inscription est d\xE9sactiv\xE9e car la banque n'a plus de cr\xE9dit bonus."],"That username can't be used because is reserved.":["Ce nom d'utilisateur ne peut pas \xEAtre utilis\xE9 car il est r\xE9serv\xE9."],"That username is already taken.":["D\xE9sol\xE9, ce nom d\u2019utilisateur est d\xE9j\xE0 pris."],"That account ID is already taken.":["D\xE9sol\xE9, cet identifiant de compte est d\xE9j\xE0 pris."],"No information for the selected authentication channel.":["Aucune information pour le canal d'authentification s\xE9lectionn\xE9."],"Authentication channel is not supported.":["Le canal d'authentification n'est pas pris en charge."],"Only an administrator is allowed to set the debt limit.":["Seul un administrateur est autoris\xE9 \xE0 fixer la limite d'endettement."],"Only the administrator can change the conversion rate.":["Seul l'administrateur peut modifier la limite minimale d'encaissement."],"The conversion rate class doesn't exist.":["Le taux de conversion a \xE9t\xE9 appliqu\xE9 de mani\xE8re incorrecte"],"Only admin can create accounts with second factor authentication.":["Seul l'administrateur peut cr\xE9er des comptes avec l'authentification \xE0 deuxi\xE8me facteur."],"The password is too short. Can't have less than 8 characters.":["Le mot de passe doit comporter plus de 8 caract\xE8res"],"The password is too long. Can't have more than 64 characters.":["Le mot de passe doit comporter plus de 8 caract\xE8res"],"Account registration":["Nouveau compte"],"Login username":["Nom d'utilisateur pour le login"],"account identification to login":[""],Password:["Mot de passe"],"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers":["Utilisez un mot de passe fort\u202F: 8 caract\xE8res minimum, n'utilisez aucune information publique vous concernant (noms, date de naissance, num\xE9ro de t\xE9l\xE9phone, etc.) et m\xE9langez minuscules, majuscules, symboles et chiffres"],"Repeat password":["R\xE9p\xE9tez le mot de passe"],"Same password":["Nouveau mot de passe"],"Full name":["Nom complet"],Register:["Inscription"],"Create a random temporary user":["Cr\xE9er un utilisateur temporaire al\xE9atoire"],logout:[""],login:[""],"The account has no rights to login.":[""],"The account is locked and cannot login. Contact administrator.":[""],'Wrong credentials for "%1$s"':[`Mauvaises informations d'identification pour "%1$s"`],"Account login.":["Intitul\xE9 du compte"],"Session expired":["L'op\xE9ration a expir\xE9."],Username:["Nom d'utilisateur"],identification:[""],"Password of the account":["Mot de passe du compte"],Forget:[""],"Log in":["Se connecter"],"Transactions history":["Historique des transactions"],"No transactions yet.":["Aucune transaction n'a encore \xE9t\xE9 effectu\xE9e."],"You can make a transfer or a withdrawal to your wallet.":["Vous pouvez effectuer un virement ou un retrait sur votre portefeuille."],Date:["Date"],Counterpart:["Contrepartie"],sent:["envoy\xE9"],received:["re\xE7u"],"Invalid value":["Valeur non valide"],to:["vers"],from:["de"],"First page":["Premi\xE8re page"],Next:["Suivante"],"confirm withdrawal":["Confirmer le retrait"],cambiar:[""],"abort withdrawal":["Confirmer le retrait"],"The withdrawal has been aborted previously and can't be confirmed":["Le retrait a \xE9t\xE9 interrompu pr\xE9c\xE9demment et ne peut \xEAtre confirm\xE9"],"The withdrawal operation can't be confirmed before a wallet accepted the transaction.":["L'op\xE9ration de retrait ne peut pas \xEAtre confirm\xE9e avant qu'un portefeuille n'accepte la transaction."],"The operation ID is invalid.":["L'identifiant de l'op\xE9ration n'est pas valide."],"The operation was not found.":["L'op\xE9ration est introuvable."],"The starting withdrawal amount and the confirmation amount differs.":["Le montant du retrait de d\xE9part et le montant de la confirmation diff\xE8rent."],"The bank requires a bank account which has not been specified yet.":["La banque exige un compte bancaire et il n'a pas encore \xE9t\xE9 sp\xE9cifi\xE9."],"Bad request":[""],"The withdrawal operation has been aborted.":["Op\xE9ration de retrait en attente"],"The withdrawal operation has been confirmed previously and can\u2019t be aborted.":["L'op\xE9ration de r\xE9serve a \xE9t\xE9 confirm\xE9e pr\xE9c\xE9demment et ne peut plus \xEAtre annul\xE9e"],"Complete withdrawal.":["Confirmer le retrait"],"Confirm the withdrawal operation":["Confirmer l'op\xE9ration de retrait"],"Wire transfer details":["D\xE9tails du virement"],"Payment Service Provider's account number":["Num\xE9ro de compte du prestataire de services de paiement"],"Payment Service Provider's name":["Nom du prestataire de services de paiement"],"Payment Service Provider's account bank hostname":["Nom du serveur de la banque du compte du prestataire de services de paiement"],"Payment Service Provider's account id":["Identifiant du compte du prestataire de services de paiement"],"Payment Service Provider's account address":["Adresse du compte du prestataire de services de paiement"],"Payment Service Provider's account cyclos hostname":["Nom du serveur de la banque du compte du prestataire de services de paiement"],"No amount has yet been determined.":["Aucun montant n'a encore \xE9t\xE9 d\xE9termin\xE9."],Transfer:["Transfert"],"Authentication required":["Authentification obligatoire"],"This operation was created with another username":["Cette op\xE9ration a \xE9t\xE9 cr\xE9\xE9e avec un autre nom d'utilisateur"],'You are currently logged in with user "%1$s" and the operation was made with user "%2$s"':[""],"The reserve operation has been confirmed previously and can't be aborted":["L'op\xE9ration de r\xE9serve a \xE9t\xE9 confirm\xE9e pr\xE9c\xE9demment et ne peut plus \xEAtre annul\xE9e"],"Wire transfer completed!":["Virement bancaire termin\xE9\u202F!"],"Confirm withdrawal.":["Confirmer le retrait"],"Unauthorized to make the operation, maybe the session has expired or the password changed.":["Non autoris\xE9 \xE0 effectuer l'op\xE9ration, peut-\xEAtre que la session a expir\xE9 ou que le mot de passe a \xE9t\xE9 modifi\xE9."],"The operation was rejected due to insufficient funds.":["L'op\xE9ration a \xE9t\xE9 rejet\xE9e en raison de fonds insuffisants."],"Withdrawal confirmed":["Retrait confirm\xE9"],"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.":["Le virement bancaire au profit du prestataire de services de paiement a \xE9t\xE9 enclench\xE9. Vous recevrez sous peu le montant demand\xE9 dans votre portefeuille Taler."],"Do not show this again":["Ne plus afficher \xE0 l'avenir"],"If you have a Taler wallet installed on this device":["Si vous avez un portefeuille Taler install\xE9 sur cet appareil"],"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions":["Votre portefeuille affichera les d\xE9tails de la transaction, y compris les frais (le cas \xE9ch\xE9ant). Si vous n'avez pas encore de portefeuille, veuillez suivre les instructions"],"on this page":["sur cette page"],Withdraw:["Retirer"],"In case you have a Taler wallet on another device":["Si vous avez un portefeuille Taler sur un autre appareil"],"Scan the QR below to start the withdrawal.":["Scannez le code QR ci-dessous pour commencer le retrait."],"create withdrawal":["Confirmer le retrait"],"The server replied with an invalid taler://withdraw URI":["Le serveur a r\xE9pondu avec un URI taler://withdraw invalide"],"Withdraw URI: %1$s":["URI de retrait\u202F: %1$s"],"The operation was rejected due to insufficient funds":["L'op\xE9ration a \xE9t\xE9 rejet\xE9e pour cause de fonds insuffisants"],"Current balance is %1$s":["Le solde actuel est de %1$s"],"You can withdraw up to %1$s":["Vous pouvez retirer jusqu'\xE0 %1$s"],Continue:["Continuer"],"Use your Taler wallet":["Utilisez votre portefeuille Taler"],"After using your wallet you will need to authorize or cancel the operation on this site.":["Apr\xE8s avoir utilis\xE9 votre portefeuille, vous devrez autoriser ou annuler l'op\xE9ration sur ce site."],"You need a Taler wallet":["Vous avez besoin d'un portefeuille Taler"],"If you don't have one yet you can follow the instruction in":["Si vous n'en avez pas encore, vous pouvez suivre les instructions dans"],"this page":["cette page"],"Send money":["Envoyer de l'argent"],"to a Taler wallet":["vers un portefeuille Taler"],"Withdraw digital money into your mobile wallet or browser extension":["Retirez de l'argent num\xE9rique dans votre portefeuille mobile ou votre extension de navigateur"],"to another bank account":["sur un autre compte bancaire"],"Make a wire transfer to an account with known bank account number.":["Effectuez un virement bancaire sur un compte dont le num\xE9ro de compte bancaire est connu."],"This is a demo":["Ceci est une d\xE9mo"],"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .":["Cette partie de la d\xE9mo montre comment fonctionnerait une banque qui supporte directement Taler. Outre l'utilisation de votre propre compte bancaire, vous pouvez \xE9galement consulter l'historique des transactions de certains %1$s ."],"Here you will be able to see how a bank that supports Taler directly would work.":["Ici, vous pourrez voir comment une banque qui prend directement en charge Taler fonctionnerait."],"Internal error, please report. There should be more information in the console.":[""],"Internal error, please report.":["Erreur interne, veuillez signaler."],Preferences:["Pr\xE9f\xE9rences"],"Show debug information":["Afficher les informations de d\xE9bogage"],Welcome:["Bienvenue"],"Welcome, %1$s":["Bienvenue, %1$s"],"No enough permission to access the conversion rate list.":["Autorisation insuffisante pour terminer l'op\xE9ration."],"Conversion list not found. Maybe conversion rate is not supported.":[""],"Conversion list not implemented.":[""],"Conversion rate classes":["Taux de conversion"],"Create conversion rate class":["Taux de conversion"],"No conversion rate class":["Taux de conversion"],Name:["Nom"],Description:["Afficher la description de la d\xE9mo"],Cashin:[""],"min:":[""],"fee:":[""],"Select a section":["S\xE9lectionner une section"],Details:["D\xE9tails"],Delete:["Supprimer"],Credentials:["Identifiants"],Cashouts:["Retraits"],Conversion:["Conversion"],"only admin can setup conversion":[""],"calculate cashout fee":["Cr\xE9er un compte"],"update conversion rate":["Taux de conversion"],"Wrong credentials":[""],"Conversion is disabled":[""],"Config cashout":[""],"Config cashin":[""],"Bad ratios":[""],"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.":[""],"Initial amount":[""],"Use it to test how the conversion will affect the amount.":[""],"Sending to this bank":[""],Converted:[""],"Cashin after fee":[""],"Sending from this bank":[""],"Cashout after fee":[""],"Bad configuration":[""],"This configuration allows users to cash out more of what has been cashed in.":[""],Update:["Modification"],Rnvalid:[""],"Must be > 0":[""],"Minimum amount":[""],"Only cashout operation above this threshold will be allowed.":[""],Ratio:[""],"Conversion ratio between currencies":[""],"Example conversion":[""],"1 %1$s will be converted into %2$s %3$s":[""],"Tiny amount":["Compte de destination"],"Rounding mode":[""],Zero:[""],"Amount will be round below to the largest possible value smaller than the input.":[""],Up:[""],"Amount will be round up to the smallest possible value larger than the input.":[""],Nearest:[""],"Amount will be round to the closest possible value.":[""],'If none specified the fallback value is "%1$s ".':[""],Examples:[""],"Rounding an amount of 1.24 with rounding value 0.1":[""],"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.":[""],'With the "zero" mode the value will be rounded to 1.2':[""],'With the "nearest" mode the value will be rounded to 1.2':[""],'With the "up" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.26 with rounding value 0.1":[""],'With the "nearest" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.24 with rounding value 0.3":[""],"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.":[""],'With the "up" mode the value will be rounded to 1.5':[""],"Rounding an amount of 1.26 with rounding value 0.3":[""],"Amount to be deducted before amount is credited.":[""],"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":["Le retrait doit \xEAtre activ\xE9 dans la configuration, le taux de conversion doit \xEAtre initialis\xE9 avec des frais, des taux et un mode d'arrondi."],"delete conversion rate class":["Taux de conversion"],Unauthorized:["L'utilisateur n'est pas autoris\xE9"],Forbidden:[""],NotFound:[""],NotImplemented:[""],"update conversion rate class":["Taux de conversion"],"Not Found":[""],"Not implemented":[""],"The name of the conversion is already used.":["Une op\xE9ration est d\xE9j\xE0 en attente"],"Conversion rate class":["Taux de conversion"],Accounts:["Comptes"],Test:[""],Users:["Nom d'utilisateur"],"Can't remove the conversion rate class":[""],"There are some user associated to this class. You need to remove them first.":[""],"You are going to remove the conversion rate class":[""],"This step can't be undone.":[""],Filters:[""],"Show from other classes":[""],Account:["Compte"],"Group ID":[""],"No users in this conversion rate class":[""],Class:[""],Action:["Actions"],Remove:["Effacer"],Add:["Adresse"],"Conversion rate name":["Taux de conversion"],"Short description of the class":[""],"create conversion rate class":["Taux de conversion"],"Conversion rate class created.":["Taux de conversion"],"The rights to change the account are not sufficient":["Les droits de modification du compte ne sont pas suffisants"],"New conversion rate class":["Taux de conversion"],Create:[""],"History of public accounts":["Historique de comptes publiques"],"Make a wire transfer":["Effectuer un virement bancaire"],"Scan the QR code below to start the withdrawal.":["Scannez le code QR ci-dessous pour commencer le retrait."],"Operation aborted":["Op\xE9ration abandonn\xE9e"],"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.":["Le virement bancaire vers le compte du prestataire de services de paiement a \xE9t\xE9 annul\xE9 depuis un autre endroit, votre solde n'a pas \xE9t\xE9 affect\xE9."],"Go to your wallet now":["Acc\xE9dez \xE0 votre portefeuille maintenant"],"The operation is marked as selected, but a process during the withdrawal failed":["L'op\xE9ration est marqu\xE9e comme s\xE9lectionn\xE9e, mais un processus pendant le retrait a \xE9chou\xE9"],"A withdrawal reserve ID was not found and no account has been selected.":["Aucun identifiant de r\xE9serve de retrait n'a \xE9t\xE9 trouv\xE9 et aucun compte n'a \xE9t\xE9 s\xE9lectionn\xE9."],"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.":["Il existe un identifiant de r\xE9serve de retrait, mais aucun compte n'a \xE9t\xE9 s\xE9lectionn\xE9 ou le compte s\xE9lectionn\xE9 n'est pas valide."],"The account was selected, but no withdrawal reserve ID was found.":["Le compte a \xE9t\xE9 s\xE9lectionn\xE9, mais aucun identifiant de r\xE9serve de retrait n'a \xE9t\xE9 trouv\xE9."],"Operation not found":["Op\xE9ration non trouv\xE9e"],"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.":["Ce processus n'est pas connu du serveur. L'identifiant du processus est incorrect ou le serveur a supprim\xE9 les informations sur le processus avant leur arriv\xE9e ici."],"Continue to dashboard":["Continuer vers le tableau de bord"],"The Withdrawal URI is not valid":["L'URI de retrait n'est pas valide"],"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.":["L'encaissement doit \xEAtre activ\xE9 dans la configuration, le taux de conversion doit \xEAtre initialis\xE9 avec des frais, des taux et un mode d'arrondi."],"Latest cashouts":["Derniers encaissements"],Created:["Cr\xE9\xE9e"],"Total debit":["D\xE9bit total"],"Total credit":["Cr\xE9dit total"],"Cashout for account %1$s":["Encaissement pour le compte %1$s"],"Invalid email format":["Valeur non valide"],"Should start with +":["Doit commencer par +"],"A phone number consists of numbers only":["Un num\xE9ro de t\xE9l\xE9phone se compose uniquement de chiffres"],"Account ID for authentication":["Identifiant de compte pour l'authentification"],"Name of the account holder":["Nom du titulaire du compte"],"Internal account":["Compte interne"],"If this field is empty, a random account ID will be assigned":["Si ce champ est vide, un identifiant de compte al\xE9atoire sera attribu\xE9"],"You can copy and share this IBAN number in order to receive wire transfers to your bank account":["Vous pouvez copier et partager ce num\xE9ro IBAN afin de recevoir des virements vers votre compte bancaire"],Email:["Adresse mail"],"To be used when second factor authentication is enabled":["\xC0 utiliser lorsque l'authentification par deuxi\xE8me facteur est activ\xE9e"],Phone:["T\xE9l\xE9phone"],"Enable second factor authentication":["\xC0 utiliser lorsque l'authentification par deuxi\xE8me facteur est activ\xE9e"],"Using email":["Vers l'email"],"Add an email in your profile to enable this option":[""],"Using SMS":[""],"Add a phone number in your profile to enable this option":[""],"Cashout account":["Compte d'encaissement"],"External account number where the money is going to be sent when doing cashouts":["Num\xE9ro de compte externe o\xF9 l'argent va \xEAtre envoy\xE9 lors des encaissements"],"Max debt":["Cr\xE9ance maximale"],"How much the balance can go below zero.":["De combien le solde peut-il descendre en dessous de z\xE9ro."],"Is this account public?":["Ce compte est-il public\u202F?"],"Public accounts have their balance publicly accessible":["Le solde des comptes publics est accessible \xE0 tous"],"Does this account belong to a Payment Service Provider?":["Ce compte appartient-il \xE0 un prestataire de services de paiement\u202F?"],"update account":["Cr\xE9er un compte"],"Account updated":["Compte mis \xE0 jour"],"The username was not found":["Le nom d'utilisateur n'a pas \xE9t\xE9 trouv\xE9"],"You can't change the legal name, please contact the your account administrator.":["Vous ne pouvez pas modifier le nom l\xE9gal, veuillez contacter l'administrateur de votre compte."],"You can't change the debt limit, please contact the your account administrator.":["Vous ne pouvez pas modifier la limite d'endettement, veuillez contacter l'administrateur de votre compte."],"You can't change the cashout address, please contact the your account administrator.":["Vous ne pouvez pas modifier l'adresse d'encaissement, veuillez contacter l'administrateur de votre compte."],"Update account information.":["Mise \xE0 jour des param\xE8tres du compte"],'Account "%1$s"':['Compte "%1$s"'],Removed:["Supprim\xE9"],"This account can't be used.":["Ce compte ne peut pas \xEAtre utilis\xE9."],"Change details":["Modifier les d\xE9tails"],"Merchant integration":["Int\xE9gration des commer\xE7ants"],'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.':['Utilisez ces informations pour relier votre compte Taler Merchant Backoffice au compte bancaire actuel. Vous pouvez commencer par copier les valeurs, puis vous rendre chez votre fournisseur de services de backoffice marchand, vous connecter \xE0 votre compte et chercher le bouton "importer" dans la section "compte bancaire".'],"Account type":["Type de compte"],"Method to use for wire transfer.":["M\xE9thode \xE0 utiliser pour un virement bancaire."],IBAN:["IBAN"],"International Bank Account Number.":["Num\xE9ro de compte bancaire international (IBAN)."],"Account name":["Intitul\xE9 du compte"],"Bank host where the service is located.":["Serveur de la banque o\xF9 se trouve le service."],"Bank account identifier for wire transfers.":["Identifiant du compte bancaire pour les virements."],Address:["Adresse"],"Owner's name":["Nom du propri\xE9taire"],"Legal name of the person holding the account.":["Nom l\xE9gal de la personne titulaire du compte."],"Account info URL":["URL d'information de compte"],"From where the merchant can download information about incoming wire transfers to this account.":["Endroit d'o\xF9 le commer\xE7ant peut t\xE9l\xE9charger des informations sur les virements entrants sur ce compte."],"Repeated password doesn't match":["Le mot de passe r\xE9p\xE9t\xE9 ne correspond pas"],"update password":["Modifier le mot de passe"],"Password changed":["Mot de passe modifi\xE9"],"Not authorized to change the password, maybe the session is invalid.":["Pas autoris\xE9 \xE0 changer le mot de passe, peut-\xEAtre que la session n'est pas valide."],"You need to provide the old password. If you don't have it contact your account administrator.":["Vous devez fournir l'ancien mot de passe. Si vous ne l'avez pas, veuillez contacter l'administrateur."],"Your current password doesn't match, can't change to a new password.":["Votre mot de passe actuel ne correspond pas, vous ne pouvez pas changer de mot de passe."],"You don't have the rights to change the password.":[""],"Update account password.":["Modifier le mot de passe"],"Update password":["Modifier le mot de passe"],"Current password":["Mot de passe actuel"],"Your current password, for security":["Votre mot de passe actuel, par s\xE9curit\xE9"],"New password":["Nouveau mot de passe"],"Type it again":["Saisissez-le \xE0 nouveau"],"Repeat the same password":["Confirmez le mot de passe"],Change:["Modifier"],"Create account":["Cr\xE9er un compte"],Actions:["Actions"],Unknown:["Inconnu"],"Change password":["Changer le mot de passe"],"Querying for the current stats failed":["\xC9chec de la requ\xEAte pour les statistiques actuelles"],"The request parameters are wrong":["Les param\xE8tres de la requ\xEAte sont erron\xE9s"],"The user is unauthorized":["L'utilisateur n'est pas autoris\xE9"],"Querying for the previous stats failed":[""],"Transaction volume report":[""],"Last hour":[""],"Previous day":[""],"Last month":[""],"Last year":[""],"Last Year":[""],"Trading volume from %1$s to %2$s":[""],"Transferred from an external account to an account in this bank.":[""],"Transferred from an account in this bank to an external account.":[""],Payin:[""],"Transferred from an account to a Taler exchange.":[""],Payout:[""],"Transferred from a Taler exchange to another account.":[""],"Download stats as CSV":[""],previous:[""],"Decreased by":[""],"Increased by":[""],"create account":["Cr\xE9er un compte"],'Account created with password "%1$s".':[""],"Server replied that phone or email is invalid":[""],"The rights to perform the operation are not sufficient":[""],"Account username is already taken":[""],"Account ID is already taken":["D\xE9sol\xE9, cet identifiant de compte est d\xE9j\xE0 pris."],"Bank ran out of bonus credit.":[""],"Account username can't be used because is reserved":[""],"Can't create accounts":[""],"Only system admin can create accounts.":[""],"New bank account":[""],"download statistics":[""],"only admin can download stats":[""],"Download bank stats":[""],"Include hour metric":[""],"Include day metric":[""],"Include month metric":[""],"Include year metric":[""],"Include table header":[""],"Add previous metric for compare":[""],"Fail on first error":[""],Download:[""],"downloading... %1$s":[""],"Download completed":[""],"Click here to save the file in your computer.":[""],"there was an error reading the balance":[""],"Can't delete the account":[""],"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.":[""],"Name doesn't match":[""],"delete account":["Cr\xE9er un compte"],"Account removed":[""],"No enough permission to delete the account.":[""],"The username was not found.":[""],"Can't delete a reserved username.":[""],"Can't delete an account with balance different than zero.":[""],"Remove account.":["Suppression du compte"],"You are going to remove the account":[""],'Deleting account "%1$s"':[""],Verification:[""],"Enter the account name that is going to be deleted":[""],"Cashout id should be a number":[""],"This cashout not found. Maybe already aborted.":[""],"Cashout detail":[""],Debited:[""],Transferred:["Transfert"],"You have no permission to this account.":["Vous n'\xEAtes pas autoris\xE9 \xE0 cr\xE9er ce compte."],"This account is locked. If you have a active session you can change the password or contact the administrator.":[""],"New web session":[""],"Welcome to %1$s!":[""]}},domain:"messages",plural_forms:"nplurals=2; plural=n > 1;",lang:"fr",completeness:66};Nn.es={locale_data:{messages:{"":{domain:"messages",plural_forms:"nplurals=2; plural=n != 1;",lang:"es_AR"},"An IBAN consists of capital letters and numbers only":["Un IBAN debe contener solo letras may\xFAsculas y n\xFAmeros"],"IBAN numbers have more that 4 digits":["Los n\xFAmeros IBAN tienen m\xE1s de 4 d\xEDgitos"],"IBAN numbers have less that 34 digits":["Los n\xFAmeros IBAN tienen menos de 34 d\xEDgitos"],"IBAN country code not found":["C\xF3digo de pa\xEDs del IBAN no encontrado"],"IBAN number is not valid, checksum is wrong":["El n\xFAmero IBAN no es v\xE1lido, fall\xF3 la verificaci\xF3n"],"Use letters, numbers or any of these characters: - . _ ~":["Us\xE1 letras, n\xFAmeros o cualquiera de estos caracteres: - . _ ~"],Required:["Requerido"],"confirm MFA challenge":["Confiormar desaf\xEDo."],"Unknown challenge.":["Desaf\xEDo desconocido."],"Failed to validate the verification code.":["No se pudo validar el c\xF3digo de verificaci\xF3n."],"Too many challenges are active right now, you must wait or confirm current challenges.":["Hay demasiados desaf\xEDos activos en este momento, ten\xE9s que esperar o confirmar los desaf\xEDos actuales."],"Wrong authentication number.":["N\xFAmero de autenticaci\xF3n incorrecto."],"Expired challenge.":["Desaf\xEDo expirado."],"Submit the transmitted code number.":["Ingres\xE1 el c\xF3digo que te fue enviado."],"The verification code sent to the email address starting with %1$s":["El c\xF3digo de verificaci\xF3n enviado a la direcci\xF3n de correo que empieza con %1$s"],"The verification code sent to the phone number ending with %1$s":["El c\xF3digo de verificaci\xF3n enviado al n\xFAmero de tel\xE9fono que empieza con %1$s"],Code:["C\xF3digo"],"Username of the account":["Nombre de usuario de la cuenta"],"It will expired at %1$s":["Expirar\xE1 el %1$s"],"The challenge is expired and can't be solved but you can go back and create a new challenge.":["El desaf\xEDo expir\xF3 y no puede resolverse, pero pod\xE9s volver atr\xE1s y crear uno nuevo."],Back:["Volver"],Verify:["Verificar"],"send MFA challenge":["Env\xEDo de desaf\xEDo"],"Failed to send the verification code.":["No se pudo enviar el c\xF3digo de verificaci\xF3n."],"The request was valid, but the server is refusing action.":["El pedido era v\xE1lido, pero el servidor est\xE1 rechazando la acci\xF3n."],"The backend is not aware of the specified MFA challenge.":["El servidor no reconoce el desaf\xEDo MFA especificado."],"It is too early to request another transmission of the challenge.":["Es demasiado pronto para solicitar otro env\xEDo del desaf\xEDo."],"Code transmission failed.":["El env\xEDo del c\xF3digo fall\xF3."],"select challenge":["Seleccionar desaf\xEDo"],"Multi-factor authentication required":["Se requiere autenticaci\xF3n de m\xFAltiples factores"],"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.":["Esta operaci\xF3n est\xE1 protegida con autenticaci\xF3n de segundo factor. Para completarla necesitamos verificar tu identidad usando el canal de autenticaci\xF3n que proporcionaste."],"The next challenge needs to be completed to confirm the operation.":["El siguiente desaf\xEDo debe completarse para confirmar la operaci\xF3n."],"All the next challenges need to be completed to confirm the operation.":["Todos los desaf\xEDos siguientes deben completarse para confirmar la operaci\xF3n."],"One of the next challenges need to be completed to confirm the operation.":["Uno de los siguientes desaf\xEDos debe completarse para confirmar la operaci\xF3n."],'To an phone ending with "%1$s"':['A un tel\xE9fono que empieza con "%1$s"'],'To an email starting with " %1$s"':['A un correo que empieza con "%1$s"'],"I have a code":["Tengo un c\xF3digo"],"Send me a message":["Enviame un mensaje"],"You have to wait until %1$s to send a new code.":["Ten\xE9s que esperar hasta el %1$s para enviar un nuevo c\xF3digo."],Cancel:["Cancelar"],Complete:["Completar"],"Unable to create a cashout":["No se puede crear un egreso"],"The bank configuration does not support cashout operations.":["La configuraci\xF3n del banco no soporta operaciones de egreso."],Close:["Cerrar"],"Cashout is disabled":["El egreso est\xE1 deshabilitado"],"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":["El egreso debe estar habilitado en la configuraci\xF3n, la tasa de conversi\xF3n debe estar inicializada con comisi\xF3n(es), tasas y un modo de redondeo."],"calculate conversion fee":["Calcular tasa de conversi\xF3n."],"The server didn't understand the request.":["El servidor no pudo entender el pedido."],"The amount is too small":["El monto es demasiado peque\xF1o"],"Conversion is not implemented.":["La conversi\xF3n no est\xE1 implementada."],"At least debit or credit needs to be provided":["Se debe indicar al menos el d\xE9bito o el cr\xE9dito"],"The amount is malfored":["El monto tiene un formato incorrecto"],"The currency is not supported":["La moneda no est\xE1 soportada"],Invalid:["Inv\xE1lido"],"Amount needs to be higher":["El monto debe ser mayor"],"Balance is not enough":["El saldo no es suficiente"],"It is not possible to cashout less than %1$s: %2$s":["No es posible retirar menos de %1$s: %2$s"],"The total transfer to the destination will be zero":["El total de la transferencia al destino ser\xE1 cero"],"create cashout":["Crear egreso."],"Cashout created":["Egreso creado"],"Second factor authentication required.":["Se requiere autenticaci\xF3n de segundo factor."],"Account not found":["Cuenta no encontrada"],"Duplicated request detected, check if the operation succeeded or try again.":["Se detect\xF3 una petici\xF3n duplicada, verific\xE1 si la operaci\xF3n tuvo \xE9xito o intent\xE1 nuevamente."],"The conversion rate was applied incorrectly":["La tasa de conversi\xF3n se aplic\xF3 de forma incorrecta"],"The account does not have sufficient funds":["La cuenta no tiene fondos suficientes"],"Missing cashout URI in the profile":["Falta la direcci\xF3n de egreso en el perfil"],"The amount is below the minimum amount permitted.":["El monto est\xE1 por debajo del m\xEDnimo permitido."],"Sending the confirmation message failed, retry later or contact the administrator.":["El env\xEDo del mensaje de confirmaci\xF3n fall\xF3, intent\xE1 m\xE1s tarde o contact\xE1 al administrador."],"The server doesn't support the current TAN channel.":["El servidor no soporta el canal TAN actual."],"Create cashout.":["Crear egreso."],Cashout:["Egreso"],"Conversion rate":["Tasa de conversi\xF3n"],Balance:["Saldo"],Fee:["Comisi\xF3n"],"To account":["Hacia la cuenta"],"Legal name":["Nombre legal"],"If this name doesn't match the account holder's name, your transaction may fail.":["Si este nombre no coincide con el titular de la cuenta, tu transacci\xF3n podr\xEDa fallar."],"Unable to cashout":["No se puede realizar el egreso"],"Before being able to cashout to a bank account, you need to complete your profile":["Antes de poder hacer un egreso a una cuenta bancaria, necesit\xE1s completar tu perfil"],"Transfer subject":["Asunto de la transferencia"],Currency:["Moneda"],"Send %1$s":["Enviar %1$s"],"Receive %1$s":["Recibir %1$s"],Amount:["Monto"],"Total cost":["Costo total"],"Balance left":["Saldo restante"],"Before fee":["Antes de la comisi\xF3n"],"Total cashout transfer":["Total del egreso"],"Not valid":["No v\xE1lido"],"Does not follow the pattern":["No sigue el formato esperado"],"send transaction":["Env\xEDo de transaccion"],"The wire transfer was successfully completed!":["\xA1La transferencia bancaria se complet\xF3 con \xE9xito!"],"The request was invalid or the payto://-URI used unacceptable features.":["El pedido era inv\xE1lido o el URI payto:// usado tiene caracter\xEDsticas inaceptables."],"Not enough permission to complete the operation.":["No ten\xE9s permisos suficientes para completar la operaci\xF3n."],"The bank administrator cannot be the transfer creditor.":["El administrador del banco no puede ser el destinatario de la transferencia."],'The destination account "%1$s" was not found.':['La cuenta de destino "%1$s" no fue encontrada.'],"The origin and the destination of the transfer can't be the same.":["El origen y el destino de la transferencia no pueden ser iguales."],"Your balance is not sufficient for the operation.":["Tu saldo no es suficiente para la operaci\xF3n."],'The origin account "%1$s" was not found.':['La cuenta origen "%1$s" no fue encontrada.'],"The attempt to create the transaction has failed. Please try again.":["El intento de crear la transacci\xF3n fall\xF3. Por favor intent\xE1 nuevamente."],"A second factor authentication is required.":["Se requiere autenticaci\xF3n de segundo factor."],"Confirm wire transfer.":["Confirm\xE1 la transferencia bancaria."],"Input wire transfer detail":["Ingres\xE1 los datos de la transferencia bancaria"],"Using a form":["Usando un formulario"],"A special URI that specifies the amount to be transferred and the destination account.":["Un URI especial que indica el monto a transferir y la cuenta de destino."],"QR code":["C\xF3digo QR"],"If your device has a camera, you can import a payto:// URI from a QR code.":["Si tu dispositivo tiene c\xE1mara, pod\xE9s importar un URI payto:// desde un c\xF3digo QR."],Recipient:["Destinatario"],"ID of the recipient's account":["ID de la cuenta del destinatario"],username:["nombre de usuario"],"IBAN of the recipient's account":["IBAN de la cuenta del destinatario"],Subject:["Asunto"],"Some text to identify the transfer":["Alg\xFAn texto para identificar la transferencia"],"Amount to transfer":["Monto a transferir"],"Payto URI:":["URI payto:"],"Uniform resource identifier of the target account":["Identificador de recurso uniforme de la cuenta destino"],"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]":["payto://x-taler-bank/[operador bancario]/[cuenta bancaria del destinatario]?message=[asunto]&amount=[%1$s:X.Y]"],"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]":["payto://iban/[IBAN del destinatario]?message=[asunto]&amount=[%1$s:X.Y]"],"The maximum amount for a wire transfer is %1$s":["El monto m\xE1ximo para una transferencia bancaria es %1$s"],Cost:["Costo"],Send:["Enviar"],'Only "x-taler-bank" target are supported':['Solo se soportan destinos "x-taler-bank"'],'Only this host is allowed. Use "%1$s"':['Solo este host est\xE1 permitido. Us\xE1 "%1$s"'],"Account name is missing":["Falta el nombre de la cuenta"],'Only "IBAN" target are supported':['Solo se soportan destinos "IBAN"'],'Missing "amount" parameter to specify the amount to be transferred':['Falta el par\xE1metro "amount" para indicar el monto a transferir'],'The "amount" parameter is not valid':['El par\xE1metro "amount" no es v\xE1lido'],'"message" parameters to specify a reference text for the transfer are missing':['Falta el par\xE1metro "message" para indicar un texto de referencia en la transferencia'],'The only currency allowed is "%1$s"':['La \xFAnica moneda permitida es "%1$s"'],"You cannot transfer an amount of zero.":["No pod\xE9s transferir un monto de cero."],"The balance is not sufficient":["El saldo no es suficiente"],"Please enter a longer subject":["Por favor ingres\xE1 un asunto m\xE1s largo"],"Show withdrawal confirmation":["Mostrar confirmaci\xF3n de extracci\xF3n"],"Withdraw without setting amount":["Retirar sin especificar monto"],"Hide demo hint.":["Ocultar la sugerencia de demo."],"Show install wallet first":["Mostrar primero la instalaci\xF3n de la billetera"],"Currently, the bank is not accepting new registrations!":["\xA1El banco no est\xE1 aceptando nuevos registros en este momento!"],"The name is missing":["Falta el nombre"],"Missing username":["Falta el nombre de usuario"],"Missing password":["Falta la contrase\xF1a"],"The password should be longer than 8 letters":["La contrase\xF1a debe tener m\xE1s de 8 caracteres"],"The passwords do not match":["Las contrase\xF1as no coinciden"],"register new account":["Registrar nueva cuenta"],"Server replied with invalid phone or email.":["El servidor respondi\xF3 con un tel\xE9fono o correo electr\xF3nico inv\xE1lido."],"You are not authorised to create this account.":["No est\xE1s autorizado a crear esta cuenta."],"Registration is disabled because the bank ran out of bonus credit.":["El registro est\xE1 deshabilitado porque el banco se qued\xF3 sin cr\xE9dito de bonificaci\xF3n."],"That username can't be used because is reserved.":["Ese nombre de usuario no puede usarse porque est\xE1 reservado."],"That username is already taken.":["Ese nombre de usuario ya est\xE1 en uso."],"That account ID is already taken.":["Ese ID de cuenta ya est\xE1 en uso."],"No information for the selected authentication channel.":["No hay informaci\xF3n para el canal de autenticaci\xF3n seleccionado."],"Authentication channel is not supported.":["El canal de autenticaci\xF3n no est\xE1 soportado."],"Only an administrator is allowed to set the debt limit.":["Solo un administrador puede establecer el l\xEDmite de deuda."],"Only the administrator can change the conversion rate.":["Solo el administrador puede cambiar la tasa de conversi\xF3n."],"The conversion rate class doesn't exist.":["La clase de tasa de conversi\xF3n no existe."],"Only admin can create accounts with second factor authentication.":["Solo el administrador puede crear cuentas con autenticaci\xF3n de segundo factor."],"The password is too short. Can't have less than 8 characters.":["La contrase\xF1a es demasiado corta. Debe tener al menos 8 caracteres."],"The password is too long. Can't have more than 64 characters.":["La contrase\xF1a es demasiado larga. No puede tener m\xE1s de 64 caracteres."],"Account registration":["Registro de cuenta"],"Login username":["Nombre de usuario"],"account identification to login":["Identificacion de cuenta para acceder"],Password:["Contrase\xF1a"],"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers":["Us\xE1 una contrase\xF1a segura: m\xEDnimo 8 caracteres, no uses informaci\xF3n p\xFAblica sobre vos (nombre, fecha de nacimiento, tel\xE9fono, etc.) y combin\xE1 min\xFAsculas, may\xFAsculas, s\xEDmbolos y n\xFAmeros"],"Repeat password":["Repetir contrase\xF1a"],"Same password":["Misma contrase\xF1a"],"Full name":["Nombre completo"],Register:["Registrarse"],"Create a random temporary user":["Crear un usuario temporal aleatorio"],logout:[""],login:["Iniciar sesi\xF3n"],"The account has no rights to login.":["La cuenta no tiene permisos para iniciar sesi\xF3n."],"The account is locked and cannot login. Contact administrator.":["Esta cuenta est\xE1 bloqueada y no puede iniciar sesi\xF3n. Contact\xE1 al administrador."],'Wrong credentials for "%1$s"':['Credenciales incorrectas para "%1$s"'],"Account login.":["Inicio de sesi\xF3n."],"Session expired":["La sesi\xF3n expir\xF3"],Username:["Usuario"],identification:["Identificaci\xF3n"],"Password of the account":["Contrase\xF1a de la cuenta"],Forget:["Olvid\xE9 mi contrase\xF1a"],"Log in":["Ingresar"],"Transactions history":["Historial de transacciones"],"No transactions yet.":["A\xFAn no hay transacciones."],"You can make a transfer or a withdrawal to your wallet.":["Pod\xE9s hacer una transferencia o un retiro a tu billetera."],Date:["Fecha"],Counterpart:["Contraparte"],sent:["enviado"],received:["recibido"],"Invalid value":["Valor inv\xE1lido"],to:["hacia"],from:["desde"],"First page":["Primera p\xE1gina"],Next:["Siguiente"],"confirm withdrawal":["Confirm\xE1 la extracci\xF3n."],cambiar:[""],"abort withdrawal":["Interrumpir la extracci\xF3n."],"The withdrawal has been aborted previously and can't be confirmed":["La extracci\xF3n fue cancelada anteriormente y no puede confirmarse"],"The withdrawal operation can't be confirmed before a wallet accepted the transaction.":["La operaci\xF3n de extracci\xF3n no puede confirmarse antes de que una billetera acepte la transacci\xF3n."],"The operation ID is invalid.":["El ID de operaci\xF3n es inv\xE1lido."],"The operation was not found.":["La operaci\xF3n no fue encontrada."],"The starting withdrawal amount and the confirmation amount differs.":["El monto inicial de la extracci\xF3n y el monto de confirmaci\xF3n son distintos."],"The bank requires a bank account which has not been specified yet.":["El banco requiere una cuenta bancaria que a\xFAn no fue especificada."],"Bad request":["Pedido incorrecto"],"The withdrawal operation has been aborted.":["La operaci\xF3n de extracci\xF3n fue cancelada."],"The withdrawal operation has been confirmed previously and can\u2019t be aborted.":["La operaci\xF3n de extracci\xF3n ya fue confirmada previamente y no puede cancelarse."],"Complete withdrawal.":["Completar la extracci\xF3n."],"Confirm the withdrawal operation":["Confirm\xE1 la operaci\xF3n de extracci\xF3n"],"Wire transfer details":["Datos de la transferencia bancaria"],"Payment Service Provider's account number":["N\xFAmero de cuenta del Proveedor de Servicios de Pago"],"Payment Service Provider's name":["Nombre del Proveedor de Servicios de Pago"],"Payment Service Provider's account bank hostname":["Nombre del host bancario del Proveedor de Servicios de Pago"],"Payment Service Provider's account id":["ID de cuenta del Proveedor de Servicios de Pago"],"Payment Service Provider's account address":["Direcci\xF3n de cuenta del Proveedor de Servicios de Pago"],"Payment Service Provider's account cyclos hostname":["Nombre del host bancario del Proveedor de Servicios de Pago"],"No amount has yet been determined.":["A\xFAn no se determin\xF3 el monto."],Transfer:["Transferencia"],"Authentication required":["Se requiere autenticaci\xF3n"],"This operation was created with another username":["Esta operaci\xF3n fue creada con otro nombre de usuario"],'You are currently logged in with user "%1$s" and the operation was made with user "%2$s"':['Actualmente est\xE1s conectado con el usuario "%1$s" pero la operaci\xF3n fue realizada con el usuario "%2$s"'],"The reserve operation has been confirmed previously and can't be aborted":["La operaci\xF3n de reserva ya fue confirmada previamente y no puede cancelarse"],"Wire transfer completed!":["\xA1Transferencia bancaria completada!"],"Confirm withdrawal.":["Confirm\xE1 la extracci\xF3n."],"Unauthorized to make the operation, maybe the session has expired or the password changed.":["No est\xE1s autorizado para realizar la operaci\xF3n, quiz\xE1s la sesi\xF3n expir\xF3 o la contrase\xF1a cambi\xF3."],"The operation was rejected due to insufficient funds.":["La operaci\xF3n fue rechazada por fondos insuficientes."],"Withdrawal confirmed":["Extracci\xF3n confirmada"],"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.":["Se inici\xF3 la transferencia bancaria al Proveedor de Servicios de Pago. En breve vas a recibir el monto solicitado en tu billetera Taler."],"Do not show this again":["No mostrar de nuevo"],"If you have a Taler wallet installed on this device":["Si ten\xE9s una billetera Taler instalada en este dispositivo"],"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions":["Tu billetera va a mostrar los detalles de la transacci\xF3n, incluyendo las comisiones (si corresponde). Si todav\xEDa no ten\xE9s una, segu\xED las instrucciones"],"on this page":["en esta p\xE1gina"],Withdraw:["Retirar"],"In case you have a Taler wallet on another device":["Si ten\xE9s la billetera Taler en otro dispositivo"],"Scan the QR below to start the withdrawal.":["Escane\xE1 el c\xF3digo QR de abajo para iniciar la extracci\xF3n."],"create withdrawal":["Completar la extracci\xF3n."],"The server replied with an invalid taler://withdraw URI":["El servidor respondi\xF3 con un URI taler://withdraw inv\xE1lido"],"Withdraw URI: %1$s":["URI de extracci\xF3n: %1$s"],"The operation was rejected due to insufficient funds":["La operaci\xF3n fue rechazada por fondos insuficientes"],"Current balance is %1$s":["El saldo actual es %1$s"],"You can withdraw up to %1$s":["Pod\xE9s retirar hasta %1$s"],Continue:["Continuar"],"Use your Taler wallet":["Us\xE1 tu billetera Taler"],"After using your wallet you will need to authorize or cancel the operation on this site.":["Despu\xE9s de usar tu billetera, vas a necesitar autorizar o cancelar la operaci\xF3n en este sitio."],"You need a Taler wallet":["Necesit\xE1s una billetera Taler"],"If you don't have one yet you can follow the instruction in":["Si todav\xEDa no ten\xE9s una, pod\xE9s seguir las instrucciones en"],"this page":["esta p\xE1gina"],"Send money":["Enviar dinero"],"to a Taler wallet":["a una billetera Taler"],"Withdraw digital money into your mobile wallet or browser extension":["Retir\xE1 dinero digital a tu billetera m\xF3vil o extensi\xF3n del navegador"],"to another bank account":["a otra cuenta bancaria"],"Make a wire transfer to an account with known bank account number.":["Realiz\xE1 una transferencia bancaria a una cuenta con n\xFAmero de cuenta conocido."],"This is a demo":["Esto es una demostraci\xF3n"],"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .":["Esta parte de la demostraci\xF3n muestra c\xF3mo funcionar\xEDa un banco que soporta Taler directamente. Adem\xE1s de usar tu propia cuenta, tambi\xE9n pod\xE9s ver el historial de transacciones de algunas %1$s."],"Here you will be able to see how a bank that supports Taler directly would work.":["Ac\xE1 vas a poder ver c\xF3mo funcionar\xEDa un banco que soporta Taler directamente."],"Internal error, please report. There should be more information in the console.":["Error interno, por favor reportalo. Deber\xEDa haber m\xE1s informaci\xF3n en la consola."],"Internal error, please report.":["Error interno, por favor reportalo."],Preferences:["Preferencias"],"Show debug information":["Mostrar informaci\xF3n de depuraci\xF3n."],Welcome:["Bienvenido/a"],"Welcome, %1$s":["Bienvenido/a, %1$s"],"No enough permission to access the conversion rate list.":["No ten\xE9s permisos suficientes para acceder a la lista de tasas de conversi\xF3n."],"Conversion list not found. Maybe conversion rate is not supported.":["Lista de conversiones no encontrada. Puede que la tasa de conversi\xF3n no est\xE9 soportada."],"Conversion list not implemented.":["La lista de conversiones no est\xE1 implementada."],"Conversion rate classes":["Clases de tasa de conversi\xF3n"],"Create conversion rate class":["Crear clase de tasa de conversi\xF3n"],"No conversion rate class":["Sin clases de tasa de conversi\xF3n"],Name:["Nombre"],Description:["Descripci\xF3n"],Cashin:["Ingreso"],"min:":["m\xEDn:"],"fee:":["comisi\xF3n:"],"Select a section":["Seleccion\xE1 una secci\xF3n"],Details:["Detalles"],Delete:["Eliminar"],Credentials:["Credenciales"],Cashouts:["Egresos"],Conversion:["Conversi\xF3n"],"only admin can setup conversion":["Solo el administrador puede configurar la conversi\xF3n"],"calculate cashout fee":["Crear tasa de egreso."],"update conversion rate":["Actualizar tasa de conversi\xF3n"],"Wrong credentials":["Credenciales incorrectas"],"Conversion is disabled":["La conversi\xF3n est\xE1 deshabilitada"],"Config cashout":["Configurar egreso"],"Config cashin":["Configurar ingreso"],"Bad ratios":["Tasas incorrectas"],"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.":["Una de las tasas debe ser mayor o igual a 1 y la otra debe ser menor o igual a 1."],"Initial amount":["Monto inicial"],"Use it to test how the conversion will affect the amount.":["Usalo para probar c\xF3mo la conversi\xF3n afectar\xE1 el monto."],"Sending to this bank":["Enviando a este banco"],Converted:["Convertido"],"Cashin after fee":["Ingreso despu\xE9s de la comisi\xF3n"],"Sending from this bank":["Enviando desde este banco"],"Cashout after fee":["Egreso despu\xE9s de la comisi\xF3n"],"Bad configuration":["Configuraci\xF3n incorrecta"],"This configuration allows users to cash out more of what has been cashed in.":["Esta configuraci\xF3n permite a los usuarios retirar m\xE1s de lo que ingresaron."],Update:["Actualizar"],Rnvalid:["Inv\xE1lido"],"Must be > 0":["Debe ser mayor que 0"],"Minimum amount":["Monto m\xEDnimo"],"Only cashout operation above this threshold will be allowed.":["Solo se permitir\xE1n operaciones de egreso por encima de este umbral."],Ratio:["Tasa"],"Conversion ratio between currencies":["Tasa de conversi\xF3n entre monedas"],"Example conversion":["Ejemplo de conversi\xF3n"],"1 %1$s will be converted into %2$s %3$s":["1 %1$s se convertir\xE1 en %2$s %3$s"],"Tiny amount":["Monto m\xEDnimo de redondeo"],"Rounding mode":["Modo de redondeo"],Zero:["Hacia cero"],"Amount will be round below to the largest possible value smaller than the input.":["El monto se redondear\xE1 hacia abajo al mayor valor posible menor que el ingresado."],Up:["Hacia arriba"],"Amount will be round up to the smallest possible value larger than the input.":["El monto se redondear\xE1 hacia arriba al menor valor posible mayor que el ingresado."],Nearest:["Al m\xE1s cercano"],"Amount will be round to the closest possible value.":["El monto se redondear\xE1 al valor m\xE1s cercano posible."],'If none specified the fallback value is "%1$s ".':['Si no se especifica ninguno, el valor por defecto es "%1$s".'],Examples:["Ejemplos"],"Rounding an amount of 1.24 with rounding value 0.1":["Redondeo de un monto de 1,24 con valor de redondeo 0,1"],"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.":["Con un valor de redondeo de 0,1, los valores m\xE1s cercanos a 1,24 son: 1,1; 1,2; 1,3; 1,4."],'With the "zero" mode the value will be rounded to 1.2':['Con el modo "hacia cero" el valor se redondear\xE1 a 1,2'],'With the "nearest" mode the value will be rounded to 1.2':['Con el modo "al m\xE1s cercano" el valor se redondear\xE1 a 1,2'],'With the "up" mode the value will be rounded to 1.3':['Con el modo "hacia arriba" el valor se redondear\xE1 a 1,3'],"Rounding an amount of 1.26 with rounding value 0.1":["Redondeo de un monto de 1,26 con valor de redondeo 0,1"],'With the "nearest" mode the value will be rounded to 1.3':['Con el modo "al m\xE1s cercano" el valor se redondear\xE1 a 1,3'],"Rounding an amount of 1.24 with rounding value 0.3":["Redondeo de un monto de 1,24 con valor de redondeo 0,3"],"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.":["Con un valor de redondeo de 0,3, los valores m\xE1s cercanos a 1,24 son: 0,9; 1,2; 1,5; 1,8."],'With the "up" mode the value will be rounded to 1.5':['Con el modo "hacia arriba" el valor se redondear\xE1 a 1,5'],"Rounding an amount of 1.26 with rounding value 0.3":["Redondeo de un monto de 1,26 con valor de redondeo 0,3"],"Amount to be deducted before amount is credited.":["Monto a deducir antes de acreditar el importe."],"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":["La conversi\xF3n debe estar habilitada en la configuraci\xF3n, y la tasa de conversi\xF3n debe estar inicializada con comisi\xF3n(es), tasas y modo de redondeo."],"delete conversion rate class":["Eliminar tasa de conversi\xF3n"],Unauthorized:["No autorizado"],Forbidden:["Prohibido"],NotFound:["No encontrado"],NotImplemented:["No implementado"],"update conversion rate class":["Crear clase de tasa de conversi\xF3n"],"Not Found":["No encontrado"],"Not implemented":["No implementado"],"The name of the conversion is already used.":["El nombre de la conversi\xF3n ya est\xE1 en uso."],"Conversion rate class":["Clase de tasa de conversi\xF3n"],Accounts:["Cuentas"],Test:["Probar"],Users:["Usuarios"],"Can't remove the conversion rate class":["No se puede eliminar la clase de tasa de conversi\xF3n"],"There are some user associated to this class. You need to remove them first.":["Hay usuarios asociados a esta clase. Primero ten\xE9s que eliminarlos."],"You are going to remove the conversion rate class":["Est\xE1s por eliminar la clase de tasa de conversi\xF3n"],"This step can't be undone.":["Este paso no puede deshacerse."],Filters:["Filtros"],"Show from other classes":["Mostrar de otras clases"],Account:["Cuenta"],"Group ID":["ID de grupo"],"No users in this conversion rate class":["No hay usuarios en esta clase de tasa de conversi\xF3n"],Class:["Clase"],Action:["Acci\xF3n"],Remove:["Eliminar"],Add:["Agregar"],"Conversion rate name":["Nombre de la tasa de conversi\xF3n"],"Short description of the class":["Descripci\xF3n breve de la clase"],"create conversion rate class":["Crear clase de tasa de conversi\xF3n"],"Conversion rate class created.":["Clase de tasa de conversi\xF3n creada."],"The rights to change the account are not sufficient":["Los permisos para modificar la cuenta no son suficientes"],"New conversion rate class":["Nueva clase de tasa de conversi\xF3n"],Create:["Crear"],"History of public accounts":["Historial de cuentas p\xFAblicas"],"Make a wire transfer":["Realizar una transferencia bancaria"],"Scan the QR code below to start the withdrawal.":["Escane\xE1 el c\xF3digo QR de abajo para iniciar la extracci\xF3n."],"Operation aborted":["Operaci\xF3n cancelada"],"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.":["La transferencia bancaria a la cuenta del Proveedor de Servicios de Pago fue cancelada desde otro lugar; tu saldo no fue afectado."],"Go to your wallet now":["Ir a tu billetera ahora"],"The operation is marked as selected, but a process during the withdrawal failed":["La operaci\xF3n est\xE1 marcada como seleccionada, pero un proceso durante la extracci\xF3n fall\xF3"],"A withdrawal reserve ID was not found and no account has been selected.":["No se encontr\xF3 un ID de reserva de extracci\xF3n y no se seleccion\xF3 ninguna cuenta."],"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.":["Hay un ID de reserva de extracci\xF3n pero no se seleccion\xF3 ninguna cuenta o la cuenta seleccionada es inv\xE1lida."],"The account was selected, but no withdrawal reserve ID was found.":["La cuenta fue seleccionada, pero no se encontr\xF3 el ID de reserva de extracci\xF3n."],"Operation not found":["Operaci\xF3n no encontrada"],"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.":["Este proceso no es conocido por el servidor. El ID de proceso es incorrecto o el servidor elimin\xF3 la informaci\xF3n del proceso antes de que llegara aqu\xED."],"Continue to dashboard":["Ir al panel principal"],"The Withdrawal URI is not valid":["El URI de extracci\xF3n no es v\xE1lido"],"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.":["El egreso debe habilitarse en la configuraci\xF3n y la tasa de conversi\xF3n debe estar inicializada con comisi\xF3n, tasa y modo de redondeo."],"Latest cashouts":["\xDAltimos egresos"],Created:["Creado"],"Total debit":["D\xE9bito total"],"Total credit":["Cr\xE9dito total"],"Cashout for account %1$s":["Egreso para la cuenta %1$s"],"Invalid email format":["Formato de email inv\xE1lido"],"Should start with +":["Debe comenzar con +"],"A phone number consists of numbers only":["Un n\xFAmero de tel\xE9fono solo puede contener n\xFAmeros"],"Account ID for authentication":["ID de cuenta para autenticaci\xF3n"],"Name of the account holder":["Nombre del titular de la cuenta"],"Internal account":["Cuenta interna"],"If this field is empty, a random account ID will be assigned":["Si este campo est\xE1 vac\xEDo, se asignar\xE1 un ID de cuenta aleatorio"],"You can copy and share this IBAN number in order to receive wire transfers to your bank account":["Pod\xE9s copiar y compartir este n\xFAmero IBAN para recibir transferencias bancarias en tu cuenta"],Email:["Correo electr\xF3nico"],"To be used when second factor authentication is enabled":["Se usa cuando la autenticaci\xF3n de segundo factor est\xE1 habilitada"],Phone:["Tel\xE9fono"],"Enable second factor authentication":["Habilitar autenticaci\xF3n de segundo factor"],"Using email":["Usando correo electr\xF3nico"],"Add an email in your profile to enable this option":["Agreg\xE1 un correo electr\xF3nico en tu perfil para habilitar esta opci\xF3n"],"Using SMS":["Usando SMS"],"Add a phone number in your profile to enable this option":["Agreg\xE1 un n\xFAmero de tel\xE9fono en tu perfil para habilitar esta opci\xF3n"],"Cashout account":["Cuenta de egreso"],"External account number where the money is going to be sent when doing cashouts":["N\xFAmero de cuenta externa a la que se enviar\xE1 el dinero al realizar egresos"],"Max debt":["Deuda m\xE1xima"],"How much the balance can go below zero.":["Cu\xE1nto puede quedar el saldo por debajo de cero."],"Is this account public?":["\xBFEsta cuenta es p\xFAblica?"],"Public accounts have their balance publicly accessible":["Las cuentas p\xFAblicas tienen su saldo accesible para todos"],"Does this account belong to a Payment Service Provider?":["\xBFEsta cuenta pertenece a un Proveedor de Servicios de Pago?"],"update account":["Actualizar cuenta"],"Account updated":["Cuenta actualizada"],"The username was not found":["El nombre de usuario no fue encontrado"],"You can't change the legal name, please contact the your account administrator.":["No pod\xE9s cambiar el nombre legal; por favor contact\xE1 al administrador de tu cuenta."],"You can't change the debt limit, please contact the your account administrator.":["No pod\xE9s cambiar el l\xEDmite de deuda; por favor contact\xE1 al administrador de tu cuenta."],"You can't change the cashout address, please contact the your account administrator.":["No pod\xE9s cambiar la direcci\xF3n de egreso; por favor contact\xE1 al administrador de tu cuenta."],"Update account information.":["Actualizar informaci\xF3n de la cuenta."],'Account "%1$s"':['Cuenta "%1$s"'],Removed:["Eliminada"],"This account can't be used.":["Esta cuenta no puede usarse."],"Change details":["Cambiar datos"],"Merchant integration":["Integraci\xF3n con comercio"],'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.':['Us\xE1 esta informaci\xF3n para vincular tu cuenta de Taler Merchant Backoffice con la cuenta bancaria actual. Pod\xE9s comenzar copiando los valores, luego ir a tu proveedor de backoffice de comercio, iniciar sesi\xF3n y buscar el bot\xF3n "importar" en la secci\xF3n "cuenta bancaria".'],"Account type":["Tipo de cuenta"],"Method to use for wire transfer.":["M\xE9todo a usar para la transferencia bancaria."],IBAN:["IBAN"],"International Bank Account Number.":["N\xFAmero de Cuenta Bancaria Internacional."],"Account name":["Nombre de la cuenta"],"Bank host where the service is located.":["Host bancario donde se encuentra el servicio."],"Bank account identifier for wire transfers.":["Identificador de cuenta bancaria para transferencias."],Address:["Direcci\xF3n"],"Owner's name":["Nombre del titular"],"Legal name of the person holding the account.":["Nombre legal de la persona titular de la cuenta."],"Account info URL":["URL de informaci\xF3n de la cuenta"],"From where the merchant can download information about incoming wire transfers to this account.":["Desde donde el comercio puede descargar informaci\xF3n sobre las transferencias bancarias entrantes a esta cuenta."],"Repeated password doesn't match":["La contrase\xF1a repetida no coincide"],"update password":["Actualizar contrase\xF1a"],"Password changed":["Contrase\xF1a cambiada"],"Not authorized to change the password, maybe the session is invalid.":["No est\xE1s autorizado a cambiar la contrase\xF1a, quiz\xE1s la sesi\xF3n es inv\xE1lida."],"You need to provide the old password. If you don't have it contact your account administrator.":["Necesit\xE1s ingresar la contrase\xF1a anterior. Si no la ten\xE9s, contact\xE1 al administrador de tu cuenta."],"Your current password doesn't match, can't change to a new password.":["Tu contrase\xF1a actual no coincide, no se puede cambiar a una nueva."],"You don't have the rights to change the password.":["No ten\xE9s permisos para cambiar la contrase\xF1a."],"Update account password.":["Actualizar contrase\xF1a de la cuenta."],"Update password":["Actualizar contrase\xF1a"],"Current password":["Contrase\xF1a actual"],"Your current password, for security":["Tu contrase\xF1a actual, por seguridad"],"New password":["Nueva contrase\xF1a"],"Type it again":["Escribila de nuevo"],"Repeat the same password":["Repet\xED la misma contrase\xF1a"],Change:["Cambiar"],"Create account":["Crear cuenta"],Actions:["Acciones"],Unknown:["Desconocido"],"Change password":["Cambiar contrase\xF1a"],"Querying for the current stats failed":["Fall\xF3 la consulta de estad\xEDsticas actuales"],"The request parameters are wrong":["Los par\xE1metros del pedido son incorrectos"],"The user is unauthorized":["El usuario no est\xE1 autorizado"],"Querying for the previous stats failed":["Fall\xF3 la consulta de estad\xEDsticas anteriores"],"Transaction volume report":["Reporte de volumen de transacciones"],"Last hour":["\xDAltima hora"],"Previous day":["D\xEDa anterior"],"Last month":["\xDAltimo mes"],"Last year":["\xDAltimo a\xF1o"],"Last Year":["\xDAltimo a\xF1o"],"Trading volume from %1$s to %2$s":["Volumen de operaciones del %1$s al %2$s"],"Transferred from an external account to an account in this bank.":["Transferido desde una cuenta externa a una cuenta en este banco."],"Transferred from an account in this bank to an external account.":["Transferido desde una cuenta de este banco a una cuenta externa."],Payin:["Env\xEDos de dinero"],"Transferred from an account to a Taler exchange.":["Transferido desde una cuenta a un exchange Taler."],Payout:["Recibos de dinero"],"Transferred from a Taler exchange to another account.":["Transferido desde un exchange Taler a otra cuenta."],"Download stats as CSV":["Descargar estad\xEDsticas en CSV"],previous:["anterior"],"Decreased by":["Disminuy\xF3 en"],"Increased by":["Aument\xF3 en"],"create account":["Crear cuenta"],'Account created with password "%1$s".':['Cuenta creada con la contrase\xF1a "%1$s".'],"Server replied that phone or email is invalid":["El servidor respondi\xF3 que el tel\xE9fono o el correo electr\xF3nico son inv\xE1lidos"],"The rights to perform the operation are not sufficient":["Los permisos para ejecutar la operaci\xF3n no son suficientes"],"Account username is already taken":["El nombre de usuario de la cuenta ya est\xE1 en uso"],"Account ID is already taken":["El ID de cuenta ya est\xE1 en uso"],"Bank ran out of bonus credit.":["El banco se qued\xF3 sin cr\xE9dito de bonificaci\xF3n."],"Account username can't be used because is reserved":["El nombre de usuario de la cuenta no puede usarse porque est\xE1 reservado"],"Can't create accounts":["No se pueden crear cuentas"],"Only system admin can create accounts.":["Solo el administrador del sistema puede crear cuentas."],"New bank account":["Nueva cuenta bancaria"],"download statistics":["Descargar estad\xEDsticas"],"only admin can download stats":["Solo el administrador puede descargar estad\xEDsticas"],"Download bank stats":["Descargar estad\xEDsticas del banco"],"Include hour metric":["Incluir m\xE9trica por hora"],"Include day metric":["Incluir m\xE9trica diaria"],"Include month metric":["Incluir m\xE9trica mensual"],"Include year metric":["Incluir m\xE9trica anual"],"Include table header":["Incluir encabezado de tabla"],"Add previous metric for compare":["Agregar m\xE9trica anterior para comparar"],"Fail on first error":["Detener en el primer error"],Download:["Descargar"],"downloading... %1$s":["descargando... %1$s"],"Download completed":["Descarga completada"],"Click here to save the file in your computer.":["Hac\xE9 clic ac\xE1 para guardar el archivo en tu computadora."],"there was an error reading the balance":["hubo un error al leer el saldo"],"Can't delete the account":["No se puede eliminar la cuenta"],"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.":["La cuenta no puede eliminarse mientras tenga saldo. Primero asegurate de que el titular realice un egreso completo."],"Name doesn't match":["El nombre no coincide"],"delete account":["Eliminar cuenta"],"Account removed":["Cuenta eliminada"],"No enough permission to delete the account.":["No ten\xE9s permisos suficientes para eliminar la cuenta."],"The username was not found.":["El nombre de usuario no fue encontrado."],"Can't delete a reserved username.":["No se puede eliminar un nombre de usuario reservado."],"Can't delete an account with balance different than zero.":["No se puede eliminar una cuenta con saldo distinto de cero."],"Remove account.":["Eliminar cuenta."],"You are going to remove the account":["Est\xE1s por eliminar la cuenta"],'Deleting account "%1$s"':['Eliminando la cuenta "%1$s"'],Verification:["Verificaci\xF3n"],"Enter the account name that is going to be deleted":["Ingres\xE1 el nombre de la cuenta que va a ser eliminada"],"Cashout id should be a number":["El ID de egreso debe ser un n\xFAmero"],"This cashout not found. Maybe already aborted.":["Este egreso no fue encontrado. Quiz\xE1s ya fue cancelado."],"Cashout detail":["Detalle del egreso"],Debited:["Debitado"],Transferred:["Transferido"],"You have no permission to this account.":["No ten\xE9s permisos para acceder a esta cuenta."],"This account is locked. If you have a active session you can change the password or contact the administrator.":["Esta cuenta est\xE1 bloqueada. Si ten\xE9s una sesi\xF3n activa pod\xE9s cambiar la contrase\xF1a o contactar al administrador."],"New web session":["Nueva sesi\xF3n web"],"Welcome to %1$s!":["\xA1Hola %1$s!"]}},domain:"messages",plural_forms:"nplurals=2; plural=n != 1;",lang:"es_AR",completeness:99};Nn.de={locale_data:{messages:{"":{domain:"messages",plural_forms:"nplurals=2; plural=n != 1;",lang:"de"},"An IBAN consists of capital letters and numbers only":["Eine IBAN besteht nur aus Gro\xDFbuchstaben und Zahlen"],"IBAN numbers have more that 4 digits":["Eine IBAN besteht normalerweise aus mehr als 4 Ziffern"],"IBAN numbers have less that 34 digits":["Eine IBAN besteht normalerweise aus weniger als 34 Ziffern"],"IBAN country code not found":["Der IBAN-L\xE4ndercode wurde nicht gefunden"],"IBAN number is not valid, checksum is wrong":["Die IBAN-Nummer ist ung\xFCltig, die Pr\xFCfsumme ist falsch"],"Use letters, numbers or any of these characters: - . _ ~":["Verwenden Sie nur Buchstaben und Zahlen sowie als Sonderzeichen - . _ ~"],Required:["Erforderlich"],"confirm MFA challenge":[""],"Unknown challenge.":[""],"Failed to validate the verification code.":[""],"Too many challenges are active right now, you must wait or confirm current challenges.":[""],"Wrong authentication number.":["Falsche Authentifizierung."],"Expired challenge.":[""],"Submit the transmitted code number.":[""],"The verification code sent to the email address starting with %1$s":[""],"The verification code sent to the phone number ending with %1$s":[""],Code:[""],"Username of the account":["Nutzername des Kontos"],"It will expired at %1$s":["Ende der G\xFCltigkeit %1$s"],"The challenge is expired and can't be solved but you can go back and create a new challenge.":["Das Pr\xFCfverfahren zur gesicherten Anmeldung ist abgelaufen und kann nicht mehr verwendet werden, es ist jedoch m\xF6glich, ein neues Pr\xFCfverfahren anzufordern (bitte gehen Sie im Browser einen Schritt zur\xFCck)."],Back:["Zur\xFCck"],Verify:["Pr\xFCfen"],"send MFA challenge":[""],"Failed to send the verification code.":["Das Versenden des Best\xE4tigungscodes hat nicht funktioniert."],"The request was valid, but the server is refusing action.":["Die Anfrage war g\xFCltig, aber der Server verweigert die Bearbeitung."],"The backend is not aware of the specified MFA challenge.":["Dieser Anwendung ist die angegebene Multi-Faktor-\xDCberpr\xFCfung nicht bekannt."],"It is too early to request another transmission of the challenge.":["Es muss noch gewartet werden, um eine weitere \xDCbertragung des \xDCberpr\xFCfungscodes zu verlangen."],"Code transmission failed.":["Die Code-\xDCbertragung ist fehlgeschlagen."],"select challenge":[""],"Multi-factor authentication required":["Authentifizierung erforderlich"],"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.":["Dieser Vorgang wird durch eine Zwei-Faktor-Authentifizierung gesch\xFCtzt. Um ihn abschlie\xDFen zu k\xF6nnen, m\xFCssen wir Ihre Identit\xE4t durch das von Ihnen gew\xE4hlte Authentifizierungsverfahren \xFCberpr\xFCfen."],"The next challenge needs to be completed to confirm the operation.":["Es besteht keine ausreichende Berechtigung, um den Vorgang abzuschlie\xDFen."],"All the next challenges need to be completed to confirm the operation.":[""],"One of the next challenges need to be completed to confirm the operation.":[""],'To an phone ending with "%1$s"':[""],'To an email starting with " %1$s"':[""],"I have a code":["Ich habe bereits einen g\xFCltigen Best\xE4tigungscode"],"Send me a message":["Best\xE4tigungscode zusenden"],"You have to wait until %1$s to send a new code.":["Sie m\xFCssen bis %1$s warten, damit ein neuer Best\xE4tigungscode gesendet werden kann."],Cancel:["Abbrechen"],Complete:["Abschliessen"],"Unable to create a cashout":["Es war nicht m\xF6glich, eine Einzahlung auszuf\xFChren"],"The bank configuration does not support cashout operations.":["Die Konfiguration der Bankverbindung unterst\xFCtzt keine Einzahlungen."],Close:["Schlie\xDFen"],"Cashout is disabled":["Einzahlungen aufs Konto sind deaktiviert"],"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":["In den Einstellungen m\xFCssen die Einzahlungen aufs Konto aktiviert und der Umrechnungskurs einschlie\xDFlich aller Geb\xFChren, Kurse und einem Rundungsverfahren initialisiert worden sein."],"calculate conversion fee":["Beispiel einer W\xE4hrungsumrechnung"],"The server didn't understand the request.":["Der Server unterst\xFCtzt nicht die aktuell gew\xE4hlte TAN-Methode."],"The amount is too small":["Das Passwort ist zu lang."],"Conversion is not implemented.":["Umrechnungen sind deaktiviert"],"At least debit or credit needs to be provided":[""],"The amount is malfored":["Diese Konto-ID ist bereits vergeben."],"The currency is not supported":["Das gew\xE4hlte Authentifizierungsverfahren wird nicht unterst\xFCtzt."],Invalid:["Ung\xFCltig"],"Amount needs to be higher":["Es muss ein h\xF6herer Betrag gew\xE4hlt werden"],"Balance is not enough":["Das Guthaben reicht nicht aus"],"It is not possible to cashout less than %1$s: %2$s":["Es ist nicht m\xF6glich, einen geringeren Betrag als %1$s: %2$s einzuzahlen"],"The total transfer to the destination will be zero":["Der zu \xFCbertragende Gesamtbetrag betr\xE4gt Null"],"create cashout":["Konto anlegen"],"Cashout created":["Die Einzahlung wurde erstellt"],"Second factor authentication required.":["Es ist die Eingabe einer weiteren Information erforderlich (zweiter Faktor der Anmeldeberechtigung)."],"Account not found":["Konto nicht gefunden"],"Duplicated request detected, check if the operation succeeded or try again.":["Eine gleichartige Anfrage wurde bereits gestellt, bitte \xFCberpr\xFCfen Sie den Vorgang oder versuchen Sie es erneut."],"The conversion rate was applied incorrectly":["Der Umrechnungskurs wurde fehlerhaft angewendet"],"The account does not have sufficient funds":["Das Konto verf\xFCgt \xFCber kein ausreichendes Guthaben"],"Missing cashout URI in the profile":["Die Einzahlungs-URI dieses Profils fehlt"],"The amount is below the minimum amount permitted.":["Der Betrag ist unterhalb des zul\xE4ssigen Minimums."],"Sending the confirmation message failed, retry later or contact the administrator.":["Der Versand der Best\xE4tigung ist fehlgeschlagen, versuchen Sie den Vorgang bittesp\xE4ter erneut oder kontaktieren Sie den Administrator."],"The server doesn't support the current TAN channel.":["Der Server unterst\xFCtzt nicht die aktuell gew\xE4hlte TAN-Methode."],"Create cashout.":["Konto anlegen"],Cashout:["Auszahlung (Cashout)"],"Conversion rate":["Umrechnungskurs"],Balance:["Salden"],Fee:["Geb\xFChr"],"To account":["Auf Bankkonto"],"Legal name":["Offizieller Name des Empf\xE4ngers (wirtschaftlich Berechtigter des empfangenden Bankkontos)"],"If this name doesn't match the account holder's name, your transaction may fail.":["Falls dieser Name nicht mit dem des wirtschaftlich Berechtigten des Bankkontos \xFCbereinstimmt, k\xF6nnte Ihre \xDCberweisung fehlschlagen."],"Unable to cashout":["Es war nicht m\xF6glich, eine Einzahlung auszuf\xFChren"],"Before being able to cashout to a bank account, you need to complete your profile":["Bevor Sie auf ein Bankkonto einzahlen k\xF6nnen, m\xFCssen Sie Ihr Profil vervollst\xE4ndigen"],"Transfer subject":["Buchungsvermerk der \xDCberweisung"],Currency:["W\xE4hrung"],"Send %1$s":["%1$s \xFCbertragen"],"Receive %1$s":["%1$s erhalten"],Amount:["Betrag"],"Total cost":["Gesamte Geb\xFChren"],"Balance left":["Verbleibendes Guthaben"],"Before fee":["Vor Abzug von Geb\xFChren"],"Total cashout transfer":["Gesamter Einzahlungsbetrag"],"Not valid":["Nicht g\xFCltig"],"Does not follow the pattern":["Weicht vom Muster ab"],"send transaction":["Es liegen noch keine Transaktionen vor."],"The wire transfer was successfully completed!":["Die Bank\xFCberweisung wurde erfolgreich durchgef\xFChrt!"],"The request was invalid or the payto://-URI used unacceptable features.":["Die Anfrage war ung\xFCltig oder die payto://-URI nutzte inakzeptable Merkmale."],"Not enough permission to complete the operation.":["Es besteht keine ausreichende Berechtigung, um den Vorgang abzuschlie\xDFen."],"The bank administrator cannot be the transfer creditor.":["Der Bankbetreiber kann nicht gleichzeitig Beg\xFCnstigter von \xDCberweisungen sein."],'The destination account "%1$s" was not found.':['Das Empf\xE4ngerkonto "%1$s" wurde nicht gefunden.'],"The origin and the destination of the transfer can't be the same.":["Ursprung und Ziel des Transfers k\xF6nnen nicht gleich sein."],"Your balance is not sufficient for the operation.":["Das Guthaben reicht f\xFCr den Vorgang nicht aus."],'The origin account "%1$s" was not found.':['Das Ursprungskonto "%1$s" wurde nicht gefunden.'],"The attempt to create the transaction has failed. Please try again.":["Die Vorbereitung der Transaktion hat nicht funktioniert. Bitte versuchen Sie es erneut."],"A second factor authentication is required.":["Dies wird verwendet, wenn die Zwei-Faktor-Authentifizierung aktiviert ist"],"Confirm wire transfer.":["Bank\xFCberweisung durchf\xFChren"],"Input wire transfer detail":["\xDCberweisungsdetails einf\xFCgen"],"Using a form":["Mithilfe eines Formulars"],"A special URI that specifies the amount to be transferred and the destination account.":["Uniform Resource Identifier (URI) zum Bestimmen des Werts, der an das Empf\xE4ngerkonto \xFCbertragen wird."],"QR code":["QR-Code"],"If your device has a camera, you can import a payto:// URI from a QR code.":["Wenn Ihr Ger\xE4t \xFCber eine Kamera verf\xFCgt, k\xF6nnen Sie automatisch eine payto-Zahlungsanweisung (payto://-URI) aus einem QR-Code erstellen."],Recipient:["Empf\xE4ngerkonto"],"ID of the recipient's account":["ID des Empf\xE4ngerkontos"],username:["Name des Nutzers"],"IBAN of the recipient's account":["IBAN des Empf\xE4ngerkontos"],Subject:["Buchungsvermerk"],"Some text to identify the transfer":["Eine Zeichenkette, um die \xDCberweisung eindeutig zu benennen"],"Amount to transfer":["Zu \xFCberweisender Betrag"],"Payto URI:":["payto-URI:"],"Uniform resource identifier of the target account":["URI (Uniform Resource Identifier) des Empf\xE4ngerkontos"],"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]":["payto://x-taler-bank/[Bankbetreiber]/[Empf\xE4ngerkonto]?message=[Buchungsvermerk]&amount=[%1$s:X.Y]"],"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]":["payto://iban/[IBAN des Empf\xE4ngers]?message=[Buchungsvermerk]&amount=[%1$s:X.Y]"],"The maximum amount for a wire transfer is %1$s":["Der H\xF6chstbetrag f\xFCr eine \xDCberweisung betr\xE4gt %1$s"],Cost:["Kosten"],Send:["\xDCberweisen"],'Only "x-taler-bank" target are supported':['Nur "x-taler-bank"-Ziele werden unterst\xFCtzt'],'Only this host is allowed. Use "%1$s"':['Nur dieser Bankbetreiber ist zul\xE4ssig. Bitte verwenden Sie "%1$s"'],"Account name is missing":["Name oder Bezeichnung des Kontos fehlt"],'Only "IBAN" target are supported':["Nur IBAN-Ziele werden unterst\xFCtzt"],'Missing "amount" parameter to specify the amount to be transferred':["Bitte geben Sie einen Betrag an, der \xFCbertragen werden soll"],'The "amount" parameter is not valid':["Der Betrag ist nicht g\xFCltig"],'"message" parameters to specify a reference text for the transfer are missing':["Es fehlen Parameter f\xFCr einen Referenz-Buchungsvermerk der \xDCberweisungen"],'The only currency allowed is "%1$s"':['Die einzig zul\xE4ssige W\xE4hrung ist "%1$s"'],"You cannot transfer an amount of zero.":["Sie k\xF6nnen keinen Betrag \xFCberweisen, der Null ist."],"The balance is not sufficient":["Das Guthaben ist nicht ausreichend"],"Please enter a longer subject":["Bitte geben Sie einen l\xE4ngeren Buchungsvermerk der \xDCberweisung an"],"Show withdrawal confirmation":["Zeige Best\xE4tigung der Abhebung"],"Withdraw without setting amount":["Abheben ohne festgelegten Betrag"],"Hide demo hint.":[""],"Show install wallet first":["Hilfstext: Zuerst Wallet installieren"],"Currently, the bank is not accepting new registrations!":["Im Augenblick nimmt die Bank keine Neuregistrierungen an!"],"The name is missing":["Der Nutzername fehlt"],"Missing username":["Fehlender Nutzername"],"Missing password":["Fehlendes Passwort"],"The password should be longer than 8 letters":["Das Passwort sollte l\xE4nger als 8 Zeichen sein"],"The passwords do not match":["Die Passw\xF6rter stimmen nicht \xFCberein"],"register new account":["Konto anlegen"],"Server replied with invalid phone or email.":["Der Server gab an, dass Telefonnummer oder E-Mail-Adresse ung\xFCltig seien."],"You are not authorised to create this account.":["Sie sind nicht berechtigt, dieses Konto zu erstellen."],"Registration is disabled because the bank ran out of bonus credit.":["Die Registrierung ist nicht m\xF6glich, da die Bank \xFCber kein ausreichendes Bonusguthaben verf\xFCgt."],"That username can't be used because is reserved.":["Dieser Nutzername kann nicht verwendet werden, da er schon reserviert ist."],"That username is already taken.":["Dieser Nutzername ist leider bereits vergeben."],"That account ID is already taken.":["Diese Konto-ID ist bereits vergeben."],"No information for the selected authentication channel.":["Es sind keine Informationen f\xFCr das gew\xE4hlte Authentifizierungsverfahren verf\xFCgbar."],"Authentication channel is not supported.":["Das gew\xE4hlte Authentifizierungsverfahren wird nicht unterst\xFCtzt."],"Only an administrator is allowed to set the debt limit.":["Nur ein Administrator ist befugt, die Kredith\xF6he festzulegen."],"Only the administrator can change the conversion rate.":["Nur der Administrator kann die geringste H\xF6he einer Auszahlung \xE4ndern."],"The conversion rate class doesn't exist.":["Der Umrechnungskurs wurde fehlerhaft angewendet"],"Only admin can create accounts with second factor authentication.":["Nur der Administrator kann Konten mit Zwei-Faktor-Authentifizierung erstellen."],"The password is too short. Can't have less than 8 characters.":["Das Passwort sollte l\xE4nger als 8 Zeichen sein"],"The password is too long. Can't have more than 64 characters.":["Das Passwort sollte l\xE4nger als 8 Zeichen sein"],"Account registration":["Kontoregistrierung"],"Login username":["Nutzername zum Anmelden"],"account identification to login":[""],Password:["Passwort"],"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers":["Verwenden Sie ein starkes Passwort: Mindestens 8 Zeichen bestehend aus Kleinbuchstaben, Gro\xDFbuchstaben, Symbolen und Zahlen und ohne \xF6ffentlich bekannte Informationen (wie Namen, Geburtstage, Telefonnummern usw.)"],"Repeat password":["Passwort wiederholen"],"Same password":["Neues Passwort"],"Full name":["Vollst\xE4ndiger Name"],Register:["Registrieren"],"Create a random temporary user":["Einen zuf\xE4lligen tempor\xE4ren Nutzer anlegen"],logout:["Abmelden"],login:[""],"The account has no rights to login.":[""],"The account is locked and cannot login. Contact administrator.":[""],'Wrong credentials for "%1$s"':['Falsche Zugangsdaten f\xFCr "%1$s"'],"Account login.":["Kontenname"],"Session expired":["Dieser Vorgang ist abgelaufen."],Username:["Nutzername"],identification:["\xDCberpr\xFCfung"],"Password of the account":["Passwort des Kontos"],Forget:[""],"Log in":["Anmelden"],"Transactions history":["Transaktions\xFCbersicht"],"No transactions yet.":["Es liegen noch keine Transaktionen vor."],"You can make a transfer or a withdrawal to your wallet.":["Sie k\xF6nnen Geld in Ihre Wallet-App \xFCbertragen oder abheben lassen."],Date:["Datum"],Counterpart:["Gegenkonto"],sent:["gesendet"],received:["empfangen"],"Invalid value":["Ung\xFCltiger Wert"],to:["an"],from:["von"],"First page":["Erste Seite"],Next:["N\xE4chste Seite"],"confirm withdrawal":["Best\xE4tigung der Abhebung"],cambiar:[""],"abort withdrawal":["Best\xE4tigung der Abhebung"],"The withdrawal has been aborted previously and can't be confirmed":["Die Abhebung wurde zuvor abgebrochen und konnte daher nicht durchgef\xFChrt werden"],"The withdrawal operation can't be confirmed before a wallet accepted the transaction.":["Der Abhebevorgang kann nicht best\xE4tigt werden, bevor eine Taler Wallet-App die Transaktion angenommen hat."],"The operation ID is invalid.":["Die Vorgangs-ID ist ung\xFCltig."],"The operation was not found.":["Der Vorgang konnte nicht gefunden werden."],"The starting withdrawal amount and the confirmation amount differs.":["Der Betrag der Abhebung und der empfangene Betrag unterscheiden sich."],"The bank requires a bank account which has not been specified yet.":["Die Bank ben\xF6tigt ein Bankkonto, das noch nicht festgelegt wurde."],"Bad request":[""],"The withdrawal operation has been aborted.":["Abhebevorgang in Bearbeitung"],"The withdrawal operation has been confirmed previously and can\u2019t be aborted.":["Der Vorgang wurde vom Verrechnungskonto bereits best\xE4tigt und kann daher nicht mehr abgebrochen werden"],"Complete withdrawal.":["Best\xE4tigung der Abhebung"],"Confirm the withdrawal operation":["Best\xE4tigen Sie den Abhebevorgang"],"Wire transfer details":["Details der Bank\xFCberweisung"],"Payment Service Provider's account number":["Bankkontonummer des Zahlungsdiensts"],"Payment Service Provider's name":["Name des Zahlungsdiensts"],"Payment Service Provider's account bank hostname":["Bezeichnung des Bankkontos des Zahlungsdiensts (PSP hostname)"],"Payment Service Provider's account id":["Konto-ID des Zahlungsdiensts"],"Payment Service Provider's account address":["Kontenadresse des Zahlungsdiensts"],"Payment Service Provider's account cyclos hostname":["Bezeichnung des Bankkontos des Zahlungsdiensts (PSP hostname)"],"No amount has yet been determined.":["Es wurde bisher noch kein Betrag ermittelt."],Transfer:["\xDCberweisung"],"Authentication required":["Authentifizierung erforderlich"],"This operation was created with another username":["Dieser Vorgang wurde mit einem anderen Nutzernamen erstellt"],'You are currently logged in with user "%1$s" and the operation was made with user "%2$s"':[""],"The reserve operation has been confirmed previously and can't be aborted":["Der Vorgang wurde vom Verrechnungskonto bereits best\xE4tigt und kann daher nicht mehr abgebrochen werden"],"Wire transfer completed!":["Bank\xFCberweisung abgeschlossen!"],"Confirm withdrawal.":["Best\xE4tigung der Abhebung"],"Unauthorized to make the operation, maybe the session has expired or the password changed.":["Sie sind nicht berechtigt, den Vorgang durchzuf\xFChren, vielleicht ist die Sitzung abgelaufen oder das Passwort wurde ge\xE4ndert."],"The operation was rejected due to insufficient funds.":["Der Vorgang wurde wegen unzureichendem Guthaben zur\xFCckgewiesen."],"Withdrawal confirmed":["Abhebung best\xE4tigt"],"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.":["Die \xDCberweisung an den Zahlungsdienst wurde eingeleitet. Ihre Taler-Wallet-App wird den angeforderten Betrag baldm\xF6glichst abrufen."],"Do not show this again":["Diese Meldung nicht mehr anzeigen"],"If you have a Taler wallet installed on this device":["Falls Sie eine Taler-Wallet-App auf diesem Ger\xE4t installiert haben"],"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions":["In Ihrer Taler-Wallet-App werden die Details der Transaktion einschlie\xDFlich der Geb\xFChren (falls diese verlangt wurden) angezeigt. Wenn Sie noch keine Taler-Wallet-App haben, folgen Sie bitte den Anweisungen"],"on this page":["auf dieser Seite"],Withdraw:["Abheben"],"In case you have a Taler wallet on another device":["Falls Sie eine Taler-Wallet-App auf einem anderen Ger\xE4t als diesem haben"],"Scan the QR below to start the withdrawal.":["Scannen Sie den QR-Code, um die Abhebung zu beginnen."],"create withdrawal":["Best\xE4tigung der Abhebung"],"The server replied with an invalid taler://withdraw URI":["Der Server antwortete mit einem ung\xFCltigen taler://withdraw URI"],"Withdraw URI: %1$s":["Abhebe-URI: %1$s"],"The operation was rejected due to insufficient funds":["Der Vorgang wurde wegen unzureichendem Guthaben zur\xFCckgewiesen"],"Current balance is %1$s":["Das aktuelle Guthaben betr\xE4gt %1$s"],"You can withdraw up to %1$s":["Sie k\xF6nnen bis zu %1$s abheben"],Continue:["Weiter"],"Use your Taler wallet":["Aktivieren Sie Ihr Taler-Wallet"],"After using your wallet you will need to authorize or cancel the operation on this site.":["Nachdem Sie Ihre Taler-Wallet-App aktiviert haben, m\xFCssen Sie auf dieser Website den Vorgang entweder mit Ihrer Freigabe best\xE4tigen oder ihn abbrechen."],"You need a Taler wallet":["Sie ben\xF6tigen eine Taler-Wallet-App"],"If you don't have one yet you can follow the instruction in":["Wenn Sie noch keine haben, folgen Sie bitte den Anweisungen in"],"this page":["diese Seite"],"Send money":["Geld senden"],"to a Taler wallet":["an ein Taler-Wallet (App oder WebExtension)"],"Withdraw digital money into your mobile wallet or browser extension":["Elektronisches Bargeld in eine Smartphone-App oder in eine Browser-Erweiterung (WebExtension) abheben"],"to another bank account":["an ein anderes Bankkonto"],"Make a wire transfer to an account with known bank account number.":["Sie \xFCberweisen auf ein Konto mit einer Ihnen bekannten Bankkontonummer."],"This is a demo":["Dies ist eine Demo-Version"],"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .":["Dieser Teil der Demo-Version zeigt die Rolle einer Kundenbank, die Zahlungen mit dem Taler-System unterst\xFCtzt. Sie sehen in der Demonstration Ihr eigenes Bankkonto und den %1$s-Transaktionsverlauf."],"Here you will be able to see how a bank that supports Taler directly would work.":["Damit k\xF6nnen Sie nachvollziehen, wie eine Kundenbank, die Zahlungen mit dem Taler-System unterst\xFCtzt, funktionieren w\xFCrde."],"Internal error, please report. There should be more information in the console.":[""],"Internal error, please report.":["Interner Fehler, um dessen Mitteilung wir Sie freundlich bitten."],Preferences:["Pr\xE4ferenzen"],"Show debug information":["Debugging-Informationen anzeigen"],Welcome:["Willkommen"],"Welcome, %1$s":["Herzlich willkommen, %1$s"],"No enough permission to access the conversion rate list.":["Es besteht keine ausreichende Berechtigung, um den Vorgang abzuschlie\xDFen."],"Conversion list not found. Maybe conversion rate is not supported.":[""],"Conversion list not implemented.":["Umrechnungen sind deaktiviert"],"Conversion rate classes":["Umrechnungskurs"],"Create conversion rate class":["Umrechnungskurs"],"No conversion rate class":["Umrechnungskurs"],Name:["Name"],Description:["Beschreibung"],Cashin:["Auszahlung (Cash-In)"],"min:":[""],"fee:":[""],"Select a section":["Bitte w\xE4hlen Sie einen Bereich aus"],Details:["Detail-Angaben"],Delete:["L\xF6schen"],Credentials:["Anmeldedaten"],Cashouts:["Auszahlungen (Cashout)"],Conversion:["Umrechnung (von W\xE4hrungen)"],"only admin can setup conversion":["Nur ein Administrator kann Umrechnungskurse einrichten"],"calculate cashout fee":["Konto anlegen"],"update conversion rate":["Umrechnungskurs"],"Wrong credentials":["Ung\xFCltige Zugangsdaten"],"Conversion is disabled":["Umrechnungen sind deaktiviert"],"Config cashout":["Einzahlungen einrichten"],"Config cashin":["Auszahlungen einrichten (Cash-In)"],"Bad ratios":["Das Verh\xE4ltnis passt nicht"],"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.":["F\xFCr ein stimmiges Verh\xE4ltnis sollte die eine W\xE4hrung h\xF6her oder gleich 1 sein und die andere W\xE4hrung niedriger oder gleich 1 sein."],"Initial amount":["Guthaben bei Erstanlage des Kontos"],"Use it to test how the conversion will affect the amount.":["Hier testen Sie, um die Auswirkung des Umrechnungskurses auf einen Betrag zu pr\xFCfen."],"Sending to this bank":["An diese Bank senden"],Converted:["Umgetauscht"],"Cashin after fee":["Auszahlung nach Abzug von Geb\xFChren"],"Sending from this bank":["Senden von dieser Bank"],"Cashout after fee":["Einzahlung nach Abzug von Geb\xFChren"],"Bad configuration":["Fehlerhafte Konfiguration"],"This configuration allows users to cash out more of what has been cashed in.":["Diese Einstellung erlaubt Nutzern, h\xF6here Betr\xE4ge auf ihre Konten einzuzahlen als sie eingenommen haben."],Update:["Aktualisieren"],Rnvalid:["Ung\xFCltig"],"Must be > 0":[""],"Minimum amount":["Minimaler Betrag"],"Only cashout operation above this threshold will be allowed.":["Es werden nur Einzahlungen oberhalb dieses Werts erlaubt"],Ratio:["Verh\xE4ltnis"],"Conversion ratio between currencies":["Umrechnungsverh\xE4ltnis zwischen den W\xE4hrungen"],"Example conversion":["Beispiel einer W\xE4hrungsumrechnung"],"1 %1$s will be converted into %2$s %3$s":["1 %1$s wird getauscht zu %2$s %3$s"],"Tiny amount":["Minimaler Betrag"],"Rounding mode":["Rundungsmethode"],Zero:["Null"],"Amount will be round below to the largest possible value smaller than the input.":["Der Betrag wird auf den gr\xF6\xDFtm\xF6glichen Wert abgerundet, der kleiner als die Eingabe ist."],Up:["Aufrunden"],"Amount will be round up to the smallest possible value larger than the input.":["Der Betrag wird auf den geringstm\xF6glichen Wert aufgerundet, der gr\xF6\xDFer als die Eingabe ist."],Nearest:["Am n\xE4hesten"],"Amount will be round to the closest possible value.":["Der Betrag wird auf den n\xE4chstm\xF6glichen Wert gerundet."],'If none specified the fallback value is "%1$s ".':[""],Examples:["Beispiele"],"Rounding an amount of 1.24 with rounding value 0.1":["Rundung eines Betrags von 1,24 mit Rundungswert 0,1"],"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.":["Angesichts des Rundungswertes von 0,1 sind die m\xF6glichen Werte, die am n\xE4chsten an 1,24 liegen, folgende: 1.1, 1.2, 1.3, 1.4."],'With the "zero" mode the value will be rounded to 1.2':["Mit der Methode \u201ENull\u201C wird der Wert auf 1,2 gerundet"],'With the "nearest" mode the value will be rounded to 1.2':["Mit der Methode \u201EN\xE4hestens\u201C wird der Wert auf 1,2 gerundet"],'With the "up" mode the value will be rounded to 1.3':["Mit der Methode \u201EAufrunden\u201C wird der Wert auf 1,3 gerundet"],"Rounding an amount of 1.26 with rounding value 0.1":["Rundung eines Betrags von 1,26 mit Rundungswert 0,1"],'With the "nearest" mode the value will be rounded to 1.3':["Mit der Methode \u201EN\xE4hestens\u201C wird der Wert auf 1,3 gerundet"],"Rounding an amount of 1.24 with rounding value 0.3":["Rundung eines Betrags von 1,24 mit Rundungswert 0,3"],"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.":["Mit einem Rundungswert von 0,3 sind die m\xF6glichen Werte, die am n\xE4hesten an 1,24 liegen, folgende: 0,9, 1,2, 1,5 und 1,8."],'With the "up" mode the value will be rounded to 1.5':["Mit der Methode \u201EAufrunden\u201C wird der Wert auf 1,5 gerundet"],"Rounding an amount of 1.26 with rounding value 0.3":["Rundung eines Betrags von 1,26 mit Rundungswert 0,3"],"Amount to be deducted before amount is credited.":["Betrag, der vor der Gutschrift abzuziehen ist."],"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":["In den Einstellungen m\xFCssen die Einzahlungen aufs Konto aktiviert und der Umrechnungskurs einschlie\xDFlich aller Geb\xFChren, Kurse und einem Rundungsverfahren initialisiert worden sein."],"delete conversion rate class":["Umrechnungskurs"],Unauthorized:["Unberechtigter Zugriff"],Forbidden:["Verboten"],NotFound:[""],NotImplemented:[""],"update conversion rate class":["Umrechnungskurs"],"Not Found":[""],"Not implemented":[""],"The name of the conversion is already used.":["Es ist bereits ein Vorgang in Bearbeitung"],"Conversion rate class":["Umrechnungskurs"],Accounts:["Konten"],Test:[""],Users:["Nutzername"],"Can't remove the conversion rate class":[""],"There are some user associated to this class. You need to remove them first.":[""],"You are going to remove the conversion rate class":["Sie sind gerade dabei, das Konto zu l\xF6schen"],"This step can't be undone.":["Dieser Schritt kann sp\xE4ter nicht mehr r\xFCckg\xE4ngig gemacht werden."],Filters:[""],"Show from other classes":[""],Account:["Konto"],"Group ID":[""],"No users in this conversion rate class":[""],Class:[""],Action:["Aktionen"],Remove:["Entfernen"],Add:["Hinzuf\xFCgen"],"Conversion rate name":["Umrechnungskurs"],"Short description of the class":[""],"create conversion rate class":["Umrechnungskurs"],"Conversion rate class created.":["Umrechnungskurs"],"The rights to change the account are not sufficient":["Es besteht keine ausreichende Berechtigung zum \xC4ndern des Kontos"],"New conversion rate class":["Umrechnungskurs"],Create:["Anlegen"],"History of public accounts":["Buchungen auf \xF6ffentlich sichtbaren Konten"],"Make a wire transfer":["Eine Bank\xFCberweisung durchf\xFChren"],"Scan the QR code below to start the withdrawal.":["Scannen Sie den QR-Code, um die Abhebung zu beginnen."],"Operation aborted":["Vorgang abgebrochen"],"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.":["Die \xDCberweisung auf das Konto des Zahlungsdiensts wurde an einer anderen Stelle abgebrochen. Ihr Guthaben ist jedoch sicher und geht nicht verloren."],"Go to your wallet now":["Geh jetzt zu deiner Wallet"],"The operation is marked as selected, but a process during the withdrawal failed":["Der Vorgang wurde als ausgew\xE4hlt markiert, aber ein Schritt w\xE4hrend des Abhebevorgangs ist gescheitert"],"A withdrawal reserve ID was not found and no account has been selected.":["Es wurde keine Abhebe-ID gefunden und daher ist kein Bankkonto ausgew\xE4hlt worden."],"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.":["Es gibt eine Abhebe-ID, aber es wurde kein Bankkonto ausgew\xE4hlt oder das gew\xE4hlte Bankkonto ist nicht g\xFCltig."],"The account was selected, but no withdrawal reserve ID was found.":["Das Konto wurde ausgew\xE4hlt, aber es wurde keine Abhebe-ID gefunden."],"Operation not found":["Vorgang nicht gefunden"],"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.":["Dieser Vorgang ist dem Server nicht bekannt. Die Vorgangs-ID stimmt nicht oder der Server hat die Informationen zum Vorgang gel\xF6scht, bevor sie hier ankamen."],"Continue to dashboard":["Weiter zum Dashboard"],"The Withdrawal URI is not valid":["Die URI f\xFCr die Abhebung ist nicht g\xFCltig"],"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.":["In den Einstellungen m\xFCssen die Einzahlungen aufs Konto aktiviert und der Umrechnungskurs einschlie\xDFlich aller Geb\xFChren, Kurse und einem Rundungsverfahren initialisiert worden sein."],"Latest cashouts":["Letzte Einzahlungen"],Created:["Erzeugt"],"Total debit":["Gesamtbetrag der Belastung"],"Total credit":["Gesamtbetrag der Gutschrift"],"Cashout for account %1$s":["Einzahlung an Konto %1$s"],"Invalid email format":["Ung\xFCltiger Wert"],"Should start with +":["Die Nummer sollte mit + beginnen"],"A phone number consists of numbers only":["Eine Telefonnummer besteht nur aus Ziffern"],"Account ID for authentication":["Konto-ID zur Authentifizierung"],"Name of the account holder":["Name des Kontoinhabers"],"Internal account":["Internes Konto"],"If this field is empty, a random account ID will be assigned":["Wenn dieses Feld leer bleibt, wird eine zuf\xE4llige Konto-ID vergeben"],"You can copy and share this IBAN number in order to receive wire transfers to your bank account":["Sie k\xF6nnen diese IBAN kopieren und \xFCbertragen, um \xDCberweisungen an Ihr Bankkonto zu erhalten"],Email:["E-Mail"],"To be used when second factor authentication is enabled":["Dies wird verwendet, wenn die Zwei-Faktor-Authentifizierung aktiviert ist"],Phone:["Telefon"],"Enable second factor authentication":["Dies wird verwendet, wenn die Zwei-Faktor-Authentifizierung aktiviert ist"],"Using email":["an die Emailadresse"],"Add an email in your profile to enable this option":[""],"Using SMS":[""],"Add a phone number in your profile to enable this option":[""],"Cashout account":["Auszahlungskonto"],"External account number where the money is going to be sent when doing cashouts":["Kontonummer f\xFCr Einzahlungen aufs eigene Bankkonto (gew\xF6hnlich eine IBAN)"],"Max debt":["Maximale Kredith\xF6he"],"How much the balance can go below zero.":["Dieser Wert gibt an, wie weit der Saldo ins Minus gehen kann."],"Is this account public?":["Ist dieses Konto ein \xF6ffentliches?"],"Public accounts have their balance publicly accessible":["\xD6ffentliche Konten zeigen ihre Salden und Bewegungen offen einsehbar"],"Does this account belong to a Payment Service Provider?":["Geh\xF6rt dieses Konto dem Anbieter eines Zahlungsdiensts?"],"update account":["Konto anlegen"],"Account updated":["Das Konto wurde aktualisiert"],"The username was not found":["Der Name des Nutzers konnte nicht gefunden werden"],"You can't change the legal name, please contact the your account administrator.":["Sie k\xF6nnen den Namen des wirtschaftlichen Berechtigten nicht \xE4ndern, bitte benachrichtigen Sie den Administrator des Kontos."],"You can't change the debt limit, please contact the your account administrator.":["Sie sind nicht befugt, die Kredith\xF6he zu \xE4ndern, bitte verst\xE4ndigen Sie den Administrator des Kontos."],"You can't change the cashout address, please contact the your account administrator.":["Sie k\xF6nnen die Adresse f\xFCr Einzahlungen nicht \xE4ndern, bitte benachrichtigen Sie Ihren Administrator des Kontos."],"Update account information.":["Aktualisieren der Kontoeinstellungen"],'Account "%1$s"':['Konto "%1$s"'],Removed:["Entfernt"],"This account can't be used.":["Dieses Konto kann nicht genutzt werden."],"Change details":["Details \xE4ndern"],"Merchant integration":["H\xE4ndler-Integration"],'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.':['Verwenden Sie diese Information, um Ihr Konto im Taler Merchant-Backend mit dem normalen Bankkonto zu verkn\xFCpfen. Sie k\xF6nnen daf\xFCr die im Onlinebanking angezeigten Angaben kopieren und mit der "Import"-Taste im Abschnitt "Bankkonto" des Taler Merchant-Backend selbst einf\xFCgen bzw. Ihren Dienste-Verwalter eintragen lassen.'],"Account type":["Kontentyp"],"Method to use for wire transfer.":["F\xFCr \xDCberweisungen zu verwendende Methode."],IBAN:["IBAN"],"International Bank Account Number.":["IBAN (Internationale Bankkontonummer)."],"Account name":["Kontobezeichnung"],"Bank host where the service is located.":["Adresse des Bankservers, der den Dienst anbietet."],"Bank account identifier for wire transfers.":["Kennung des Bankkontos f\xFCr \xDCberweisungen."],Address:["Adresse"],"Owner's name":["Name des Kontoinhabers"],"Legal name of the person holding the account.":["Rechtsg\xFCltiger Name des Kontoinhabers."],"Account info URL":["URL f\xFCr Kontoinformationen"],"From where the merchant can download information about incoming wire transfers to this account.":["Von wo der H\xE4ndler Informationen \xFCber eingehende \xDCberweisungen auf dieses Konto herunterladen kann."],"Repeated password doesn't match":["Das Passwort stimmt nicht mit dem ersten \xFCberein"],"update password":["Passwort erneuern"],"Password changed":["Passwort ge\xE4ndert"],"Not authorized to change the password, maybe the session is invalid.":["Sie sind zum \xC4ndern des Passworts nicht berechtigt, m\xF6glicherweise ist die Sitzung nicht mehr g\xFCltig."],"You need to provide the old password. If you don't have it contact your account administrator.":["Sie m\xFCssen das alte Passwort eingeben, sollten Sie es nicht mehr haben, verst\xE4ndigen Sie bitte Ihren Administrator des Kontos."],"Your current password doesn't match, can't change to a new password.":["Dies stimmt nicht mit dem bisherigen Passwort \xFCberein, daher kann kein neues Passwort vergeben werden."],"You don't have the rights to change the password.":[""],"Update account password.":["Passwort erneuern"],"Update password":["Passwort erneuern"],"Current password":["Aktuelles Passwort dieser Instanz"],"Your current password, for security":["Zur Sicherheit bitte ihr bisheriges Passwort"],"New password":["Neues Passwort"],"Type it again":["Bitte das Passwort wiederholen"],"Repeat the same password":["Geben Sie das gleiche Passwort noch einmal ein"],Change:["\xC4ndern"],"Create account":["Konto anlegen"],Actions:["Aktionen"],Unknown:["Unbekannt"],"Change password":["Passwort \xE4ndern"],"Querying for the current stats failed":["Die Abfrage der aktuellen Statistik ist fehlgeschlagen"],"The request parameters are wrong":["Die Abfrageparameter sind falsch"],"The user is unauthorized":["Dieser Nutzer ist nicht berechtigt"],"Querying for the previous stats failed":["Die Abfrage der vorherigen Statistik ist fehlgeschlagen"],"Transaction volume report":["Umsatzbericht"],"Last hour":["Vergangene Stunde"],"Previous day":["Tag zuvor"],"Last month":["Vergangener Monat"],"Last year":["Letztes Jahr"],"Last Year":["Vergangenes Jahr"],"Trading volume from %1$s to %2$s":["Umsatzvolumen von %1$s bis %2$s"],"Transferred from an external account to an account in this bank.":["\xDCberwiesen von einem externen Bankkonto auf das Konto dieser Bank."],"Transferred from an account in this bank to an external account.":["\xDCberwiesen von einem Konto dieser Bank auf ein externes Bankkonto."],Payin:["Auszahlung (Pay-In)"],"Transferred from an account to a Taler exchange.":["\xDCberwiesen von einem Bankkonto an einen Taler Exchange (der Zahlungsdienst dieses Bezahlsystems)."],Payout:["Einzahlung (Pay-Out)"],"Transferred from a Taler exchange to another account.":["\xDCberwiesen von einem Taler Exchange (Zahlungsdienst dieses Bezahlsystems) auf ein anderes Bankkonto."],"Download stats as CSV":["Statistik herunterladen als CSV-Datei"],previous:["vorherige"],"Decreased by":["Verringert um"],"Increased by":["Vermehrt um"],"create account":["Konto anlegen"],'Account created with password "%1$s".':['Das Konto wurde angelegt mit dem Passwort "%1$s".'],"Server replied that phone or email is invalid":["Der Server meldete zur\xFCck, dass die Telefonnummer oder die Emailadresse falsch seien"],"The rights to perform the operation are not sufficient":["Die Berechtigung zum Durchf\xFChren des Vorgangs ist unzureichend"],"Account username is already taken":["Dieser Nutzername ist bereits vergeben"],"Account ID is already taken":["Diese Konto-ID ist bereits vergeben"],"Bank ran out of bonus credit.":["Die Bank verf\xFCgt \xFCber kein Bonusguthaben mehr."],"Account username can't be used because is reserved":["Dieser Nutzername kann f\xFCr das Konto nicht verwendet werden, da er bereits reserviert ist"],"Can't create accounts":["Die Anlage von Konten ist nicht m\xF6glich"],"Only system admin can create accounts.":["Nur ein Systemadministrator kann Konten anlegen."],"New bank account":["Neues Konto"],"download statistics":["Statistik herunterladen als CSV-Datei"],"only admin can download stats":["Nur ein Administrator kann Umrechnungskurse einrichten"],"Download bank stats":["Bankstatistik herunterladen"],"Include hour metric":["Stunden-Metrik einbeziehen"],"Include day metric":["Tages-Metrik einbeziehen"],"Include month metric":["Monats-Metrik einbeziehen"],"Include year metric":["Jahres-Metrik einbeziehen"],"Include table header":["Tabellenkopfzeilen einbeziehen"],"Add previous metric for compare":["Vorherige Metrik zum Vergleich hinzuf\xFCgen"],"Fail on first error":["Beim ersten Fehler abbrechen"],Download:["Herunterladen"],"downloading... %1$s":["Beim Herunterladen... %1$s"],"Download completed":["Download abgeschlossen"],"Click here to save the file in your computer.":["Hier klicken zum Speichern der Datei auf Ihrem Rechner."],"there was an error reading the balance":[""],"Can't delete the account":["Es war nicht m\xF6glich, das Konto zu l\xF6schen"],"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.":["Das Konto kann nicht gel\xF6scht werden, solange es noch ein Guthaben aufweist. Bitte sorgen Sie daf\xFCr, dass der Konteninhaber eine vollst\xE4ndige Einzahlung auf das eigene Bankkonto durchf\xFChrt."],"Name doesn't match":["Der Name stimmt nicht \xFCberein"],"delete account":["Konto anlegen"],"Account removed":["Das Konto wurde gel\xF6scht"],"No enough permission to delete the account.":["Es besteht keine ausreichende Berechtigung zum L\xF6schen des Kontos."],"The username was not found.":["Der Nutzername wurde nicht gefunden."],"Can't delete a reserved username.":["Es ist nicht m\xF6glich, den reservierten Nutzernamen zu entfernen."],"Can't delete an account with balance different than zero.":["Es ist nicht m\xF6glich, ein Konto mit einem Saldo ungleich Null zu l\xF6schen."],"Remove account.":["Das Konto wird gel\xF6scht"],"You are going to remove the account":["Sie sind gerade dabei, das Konto zu l\xF6schen"],'Deleting account "%1$s"':['Das Konto "%1$s" wird gel\xF6scht'],Verification:["\xDCberpr\xFCfung"],"Enter the account name that is going to be deleted":["Zum L\xF6schen geben Sie den Namen des Kontos an"],"Cashout id should be a number":["Die Einzahlungs-ID sollte eine Zahl sein"],"This cashout not found. Maybe already aborted.":["Diese Einzahlung konnte nicht gefunden werden, vielleicht wurde sie bereits abgebrochen."],"Cashout detail":["Einzahlungsdetails"],Debited:["Belastet"],Transferred:["\xDCberweisung"],"You have no permission to this account.":["Es besteht keine ausreichende Berechtigung zum L\xF6schen des Kontos."],"This account is locked. If you have a active session you can change the password or contact the administrator.":[""],"New web session":[""],"Welcome to %1$s!":["Willkommen bei %1$s!"]}},domain:"messages",plural_forms:"nplurals=2; plural=n != 1;",lang:"de",completeness:90};Nn.ca={locale_data:{messages:{"":{domain:"messages",plural_forms:"nplurals=2; plural=n != 1;",lang:"ca"},"An IBAN consists of capital letters and numbers only":[""],"IBAN numbers have more that 4 digits":[""],"IBAN numbers have less that 34 digits":[""],"IBAN country code not found":[""],"IBAN number is not valid, checksum is wrong":[""],"Use letters, numbers or any of these characters: - . _ ~":[""],Required:[""],"confirm MFA challenge":[""],"Unknown challenge.":[""],"Failed to validate the verification code.":[""],"Too many challenges are active right now, you must wait or confirm current challenges.":[""],"Wrong authentication number.":[""],"Expired challenge.":[""],"Submit the transmitted code number.":[""],"The verification code sent to the email address starting with %1$s":[""],"The verification code sent to the phone number ending with %1$s":[""],Code:[""],"Username of the account":[""],"It will expired at %1$s":[""],"The challenge is expired and can't be solved but you can go back and create a new challenge.":[""],Back:[""],Verify:[""],"send MFA challenge":[""],"Failed to send the verification code.":[""],"The request was valid, but the server is refusing action.":[""],"The backend is not aware of the specified MFA challenge.":[""],"It is too early to request another transmission of the challenge.":[""],"Code transmission failed.":[""],"select challenge":[""],"Multi-factor authentication required":[""],"This operation is protected with second factor authentication. In order to complete it we need to verify your identity using the authentication channel you provided.":[""],"The next challenge needs to be completed to confirm the operation.":[""],"All the next challenges need to be completed to confirm the operation.":[""],"One of the next challenges need to be completed to confirm the operation.":[""],'To an phone ending with "%1$s"':[""],'To an email starting with " %1$s"':[""],"I have a code":[""],"Send me a message":[""],"You have to wait until %1$s to send a new code.":[""],Cancel:[""],Complete:[""],"Unable to create a cashout":[""],"The bank configuration does not support cashout operations.":[""],Close:[""],"Cashout is disabled":[""],"Cashout should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"calculate conversion fee":[""],"The server didn't understand the request.":[""],"The amount is too small":[""],"Conversion is not implemented.":[""],"At least debit or credit needs to be provided":[""],"The amount is malfored":[""],"The currency is not supported":[""],Invalid:[""],"Amount needs to be higher":[""],"Balance is not enough":[""],"It is not possible to cashout less than %1$s: %2$s":[""],"The total transfer to the destination will be zero":[""],"create cashout":[""],"Cashout created":[""],"Second factor authentication required.":[""],"Account not found":[""],"Duplicated request detected, check if the operation succeeded or try again.":[""],"The conversion rate was applied incorrectly":[""],"The account does not have sufficient funds":[""],"Missing cashout URI in the profile":[""],"The amount is below the minimum amount permitted.":[""],"Sending the confirmation message failed, retry later or contact the administrator.":[""],"The server doesn't support the current TAN channel.":[""],"Create cashout.":[""],Cashout:[""],"Conversion rate":[""],Balance:[""],Fee:[""],"To account":[""],"Legal name":[""],"If this name doesn't match the account holder's name, your transaction may fail.":[""],"Unable to cashout":[""],"Before being able to cashout to a bank account, you need to complete your profile":[""],"Transfer subject":[""],Currency:[""],"Send %1$s":[""],"Receive %1$s":[""],Amount:[""],"Total cost":[""],"Balance left":[""],"Before fee":[""],"Total cashout transfer":[""],"Not valid":[""],"Does not follow the pattern":[""],"send transaction":[""],"The wire transfer was successfully completed!":[""],"The request was invalid or the payto://-URI used unacceptable features.":[""],"Not enough permission to complete the operation.":[""],"The bank administrator cannot be the transfer creditor.":[""],'The destination account "%1$s" was not found.':[""],"The origin and the destination of the transfer can't be the same.":[""],"Your balance is not sufficient for the operation.":[""],'The origin account "%1$s" was not found.':[""],"The attempt to create the transaction has failed. Please try again.":[""],"A second factor authentication is required.":[""],"Confirm wire transfer.":[""],"Input wire transfer detail":[""],"Using a form":[""],"A special URI that specifies the amount to be transferred and the destination account.":[""],"QR code":[""],"If your device has a camera, you can import a payto:// URI from a QR code.":[""],Recipient:[""],"ID of the recipient's account":[""],username:[""],"IBAN of the recipient's account":[""],Subject:[""],"Some text to identify the transfer":[""],"Amount to transfer":[""],"Payto URI:":[""],"Uniform resource identifier of the target account":[""],"payto://x-taler-bank/[bank-host]/[receiver-account]?message=[subject]&amount=[%1$s:X.Y]":[""],"payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]":[""],"The maximum amount for a wire transfer is %1$s":[""],Cost:[""],Send:[""],'Only "x-taler-bank" target are supported':[""],'Only this host is allowed. Use "%1$s"':[""],"Account name is missing":[""],'Only "IBAN" target are supported':[""],'Missing "amount" parameter to specify the amount to be transferred':[""],'The "amount" parameter is not valid':[""],'"message" parameters to specify a reference text for the transfer are missing':[""],'The only currency allowed is "%1$s"':[""],"You cannot transfer an amount of zero.":[""],"The balance is not sufficient":[""],"Please enter a longer subject":[""],"Show withdrawal confirmation":["Mostrar informaci\xF3 de retirada"],"Withdraw without setting amount":["Retirar sense fixar un import"],"Hide demo hint.":[""],"Show install wallet first":[""],"Currently, the bank is not accepting new registrations!":[""],"The name is missing":[""],"Missing username":[""],"Missing password":[""],"The password should be longer than 8 letters":[""],"The passwords do not match":[""],"register new account":[""],"Server replied with invalid phone or email.":[""],"You are not authorised to create this account.":[""],"Registration is disabled because the bank ran out of bonus credit.":[""],"That username can't be used because is reserved.":[""],"That username is already taken.":[""],"That account ID is already taken.":[""],"No information for the selected authentication channel.":[""],"Authentication channel is not supported.":[""],"Only an administrator is allowed to set the debt limit.":[""],"Only the administrator can change the conversion rate.":[""],"The conversion rate class doesn't exist.":[""],"Only admin can create accounts with second factor authentication.":[""],"The password is too short. Can't have less than 8 characters.":[""],"The password is too long. Can't have more than 64 characters.":[""],"Account registration":[""],"Login username":[""],"account identification to login":[""],Password:[""],"Use a strong password: 8 characters minimum, don't use any public information related to you (names, birthday, phone number, etc...) and mix lowercase, uppercase, symbols and numbers":[""],"Repeat password":[""],"Same password":[""],"Full name":[""],Register:[""],"Create a random temporary user":[""],logout:[""],login:[""],"The account has no rights to login.":[""],"The account is locked and cannot login. Contact administrator.":[""],'Wrong credentials for "%1$s"':[""],"Account login.":[""],"Session expired":[""],Username:[""],identification:[""],"Password of the account":[""],Forget:[""],"Log in":[""],"Transactions history":[""],"No transactions yet.":[""],"You can make a transfer or a withdrawal to your wallet.":[""],Date:[""],Counterpart:[""],sent:[""],received:[""],"Invalid value":[""],to:[""],from:[""],"First page":[""],Next:[""],"confirm withdrawal":[""],cambiar:[""],"abort withdrawal":[""],"The withdrawal has been aborted previously and can't be confirmed":[""],"The withdrawal operation can't be confirmed before a wallet accepted the transaction.":[""],"The operation ID is invalid.":[""],"The operation was not found.":[""],"The starting withdrawal amount and the confirmation amount differs.":[""],"The bank requires a bank account which has not been specified yet.":[""],"Bad request":[""],"The withdrawal operation has been aborted.":[""],"The withdrawal operation has been confirmed previously and can\u2019t be aborted.":[""],"Complete withdrawal.":[""],"Confirm the withdrawal operation":[""],"Wire transfer details":[""],"Payment Service Provider's account number":[""],"Payment Service Provider's name":[""],"Payment Service Provider's account bank hostname":[""],"Payment Service Provider's account id":[""],"Payment Service Provider's account address":[""],"Payment Service Provider's account cyclos hostname":[""],"No amount has yet been determined.":[""],Transfer:[""],"Authentication required":[""],"This operation was created with another username":[""],'You are currently logged in with user "%1$s" and the operation was made with user "%2$s"':[""],"The reserve operation has been confirmed previously and can't be aborted":[""],"Wire transfer completed!":[""],"Confirm withdrawal.":[""],"Unauthorized to make the operation, maybe the session has expired or the password changed.":[""],"The operation was rejected due to insufficient funds.":[""],"Withdrawal confirmed":[""],"The wire transfer to the Payment Service Provider has been initiated. You will shortly receive the requested amount in your Taler wallet.":[""],"Do not show this again":[""],"If you have a Taler wallet installed on this device":[""],"Your wallet will display the details of the transaction including the fees (if applicable). If you do not yet have a wallet, please follow the instructions":[""],"on this page":[""],Withdraw:[""],"In case you have a Taler wallet on another device":[""],"Scan the QR below to start the withdrawal.":[""],"create withdrawal":[""],"The server replied with an invalid taler://withdraw URI":[""],"Withdraw URI: %1$s":[""],"The operation was rejected due to insufficient funds":[""],"Current balance is %1$s":[""],"You can withdraw up to %1$s":[""],Continue:[""],"Use your Taler wallet":[""],"After using your wallet you will need to authorize or cancel the operation on this site.":[""],"You need a Taler wallet":[""],"If you don't have one yet you can follow the instruction in":[""],"this page":[""],"Send money":[""],"to a Taler wallet":[""],"Withdraw digital money into your mobile wallet or browser extension":[""],"to another bank account":[""],"Make a wire transfer to an account with known bank account number.":[""],"This is a demo":[""],"This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s .":[""],"Here you will be able to see how a bank that supports Taler directly would work.":[""],"Internal error, please report. There should be more information in the console.":[""],"Internal error, please report.":[""],Preferences:[""],"Show debug information":["Mostrar informaci\xF3 de retirada"],Welcome:[""],"Welcome, %1$s":[""],"No enough permission to access the conversion rate list.":[""],"Conversion list not found. Maybe conversion rate is not supported.":[""],"Conversion list not implemented.":[""],"Conversion rate classes":[""],"Create conversion rate class":[""],"No conversion rate class":[""],Name:[""],Description:["Mostrar descripci\xF3 de demostraci\xF3"],Cashin:[""],"min:":[""],"fee:":[""],"Select a section":[""],Details:[""],Delete:[""],Credentials:[""],Cashouts:[""],Conversion:[""],"only admin can setup conversion":[""],"calculate cashout fee":[""],"update conversion rate":[""],"Wrong credentials":[""],"Conversion is disabled":[""],"Config cashout":[""],"Config cashin":[""],"Bad ratios":[""],"One of the ratios should be higher or equal than 1 an the other should be lower or equal than 1.":[""],"Initial amount":[""],"Use it to test how the conversion will affect the amount.":[""],"Sending to this bank":[""],Converted:[""],"Cashin after fee":[""],"Sending from this bank":[""],"Cashout after fee":[""],"Bad configuration":[""],"This configuration allows users to cash out more of what has been cashed in.":[""],Update:[""],Rnvalid:[""],"Must be > 0":[""],"Minimum amount":[""],"Only cashout operation above this threshold will be allowed.":[""],Ratio:[""],"Conversion ratio between currencies":[""],"Example conversion":[""],"1 %1$s will be converted into %2$s %3$s":[""],"Tiny amount":[""],"Rounding mode":[""],Zero:[""],"Amount will be round below to the largest possible value smaller than the input.":[""],Up:[""],"Amount will be round up to the smallest possible value larger than the input.":[""],Nearest:[""],"Amount will be round to the closest possible value.":[""],'If none specified the fallback value is "%1$s ".':[""],Examples:[""],"Rounding an amount of 1.24 with rounding value 0.1":[""],"Given the rounding value of 0.1 the possible values closest to 1.24 are: 1.1, 1.2, 1.3, 1.4.":[""],'With the "zero" mode the value will be rounded to 1.2':[""],'With the "nearest" mode the value will be rounded to 1.2':[""],'With the "up" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.26 with rounding value 0.1":[""],'With the "nearest" mode the value will be rounded to 1.3':[""],"Rounding an amount of 1.24 with rounding value 0.3":[""],"Given the rounding value of 0.3 the possible values closest to 1.24 are: 0.9, 1.2, 1.5, 1.8.":[""],'With the "up" mode the value will be rounded to 1.5':[""],"Rounding an amount of 1.26 with rounding value 0.3":[""],"Amount to be deducted before amount is credited.":[""],"Conversion should be enabled in the configuration, the conversion rate should be initialized with fee(s), rates and a rounding mode.":[""],"delete conversion rate class":[""],Unauthorized:[""],Forbidden:[""],NotFound:[""],NotImplemented:[""],"update conversion rate class":[""],"Not Found":[""],"Not implemented":[""],"The name of the conversion is already used.":[""],"Conversion rate class":[""],Accounts:[""],Test:[""],Users:[""],"Can't remove the conversion rate class":[""],"There are some user associated to this class. You need to remove them first.":[""],"You are going to remove the conversion rate class":[""],"This step can't be undone.":[""],Filters:[""],"Show from other classes":[""],Account:[""],"Group ID":[""],"No users in this conversion rate class":[""],Class:[""],Action:[""],Remove:[""],Add:[""],"Conversion rate name":[""],"Short description of the class":[""],"create conversion rate class":[""],"Conversion rate class created.":[""],"The rights to change the account are not sufficient":[""],"New conversion rate class":[""],Create:[""],"History of public accounts":[""],"Make a wire transfer":[""],"Scan the QR code below to start the withdrawal.":[""],"Operation aborted":[""],"The wire transfer to the Payment Service Provider's account was aborted from somewhere else, your balance was not affected.":[""],"Go to your wallet now":[""],"The operation is marked as selected, but a process during the withdrawal failed":[""],"A withdrawal reserve ID was not found and no account has been selected.":[""],"There is a withdrawal reserve ID but no account has been selected or the selected account is invalid.":[""],"The account was selected, but no withdrawal reserve ID was found.":[""],"Operation not found":[""],"This process is not known to the server. The process ID is incorrect or the server has deleted the process information before it arrived here.":[""],"Continue to dashboard":[""],"The Withdrawal URI is not valid":[""],"Cashout should be enable by configuration and the conversion rate should be initialized with fee, ratio and rounding mode.":[""],"Latest cashouts":[""],Created:[""],"Total debit":[""],"Total credit":[""],"Cashout for account %1$s":[""],"Invalid email format":[""],"Should start with +":[""],"A phone number consists of numbers only":[""],"Account ID for authentication":[""],"Name of the account holder":[""],"Internal account":[""],"If this field is empty, a random account ID will be assigned":[""],"You can copy and share this IBAN number in order to receive wire transfers to your bank account":[""],Email:[""],"To be used when second factor authentication is enabled":[""],Phone:[""],"Enable second factor authentication":[""],"Using email":[""],"Add an email in your profile to enable this option":[""],"Using SMS":[""],"Add a phone number in your profile to enable this option":[""],"Cashout account":[""],"External account number where the money is going to be sent when doing cashouts":[""],"Max debt":[""],"How much the balance can go below zero.":[""],"Is this account public?":[""],"Public accounts have their balance publicly accessible":[""],"Does this account belong to a Payment Service Provider?":[""],"update account":[""],"Account updated":[""],"The username was not found":[""],"You can't change the legal name, please contact the your account administrator.":[""],"You can't change the debt limit, please contact the your account administrator.":[""],"You can't change the cashout address, please contact the your account administrator.":[""],"Update account information.":[""],'Account "%1$s"':[""],Removed:[""],"This account can't be used.":[""],"Change details":[""],"Merchant integration":[""],'Use this information to link your Taler Merchant Backoffice account with the current bank account. You can start by copying the values, then go to your merchant backoffice service provider, login into your account and look for the "import" button in the "bank account" section.':[""],"Account type":[""],"Method to use for wire transfer.":[""],IBAN:[""],"International Bank Account Number.":[""],"Account name":[""],"Bank host where the service is located.":[""],"Bank account identifier for wire transfers.":[""],Address:[""],"Owner's name":[""],"Legal name of the person holding the account.":[""],"Account info URL":[""],"From where the merchant can download information about incoming wire transfers to this account.":[""],"Repeated password doesn't match":[""],"update password":[""],"Password changed":[""],"Not authorized to change the password, maybe the session is invalid.":[""],"You need to provide the old password. If you don't have it contact your account administrator.":[""],"Your current password doesn't match, can't change to a new password.":[""],"You don't have the rights to change the password.":[""],"Update account password.":[""],"Update password":[""],"Current password":[""],"Your current password, for security":[""],"New password":[""],"Type it again":[""],"Repeat the same password":[""],Change:[""],"Create account":[""],Actions:[""],Unknown:[""],"Change password":[""],"Querying for the current stats failed":[""],"The request parameters are wrong":[""],"The user is unauthorized":[""],"Querying for the previous stats failed":[""],"Transaction volume report":[""],"Last hour":[""],"Previous day":[""],"Last month":[""],"Last year":[""],"Last Year":[""],"Trading volume from %1$s to %2$s":[""],"Transferred from an external account to an account in this bank.":[""],"Transferred from an account in this bank to an external account.":[""],Payin:[""],"Transferred from an account to a Taler exchange.":[""],Payout:[""],"Transferred from a Taler exchange to another account.":[""],"Download stats as CSV":[""],previous:[""],"Decreased by":[""],"Increased by":[""],"create account":[""],'Account created with password "%1$s".':[""],"Server replied that phone or email is invalid":[""],"The rights to perform the operation are not sufficient":[""],"Account username is already taken":[""],"Account ID is already taken":[""],"Bank ran out of bonus credit.":[""],"Account username can't be used because is reserved":[""],"Can't create accounts":[""],"Only system admin can create accounts.":[""],"New bank account":[""],"download statistics":[""],"only admin can download stats":[""],"Download bank stats":[""],"Include hour metric":[""],"Include day metric":[""],"Include month metric":[""],"Include year metric":[""],"Include table header":[""],"Add previous metric for compare":[""],"Fail on first error":[""],Download:[""],"downloading... %1$s":[""],"Download completed":[""],"Click here to save the file in your computer.":[""],"there was an error reading the balance":[""],"Can't delete the account":[""],"The account can't be delete while still holding some balance. First make sure that the owner make a complete cashout.":[""],"Name doesn't match":[""],"delete account":[""],"Account removed":[""],"No enough permission to delete the account.":[""],"The username was not found.":[""],"Can't delete a reserved username.":[""],"Can't delete an account with balance different than zero.":[""],"Remove account.":[""],"You are going to remove the account":[""],'Deleting account "%1$s"':[""],Verification:[""],"Enter the account name that is going to be deleted":[""],"Cashout id should be a number":[""],"This cashout not found. Maybe already aborted.":[""],"Cashout detail":[""],Debited:[""],Transferred:[""],"You have no permission to this account.":[""],"This account is locked. If you have a active session you can change the password or contact the administrator.":[""],"New web session":[""],"Welcome to %1$s!":[""]}},domain:"messages",plural_forms:"nplurals=2; plural=n != 1;",lang:"ca",completeness:0};var G1={backendBaseURL:mM(),iconLinkURL:void 0,allowRandomAccountCreation:!1,showDemoDescription:!1,topNavSites:{},defaultSuggestedAmount:10},pM=()=>W().property("backendBaseURL",U(L())).property("allowRandomAccountCreation",U(Se())).property("showDemoDescription",U(Se())).property("defaultSuggestedAmount",U(ne())).property("iconLinkURL",U(L())).property("topNavSites",U(Ar(L()))).build("UiSettings");function hM(e){return Object.keys(e).reduce((r,n)=>(typeof r[n]>"u"&&delete r[n],r),e)}function B1(e){fetch("./settings.json").then(t=>t.json()).then(t=>pM().decode(t)).then(t=>e({...G1,...hM(t)})).catch(t=>{console.log("failed to fetch settings",t),e(G1)})}function mM(){if(typeof window<"u"){let e=new URL(window.location.pathname,window.location.origin).href;return ia(e.replace("/webui",""))}throw Error("No default URL")}var gM=!1;function W1(){let[e,t]=de();if(Ge(()=>{B1(t)},[]),!e)return i(st,null);let r=yM(e.backendBaseURL);return i(vE,{value:e},i(Tv,{source:Nn},i(EM,{baseUrl:r})))}window.setGlobalLogLevelFromString=kh;window.getGlobalLevel=Mh;function _M(){let e=new Map(JSON.parse(localStorage.getItem("app-cache")||"[]"));return window.addEventListener("beforeunload",()=>{let t=JSON.stringify(Array.from(e.entries()));localStorage.setItem("app-cache",t)}),e}function yM(e){let t=typeof localStorage<"u"?localStorage.getItem("corebank-api-base-url"):void 0,r;t?r=t:e?r=e:(console.error("ERROR: backendBaseURL was overridden by a setting file and missing. Setting value to 'window.origin'"),r=window.origin);try{return ia(r)}catch{return ia(window.origin)}}var bM={async notifySuccess(e){switch(e){case Gt.DELETE_ACCOUNT:{await Promise.all([up(),dp()]);return}case Gt.CREATE_ACCOUNT:{await Promise.all([ro(),ao(),up(),dp()]);return}case Gt.UPDATE_ACCOUNT:{await Promise.all([ro()]);return}case Gt.CREATE_TRANSACTION:{await Promise.all([ro(),ao()]);return}case Gt.CONFIRM_WITHDRAWAL:{await Promise.all([ro(),ao()]);return}case Gt.CREATE_CASHOUT:{await Promise.all([ro(),fp(),ao()]);return}case Gt.UPDATE_PASSWORD:case Gt.ABORT_WITHDRAWAL:case Gt.CREATE_WITHDRAWAL:return;case Gt.UPDATE_CONVERSION_RATE_CLASS:case Gt.CREATE_CONVERSION_RATE_CLASS:case Gt.DELETE_CONVERSION_RATE_CLASS:await Promise.all([lp(),fp(),ao(),ri(),pE()]);return;default:ue(e)}}},vM={async notifySuccess(e){if(e===Po.UPDATE_RATE){await lp();return}else ue(e)}};function EM({baseUrl:e}){return i(Rv,{baseUrl:new URL("/",e),frameOnError:co,evictors:{bank:bM,conversion:vM}},i(Zv,{value:{provider:gM?_M:void 0,revalidateOnFocus:!1,revalidateOnReconnect:!1,revalidateIfStale:!1,revalidateOnMount:void 0,focusThrottleInterval:void 0,refreshInterval:void 0,dedupingInterval:2e3,refreshWhenHidden:!1,refreshWhenOffline:!1,shouldRetryOnError:!1,errorRetryCount:0,errorRetryInterval:void 0,keepPreviousData:!0}},i(Cv,null,i(Iv,null,i(Gp,null)))))}Re();function wM(e){let t=e.type;return{key:e.key,props:e.props,screen:t.SCREEN_ID}}var V1=document.getElementById("app");if(V1){let e=i(W1,null);window.showPreactState=()=>{console.log(JSON.stringify(wM(e),void 0,2))},Pn(e,V1)}else console.error("HTML element with id 'app' not found."); /*! Bundled license information: jed/jed.js: (** * @preserve jed.js https://github.com/SlexAxton/Jed *) use-sync-external-store/cjs/use-sync-external-store-shim.production.min.js: (** * @license React * use-sync-external-store-shim.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. *) */ //# sourceMappingURL=index.js.map ��������������������������������������������������������������������libeufin-1.6.8/contrib/wallet-core/bank/index.css.map�����������������������������������������������0000664�0001750�0001750�00000333300�15204341712�022732� 0����������������������������������������������������������������������������������������������������ustar �grothoff������������������������grothoff���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{ "version": 3, "sources": ["../../src/scss/main.css"], "sourcesContent": ["*, ::before, ::after {\n --tw-border-spacing-x: 0;\n --tw-border-spacing-y: 0;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-gradient-from-position: ;\n --tw-gradient-via-position: ;\n --tw-gradient-to-position: ;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(59 130 246 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n --tw-contain-size: ;\n --tw-contain-layout: ;\n --tw-contain-paint: ;\n --tw-contain-style: ;\n}\n\n::backdrop {\n --tw-border-spacing-x: 0;\n --tw-border-spacing-y: 0;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-gradient-from-position: ;\n --tw-gradient-via-position: ;\n --tw-gradient-to-position: ;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(59 130 246 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n --tw-contain-size: ;\n --tw-contain-layout: ;\n --tw-contain-paint: ;\n --tw-contain-style: ;\n}/*\n! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com\n*//*\n1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)\n2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)\n*/\n\n*,\n::before,\n::after {\n box-sizing: border-box; /* 1 */\n border-width: 0; /* 2 */\n border-style: solid; /* 2 */\n border-color: #e5e7eb; /* 2 */\n}\n\n::before,\n::after {\n --tw-content: '';\n}\n\n/*\n1. Use a consistent sensible line-height in all browsers.\n2. Prevent adjustments of font size after orientation changes in iOS.\n3. Use a more readable tab size.\n4. Use the user's configured `sans` font-family by default.\n5. Use the user's configured `sans` font-feature-settings by default.\n6. Use the user's configured `sans` font-variation-settings by default.\n7. Disable tap highlights on iOS\n*/\n\nhtml,\n:host {\n line-height: 1.5; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n -moz-tab-size: 4; /* 3 */\n -o-tab-size: 4;\n tab-size: 4; /* 3 */\n font-family: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\"; /* 4 */\n font-feature-settings: normal; /* 5 */\n font-variation-settings: normal; /* 6 */\n -webkit-tap-highlight-color: transparent; /* 7 */\n}\n\n/*\n1. Remove the margin in all browsers.\n2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.\n*/\n\nbody {\n margin: 0; /* 1 */\n line-height: inherit; /* 2 */\n}\n\n/*\n1. Add the correct height in Firefox.\n2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)\n3. Ensure horizontal rules are visible by default.\n*/\n\nhr {\n height: 0; /* 1 */\n color: inherit; /* 2 */\n border-top-width: 1px; /* 3 */\n}\n\n/*\nAdd the correct text decoration in Chrome, Edge, and Safari.\n*/\n\nabbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n}\n\n/*\nRemove the default font size and weight for headings.\n*/\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-size: inherit;\n font-weight: inherit;\n}\n\n/*\nReset links to optimize for opt-in styling instead of opt-out.\n*/\n\na {\n color: inherit;\n text-decoration: inherit;\n}\n\n/*\nAdd the correct font weight in Edge and Safari.\n*/\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/*\n1. Use the user's configured `mono` font-family by default.\n2. Use the user's configured `mono` font-feature-settings by default.\n3. Use the user's configured `mono` font-variation-settings by default.\n4. Correct the odd `em` font sizing in all browsers.\n*/\n\ncode,\nkbd,\nsamp,\npre {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace; /* 1 */\n font-feature-settings: normal; /* 2 */\n font-variation-settings: normal; /* 3 */\n font-size: 1em; /* 4 */\n}\n\n/*\nAdd the correct font size in all browsers.\n*/\n\nsmall {\n font-size: 80%;\n}\n\n/*\nPrevent `sub` and `sup` elements from affecting the line height in all browsers.\n*/\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/*\n1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)\n2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)\n3. Remove gaps between table borders by default.\n*/\n\ntable {\n text-indent: 0; /* 1 */\n border-color: inherit; /* 2 */\n border-collapse: collapse; /* 3 */\n}\n\n/*\n1. Change the font styles in all browsers.\n2. Remove the margin in Firefox and Safari.\n3. Remove default padding in all browsers.\n*/\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-feature-settings: inherit; /* 1 */\n font-variation-settings: inherit; /* 1 */\n font-size: 100%; /* 1 */\n font-weight: inherit; /* 1 */\n line-height: inherit; /* 1 */\n letter-spacing: inherit; /* 1 */\n color: inherit; /* 1 */\n margin: 0; /* 2 */\n padding: 0; /* 3 */\n}\n\n/*\nRemove the inheritance of text transform in Edge and Firefox.\n*/\n\nbutton,\nselect {\n text-transform: none;\n}\n\n/*\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Remove default button styles.\n*/\n\nbutton,\ninput:where([type='button']),\ninput:where([type='reset']),\ninput:where([type='submit']) {\n -webkit-appearance: button; /* 1 */\n background-color: transparent; /* 2 */\n background-image: none; /* 2 */\n}\n\n/*\nUse the modern Firefox focus style for all focusable elements.\n*/\n\n:-moz-focusring {\n outline: auto;\n}\n\n/*\nRemove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)\n*/\n\n:-moz-ui-invalid {\n box-shadow: none;\n}\n\n/*\nAdd the correct vertical alignment in Chrome and Firefox.\n*/\n\nprogress {\n vertical-align: baseline;\n}\n\n/*\nCorrect the cursor style of increment and decrement buttons in Safari.\n*/\n\n::-webkit-inner-spin-button,\n::-webkit-outer-spin-button {\n height: auto;\n}\n\n/*\n1. Correct the odd appearance in Chrome and Safari.\n2. Correct the outline style in Safari.\n*/\n\n[type='search'] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/*\nRemove the inner padding in Chrome and Safari on macOS.\n*/\n\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/*\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Change font properties to `inherit` in Safari.\n*/\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/*\nAdd the correct display in Chrome and Safari.\n*/\n\nsummary {\n display: list-item;\n}\n\n/*\nRemoves the default spacing and border for appropriate elements.\n*/\n\nblockquote,\ndl,\ndd,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nhr,\nfigure,\np,\npre {\n margin: 0;\n}\n\nfieldset {\n margin: 0;\n padding: 0;\n}\n\nlegend {\n padding: 0;\n}\n\nol,\nul,\nmenu {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/*\nReset default styling for dialogs.\n*/\ndialog {\n padding: 0;\n}\n\n/*\nPrevent resizing textareas horizontally by default.\n*/\n\ntextarea {\n resize: vertical;\n}\n\n/*\n1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)\n2. Set the default placeholder color to the user's configured gray 400 color.\n*/\n\ninput::-moz-placeholder, textarea::-moz-placeholder {\n opacity: 1; /* 1 */\n color: #9ca3af; /* 2 */\n}\n\ninput::placeholder,\ntextarea::placeholder {\n opacity: 1; /* 1 */\n color: #9ca3af; /* 2 */\n}\n\n/*\nSet the default cursor for buttons.\n*/\n\nbutton,\n[role=\"button\"] {\n cursor: pointer;\n}\n\n/*\nMake sure disabled buttons don't get the pointer cursor.\n*/\n:disabled {\n cursor: default;\n}\n\n/*\n1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)\n2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)\n This can trigger a poorly considered lint error in some tools but is included by design.\n*/\n\nimg,\nsvg,\nvideo,\ncanvas,\naudio,\niframe,\nembed,\nobject {\n display: block; /* 1 */\n vertical-align: middle; /* 2 */\n}\n\n/*\nConstrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)\n*/\n\nimg,\nvideo {\n max-width: 100%;\n height: auto;\n}\n\n/* Make elements with the HTML hidden attribute stay hidden by default */\n[hidden]:where(:not([hidden=\"until-found\"])) {\n display: none;\n}\n\n[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n background-color: #fff;\n border-color: #6b7280;\n border-width: 1px;\n border-radius: 0px;\n padding-top: 0.5rem;\n padding-right: 0.75rem;\n padding-bottom: 0.5rem;\n padding-left: 0.75rem;\n font-size: 1rem;\n line-height: 1.5rem;\n --tw-shadow: 0 0 #0000;\n}\n\n[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {\n outline: 2px solid transparent;\n outline-offset: 2px;\n --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: #2563eb;\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n border-color: #2563eb;\n}\n\ninput::-moz-placeholder, textarea::-moz-placeholder {\n color: #6b7280;\n opacity: 1;\n}\n\ninput::placeholder,textarea::placeholder {\n color: #6b7280;\n opacity: 1;\n}\n\n::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n}\n\n::-webkit-date-and-time-value {\n min-height: 1.5em;\n}\n\n::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {\n padding-top: 0;\n padding-bottom: 0;\n}\n\nselect {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e\");\n background-position: right 0.5rem center;\n background-repeat: no-repeat;\n background-size: 1.5em 1.5em;\n padding-right: 2.5rem;\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n}\n\n[multiple] {\n background-image: initial;\n background-position: initial;\n background-repeat: unset;\n background-size: initial;\n padding-right: 0.75rem;\n -webkit-print-color-adjust: unset;\n print-color-adjust: unset;\n}\n\n[type='checkbox'],[type='radio'] {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n padding: 0;\n -webkit-print-color-adjust: exact;\n print-color-adjust: exact;\n display: inline-block;\n vertical-align: middle;\n background-origin: border-box;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n flex-shrink: 0;\n height: 1rem;\n width: 1rem;\n color: #2563eb;\n background-color: #fff;\n border-color: #6b7280;\n border-width: 1px;\n --tw-shadow: 0 0 #0000;\n}\n\n[type='checkbox'] {\n border-radius: 0px;\n}\n\n[type='radio'] {\n border-radius: 100%;\n}\n\n[type='checkbox']:focus,[type='radio']:focus {\n outline: 2px solid transparent;\n outline-offset: 2px;\n --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);\n --tw-ring-offset-width: 2px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: #2563eb;\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n}\n\n[type='checkbox']:checked,[type='radio']:checked {\n border-color: transparent;\n background-color: currentColor;\n background-size: 100% 100%;\n background-position: center;\n background-repeat: no-repeat;\n}\n\n[type='checkbox']:checked {\n background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e\");\n}\n\n[type='radio']:checked {\n background-image: url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e\");\n}\n\n[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {\n border-color: transparent;\n background-color: currentColor;\n}\n\n[type='checkbox']:indeterminate {\n background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e\");\n border-color: transparent;\n background-color: currentColor;\n background-size: 100% 100%;\n background-position: center;\n background-repeat: no-repeat;\n}\n\n[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {\n border-color: transparent;\n background-color: currentColor;\n}\n\n[type='file'] {\n background: unset;\n border-color: inherit;\n border-width: 0;\n border-radius: 0;\n padding: 0;\n font-size: unset;\n line-height: inherit;\n}\n\n[type='file']:focus {\n outline: 1px solid ButtonText;\n outline: 1px auto -webkit-focus-ring-color;\n}\n.\\!container {\n width: 100% !important;\n}\n.container {\n width: 100%;\n}\n@media (min-width: 640px) {\n\n .\\!container {\n max-width: 640px !important;\n }\n\n .container {\n max-width: 640px;\n }\n}\n@media (min-width: 768px) {\n\n .\\!container {\n max-width: 768px !important;\n }\n\n .container {\n max-width: 768px;\n }\n}\n@media (min-width: 1024px) {\n\n .\\!container {\n max-width: 1024px !important;\n }\n\n .container {\n max-width: 1024px;\n }\n}\n@media (min-width: 1280px) {\n\n .\\!container {\n max-width: 1280px !important;\n }\n\n .container {\n max-width: 1280px;\n }\n}\n@media (min-width: 1536px) {\n\n .\\!container {\n max-width: 1536px !important;\n }\n\n .container {\n max-width: 1536px;\n }\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n.pointer-events-none {\n pointer-events: none;\n}\n.pointer-events-auto {\n pointer-events: auto;\n}\n.visible {\n visibility: visible;\n}\n.invisible {\n visibility: hidden;\n}\n.static {\n position: static;\n}\n.\\!fixed {\n position: fixed !important;\n}\n.fixed {\n position: fixed;\n}\n.absolute {\n position: absolute;\n}\n.relative {\n position: relative;\n}\n.-inset-0\\.5 {\n inset: -0.125rem;\n}\n.-inset-1 {\n inset: -0.25rem;\n}\n.-inset-2\\.5 {\n inset: -0.625rem;\n}\n.inset-0 {\n inset: 0px;\n}\n.inset-x-0 {\n left: 0px;\n right: 0px;\n}\n.inset-y-0 {\n top: 0px;\n bottom: 0px;\n}\n.-left-\\[15px\\] {\n left: -15px;\n}\n.-top-\\[21px\\] {\n top: -21px;\n}\n.bottom-0 {\n bottom: 0px;\n}\n.bottom-1\\/2 {\n bottom: 50%;\n}\n.bottom-4 {\n bottom: 1rem;\n}\n.left-0 {\n left: 0px;\n}\n.left-1\\/2 {\n left: 50%;\n}\n.left-\\[calc\\(50\\%-1px\\)\\] {\n left: calc(50% - 1px);\n}\n.right-0 {\n right: 0px;\n}\n.top-0 {\n top: 0px;\n}\n.top-1\\/2 {\n top: 50%;\n}\n.top-14 {\n top: 3.5rem;\n}\n.isolate {\n isolation: isolate;\n}\n.z-10 {\n z-index: 10;\n}\n.z-20 {\n z-index: 20;\n}\n.col-span-2 {\n grid-column: span 2 / span 2;\n}\n.col-span-6 {\n grid-column: span 6 / span 6;\n}\n.col-span-full {\n grid-column: 1 / -1;\n}\n.m-0 {\n margin: 0px;\n}\n.m-1 {\n margin: 0.25rem;\n}\n.m-1\\.5 {\n margin: 0.375rem;\n}\n.m-2 {\n margin: 0.5rem;\n}\n.m-4 {\n margin: 1rem;\n}\n.m-auto {\n margin: auto;\n}\n.-mx-4 {\n margin-left: -1rem;\n margin-right: -1rem;\n}\n.-my-2 {\n margin-top: -0.5rem;\n margin-bottom: -0.5rem;\n}\n.mx-8 {\n margin-left: 2rem;\n margin-right: 2rem;\n}\n.mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n.my-0 {\n margin-top: 0px;\n margin-bottom: 0px;\n}\n.my-2 {\n margin-top: 0.5rem;\n margin-bottom: 0.5rem;\n}\n.my-4 {\n margin-top: 1rem;\n margin-bottom: 1rem;\n}\n.my-auto {\n margin-top: auto;\n margin-bottom: auto;\n}\n.-ml-1 {\n margin-left: -0.25rem;\n}\n.-ml-10 {\n margin-left: -2.5rem;\n}\n.-ml-px {\n margin-left: -1px;\n}\n.-mr-px {\n margin-right: -1px;\n}\n.-mt-1 {\n margin-top: -0.25rem;\n}\n.-mt-2 {\n margin-top: -0.5rem;\n}\n.-mt-32 {\n margin-top: -8rem;\n}\n.mb-3 {\n margin-bottom: 0.75rem;\n}\n.mb-4 {\n margin-bottom: 1rem;\n}\n.mb-5 {\n margin-bottom: 1.25rem;\n}\n.mb-6 {\n margin-bottom: 1.5rem;\n}\n.ml-2 {\n margin-left: 0.5rem;\n}\n.ml-3 {\n margin-left: 0.75rem;\n}\n.ml-4 {\n margin-left: 1rem;\n}\n.ml-6 {\n margin-left: 1.5rem;\n}\n.ml-auto {\n margin-left: auto;\n}\n.mr-2 {\n margin-right: 0.5rem;\n}\n.mr-4 {\n margin-right: 1rem;\n}\n.mr-auto {\n margin-right: auto;\n}\n.mt-0 {\n margin-top: 0px;\n}\n.mt-0\\.5 {\n margin-top: 0.125rem;\n}\n.mt-1 {\n margin-top: 0.25rem;\n}\n.mt-10 {\n margin-top: 2.5rem;\n}\n.mt-2 {\n margin-top: 0.5rem;\n}\n.mt-3 {\n margin-top: 0.75rem;\n}\n.mt-4 {\n margin-top: 1rem;\n}\n.mt-5 {\n margin-top: 1.25rem;\n}\n.mt-6 {\n margin-top: 1.5rem;\n}\n.mt-8 {\n margin-top: 2rem;\n}\n.box-content {\n box-sizing: content-box;\n}\n.block {\n display: block;\n}\n.inline-block {\n display: inline-block;\n}\n.inline {\n display: inline;\n}\n.flex {\n display: flex;\n}\n.inline-flex {\n display: inline-flex;\n}\n.table {\n display: table;\n}\n.table-row {\n display: table-row;\n}\n.flow-root {\n display: flow-root;\n}\n.grid {\n display: grid;\n}\n.contents {\n display: contents;\n}\n.\\!hidden {\n display: none !important;\n}\n.hidden {\n display: none;\n}\n.size-4 {\n width: 1rem;\n height: 1rem;\n}\n.size-6 {\n width: 1.5rem;\n height: 1.5rem;\n}\n.h-0\\.5 {\n height: 0.125rem;\n}\n.h-1 {\n height: 0.25rem;\n}\n.h-1\\.5 {\n height: 0.375rem;\n}\n.h-10 {\n height: 2.5rem;\n}\n.h-12 {\n height: 3rem;\n}\n.h-16 {\n height: 4rem;\n}\n.h-2\\/5 {\n height: 40%;\n}\n.h-24 {\n height: 6rem;\n}\n.h-3 {\n height: 0.75rem;\n}\n.h-4 {\n height: 1rem;\n}\n.h-5 {\n height: 1.25rem;\n}\n.h-6 {\n height: 1.5rem;\n}\n.h-7 {\n height: 1.75rem;\n}\n.h-8 {\n height: 2rem;\n}\n.h-\\[260px\\] {\n height: 260px;\n}\n.h-\\[32px\\] {\n height: 32px;\n}\n.h-\\[4px\\] {\n height: 4px;\n}\n.h-\\[56px\\] {\n height: 56px;\n}\n.h-\\[6px\\] {\n height: 6px;\n}\n.h-full {\n height: 100%;\n}\n.max-h-60 {\n max-height: 15rem;\n}\n.min-h-\\[305px\\] {\n min-height: 305px;\n}\n.min-h-full {\n min-height: 100%;\n}\n.w-1\\.5 {\n width: 0.375rem;\n}\n.w-10 {\n width: 2.5rem;\n}\n.w-11 {\n width: 2.75rem;\n}\n.w-12 {\n width: 3rem;\n}\n.w-28 {\n width: 7rem;\n}\n.w-3 {\n width: 0.75rem;\n}\n.w-4 {\n width: 1rem;\n}\n.w-4\\/5 {\n width: 80%;\n}\n.w-44 {\n width: 11rem;\n}\n.w-5 {\n width: 1.25rem;\n}\n.w-56 {\n width: 14rem;\n}\n.w-6 {\n width: 1.5rem;\n}\n.w-7 {\n width: 1.75rem;\n}\n.w-8 {\n width: 2rem;\n}\n.w-\\[260px\\] {\n width: 260px;\n}\n.w-\\[2px\\] {\n width: 2px;\n}\n.w-\\[32px\\] {\n width: 32px;\n}\n.w-\\[4px\\] {\n width: 4px;\n}\n.w-\\[6px\\] {\n width: 6px;\n}\n.w-auto {\n width: auto;\n}\n.w-fit {\n width: -moz-fit-content;\n width: fit-content;\n}\n.w-full {\n width: 100%;\n}\n.w-screen {\n width: 100vw;\n}\n.min-w-0 {\n min-width: 0px;\n}\n.min-w-\\[310px\\] {\n min-width: 310px;\n}\n.min-w-fit {\n min-width: -moz-fit-content;\n min-width: fit-content;\n}\n.min-w-full {\n min-width: 100%;\n}\n.max-w-2xl {\n max-width: 42rem;\n}\n.max-w-7xl {\n max-width: 80rem;\n}\n.max-w-\\[325px\\] {\n max-width: 325px;\n}\n.max-w-full {\n max-width: 100%;\n}\n.max-w-md {\n max-width: 28rem;\n}\n.max-w-xl {\n max-width: 36rem;\n}\n.max-w-xs {\n max-width: 20rem;\n}\n.flex-1 {\n flex: 1 1 0%;\n}\n.flex-auto {\n flex: 1 1 auto;\n}\n.flex-none {\n flex: none;\n}\n.flex-shrink-0 {\n flex-shrink: 0;\n}\n.shrink-0 {\n flex-shrink: 0;\n}\n.flex-grow {\n flex-grow: 1;\n}\n.grow {\n flex-grow: 1;\n}\n.origin-\\[center_bottom_0\\] {\n transform-origin: center bottom 0;\n}\n.-translate-x-1\\/2 {\n --tw-translate-x: -50%;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.-translate-y-1\\/2 {\n --tw-translate-y: -50%;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.translate-x-5 {\n --tw-translate-x: 1.25rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.translate-x-6 {\n --tw-translate-x: 1.5rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.rotate-0 {\n --tw-rotate: 0deg;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.rotate-45 {\n --tw-rotate: 45deg;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.animate-\\[show-up-clock_350ms_linear\\] {\n animation: show-up-clock 350ms linear;\n}\n@keyframes pulse {\n\n 50% {\n opacity: .5;\n }\n}\n.animate-pulse {\n animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n@keyframes spin {\n\n to {\n transform: rotate(360deg);\n }\n}\n.animate-spin {\n animation: spin 1s linear infinite;\n}\n.cursor-default {\n cursor: default;\n}\n.cursor-not-allowed {\n cursor: not-allowed;\n}\n.cursor-pointer {\n cursor: pointer;\n}\n.select-none {\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n}\n.grid-cols-1 {\n grid-template-columns: repeat(1, minmax(0, 1fr));\n}\n.grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.grid-cols-7 {\n grid-template-columns: repeat(7, minmax(0, 1fr));\n}\n.flex-row {\n flex-direction: row;\n}\n.flex-col {\n flex-direction: column;\n}\n.flex-wrap {\n flex-wrap: wrap;\n}\n.items-start {\n align-items: flex-start;\n}\n.items-center {\n align-items: center;\n}\n.items-baseline {\n align-items: baseline;\n}\n.items-stretch {\n align-items: stretch;\n}\n.justify-start {\n justify-content: flex-start;\n}\n.justify-end {\n justify-content: flex-end;\n}\n.justify-center {\n justify-content: center;\n}\n.justify-between {\n justify-content: space-between;\n}\n.justify-around {\n justify-content: space-around;\n}\n.justify-evenly {\n justify-content: space-evenly;\n}\n.gap-1 {\n gap: 0.25rem;\n}\n.gap-4 {\n gap: 1rem;\n}\n.gap-px {\n gap: 1px;\n}\n.gap-x-0\\.5 {\n -moz-column-gap: 0.125rem;\n column-gap: 0.125rem;\n}\n.gap-x-1\\.5 {\n -moz-column-gap: 0.375rem;\n column-gap: 0.375rem;\n}\n.gap-x-2 {\n -moz-column-gap: 0.5rem;\n column-gap: 0.5rem;\n}\n.gap-x-3 {\n -moz-column-gap: 0.75rem;\n column-gap: 0.75rem;\n}\n.gap-x-4 {\n -moz-column-gap: 1rem;\n column-gap: 1rem;\n}\n.gap-x-6 {\n -moz-column-gap: 1.5rem;\n column-gap: 1.5rem;\n}\n.gap-x-8 {\n -moz-column-gap: 2rem;\n column-gap: 2rem;\n}\n.gap-y-2 {\n row-gap: 0.5rem;\n}\n.gap-y-3 {\n row-gap: 0.75rem;\n}\n.gap-y-4 {\n row-gap: 1rem;\n}\n.gap-y-6 {\n row-gap: 1.5rem;\n}\n.gap-y-7 {\n row-gap: 1.75rem;\n}\n.gap-y-8 {\n row-gap: 2rem;\n}\n.-space-y-px > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(-1px * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(-1px * var(--tw-space-y-reverse));\n}\n.space-x-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-x-reverse: 0;\n margin-right: calc(1rem * var(--tw-space-x-reverse));\n margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));\n}\n.space-y-1 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));\n}\n.space-y-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\n}\n.space-y-6 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));\n}\n.divide-x > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-x-reverse: 0;\n border-right-width: calc(1px * var(--tw-divide-x-reverse));\n border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));\n}\n.divide-y > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-y-reverse: 0;\n border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\n border-bottom-width: calc(1px * var(--tw-divide-y-reverse));\n}\n.divide-gray-100 > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-opacity: 1;\n border-color: rgb(243 244 246 / var(--tw-divide-opacity, 1));\n}\n.divide-gray-200 > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-opacity: 1;\n border-color: rgb(229 231 235 / var(--tw-divide-opacity, 1));\n}\n.divide-gray-300 > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-divide-opacity, 1));\n}\n.self-center {\n align-self: center;\n}\n.overflow-auto {\n overflow: auto;\n}\n.overflow-hidden {\n overflow: hidden;\n}\n.overflow-visible {\n overflow: visible;\n}\n.overflow-x-auto {\n overflow-x: auto;\n}\n.overflow-y-auto {\n overflow-y: auto;\n}\n.overflow-x-hidden {\n overflow-x: hidden;\n}\n.overflow-y-scroll {\n overflow-y: scroll;\n}\n.truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.whitespace-nowrap {\n white-space: nowrap;\n}\n.whitespace-pre {\n white-space: pre;\n}\n.whitespace-pre-wrap {\n white-space: pre-wrap;\n}\n.whitespace-break-spaces {\n white-space: break-spaces;\n}\n.break-words {\n overflow-wrap: break-word;\n}\n.break-all {\n word-break: break-all;\n}\n.rounded {\n border-radius: 0.25rem;\n}\n.rounded-\\[100\\%\\] {\n border-radius: 100%;\n}\n.rounded-\\[50\\%\\] {\n border-radius: 50%;\n}\n.rounded-full {\n border-radius: 9999px;\n}\n.rounded-lg {\n border-radius: 0.5rem;\n}\n.rounded-md {\n border-radius: 0.375rem;\n}\n.rounded-none {\n border-radius: 0px;\n}\n.rounded-sm {\n border-radius: 0.125rem;\n}\n.rounded-xl {\n border-radius: 0.75rem;\n}\n.rounded-b-lg {\n border-bottom-right-radius: 0.5rem;\n border-bottom-left-radius: 0.5rem;\n}\n.rounded-l-lg {\n border-top-left-radius: 0.5rem;\n border-bottom-left-radius: 0.5rem;\n}\n.rounded-l-md {\n border-top-left-radius: 0.375rem;\n border-bottom-left-radius: 0.375rem;\n}\n.rounded-l-none {\n border-top-left-radius: 0px;\n border-bottom-left-radius: 0px;\n}\n.rounded-r-lg {\n border-top-right-radius: 0.5rem;\n border-bottom-right-radius: 0.5rem;\n}\n.rounded-r-md {\n border-top-right-radius: 0.375rem;\n border-bottom-right-radius: 0.375rem;\n}\n.rounded-t-lg {\n border-top-left-radius: 0.5rem;\n border-top-right-radius: 0.5rem;\n}\n.rounded-t-sm {\n border-top-left-radius: 0.125rem;\n border-top-right-radius: 0.125rem;\n}\n.rounded-bl-md {\n border-bottom-left-radius: 0.375rem;\n}\n.rounded-br-md {\n border-bottom-right-radius: 0.375rem;\n}\n.rounded-tl-md {\n border-top-left-radius: 0.375rem;\n}\n.rounded-tr-md {\n border-top-right-radius: 0.375rem;\n}\n.border {\n border-width: 1px;\n}\n.border-0 {\n border-width: 0px;\n}\n.border-2 {\n border-width: 2px;\n}\n.border-\\[14px\\] {\n border-width: 14px;\n}\n.border-b {\n border-bottom-width: 1px;\n}\n.border-b-2 {\n border-bottom-width: 2px;\n}\n.border-r-0 {\n border-right-width: 0px;\n}\n.border-r-2 {\n border-right-width: 2px;\n}\n.border-t {\n border-top-width: 1px;\n}\n.border-t-2 {\n border-top-width: 2px;\n}\n.border-solid {\n border-style: solid;\n}\n.border-dashed {\n border-style: dashed;\n}\n.border-none {\n border-style: none;\n}\n.border-\\[\\#3b71ca\\] {\n --tw-border-opacity: 1;\n border-color: rgb(59 113 202 / var(--tw-border-opacity, 1));\n}\n.border-gray-100 {\n --tw-border-opacity: 1;\n border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));\n}\n.border-gray-200 {\n --tw-border-opacity: 1;\n border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));\n}\n.border-gray-300 {\n --tw-border-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\n}\n.border-gray-800 {\n --tw-border-opacity: 1;\n border-color: rgb(31 41 55 / var(--tw-border-opacity, 1));\n}\n.border-gray-900\\/10 {\n border-color: rgb(17 24 39 / 0.1);\n}\n.border-gray-900\\/25 {\n border-color: rgb(17 24 39 / 0.25);\n}\n.border-indigo-200 {\n --tw-border-opacity: 1;\n border-color: rgb(199 210 254 / var(--tw-border-opacity, 1));\n}\n.border-indigo-400 {\n --tw-border-opacity: 1;\n border-color: rgb(129 140 248 / var(--tw-border-opacity, 1));\n}\n.border-indigo-600 {\n --tw-border-opacity: 1;\n border-color: rgb(79 70 229 / var(--tw-border-opacity, 1));\n}\n.border-red-700 {\n --tw-border-opacity: 1;\n border-color: rgb(185 28 28 / var(--tw-border-opacity, 1));\n}\n.border-transparent {\n border-color: transparent;\n}\n.border-opacity-25 {\n --tw-border-opacity: 0.25;\n}\n.bg-\\[\\#00000012\\] {\n background-color: #00000012;\n}\n.bg-\\[\\#3b71ca\\] {\n --tw-bg-opacity: 1;\n background-color: rgb(59 113 202 / var(--tw-bg-opacity, 1));\n}\n.bg-black {\n --tw-bg-opacity: 1;\n background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));\n}\n.bg-blue-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));\n}\n.bg-blue-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-300 {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(107 114 128 / var(--tw-bg-opacity, 1));\n}\n.bg-green-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(220 252 231 / var(--tw-bg-opacity, 1));\n}\n.bg-green-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));\n}\n.bg-indigo-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(238 242 255 / var(--tw-bg-opacity, 1));\n}\n.bg-indigo-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(79 70 229 / var(--tw-bg-opacity, 1));\n}\n.bg-red-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1));\n}\n.bg-red-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1));\n}\n.bg-slate-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(226 232 240 / var(--tw-bg-opacity, 1));\n}\n.bg-transparent {\n background-color: transparent;\n}\n.bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.bg-yellow-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 249 195 / var(--tw-bg-opacity, 1));\n}\n.bg-opacity-75 {\n --tw-bg-opacity: 0.75;\n}\n.fill-yellow-500 {\n fill: #eab308;\n}\n.stroke-gray-700\\/50 {\n stroke: rgb(55 65 81 / 0.5);\n}\n.object-cover {\n -o-object-fit: cover;\n object-fit: cover;\n}\n.p-0 {\n padding: 0px;\n}\n.p-1 {\n padding: 0.25rem;\n}\n.p-1\\.5 {\n padding: 0.375rem;\n}\n.p-12 {\n padding: 3rem;\n}\n.p-2 {\n padding: 0.5rem;\n}\n.p-3 {\n padding: 0.75rem;\n}\n.p-4 {\n padding: 1rem;\n}\n.p-8 {\n padding: 2rem;\n}\n.px-0 {\n padding-left: 0px;\n padding-right: 0px;\n}\n.px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n}\n.px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n.px-4 {\n padding-left: 1rem;\n padding-right: 1rem;\n}\n.px-5 {\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n}\n.px-6 {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n}\n.px-\\[12px\\] {\n padding-left: 12px;\n padding-right: 12px;\n}\n.py-1 {\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n}\n.py-1\\.5 {\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n}\n.py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n.py-3 {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n}\n.py-3\\.5 {\n padding-top: 0.875rem;\n padding-bottom: 0.875rem;\n}\n.py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n.py-5 {\n padding-top: 1.25rem;\n padding-bottom: 1.25rem;\n}\n.py-6 {\n padding-top: 1.5rem;\n padding-bottom: 1.5rem;\n}\n.pb-32 {\n padding-bottom: 8rem;\n}\n.pb-4 {\n padding-bottom: 1rem;\n}\n.pl-1 {\n padding-left: 0.25rem;\n}\n.pl-10 {\n padding-left: 2.5rem;\n}\n.pl-2 {\n padding-left: 0.5rem;\n}\n.pl-3 {\n padding-left: 0.75rem;\n}\n.pl-4 {\n padding-left: 1rem;\n}\n.pr-10 {\n padding-right: 2.5rem;\n}\n.pr-12 {\n padding-right: 3rem;\n}\n.pr-2 {\n padding-right: 0.5rem;\n}\n.pr-3 {\n padding-right: 0.75rem;\n}\n.pr-4 {\n padding-right: 1rem;\n}\n.pr-9 {\n padding-right: 2.25rem;\n}\n.pt-2 {\n padding-top: 0.5rem;\n}\n.pt-4 {\n padding-top: 1rem;\n}\n.pt-5 {\n padding-top: 1.25rem;\n}\n.pt-6 {\n padding-top: 1.5rem;\n}\n.text-left {\n text-align: left;\n}\n.text-center {\n text-align: center;\n}\n.text-right {\n text-align: right;\n}\n.align-middle {\n vertical-align: middle;\n}\n.text-2xl {\n font-size: 1.5rem;\n line-height: 2rem;\n}\n.text-4xl {\n font-size: 2.25rem;\n line-height: 2.5rem;\n}\n.text-\\[0\\.625rem\\] {\n font-size: 0.625rem;\n}\n.text-\\[1\\.1rem\\] {\n font-size: 1.1rem;\n}\n.text-\\[18px\\] {\n font-size: 18px;\n}\n.text-\\[3\\.75rem\\] {\n font-size: 3.75rem;\n}\n.text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n.text-base\\/7 {\n font-size: 1rem;\n line-height: 1.75rem;\n}\n.text-lg {\n font-size: 1.125rem;\n line-height: 1.75rem;\n}\n.text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.text-sm\\/6 {\n font-size: 0.875rem;\n line-height: 1.5rem;\n}\n.text-xl {\n font-size: 1.25rem;\n line-height: 1.75rem;\n}\n.text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n.font-bold {\n font-weight: 700;\n}\n.font-light {\n font-weight: 300;\n}\n.font-medium {\n font-weight: 500;\n}\n.font-normal {\n font-weight: 400;\n}\n.font-semibold {\n font-weight: 600;\n}\n.uppercase {\n text-transform: uppercase;\n}\n.lowercase {\n text-transform: lowercase;\n}\n.leading-10 {\n line-height: 2.5rem;\n}\n.leading-5 {\n line-height: 1.25rem;\n}\n.leading-6 {\n line-height: 1.5rem;\n}\n.leading-7 {\n line-height: 1.75rem;\n}\n.leading-9 {\n line-height: 2.25rem;\n}\n.leading-\\[1\\.2\\] {\n line-height: 1.2;\n}\n.leading-none {\n line-height: 1;\n}\n.tracking-tight {\n letter-spacing: -0.025em;\n}\n.text-\\[\\#ffffff8a\\] {\n color: #ffffff8a;\n}\n.text-\\[grey\\] {\n --tw-text-opacity: 1;\n color: rgb(128 128 128 / var(--tw-text-opacity, 1));\n}\n.text-\\[red\\] {\n --tw-text-opacity: 1;\n color: rgb(255 0 0 / var(--tw-text-opacity, 1));\n}\n.text-black {\n --tw-text-opacity: 1;\n color: rgb(0 0 0 / var(--tw-text-opacity, 1));\n}\n.text-blue-600 {\n --tw-text-opacity: 1;\n color: rgb(37 99 235 / var(--tw-text-opacity, 1));\n}\n.text-blue-700 {\n --tw-text-opacity: 1;\n color: rgb(29 78 216 / var(--tw-text-opacity, 1));\n}\n.text-gray-300 {\n --tw-text-opacity: 1;\n color: rgb(209 213 219 / var(--tw-text-opacity, 1));\n}\n.text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\n}\n.text-gray-700 {\n --tw-text-opacity: 1;\n color: rgb(55 65 81 / var(--tw-text-opacity, 1));\n}\n.text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.text-green-600 {\n --tw-text-opacity: 1;\n color: rgb(22 163 74 / var(--tw-text-opacity, 1));\n}\n.text-green-800 {\n --tw-text-opacity: 1;\n color: rgb(22 101 52 / var(--tw-text-opacity, 1));\n}\n.text-indigo-200 {\n --tw-text-opacity: 1;\n color: rgb(199 210 254 / var(--tw-text-opacity, 1));\n}\n.text-indigo-600 {\n --tw-text-opacity: 1;\n color: rgb(79 70 229 / var(--tw-text-opacity, 1));\n}\n.text-indigo-700 {\n --tw-text-opacity: 1;\n color: rgb(67 56 202 / var(--tw-text-opacity, 1));\n}\n.text-indigo-900 {\n --tw-text-opacity: 1;\n color: rgb(49 46 129 / var(--tw-text-opacity, 1));\n}\n.text-red-600 {\n --tw-text-opacity: 1;\n color: rgb(220 38 38 / var(--tw-text-opacity, 1));\n}\n.text-red-700 {\n --tw-text-opacity: 1;\n color: rgb(185 28 28 / var(--tw-text-opacity, 1));\n}\n.text-red-900 {\n --tw-text-opacity: 1;\n color: rgb(127 29 29 / var(--tw-text-opacity, 1));\n}\n.text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.text-yellow-400 {\n --tw-text-opacity: 1;\n color: rgb(250 204 21 / var(--tw-text-opacity, 1));\n}\n.text-yellow-700 {\n --tw-text-opacity: 1;\n color: rgb(161 98 7 / var(--tw-text-opacity, 1));\n}\n.underline {\n text-decoration-line: underline;\n}\n.underline-offset-2 {\n text-underline-offset: 2px;\n}\n.opacity-0 {\n opacity: 0;\n}\n.opacity-\\[\\.54\\] {\n opacity: .54;\n}\n.shadow {\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-sm {\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-xl {\n --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.ring-0 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.ring-1 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.ring-2 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.ring-inset {\n --tw-ring-inset: inset;\n}\n.ring-black {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity, 1));\n}\n.ring-gray-200 {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity, 1));\n}\n.ring-gray-300 {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity, 1));\n}\n.ring-gray-600 {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity, 1));\n}\n.ring-gray-900\\/5 {\n --tw-ring-color: rgb(17 24 39 / 0.05);\n}\n.ring-indigo-600 {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1));\n}\n.ring-red-300 {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(252 165 165 / var(--tw-ring-opacity, 1));\n}\n.ring-opacity-5 {\n --tw-ring-opacity: 0.05;\n}\n.filter {\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\n}\n.transition {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-all {\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-colors {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-opacity {\n transition-property: opacity;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-transform {\n transition-property: transform;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.delay-1000 {\n transition-delay: 1000ms;\n}\n.duration-200 {\n transition-duration: 200ms;\n}\n.duration-300 {\n transition-duration: 300ms;\n}\n.ease-in-out {\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n}\n.selection\\:bg-transparent *::-moz-selection {\n background-color: transparent;\n}\n.selection\\:bg-transparent *::selection {\n background-color: transparent;\n}\n.selection\\:bg-transparent::-moz-selection {\n background-color: transparent;\n}\n.selection\\:bg-transparent::selection {\n background-color: transparent;\n}\n.placeholder\\:text-gray-400::-moz-placeholder {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.placeholder\\:text-gray-400::placeholder {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.placeholder\\:text-red-300::-moz-placeholder {\n --tw-text-opacity: 1;\n color: rgb(252 165 165 / var(--tw-text-opacity, 1));\n}\n.placeholder\\:text-red-300::placeholder {\n --tw-text-opacity: 1;\n color: rgb(252 165 165 / var(--tw-text-opacity, 1));\n}\n.last\\:border-none:last-child {\n border-style: none;\n}\n.odd\\:bg-white:nth-child(odd) {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.even\\:bg-gray-100:nth-child(even) {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.visited\\:text-purple-600:visited {\n color: rgb(147 51 234 );\n}\n.focus-within\\:z-10:focus-within {\n z-index: 10;\n}\n.focus-within\\:outline-none:focus-within {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n.focus-within\\:ring-2:focus-within {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.focus-within\\:ring-indigo-600:focus-within {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1));\n}\n.focus-within\\:ring-offset-2:focus-within {\n --tw-ring-offset-width: 2px;\n}\n.hover\\:bg-\\[\\#00000026\\]:hover {\n background-color: #00000026;\n}\n.hover\\:bg-blue-500:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-200:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-300:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-50:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-500\\/20:hover {\n background-color: rgb(107 114 128 / 0.2);\n}\n.hover\\:bg-gray-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-green-500:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-indigo-500:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(99 102 241 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-indigo-600:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(79 70 229 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-red-500:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-opacity-75:hover {\n --tw-bg-opacity: 0.75;\n}\n.hover\\:text-blue-600:hover {\n --tw-text-opacity: 1;\n color: rgb(37 99 235 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-blue-900:hover {\n --tw-text-opacity: 1;\n color: rgb(30 58 138 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-gray-400:hover {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-gray-500:hover {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-gray-700:hover {\n --tw-text-opacity: 1;\n color: rgb(55 65 81 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-indigo-500:hover {\n --tw-text-opacity: 1;\n color: rgb(99 102 241 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-indigo-600:hover {\n --tw-text-opacity: 1;\n color: rgb(79 70 229 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-indigo-900:hover {\n --tw-text-opacity: 1;\n color: rgb(49 46 129 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-white:hover {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.hover\\:opacity-70:hover {\n opacity: 0.7;\n}\n.hover\\:outline-none:hover {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n.hover\\:ring-indigo-500:hover {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1));\n}\n.focus\\:z-10:focus {\n z-index: 10;\n}\n.focus\\:border-indigo-500:focus {\n --tw-border-opacity: 1;\n border-color: rgb(99 102 241 / var(--tw-border-opacity, 1));\n}\n.focus\\:bg-\\[\\#00000026\\]:focus {\n background-color: #00000026;\n}\n.focus\\:outline-none:focus {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n.focus\\:ring-2:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.focus\\:ring-inset:focus {\n --tw-ring-inset: inset;\n}\n.focus\\:ring-indigo-500:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity, 1));\n}\n.focus\\:ring-indigo-600:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1));\n}\n.focus\\:ring-red-500:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1));\n}\n.focus\\:ring-white:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity, 1));\n}\n.focus\\:ring-offset-2:focus {\n --tw-ring-offset-width: 2px;\n}\n.focus\\:ring-offset-indigo-600:focus {\n --tw-ring-offset-color: #4f46e5;\n}\n.focus-visible\\:outline:focus-visible {\n outline-style: solid;\n}\n.focus-visible\\:outline-2:focus-visible {\n outline-width: 2px;\n}\n.focus-visible\\:outline-offset-0:focus-visible {\n outline-offset: 0px;\n}\n.focus-visible\\:outline-offset-2:focus-visible {\n outline-offset: 2px;\n}\n.focus-visible\\:outline-blue-600:focus-visible {\n outline-color: #2563eb;\n}\n.focus-visible\\:outline-gray-600:focus-visible {\n outline-color: #4b5563;\n}\n.focus-visible\\:outline-green-600:focus-visible {\n outline-color: #16a34a;\n}\n.focus-visible\\:outline-indigo-600:focus-visible {\n outline-color: #4f46e5;\n}\n.focus-visible\\:outline-red-600:focus-visible {\n outline-color: #dc2626;\n}\n.active\\:ring-2:active {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.active\\:ring-indigo-600:active {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1));\n}\n.active\\:ring-offset-2:active {\n --tw-ring-offset-width: 2px;\n}\n.disabled\\:cursor-default:disabled {\n cursor: default;\n}\n.disabled\\:cursor-not-allowed:disabled {\n cursor: not-allowed;\n}\n.disabled\\:bg-gray-100:disabled {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.disabled\\:bg-gray-200:disabled {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.disabled\\:bg-gray-300:disabled {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\n}\n.disabled\\:bg-gray-50:disabled {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\n}\n.disabled\\:bg-gray-600:disabled {\n --tw-bg-opacity: 1;\n background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));\n}\n.disabled\\:text-gray-500:disabled {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.disabled\\:opacity-50:disabled {\n opacity: 0.5;\n}\n.disabled\\:ring-gray-200:disabled {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity, 1));\n}\n.disabled\\:hover\\:bg-gray-600:hover:disabled {\n --tw-bg-opacity: 1;\n background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));\n}\n.group[open] .group-open\\:rotate-180 {\n --tw-rotate: 180deg;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.group:hover .group-hover\\:flex {\n display: flex;\n}\n.group:hover .group-hover\\:border-indigo-600 {\n --tw-border-opacity: 1;\n border-color: rgb(79 70 229 / var(--tw-border-opacity, 1));\n}\n.group:hover .group-hover\\:stroke-gray-700\\/75 {\n stroke: rgb(55 65 81 / 0.75);\n}\n.group:hover .group-hover\\:text-indigo-600 {\n --tw-text-opacity: 1;\n color: rgb(79 70 229 / var(--tw-text-opacity, 1));\n}\n.group.attention-danger .group-\\[\\.attention-danger\\]\\:bg-red-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\n}\n.group.attention-danger .group-\\[\\.attention-danger\\]\\:bg-red-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1));\n}\n.group.attention-info .group-\\[\\.attention-info\\]\\:bg-blue-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));\n}\n.group.attention-info .group-\\[\\.attention-info\\]\\:bg-blue-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));\n}\n.group.attention-low .group-\\[\\.attention-low\\]\\:bg-gray-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.group.attention-low .group-\\[\\.attention-low\\]\\:bg-gray-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));\n}\n.group.attention-success .group-\\[\\.attention-success\\]\\:bg-green-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(240 253 244 / var(--tw-bg-opacity, 1));\n}\n.group.attention-success .group-\\[\\.attention-success\\]\\:bg-green-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));\n}\n.group.attention-warning .group-\\[\\.attention-warning\\]\\:bg-yellow-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 252 232 / var(--tw-bg-opacity, 1));\n}\n.group.attention-warning .group-\\[\\.attention-warning\\]\\:bg-yellow-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(202 138 4 / var(--tw-bg-opacity, 1));\n}\n.group.attention-danger .group-\\[\\.attention-danger\\]\\:text-red-400 {\n --tw-text-opacity: 1;\n color: rgb(248 113 113 / var(--tw-text-opacity, 1));\n}\n.group.attention-danger .group-\\[\\.attention-danger\\]\\:text-red-700 {\n --tw-text-opacity: 1;\n color: rgb(185 28 28 / var(--tw-text-opacity, 1));\n}\n.group.attention-danger .group-\\[\\.attention-danger\\]\\:text-red-800 {\n --tw-text-opacity: 1;\n color: rgb(153 27 27 / var(--tw-text-opacity, 1));\n}\n.group.attention-info .group-\\[\\.attention-info\\]\\:text-blue-400 {\n --tw-text-opacity: 1;\n color: rgb(96 165 250 / var(--tw-text-opacity, 1));\n}\n.group.attention-info .group-\\[\\.attention-info\\]\\:text-blue-700 {\n --tw-text-opacity: 1;\n color: rgb(29 78 216 / var(--tw-text-opacity, 1));\n}\n.group.attention-info .group-\\[\\.attention-info\\]\\:text-blue-800 {\n --tw-text-opacity: 1;\n color: rgb(30 64 175 / var(--tw-text-opacity, 1));\n}\n.group.attention-success .group-\\[\\.attention-success\\]\\:text-green-400 {\n --tw-text-opacity: 1;\n color: rgb(74 222 128 / var(--tw-text-opacity, 1));\n}\n.group.attention-success .group-\\[\\.attention-success\\]\\:text-green-700 {\n --tw-text-opacity: 1;\n color: rgb(21 128 61 / var(--tw-text-opacity, 1));\n}\n.group.attention-success .group-\\[\\.attention-success\\]\\:text-green-800 {\n --tw-text-opacity: 1;\n color: rgb(22 101 52 / var(--tw-text-opacity, 1));\n}\n.group.attention-warning .group-\\[\\.attention-warning\\]\\:text-yellow-400 {\n --tw-text-opacity: 1;\n color: rgb(250 204 21 / var(--tw-text-opacity, 1));\n}\n.group.attention-warning .group-\\[\\.attention-warning\\]\\:text-yellow-700 {\n --tw-text-opacity: 1;\n color: rgb(161 98 7 / var(--tw-text-opacity, 1));\n}\n.group.attention-warning .group-\\[\\.attention-warning\\]\\:text-yellow-800 {\n --tw-text-opacity: 1;\n color: rgb(133 77 14 / var(--tw-text-opacity, 1));\n}\n.data-\\[selection\\=charge-wallet\\]\\:visible[data-selection=\"charge-wallet\"] {\n visibility: visible;\n}\n.data-\\[selection\\=wire-transfer\\]\\:visible[data-selection=\"wire-transfer\"] {\n visibility: visible;\n}\n.data-\\[checked\\=true\\]\\:z-10[data-checked=\"true\"] {\n z-index: 10;\n}\n.data-\\[selected\\=false\\]\\:hidden[data-selected=\"false\"] {\n display: none;\n}\n.data-\\[enabled\\=false\\]\\:translate-x-0[data-enabled=\"false\"] {\n --tw-translate-x: 0px;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.data-\\[state\\=off\\]\\:translate-x-0[data-state=\"off\"] {\n --tw-translate-x: 0px;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.data-\\[state\\=undefined\\]\\:translate-x-3[data-state=\"undefined\"] {\n --tw-translate-x: 0.75rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.data-\\[status\\=ok\\]\\:scale-y-0[data-status=\"ok\"] {\n --tw-scale-y: 0;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.data-\\[disabled\\=false\\]\\:cursor-pointer[data-disabled=\"false\"] {\n cursor: pointer;\n}\n.data-\\[disabled\\=true\\]\\:cursor-not-allowed[data-disabled=\"true\"] {\n cursor: not-allowed;\n}\n.data-\\[fixed\\=false\\]\\:cursor-pointer[data-fixed=\"false\"] {\n cursor: pointer;\n}\n.data-\\[left\\=true\\]\\:rounded-l-md[data-left=\"true\"] {\n border-top-left-radius: 0.375rem;\n border-bottom-left-radius: 0.375rem;\n}\n.data-\\[right\\=true\\]\\:rounded-r-md[data-right=\"true\"] {\n border-top-right-radius: 0.375rem;\n border-bottom-right-radius: 0.375rem;\n}\n.data-\\[timed\\=true\\]\\:rounded-b-none[data-timed=\"true\"] {\n border-bottom-right-radius: 0px;\n border-bottom-left-radius: 0px;\n}\n.data-\\[checked\\=true\\]\\:border-indigo-200[data-checked=\"true\"] {\n --tw-border-opacity: 1;\n border-color: rgb(199 210 254 / var(--tw-border-opacity, 1));\n}\n.data-\\[enabled\\=true\\]\\:border-indigo-600[data-enabled=\"true\"] {\n --tw-border-opacity: 1;\n border-color: rgb(79 70 229 / var(--tw-border-opacity, 1));\n}\n.data-\\[checked\\=true\\]\\:bg-indigo-50[data-checked=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(238 242 255 / var(--tw-bg-opacity, 1));\n}\n.data-\\[disabled\\=true\\]\\:bg-gray-200[data-disabled=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.data-\\[disabled\\=true\\]\\:bg-gray-50[data-disabled=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\n}\n.data-\\[enabled\\=false\\]\\:bg-gray-200[data-enabled=\"false\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.data-\\[month\\=false\\]\\:bg-gray-100[data-month=\"false\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.data-\\[month\\=true\\]\\:bg-white[data-month=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.data-\\[negative\\=true\\]\\:bg-red-100[data-negative=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1));\n}\n.data-\\[selected\\=true\\]\\:\\!bg-blue-400[data-selected=\"true\"] {\n --tw-bg-opacity: 1 !important;\n background-color: rgb(96 165 250 / var(--tw-bg-opacity, 1)) !important;\n}\n.data-\\[selected\\=true\\]\\:bg-\\[\\#3b71ca\\][data-selected=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(59 113 202 / var(--tw-bg-opacity, 1));\n}\n.data-\\[selected\\=true\\]\\:bg-indigo-500[data-selected=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(99 102 241 / var(--tw-bg-opacity, 1));\n}\n.data-\\[state\\=off\\]\\:bg-gray-200[data-state=\"off\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.data-\\[state\\=undefined\\]\\:bg-gray-200[data-state=\"undefined\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.data-\\[status\\=deleted\\]\\:bg-gray-100[data-status=\"deleted\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.data-\\[status\\=fail\\]\\:bg-red-200[data-status=\"fail\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(254 202 202 / var(--tw-bg-opacity, 1));\n}\n.data-\\[status\\=ok\\]\\:bg-green-200[data-status=\"ok\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(187 247 208 / var(--tw-bg-opacity, 1));\n}\n.data-\\[today\\=true\\]\\:bg-red-300[data-today=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(252 165 165 / var(--tw-bg-opacity, 1));\n}\n.data-\\[left\\=true\\]\\:text-left[data-left=\"true\"] {\n text-align: left;\n}\n.data-\\[selected\\=true\\]\\:font-normal[data-selected=\"true\"] {\n font-weight: 400;\n}\n.data-\\[today\\=true\\]\\:font-semibold[data-today=\"true\"] {\n font-weight: 600;\n}\n.data-\\[checked\\=true\\]\\:text-indigo-600[data-checked=\"true\"] {\n --tw-text-opacity: 1;\n color: rgb(79 70 229 / var(--tw-text-opacity, 1));\n}\n.data-\\[checked\\=true\\]\\:text-indigo-900[data-checked=\"true\"] {\n --tw-text-opacity: 1;\n color: rgb(49 46 129 / var(--tw-text-opacity, 1));\n}\n.data-\\[disabled\\=true\\]\\:text-gray-500[data-disabled=\"true\"] {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.data-\\[month\\=true\\]\\:text-gray-900[data-month=\"true\"] {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.data-\\[negative\\=false\\]\\:text-green-600[data-negative=\"false\"] {\n --tw-text-opacity: 1;\n color: rgb(22 163 74 / var(--tw-text-opacity, 1));\n}\n.data-\\[negative\\=true\\]\\:text-red-600[data-negative=\"true\"] {\n --tw-text-opacity: 1;\n color: rgb(220 38 38 / var(--tw-text-opacity, 1));\n}\n.data-\\[negative\\=true\\]\\:text-red-700[data-negative=\"true\"] {\n --tw-text-opacity: 1;\n color: rgb(185 28 28 / var(--tw-text-opacity, 1));\n}\n.data-\\[selected\\=true\\]\\:text-gray-900[data-selected=\"true\"] {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.data-\\[selected\\=true\\]\\:text-white[data-selected=\"true\"] {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.data-\\[enabled\\=true\\]\\:ring-2[data-enabled=\"true\"] {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.data-\\[selected\\=true\\]\\:ring-2[data-selected=\"true\"] {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.data-\\[enabled\\=true\\]\\:ring-indigo-600[data-enabled=\"true\"] {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1));\n}\n.data-\\[error\\=true\\]\\:ring-red-500[data-error=\"true\"] {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity, 1));\n}\n.data-\\[selected\\=true\\]\\:ring-indigo-600[data-selected=\"true\"] {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(79 70 229 / var(--tw-ring-opacity, 1));\n}\n.data-\\[month\\=true\\]\\:hover\\:bg-gray-200:hover[data-month=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.data-\\[selected\\=true\\]\\:hover\\:\\!bg-blue-300:hover[data-selected=\"true\"] {\n --tw-bg-opacity: 1 !important;\n background-color: rgb(147 197 253 / var(--tw-bg-opacity, 1)) !important;\n}\n.data-\\[today\\=true\\]\\:hover\\:bg-red-200:hover[data-today=\"true\"] {\n --tw-bg-opacity: 1;\n background-color: rgb(254 202 202 / var(--tw-bg-opacity, 1));\n}\n@media (min-width: 640px) {\n\n .sm\\:col-span-2 {\n grid-column: span 2 / span 2;\n }\n\n .sm\\:col-span-5 {\n grid-column: span 5 / span 5;\n }\n\n .sm\\:col-span-6 {\n grid-column: span 6 / span 6;\n }\n\n .sm\\:-mx-6 {\n margin-left: -1.5rem;\n margin-right: -1.5rem;\n }\n\n .sm\\:mx-0 {\n margin-left: 0px;\n margin-right: 0px;\n }\n\n .sm\\:mx-auto {\n margin-left: auto;\n margin-right: auto;\n }\n\n .sm\\:my-8 {\n margin-top: 2rem;\n margin-bottom: 2rem;\n }\n\n .sm\\:ml-16 {\n margin-left: 4rem;\n }\n\n .sm\\:mt-0 {\n margin-top: 0px;\n }\n\n .sm\\:mt-5 {\n margin-top: 1.25rem;\n }\n\n .sm\\:mt-6 {\n margin-top: 1.5rem;\n }\n\n .sm\\:block {\n display: block;\n }\n\n .sm\\:inline {\n display: inline;\n }\n\n .sm\\:flex {\n display: flex;\n }\n\n .sm\\:table-cell {\n display: table-cell;\n }\n\n .sm\\:grid {\n display: grid;\n }\n\n .sm\\:hidden {\n display: none;\n }\n\n .sm\\:w-96 {\n width: 24rem;\n }\n\n .sm\\:w-full {\n width: 100%;\n }\n\n .sm\\:max-w-sm {\n max-width: 24rem;\n }\n\n .sm\\:flex-auto {\n flex: 1 1 auto;\n }\n\n .sm\\:flex-none {\n flex: none;\n }\n\n .sm\\:grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .sm\\:grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n\n .sm\\:grid-cols-6 {\n grid-template-columns: repeat(6, minmax(0, 1fr));\n }\n\n .sm\\:flex-nowrap {\n flex-wrap: nowrap;\n }\n\n .sm\\:items-center {\n align-items: center;\n }\n\n .sm\\:justify-end {\n justify-content: flex-end;\n }\n\n .sm\\:justify-between {\n justify-content: space-between;\n }\n\n .sm\\:gap-4 {\n gap: 1rem;\n }\n\n .sm\\:gap-x-4 {\n -moz-column-gap: 1rem;\n column-gap: 1rem;\n }\n\n .sm\\:rounded-lg {\n border-radius: 0.5rem;\n }\n\n .sm\\:rounded-none {\n border-radius: 0px;\n }\n\n .sm\\:rounded-xl {\n border-radius: 0.75rem;\n }\n\n .sm\\:p-6 {\n padding: 1.5rem;\n }\n\n .sm\\:p-8 {\n padding: 2rem;\n }\n\n .sm\\:px-0 {\n padding-left: 0px;\n padding-right: 0px;\n }\n\n .sm\\:px-6 {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n }\n\n .sm\\:px-8 {\n padding-left: 2rem;\n padding-right: 2rem;\n }\n\n .sm\\:pl-0 {\n padding-left: 0px;\n }\n\n .sm\\:pl-3 {\n padding-left: 0.75rem;\n }\n\n .sm\\:pr-0 {\n padding-right: 0px;\n }\n\n .sm\\:text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n }\n\n .sm\\:leading-6 {\n line-height: 1.5rem;\n }\n}\n@media (min-width: 768px) {\n\n .md\\:col-span-2 {\n grid-column: span 2 / span 2;\n }\n\n .md\\:grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .md\\:grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n\n .md\\:divide-x > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-x-reverse: 0;\n border-right-width: calc(1px * var(--tw-divide-x-reverse));\n border-left-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));\n }\n\n .md\\:divide-y-0 > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-y-reverse: 0;\n border-top-width: calc(0px * calc(1 - var(--tw-divide-y-reverse)));\n border-bottom-width: calc(0px * var(--tw-divide-y-reverse));\n }\n}\n@media (min-width: 1024px) {\n\n .lg\\:-mx-8 {\n margin-left: -2rem;\n margin-right: -2rem;\n }\n\n .lg\\:px-8 {\n padding-left: 2rem;\n padding-right: 2rem;\n }\n}\n.rtl\\:\\!left-auto:where([dir=\"rtl\"], [dir=\"rtl\"] *) {\n left: auto !important;\n}\n.rtl\\:\\!origin-\\[50\\%_50\\%_0\\]:where([dir=\"rtl\"], [dir=\"rtl\"] *) {\n transform-origin: 50% 50% 0 !important;\n}\n@media (prefers-color-scheme: dark) {\n\n .dark\\:bg-zinc-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(113 113 122 / var(--tw-bg-opacity, 1));\n }\n\n .dark\\:bg-zinc-600\\/50 {\n background-color: rgb(82 82 91 / 0.5);\n }\n\n .dark\\:bg-zinc-700 {\n --tw-bg-opacity: 1;\n background-color: rgb(63 63 70 / var(--tw-bg-opacity, 1));\n }\n}\n"], "mappings": "AAAA,EAAG,QAAU,OACX,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,aACA,aACA,kBACA,6BAA6B,UAC7B,8BACA,6BACA,4BACA,eACA,oBACA,sBACA,uBACA,wBACA,kBACA,wBAAwB,IACxB,wBAAwB,KACxB,iBAAiB,IAAI,GAAG,IAAI,IAAI,EAAE,IAClC,yBAAyB,EAAE,EAAE,MAC7B,kBAAkB,EAAE,EAAE,MACtB,aAAa,EAAE,EAAE,MACjB,qBAAqB,EAAE,EAAE,MACzB,YACA,kBACA,gBACA,iBACA,kBACA,cACA,gBACA,aACA,mBACA,qBACA,2BACA,yBACA,0BACA,2BACA,uBACA,wBACA,yBACA,sBACA,oBACA,sBACA,qBACA,oBACF,CAEA,WACE,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,aACA,aACA,kBACA,6BAA6B,UAC7B,8BACA,6BACA,4BACA,eACA,oBACA,sBACA,uBACA,wBACA,kBACA,wBAAwB,IACxB,wBAAwB,KACxB,iBAAiB,IAAI,GAAG,IAAI,IAAI,EAAE,IAClC,yBAAyB,EAAE,EAAE,MAC7B,kBAAkB,EAAE,EAAE,MACtB,aAAa,EAAE,EAAE,MACjB,qBAAqB,EAAE,EAAE,MACzB,YACA,kBACA,gBACA,iBACA,kBACA,cACA,gBACA,aACA,mBACA,qBACA,2BACA,yBACA,0BACA,2BACA,uBACA,wBACA,yBACA,sBACA,oBACA,sBACA,qBACA,oBACF,CAOA,EACA,QACA,OACE,WAAY,WACZ,aAAc,EACd,aAAc,MACd,aAAc,OAChB,CAEA,QACA,OACE,cAAc,EAChB,CAYA,KACA,MACE,YAAa,IACb,yBAA0B,KAC1B,cAAe,EACf,YAAa,EACV,SAAU,EACb,YAAa,aAAa,CAAE,SAAS,CAAE,UAAU,CAAE,mBAAmB,CAAE,gBAAgB,CAAE,eAAiB,CAAE,mBAC7G,sBAA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e,KACjB,CACA,CAAC,KACC,WAAY,KACZ,cAAe,IACjB,CACA,CAAC,QACC,WAAY,KACZ,cAAe,IACjB,CACA,CAAC,MACC,YAAa,OACf,CACA,CAAC,OACC,YAAa,OACf,CACA,CAAC,OACC,YAAa,IACf,CACA,CAAC,OACC,aAAc,IAChB,CACA,CAAC,MACC,WAAY,OACd,CACA,CAAC,MACC,WAAY,MACd,CACA,CAAC,OACC,WAAY,KACd,CACA,CAAC,KACC,cAAe,MACjB,CACA,CAAC,KACC,cAAe,IACjB,CACA,CAAC,KACC,cAAe,OACjB,CACA,CAAC,KACC,cAAe,MACjB,CACA,CAAC,KACC,YAAa,KACf,CACA,CAAC,KACC,YAAa,MACf,CACA,CAAC,KACC,YAAa,IACf,CACA,CAAC,KACC,YAAa,MACf,CACA,CAAC,QACC,YAAa,IACf,CACA,CAAC,KACC,aAAc,KAChB,CACA,CAAC,KACC,aAAc,IAChB,CACA,CAAC,QACC,aAAc,IAChB,CACA,CAAC,KACC,WAAY,CACd,CACA,CAAC,QACC,WAAY,OACd,CACA,CAAC,KACC,WAAY,MACd,CACA,CAAC,MACC,WAAY,MACd,CACA,CAAC,KACC,WAAY,KACd,CACA,CAAC,KACC,WAAY,MACd,CACA,CAAC,KACC,WAAY,IACd,CACA,CAAC,KACC,WAAY,OACd,CACA,CAAC,KACC,WAAY,MACd,CACA,CAAC,KACC,WAAY,IACd,CACA,CAAC,YACC,WAAY,WACd,CACA,CAAC,MACC,QAAS,KACX,CACA,CAAC,aACC,QAAS,YACX,CACA,CAAC,OACC,QAAS,MACX,CACA,CAAC,KACC,QAAS,IACX,CACA,CAAC,YACC,QAAS,WACX,CACA,CAAC,MACC,QAAS,KACX,CACA,CAAC,UACC,QAAS,SACX,CACA,CAAC,UACC,QAAS,SACX,CACA,CAAC,KACC,QAAS,IACX,CACA,CAAC,SACC,QAAS,QACX,CACA,CAAC,SACC,QAAS,cACX,CACA,CAAC,OACC,QAAS,IACX,CACA,CAAC,OACC,MAAO,KACP,OAAQ,IACV,CACA,CAAC,OACC,MAAO,OACP,OAAQ,MACV,CACA,CAAC,OACC,OAAQ,OACV,CACA,CAAC,IACC,OAAQ,MACV,CACA,CAAC,OACC,OAAQ,OACV,CACA,CAAC,KACC,OAAQ,MACV,CACA,CAAC,KACC,OAAQ,IACV,CACA,CAAC,KACC,OAAQ,IACV,CACA,CAAC,OACC,OAAQ,GACV,CACA,CAAC,KACC,OAAQ,IACV,CACA,CAAC,IACC,OAAQ,MACV,CACA,CAAC,IACC,OAAQ,IACV,CACA,CAAC,IACC,OAAQ,OACV,CACA,CAAC,IACC,OAAQ,MACV,CACA,CAAC,IACC,OAAQ,OACV,CACA,CAAC,IACC,OAAQ,IACV,CACA,CAAC,YACC,OAAQ,KACV,CACA,CAAC,WACC,OAAQ,IACV,CACA,CAAC,UACC,OAAQ,GACV,CACA,CAAC,WACC,OAAQ,IACV,CACA,CAAC,UACC,OAAQ,GACV,CACA,CAAC,OACC,OAAQ,IACV,CACA,CAAC,SACC,WAAY,KACd,CACA,CAAC,gBACC,WAAY,KACd,CACA,CAAC,WACC,WAAY,IACd,CACA,CAAC,OACC,MAAO,OACT,CACA,CAAC,KACC,MAAO,MACT,CACA,CAAC,KACC,MAAO,OACT,CACA,CAAC,KACC,MAAO,IACT,CACA,CAAC,KACC,MAAO,IACT,CACA,CAAC,IACC,MAAO,MACT,CACA,CAAC,IACC,MAAO,IACT,CACA,CAAC,OACC,MAAO,GACT,CACA,CAAC,KACC,MAAO,KACT,CACA,CAAC,IACC,MAAO,OACT,CACA,CAAC,KACC,MAAO,KACT,CACA,CAAC,IACC,MAAO,MACT,CACA,CAAC,IACC,MAAO,OACT,CACA,CAAC,IACC,MAAO,IACT,CACA,CAAC,YACC,MAAO,KACT,CACA,CAAC,UACC,MAAO,GACT,CACA,CAAC,WACC,MAAO,IACT,CACA,CAAC,UACC,MAAO,GACT,CACA,CAAC,UACC,MAAO,GACT,CACA,CAAC,OACC,MAAO,IACT,CACA,CAAC,MACC,MAAO,iBACP,MAAO,WACT,CACA,CAAC,OACC,MAAO,IACT,CACA,CAAC,SACC,MAAO,KACT,CACA,CAAC,QACC,UAAW,GACb,CACA,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jtDD,QAktDW,IACX,CACA,CAAC,KACC,aAAc,EACd,cAAe,CACjB,CACA,CAAC,KACC,aAAc,MACd,cAAe,KACjB,CACA,CAAC,KACC,aAAc,OACd,cAAe,MACjB,CACA,CAAC,KACC,aAAc,KACd,cAAe,IACjB,CACA,CAAC,KACC,aAAc,QACd,cAAe,OACjB,CACA,CAAC,KACC,aAAc,OACd,cAAe,MACjB,CACA,CAAC,YACC,aAAc,KACd,cAAe,IACjB,CACA,CAAC,KACC,YAAa,OACb,eAAgB,MAClB,CACA,CAAC,QACC,YAAa,QACb,eAAgB,OAClB,CACA,CAAC,KACC,YAAa,MACb,eAAgB,KAClB,CACA,CAAC,KACC,YAAa,OACb,eAAgB,MAClB,CACA,CAAC,QACC,YAAa,QACb,eAAgB,OAClB,CACA,CAAC,KACC,YAAa,KACb,eAAgB,IAClB,CACA,CAAC,KACC,YAAa,QACb,eAAgB,OAClB,CACA,CAAC,KACC,YAAa,OACb,eAAgB,MAClB,CACA,CAAC,MACC,eAAgB,IAClB,CACA,CAAC,KACC,eAAgB,IAClB,CACA,CAAC,KACC,aAAc,MAChB,CACA,CAAC,MACC,aAAc,MAChB,CACA,CAAC,KACC,aAAc,KAChB,CACA,CAAC,KACC,aAAc,MAChB,CACA,CAAC,KACC,aAAc,IAChB,CACA,CAAC,MACC,cAAe,MACjB,CACA,CAAC,MACC,cAAe,IACjB,CACA,CAAC,KACC,cAAe,KACjB,CACA,CAAC,KACC,cAAe,MACjB,CACA,CAAC,KACC,cAAe,IACjB,CACA,CAAC,KACC,cAAe,OACjB,CACA,CAAC,KACC,YAAa,KACf,CACA,CAAC,KACC,YAAa,IACf,CACA,CAAC,KACC,YAAa,OACf,CACA,CAAC,KACC,YAAa,MACf,CACA,CAAC,UACC,WAAY,IACd,CACA,CAAC,YACC,WAAY,MACd,CACA,CAAC,WACC,WAAY,KACd,CACA,CAAC,aACC,eAAgB,MAClB,CACA,CAAC,SACC,UAAW,OACX,YAAa,IACf,CACA,CAAC,SACC,UAAW,QACX,YAAa,MACf,CACA,CAAC,mBACC,UAAW,OA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", "names": [] } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libeufin-1.6.8/contrib/wallet-core/bank/build-metadata.json�����������������������������������������0000664�0001750�0001750�00001262050�15204341712�024111� 0����������������������������������������������������������������������������������������������������ustar �grothoff������������������������grothoff���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{"inputs":{"../taler-util/lib/nacl-fast.js":{"bytes":74831,"imports":[],"format":"esm"},"../taler-util/lib/prng-browser.js":{"bytes":970,"imports":[{"path":"../taler-util/lib/nacl-fast.js","kind":"import-statement","original":"./nacl-fast.js"}],"format":"esm"},"../taler-util/lib/punycode.js":{"bytes":14970,"imports":[],"format":"esm"},"../taler-util/lib/whatwg-url.js":{"bytes":55145,"imports":[{"path":"../taler-util/lib/punycode.js","kind":"import-statement","original":"./punycode.js"}],"format":"esm"},"../taler-util/lib/url.js":{"bytes":1850,"imports":[{"path":"../taler-util/lib/whatwg-url.js","kind":"import-statement","original":"./whatwg-url.js"}],"format":"esm"},"../taler-util/lib/helpers.js":{"bytes":3146,"imports":[{"path":"../taler-util/lib/url.js","kind":"import-statement","original":"./url.js"}],"format":"esm"},"../taler-util/lib/logging.js":{"bytes":7650,"imports":[],"format":"esm"},"../taler-util/lib/codec.js":{"bytes":14511,"imports":[{"path":"../taler-util/lib/helpers.js","kind":"import-statement","original":"./helpers.js"},{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"}],"format":"esm"},"../taler-util/lib/CancellationToken.js":{"bytes":7762,"imports":[],"format":"esm"},"../taler-util/lib/taler-error-codes.js":{"bytes":283939,"imports":[],"format":"esm"},"../taler-util/lib/time.js":{"bytes":20908,"imports":[{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"}],"format":"esm"},"../taler-util/lib/errors.js":{"bytes":4628,"imports":[{"path":"../taler-util/lib/CancellationToken.js","kind":"import-statement","original":"./CancellationToken.js"},{"path":"../taler-util/lib/taler-error-codes.js","kind":"import-statement","original":"./taler-error-codes.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/http-common.js":{"bytes":13519,"imports":[{"path":"../taler-util/lib/errors.js","kind":"import-statement","original":"./errors.js"},{"path":"../taler-util/lib/helpers.js","kind":"import-statement","original":"./helpers.js"},{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"},{"path":"../taler-util/lib/taler-error-codes.js","kind":"import-statement","original":"./taler-error-codes.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/libtool-version.js":{"bytes":2266,"imports":[],"format":"esm"},"../taler-util/lib/types-taler-common.js":{"bytes":6127,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/operation.js":{"bytes":6461,"imports":[{"path":"../taler-util/lib/errors.js","kind":"import-statement","original":"./errors.js"},{"path":"../taler-util/lib/http-common.js","kind":"import-statement","original":"./http-common.js"},{"path":"../taler-util/lib/libtool-version.js","kind":"import-statement","original":"./libtool-version.js"},{"path":"../taler-util/lib/taler-error-codes.js","kind":"import-statement","original":"./taler-error-codes.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"}],"format":"esm"},"../taler-util/lib/amounts.js":{"bytes":21858,"imports":[{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"./operation.js"}],"format":"esm"},"../taler-util/lib/http-impl.missing.js":{"bytes":957,"imports":[],"format":"esm"},"../taler-util/lib/http.js":{"bytes":1042,"imports":[{"path":"../taler-util/lib/http-impl.missing.js","kind":"import-statement","original":"#http-impl"},{"path":"../taler-util/lib/http-common.js","kind":"import-statement","original":"./http-common.js"}],"format":"esm"},"../taler-util/lib/base64.js":{"bytes":3325,"imports":[],"format":"esm"},"../../node_modules/.pnpm/big-integer@1.6.52/node_modules/big-integer/BigInteger.js":{"bytes":51958,"imports":[],"format":"cjs"},"../../node_modules/.pnpm/fflate@0.8.1/node_modules/fflate/esm/browser.js":{"bytes":87479,"imports":[],"format":"esm"},"../../node_modules/.pnpm/hash-wasm@4.11.0/node_modules/hash-wasm/dist/index.esm.js":{"bytes":263595,"imports":[],"format":"esm"},"../taler-util/lib/argon2-impl.wasm.js":{"bytes":411,"imports":[{"path":"../../node_modules/.pnpm/hash-wasm@4.11.0/node_modules/hash-wasm/dist/index.esm.js","kind":"import-statement","original":"hash-wasm"}],"format":"esm"},"../taler-util/lib/argon2.js":{"bytes":255,"imports":[{"path":"../taler-util/lib/argon2-impl.wasm.js","kind":"import-statement","original":"#argon2-impl"}],"format":"esm"},"../taler-util/lib/sha256.js":{"bytes":10718,"imports":[],"format":"esm"},"../taler-util/lib/kdf.js":{"bytes":1750,"imports":[{"path":"../taler-util/lib/nacl-fast.js","kind":"import-statement","original":"./nacl-fast.js"},{"path":"../taler-util/lib/sha256.js","kind":"import-statement","original":"./sha256.js"}],"format":"esm"},"../taler-util/lib/taler_signatures.js":{"bytes":16438,"imports":[],"format":"esm"},"../taler-util/lib/result.js":{"bytes":1471,"imports":[],"format":"esm"},"../taler-util/lib/bech32.js":{"bytes":6022,"imports":[{"path":"../taler-util/lib/errors.js","kind":"import-statement","original":"./errors.js"},{"path":"../taler-util/lib/result.js","kind":"import-statement","original":"./result.js"}],"format":"esm"},"../taler-util/lib/segwit_addr.js":{"bytes":4194,"imports":[{"path":"../taler-util/lib/bech32.js","kind":"import-statement","original":"./bech32.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"./operation.js"},{"path":"../taler-util/lib/result.js","kind":"import-statement","original":"./result.js"}],"format":"esm"},"../taler-util/lib/bitcoin.js":{"bytes":3047,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/result.js","kind":"import-statement","original":"./result.js"},{"path":"../taler-util/lib/segwit_addr.js","kind":"import-statement","original":"./segwit_addr.js"}],"format":"esm"},"../taler-util/lib/iban.js":{"bytes":11984,"imports":[{"path":"../taler-util/lib/result.js","kind":"import-statement","original":"./result.js"}],"format":"esm"},"../taler-util/lib/payto.js":{"bytes":31242,"imports":[{"path":"../taler-util/lib/bech32.js","kind":"import-statement","original":"./bech32.js"},{"path":"../taler-util/lib/bitcoin.js","kind":"import-statement","original":"./bitcoin.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/errors.js","kind":"import-statement","original":"./errors.js"},{"path":"../taler-util/lib/iban.js","kind":"import-statement","original":"./iban.js"},{"path":"../taler-util/lib/result.js","kind":"import-statement","original":"./result.js"},{"path":"../taler-util/lib/taler-crypto.js","kind":"import-statement","original":"./taler-crypto.js"},{"path":"../taler-util/lib/url.js","kind":"import-statement","original":"./url.js"}],"format":"esm"},"../taler-util/lib/taler-form-attributes.js":{"bytes":23144,"imports":[],"format":"esm"},"../taler-util/lib/types-taler-exchange.js":{"bytes":30881,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/helpers.js","kind":"import-statement","original":"./helpers.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"},{"path":"../taler-util/lib/taler-error-codes.js","kind":"import-statement","original":"./taler-error-codes.js"},{"path":"../taler-util/lib/taler-form-attributes.js","kind":"import-statement","original":"./taler-form-attributes.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"}],"format":"esm"},"../taler-util/lib/taler-crypto.js":{"bytes":54476,"imports":[{"path":"../../node_modules/.pnpm/big-integer@1.6.52/node_modules/big-integer/BigInteger.js","kind":"import-statement","original":"big-integer"},{"path":"../../node_modules/.pnpm/fflate@0.8.1/node_modules/fflate/esm/browser.js","kind":"import-statement","original":"fflate"},{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/argon2.js","kind":"import-statement","original":"./argon2.js"},{"path":"../taler-util/lib/helpers.js","kind":"import-statement","original":"./helpers.js"},{"path":"../taler-util/lib/kdf.js","kind":"import-statement","original":"./kdf.js"},{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"},{"path":"../taler-util/lib/nacl-fast.js","kind":"import-statement","original":"./nacl-fast.js"},{"path":"../taler-util/lib/nacl-fast.js","kind":"import-statement","original":"./nacl-fast.js"},{"path":"../taler-util/lib/taler_signatures.js","kind":"import-statement","original":"./taler_signatures.js"},{"path":"../taler-util/lib/types-taler-exchange.js","kind":"import-statement","original":"./types-taler-exchange.js"}],"format":"esm"},"../taler-util/lib/http-client/utils.js":{"bytes":2236,"imports":[{"path":"../taler-util/lib/base64.js","kind":"import-statement","original":"../base64.js"},{"path":"../taler-util/lib/taler-crypto.js","kind":"import-statement","original":"../taler-crypto.js"}],"format":"esm"},"../taler-util/lib/bank-api-client.js":{"bytes":8169,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"@gnu-taler/taler-util/http"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./http-client/utils.js"}],"format":"esm"},"../taler-util/lib/types-taler-wallet.js":{"bytes":47555,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/helpers.js","kind":"import-statement","original":"./helpers.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"},{"path":"../taler-util/lib/types-taler-exchange.js","kind":"import-statement","original":"./types-taler-exchange.js"},{"path":"../taler-util/lib/types-taler-merchant.js","kind":"import-statement","original":"./types-taler-merchant.js"}],"format":"esm"},"../taler-util/lib/types-taler-merchant.js":{"bytes":68247,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"./index.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"},{"path":"../taler-util/lib/types-taler-wallet.js","kind":"import-statement","original":"./types-taler-wallet.js"}],"format":"esm"},"../taler-util/lib/contract-terms.js":{"bytes":13701,"imports":[{"path":"../taler-util/lib/errors.js","kind":"import-statement","original":"./errors.js"},{"path":"../taler-util/lib/helpers.js","kind":"import-statement","original":"./helpers.js"},{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"},{"path":"../taler-util/lib/taler-crypto.js","kind":"import-statement","original":"./taler-crypto.js"},{"path":"../taler-util/lib/types-taler-merchant.js","kind":"import-statement","original":"./types-taler-merchant.js"}],"format":"esm"},"../taler-util/lib/fnutils.js":{"bytes":1206,"imports":[],"format":"esm"},"../taler-util/lib/http-status-codes.js":{"bytes":18535,"imports":[],"format":"esm"},"../taler-util/lib/types-taler-bank-conversion.js":{"bytes":2959,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"}],"format":"esm"},"../taler-util/lib/http-client/bank-conversion.js":{"bytes":8169,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"../amounts.js"},{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"../http-status-codes.js"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"../http.js"},{"path":"../taler-util/lib/libtool-version.js","kind":"import-statement","original":"../libtool-version.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/taler-error-codes.js","kind":"import-statement","original":"../taler-error-codes.js"},{"path":"../taler-util/lib/types-taler-bank-conversion.js","kind":"import-statement","original":"../types-taler-bank-conversion.js"},{"path":"../taler-util/lib/types-taler-wallet.js","kind":"import-statement","original":"../types-taler-wallet.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"../taler-util/lib/taleruri.js":{"bytes":48419,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/errors.js","kind":"import-statement","original":"./errors.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"},{"path":"../taler-util/lib/result.js","kind":"import-statement","original":"./result.js"},{"path":"../taler-util/lib/taler-error-codes.js","kind":"import-statement","original":"./taler-error-codes.js"},{"path":"../taler-util/lib/url.js","kind":"import-statement","original":"./url.js"}],"format":"esm"},"../taler-util/lib/types-taler-corebank.js":{"bytes":13214,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"},{"path":"../taler-util/lib/taleruri.js","kind":"import-statement","original":"./taleruri.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-bank-conversion.js","kind":"import-statement","original":"./types-taler-bank-conversion.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"},{"path":"../taler-util/lib/types-taler-merchant.js","kind":"import-statement","original":"./types-taler-merchant.js"}],"format":"esm"},"../taler-util/lib/http-client/bank-core.js":{"bytes":51071,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"@gnu-taler/taler-util/http"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/types-taler-corebank.js","kind":"import-statement","original":"../types-taler-corebank.js"},{"path":"../taler-util/lib/types-taler-merchant.js","kind":"import-statement","original":"../types-taler-merchant.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"../taler-util/lib/types-taler-bank-integration.js":{"bytes":3370,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"}],"format":"esm"},"../taler-util/lib/http-client/bank-integration.js":{"bytes":6418,"imports":[{"path":"../taler-util/lib/http-common.js","kind":"import-statement","original":"../http-common.js"},{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"../http-status-codes.js"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"../http.js"},{"path":"../taler-util/lib/libtool-version.js","kind":"import-statement","original":"../libtool-version.js"},{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"../logging.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/taler-error-codes.js","kind":"import-statement","original":"../taler-error-codes.js"},{"path":"../taler-util/lib/types-taler-bank-integration.js","kind":"import-statement","original":"../types-taler-bank-integration.js"},{"path":"../taler-util/lib/types-taler-corebank.js","kind":"import-statement","original":"../types-taler-corebank.js"},{"path":"../taler-util/lib/types-taler-wallet.js","kind":"import-statement","original":"../types-taler-wallet.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"../taler-util/lib/types-taler-revenue.js":{"bytes":2048,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/http-client/bank-revenue.js":{"bytes":3751,"imports":[{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"../http-status-codes.js"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"../http.js"},{"path":"../taler-util/lib/libtool-version.js","kind":"import-statement","original":"../libtool-version.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/types-taler-revenue.js","kind":"import-statement","original":"../types-taler-revenue.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"../taler-util/lib/types-taler-wire-gateway.js":{"bytes":6550,"imports":[{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"./index.js"},{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"}],"format":"esm"},"../taler-util/lib/http-client/bank-wire.js":{"bytes":11631,"imports":[{"path":"../taler-util/lib/http-common.js","kind":"import-statement","original":"../http-common.js"},{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"../http-status-codes.js"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"../http.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/types-taler-wire-gateway.js","kind":"import-statement","original":"../types-taler-wire-gateway.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"},{"path":"../taler-util/lib/types-taler-wire-gateway.js","kind":"import-statement","original":"../types-taler-wire-gateway.js"},{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"../index.js"}],"format":"esm"},"../taler-util/lib/types-taler-prepared-transfer.js":{"bytes":4000,"imports":[{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"}],"format":"esm"},"../taler-util/lib/http-client/bank-prepared.js":{"bytes":4615,"imports":[{"path":"../taler-util/lib/http-common.js","kind":"import-statement","original":"../http-common.js"},{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"../http-status-codes.js"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"../http.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"../index.js"},{"path":"../taler-util/lib/types-taler-prepared-transfer.js","kind":"import-statement","original":"../types-taler-prepared-transfer.js"}],"format":"esm"},"../taler-util/lib/types-taler-challenger.js":{"bytes":4591,"imports":[{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/http-client/challenger.js":{"bytes":9801,"imports":[{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"../http-status-codes.js"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"../http.js"},{"path":"../taler-util/lib/libtool-version.js","kind":"import-statement","original":"../libtool-version.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/types-taler-challenger.js","kind":"import-statement","original":"../types-taler-challenger.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"../taler-util/lib/types-donau.js":{"bytes":3122,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"}],"format":"esm"},"../taler-util/lib/http-client/donau-client.js":{"bytes":11135,"imports":[{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"../http-status-codes.js"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"../http.js"},{"path":"../taler-util/lib/libtool-version.js","kind":"import-statement","original":"../libtool-version.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"../index.js"},{"path":"../taler-util/lib/types-donau.js","kind":"import-statement","original":"../types-donau.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"../taler-util/lib/http-client/exchange-client.js":{"bytes":38604,"imports":[{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"../codec.js"},{"path":"../taler-util/lib/http-common.js","kind":"import-statement","original":"../http-common.js"},{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"../http-status-codes.js"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"../http.js"},{"path":"../taler-util/lib/libtool-version.js","kind":"import-statement","original":"../libtool-version.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/taler-crypto.js","kind":"import-statement","original":"../taler-crypto.js"},{"path":"../taler-util/lib/types-taler-exchange.js","kind":"import-statement","original":"../types-taler-exchange.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"},{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"../index.js"},{"path":"../taler-util/lib/types-taler-wallet.js","kind":"import-statement","original":"../types-taler-wallet.js"}],"format":"esm"},"../taler-util/lib/http-client/mailbox.js":{"bytes":7964,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"@gnu-taler/taler-util/http"}],"format":"esm"},"../taler-util/lib/http-client/merchant.js":{"bytes":133620,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"@gnu-taler/taler-util/http"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"../operation.js"},{"path":"../taler-util/lib/http-client/utils.js","kind":"import-statement","original":"./utils.js"}],"format":"esm"},"../taler-util/lib/http-client/officer-account.js":{"bytes":3344,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"}],"format":"esm"},"../../node_modules/.pnpm/jed@1.1.1/node_modules/jed/jed.js":{"bytes":37829,"imports":[],"format":"cjs"},"../taler-util/lib/i18n.js":{"bytes":4086,"imports":[{"path":"../../node_modules/.pnpm/jed@1.1.1/node_modules/jed/jed.js","kind":"import-statement","original":"jed"},{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"}],"format":"esm"},"../taler-util/lib/invariants.js":{"bytes":2078,"imports":[],"format":"esm"},"../taler-util/lib/promises.js":{"bytes":2728,"imports":[],"format":"esm"},"../taler-util/lib/longpool-queue.js":{"bytes":2689,"imports":[{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"},{"path":"../taler-util/lib/promises.js","kind":"import-statement","original":"./promises.js"}],"format":"esm"},"../taler-util/lib/notifications.js":{"bytes":3363,"imports":[],"format":"esm"},"../taler-util/lib/timer.js":{"bytes":4774,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"}],"format":"esm"},"../taler-util/lib/observability.js":{"bytes":3101,"imports":[{"path":"../taler-util/lib/notifications.js","kind":"import-statement","original":"./notifications.js"},{"path":"../taler-util/lib/errors.js","kind":"import-statement","original":"./errors.js"},{"path":"../taler-util/lib/CancellationToken.js","kind":"import-statement","original":"./CancellationToken.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/timer.js","kind":"import-statement","original":"./timer.js"}],"format":"esm"},"../taler-util/lib/performance.js":{"bytes":7356,"imports":[{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"./index.js"},{"path":"../taler-util/lib/notifications.js","kind":"import-statement","original":"./notifications.js"}],"format":"esm"},"../taler-util/lib/qr.js":{"bytes":5173,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"}],"format":"esm"},"../taler-util/lib/RequestThrottler.js":{"bytes":4412,"imports":[{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/ReserveStatus.js":{"bytes":1136,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"}],"format":"esm"},"../taler-util/lib/ReserveTransaction.js":{"bytes":3814,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/rfc3548.js":{"bytes":1996,"imports":[{"path":"../taler-util/lib/taler-crypto.js","kind":"import-statement","original":"./taler-crypto.js"}],"format":"esm"},"../taler-util/lib/TaskThrottler.js":{"bytes":4486,"imports":[{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/types-taler-wallet-transactions.js":{"bytes":9039,"imports":[{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"},{"path":"../taler-util/lib/types-taler-merchant.js","kind":"import-statement","original":"./types-taler-merchant.js"},{"path":"../taler-util/lib/types-taler-wallet.js","kind":"import-statement","original":"./types-taler-wallet.js"}],"format":"esm"},"../taler-util/lib/transaction-test-data.js":{"bytes":3796,"imports":[{"path":"../taler-util/lib/types-taler-wallet-transactions.js","kind":"import-statement","original":"./types-taler-wallet-transactions.js"},{"path":"../taler-util/lib/types-taler-wallet.js","kind":"import-statement","original":"./types-taler-wallet.js"}],"format":"esm"},"../taler-util/lib/types-taler-mailbox.js":{"bytes":3247,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"./index.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"}],"format":"esm"},"../taler-util/lib/types-taler-sync.js":{"bytes":832,"imports":[],"format":"esm"},"../taler-util/lib/types-taler-kyc-aml.js":{"bytes":1229,"imports":[{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"./index.js"}],"format":"esm"},"../taler-util/lib/taler-account-properties.js":{"bytes":4240,"imports":[],"format":"esm"},"../taler-util/lib/taler-signatures.js":{"bytes":2921,"imports":[{"path":"../taler-util/lib/helpers.js","kind":"import-statement","original":"./helpers.js"},{"path":"../taler-util/lib/taler-crypto.js","kind":"import-statement","original":"./taler-crypto.js"},{"path":"../taler-util/lib/taler_signatures.js","kind":"import-statement","original":"./taler_signatures.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"}],"format":"esm"},"../taler-util/lib/account-restrictions.js":{"bytes":1387,"imports":[],"format":"esm"},"../taler-util/lib/aml/properties.js":{"bytes":6511,"imports":[{"path":"../taler-util/lib/taler-account-properties.js","kind":"import-statement","original":"../taler-account-properties.js"},{"path":"../taler-util/lib/taler-form-attributes.js","kind":"import-statement","original":"../taler-form-attributes.js"}],"format":"esm"},"../taler-util/lib/aml/events.js":{"bytes":17833,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"../amounts.js"},{"path":"../taler-util/lib/taler-account-properties.js","kind":"import-statement","original":"../taler-account-properties.js"},{"path":"../taler-util/lib/types-taler-exchange.js","kind":"import-statement","original":"../types-taler-exchange.js"},{"path":"../taler-util/lib/aml/properties.js","kind":"import-statement","original":"./properties.js"}],"format":"esm"},"../taler-util/lib/aml/reporting.js":{"bytes":13861,"imports":[{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"../time.js"},{"path":"../taler-util/lib/aml/events.js","kind":"import-statement","original":"./events.js"}],"format":"esm"},"../taler-util/lib/iso-3166.js":{"bytes":29927,"imports":[],"format":"esm"},"../taler-util/lib/iso-4217.js":{"bytes":20681,"imports":[],"format":"esm"},"../taler-util/lib/iso-639.js":{"bytes":37822,"imports":[],"format":"esm"},"../taler-util/lib/index.js":{"bytes":3721,"imports":[{"path":"../taler-util/lib/amounts.js","kind":"import-statement","original":"./amounts.js"},{"path":"../taler-util/lib/bank-api-client.js","kind":"import-statement","original":"./bank-api-client.js"},{"path":"../taler-util/lib/base64.js","kind":"import-statement","original":"./base64.js"},{"path":"../taler-util/lib/bech32.js","kind":"import-statement","original":"./bech32.js"},{"path":"../taler-util/lib/bitcoin.js","kind":"import-statement","original":"./bitcoin.js"},{"path":"../taler-util/lib/CancellationToken.js","kind":"import-statement","original":"./CancellationToken.js"},{"path":"../taler-util/lib/codec.js","kind":"import-statement","original":"./codec.js"},{"path":"../taler-util/lib/contract-terms.js","kind":"import-statement","original":"./contract-terms.js"},{"path":"../taler-util/lib/errors.js","kind":"import-statement","original":"./errors.js"},{"path":"../taler-util/lib/fnutils.js","kind":"import-statement","original":"./fnutils.js"},{"path":"../taler-util/lib/helpers.js","kind":"import-statement","original":"./helpers.js"},{"path":"../taler-util/lib/taler-error-codes.js","kind":"import-statement","original":"./taler-error-codes.js"},{"path":"../taler-util/lib/http-client/bank-conversion.js","kind":"import-statement","original":"./http-client/bank-conversion.js"},{"path":"../taler-util/lib/http-client/bank-core.js","kind":"import-statement","original":"./http-client/bank-core.js"},{"path":"../taler-util/lib/http-client/bank-integration.js","kind":"import-statement","original":"./http-client/bank-integration.js"},{"path":"../taler-util/lib/http-client/bank-revenue.js","kind":"import-statement","original":"./http-client/bank-revenue.js"},{"path":"../taler-util/lib/http-client/bank-wire.js","kind":"import-statement","original":"./http-client/bank-wire.js"},{"path":"../taler-util/lib/http-client/bank-prepared.js","kind":"import-statement","original":"./http-client/bank-prepared.js"},{"path":"../taler-util/lib/http-client/challenger.js","kind":"import-statement","original":"./http-client/challenger.js"},{"path":"../taler-util/lib/http-client/donau-client.js","kind":"import-statement","original":"./http-client/donau-client.js"},{"path":"../taler-util/lib/http-client/exchange-client.js","kind":"import-statement","original":"./http-client/exchange-client.js"},{"path":"../taler-util/lib/http-client/mailbox.js","kind":"import-statement","original":"./http-client/mailbox.js"},{"path":"../taler-util/lib/http-client/merchant.js","kind":"import-statement","original":"./http-client/merchant.js"},{"path":"../taler-util/lib/http-client/officer-account.js","kind":"import-statement","original":"./http-client/officer-account.js"},{"path":"../taler-util/lib/http-status-codes.js","kind":"import-statement","original":"./http-status-codes.js"},{"path":"../taler-util/lib/i18n.js","kind":"import-statement","original":"./i18n.js"},{"path":"../taler-util/lib/iban.js","kind":"import-statement","original":"./iban.js"},{"path":"../taler-util/lib/invariants.js","kind":"import-statement","original":"./invariants.js"},{"path":"../taler-util/lib/kdf.js","kind":"import-statement","original":"./kdf.js"},{"path":"../taler-util/lib/sha256.js","kind":"import-statement","original":"./sha256.js"},{"path":"../taler-util/lib/libtool-version.js","kind":"import-statement","original":"./libtool-version.js"},{"path":"../taler-util/lib/logging.js","kind":"import-statement","original":"./logging.js"},{"path":"../taler-util/lib/longpool-queue.js","kind":"import-statement","original":"./longpool-queue.js"},{"path":"../taler-util/lib/nacl-fast.js","kind":"import-statement","original":"./nacl-fast.js"},{"path":"../taler-util/lib/notifications.js","kind":"import-statement","original":"./notifications.js"},{"path":"../taler-util/lib/observability.js","kind":"import-statement","original":"./observability.js"},{"path":"../taler-util/lib/operation.js","kind":"import-statement","original":"./operation.js"},{"path":"../taler-util/lib/payto.js","kind":"import-statement","original":"./payto.js"},{"path":"../taler-util/lib/performance.js","kind":"import-statement","original":"./performance.js"},{"path":"../taler-util/lib/promises.js","kind":"import-statement","original":"./promises.js"},{"path":"../taler-util/lib/qr.js","kind":"import-statement","original":"./qr.js"},{"path":"../taler-util/lib/RequestThrottler.js","kind":"import-statement","original":"./RequestThrottler.js"},{"path":"../taler-util/lib/ReserveStatus.js","kind":"import-statement","original":"./ReserveStatus.js"},{"path":"../taler-util/lib/ReserveTransaction.js","kind":"import-statement","original":"./ReserveTransaction.js"},{"path":"../taler-util/lib/rfc3548.js","kind":"import-statement","original":"./rfc3548.js"},{"path":"../taler-util/lib/taler-crypto.js","kind":"import-statement","original":"./taler-crypto.js"},{"path":"../taler-util/lib/taler_signatures.js","kind":"import-statement","original":"./taler_signatures.js"},{"path":"../taler-util/lib/taleruri.js","kind":"import-statement","original":"./taleruri.js"},{"path":"../taler-util/lib/TaskThrottler.js","kind":"import-statement","original":"./TaskThrottler.js"},{"path":"../taler-util/lib/time.js","kind":"import-statement","original":"./time.js"},{"path":"../taler-util/lib/timer.js","kind":"import-statement","original":"./timer.js"},{"path":"../taler-util/lib/transaction-test-data.js","kind":"import-statement","original":"./transaction-test-data.js"},{"path":"../taler-util/lib/url.js","kind":"import-statement","original":"./url.js"},{"path":"../taler-util/lib/types-donau.js","kind":"import-statement","original":"./types-donau.js"},{"path":"../taler-util/lib/types-taler-bank-conversion.js","kind":"import-statement","original":"./types-taler-bank-conversion.js"},{"path":"../taler-util/lib/types-taler-bank-integration.js","kind":"import-statement","original":"./types-taler-bank-integration.js"},{"path":"../taler-util/lib/types-taler-exchange.js","kind":"import-statement","original":"./types-taler-exchange.js"},{"path":"../taler-util/lib/types-taler-mailbox.js","kind":"import-statement","original":"./types-taler-mailbox.js"},{"path":"../taler-util/lib/types-taler-merchant.js","kind":"import-statement","original":"./types-taler-merchant.js"},{"path":"../taler-util/lib/types-taler-common.js","kind":"import-statement","original":"./types-taler-common.js"},{"path":"../taler-util/lib/types-taler-sync.js","kind":"import-statement","original":"./types-taler-sync.js"},{"path":"../taler-util/lib/types-taler-wallet-transactions.js","kind":"import-statement","original":"./types-taler-wallet-transactions.js"},{"path":"../taler-util/lib/types-taler-wallet.js","kind":"import-statement","original":"./types-taler-wallet.js"},{"path":"../taler-util/lib/types-taler-bank-conversion.js","kind":"import-statement","original":"./types-taler-bank-conversion.js"},{"path":"../taler-util/lib/types-taler-bank-integration.js","kind":"import-statement","original":"./types-taler-bank-integration.js"},{"path":"../taler-util/lib/types-taler-challenger.js","kind":"import-statement","original":"./types-taler-challenger.js"},{"path":"../taler-util/lib/types-taler-corebank.js","kind":"import-statement","original":"./types-taler-corebank.js"},{"path":"../taler-util/lib/types-taler-exchange.js","kind":"import-statement","original":"./types-taler-exchange.js"},{"path":"../taler-util/lib/types-taler-kyc-aml.js","kind":"import-statement","original":"./types-taler-kyc-aml.js"},{"path":"../taler-util/lib/types-taler-mailbox.js","kind":"import-statement","original":"./types-taler-mailbox.js"},{"path":"../taler-util/lib/types-taler-merchant.js","kind":"import-statement","original":"./types-taler-merchant.js"},{"path":"../taler-util/lib/types-taler-revenue.js","kind":"import-statement","original":"./types-taler-revenue.js"},{"path":"../taler-util/lib/types-taler-wire-gateway.js","kind":"import-statement","original":"./types-taler-wire-gateway.js"},{"path":"../taler-util/lib/types-taler-prepared-transfer.js","kind":"import-statement","original":"./types-taler-prepared-transfer.js"},{"path":"../taler-util/lib/taler-account-properties.js","kind":"import-statement","original":"./taler-account-properties.js"},{"path":"../taler-util/lib/taler-form-attributes.js","kind":"import-statement","original":"./taler-form-attributes.js"},{"path":"../taler-util/lib/taler-signatures.js","kind":"import-statement","original":"./taler-signatures.js"},{"path":"../taler-util/lib/account-restrictions.js","kind":"import-statement","original":"./account-restrictions.js"},{"path":"../taler-util/lib/aml/events.js","kind":"import-statement","original":"./aml/events.js"},{"path":"../taler-util/lib/aml/properties.js","kind":"import-statement","original":"./aml/properties.js"},{"path":"../taler-util/lib/aml/reporting.js","kind":"import-statement","original":"./aml/reporting.js"},{"path":"../taler-util/lib/iso-3166.js","kind":"import-statement","original":"./iso-3166.js"},{"path":"../taler-util/lib/iso-4217.js","kind":"import-statement","original":"./iso-4217.js"},{"path":"../taler-util/lib/iso-639.js","kind":"import-statement","original":"./iso-639.js"},{"path":"../taler-util/lib/result.js","kind":"import-statement","original":"./result.js"}],"format":"esm"},"../taler-util/lib/index.browser.js":{"bytes":1012,"imports":[{"path":"../taler-util/lib/prng-browser.js","kind":"import-statement","original":"./prng-browser.js"},{"path":"../taler-util/lib/index.js","kind":"import-statement","original":"./index.js"},{"path":"../taler-util/lib/http-common.js","kind":"import-statement","original":"./http-common.js"}],"format":"esm"},"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js":{"bytes":10167,"imports":[],"format":"esm"},"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js":{"bytes":3562,"imports":[{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"}],"format":"esm"},"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/dist/compat.module.js":{"bytes":9341,"imports":[{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"}],"format":"esm"},"../web-util/lib/index.browser.mjs":{"bytes":773863,"imports":[{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/dist/compat.module.js","kind":"import-statement","original":"preact/compat"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/dist/compat.module.js","kind":"import-statement","original":"preact/compat"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"@gnu-taler/taler-util/http"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/http.js","kind":"import-statement","original":"@gnu-taler/taler-util/http"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"}],"format":"esm"},"../../node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.min.js":{"bytes":1045,"imports":[{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/dist/compat.module.js","kind":"require-call","original":"react"}],"format":"cjs"},"../../node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store/shim/index.js":{"bytes":238,"imports":[{"path":"../../node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.min.js","kind":"require-call","original":"../cjs/use-sync-external-store-shim.production.min.js"}],"format":"cjs"},"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/_internal/dist/index.mjs":{"bytes":26836,"imports":[{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/dist/compat.module.js","kind":"import-statement","original":"react"}],"format":"esm"},"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/core/dist/index.mjs":{"bytes":21304,"imports":[{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/dist/compat.module.js","kind":"import-statement","original":"react"},{"path":"../../node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store/shim/index.js","kind":"import-statement","original":"use-sync-external-store/shim/index.js"},{"path":"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/_internal/dist/index.mjs","kind":"import-statement","original":"swr/_internal"},{"path":"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/_internal/dist/index.mjs","kind":"import-statement","original":"swr/_internal"}],"format":"esm"},"src/utils.ts":{"bytes":9188,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"@gnu-taler/web-util/browser","kind":"import-statement","external":true}],"format":"esm"},"src/pages/SolveMFA.tsx":{"bytes":17521,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"./PaytoWireTransferForm.js"}],"format":"esm"},"src/hooks/account.ts":{"bytes":8697,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"./session.js"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/core/dist/index.mjs","kind":"import-statement","original":"swr"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"src/hooks/regional.ts":{"bytes":19351,"imports":[{"path":"src/hooks/session.ts","kind":"import-statement","original":"./session.js"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/core/dist/index.mjs","kind":"import-statement","original":"swr"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils.js"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"./account.js"}],"format":"esm"},"src/pages/regional/CreateCashout.tsx":{"bytes":30135,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../../hooks/account.js"},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../../hooks/regional.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../../utils.js"},{"path":"src/pages/LoginForm.tsx","kind":"import-statement","original":"../LoginForm.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"../PaytoWireTransferForm.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"../SolveMFA.js"}],"format":"esm"},"src/pages/PaytoWireTransferForm.tsx":{"bytes":32190,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"./SolveMFA.js"},{"path":"src/pages/regional/CreateCashout.tsx","kind":"import-statement","original":"./regional/CreateCashout.js"}],"format":"esm"},"src/context/settings.ts":{"bytes":1281,"imports":[{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../settings.js","kind":"import-statement","external":true}],"format":"esm"},"src/hooks/preferences.ts":{"bytes":3214,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../settings.js","kind":"import-statement","external":true},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"}],"format":"esm"},"src/pages/rnd.ts":{"bytes":37049,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"}],"format":"esm"},"src/pages/RegistrationPage.tsx":{"bytes":14789,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/context/settings.ts","kind":"import-statement","original":"../context/settings.js"},{"path":"src/hooks/preferences.ts","kind":"import-statement","original":"../hooks/preferences.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils.js"},{"path":"src/pages/rnd.ts","kind":"import-statement","original":"./rnd.js"},{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true}],"format":"esm"},"src/pages/LoginForm.tsx":{"bytes":10313,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"./PaytoWireTransferForm.js"},{"path":"src/pages/RegistrationPage.tsx","kind":"import-statement","original":"./RegistrationPage.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"./SolveMFA.js"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"}],"format":"esm"},"src/hooks/session.ts":{"bytes":6848,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/core/dist/index.mjs","kind":"import-statement","original":"swr"},{"path":"src/pages/LoginForm.tsx","kind":"import-statement","original":"../pages/LoginForm.js"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"}],"format":"esm"},"src/pages/AccountPage/state.ts":{"bytes":2933,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../../hooks/account.js"},{"path":"src/pages/regional/CreateCashout.tsx","kind":"import-statement","original":"../regional/CreateCashout.js"},{"path":"./index.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/Transactions/state.ts":{"bytes":2121,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../../hooks/account.js"},{"path":"./index.js","kind":"import-statement","external":true}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js":{"bytes":296,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js":{"bytes":221,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js":{"bytes":2355,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js":{"bytes":1197,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js":{"bytes":2747,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/add/index.js":{"bytes":3243,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"../addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js","kind":"import-statement","original":"../addMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWeekend/index.js":{"bytes":706,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSunday/index.js":{"bytes":610,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSaturday/index.js":{"bytes":624,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addBusinessDays/index.js":{"bytes":2342,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWeekend/index.js","kind":"import-statement","original":"../isWeekend/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSunday/index.js","kind":"import-statement","original":"../isSunday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSaturday/index.js","kind":"import-statement","original":"../isSaturday/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js":{"bytes":1122,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addHours/index.js":{"bytes":1075,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js","kind":"import-statement","original":"../addMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js":{"bytes":170,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js":{"bytes":2903,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeek/index.js":{"bytes":887,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js","kind":"import-statement","original":"../startOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeekYear/index.js":{"bytes":1561,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeek/index.js","kind":"import-statement","original":"../startOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeekYear/index.js":{"bytes":1218,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeekYear/index.js","kind":"import-statement","original":"../getISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeek/index.js","kind":"import-statement","original":"../startOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js":{"bytes":879,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfDay/index.js":{"bytes":778,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js":{"bytes":1899,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfDay/index.js","kind":"import-statement","original":"../startOfDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setISOWeekYear/index.js":{"bytes":1529,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeekYear/index.js","kind":"import-statement","original":"../startOfISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js","kind":"import-statement","original":"../differenceInCalendarDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addISOWeekYears/index.js":{"bytes":1289,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeekYear/index.js","kind":"import-statement","original":"../getISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setISOWeekYear/index.js","kind":"import-statement","original":"../setISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMinutes/index.js":{"bytes":1097,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js","kind":"import-statement","original":"../addMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addQuarters/index.js":{"bytes":1048,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js","kind":"import-statement","original":"../addMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addSeconds/index.js":{"bytes":1047,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js","kind":"import-statement","original":"../addMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addWeeks/index.js":{"bytes":1001,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"../addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addYears/index.js":{"bytes":990,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js","kind":"import-statement","original":"../addMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/areIntervalsOverlapping/index.js":{"bytes":3200,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/max/index.js":{"bytes":1878,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/min/index.js":{"bytes":1892,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/clamp/index.js":{"bytes":1281,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/max/index.js","kind":"import-statement","original":"../max/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/min/index.js","kind":"import-statement","original":"../min/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/closestIndexTo/index.js":{"bytes":2109,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/closestTo/index.js":{"bytes":2063,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js":{"bytes":1432,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareDesc/index.js":{"bytes":1514,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js":{"bytes":2756,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/daysToWeeks/index.js":{"bytes":762,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameDay/index.js":{"bytes":1339,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfDay/index.js","kind":"import-statement","original":"../startOfDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isDate/index.js":{"bytes":1357,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js":{"bytes":1191,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isDate/index.js","kind":"import-statement","original":"../isDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInBusinessDays/index.js":{"bytes":2678,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"../addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js","kind":"import-statement","original":"../differenceInCalendarDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameDay/index.js","kind":"import-statement","original":"../isSameDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js","kind":"import-statement","original":"../isValid/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWeekend/index.js","kind":"import-statement","original":"../isWeekend/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarISOWeekYears/index.js":{"bytes":1109,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeekYear/index.js","kind":"import-statement","original":"../getISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarISOWeeks/index.js":{"bytes":1695,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeek/index.js","kind":"import-statement","original":"../startOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarMonths/index.js":{"bytes":1097,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getQuarter/index.js":{"bytes":690,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarQuarters/index.js":{"bytes":1164,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getQuarter/index.js","kind":"import-statement","original":"../getQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarWeeks/index.js":{"bytes":2207,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js","kind":"import-statement","original":"../startOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarYears/index.js":{"bytes":986,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInDays/index.js":{"bytes":3364,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js","kind":"import-statement","original":"../differenceInCalendarDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMilliseconds/index.js":{"bytes":954,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/roundingMethods/index.js":{"bytes":378,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInHours/index.js":{"bytes":1324,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMilliseconds/index.js","kind":"import-statement","original":"../differenceInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/roundingMethods/index.js","kind":"import-statement","original":"../_lib/roundingMethods/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subISOWeekYears/index.js":{"bytes":1244,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addISOWeekYears/index.js","kind":"import-statement","original":"../addISOWeekYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInISOWeekYears/index.js":{"bytes":1844,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarISOWeekYears/index.js","kind":"import-statement","original":"../differenceInCalendarISOWeekYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js","kind":"import-statement","original":"../compareAsc/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subISOWeekYears/index.js","kind":"import-statement","original":"../subISOWeekYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMinutes/index.js":{"bytes":1585,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMilliseconds/index.js","kind":"import-statement","original":"../differenceInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/roundingMethods/index.js","kind":"import-statement","original":"../_lib/roundingMethods/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfDay/index.js":{"bytes":773,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfMonth/index.js":{"bytes":874,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isLastDayOfMonth/index.js":{"bytes":848,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfDay/index.js","kind":"import-statement","original":"../endOfDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfMonth/index.js","kind":"import-statement","original":"../endOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMonths/index.js":{"bytes":2200,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarMonths/index.js","kind":"import-statement","original":"../differenceInCalendarMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js","kind":"import-statement","original":"../compareAsc/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isLastDayOfMonth/index.js","kind":"import-statement","original":"../isLastDayOfMonth/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInQuarters/index.js":{"bytes":1222,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMonths/index.js","kind":"import-statement","original":"../differenceInMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/roundingMethods/index.js","kind":"import-statement","original":"../_lib/roundingMethods/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInSeconds/index.js":{"bytes":1297,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMilliseconds/index.js","kind":"import-statement","original":"../differenceInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/roundingMethods/index.js","kind":"import-statement","original":"../_lib/roundingMethods/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInWeeks/index.js":{"bytes":1996,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInDays/index.js","kind":"import-statement","original":"../differenceInDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/roundingMethods/index.js","kind":"import-statement","original":"../_lib/roundingMethods/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInYears/index.js":{"bytes":1634,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarYears/index.js","kind":"import-statement","original":"../differenceInCalendarYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js","kind":"import-statement","original":"../compareAsc/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachDayOfInterval/index.js":{"bytes":2323,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachHourOfInterval/index.js":{"bytes":2342,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addHours/index.js","kind":"import-statement","original":"../addHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMinute/index.js":{"bytes":808,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachMinuteOfInterval/index.js":{"bytes":2311,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMinutes/index.js","kind":"import-statement","original":"../addMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMinute/index.js","kind":"import-statement","original":"../startOfMinute/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachMonthOfInterval/index.js":{"bytes":1877,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfQuarter/index.js":{"bytes":932,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachQuarterOfInterval/index.js":{"bytes":1974,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addQuarters/index.js","kind":"import-statement","original":"../addQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfQuarter/index.js","kind":"import-statement","original":"../startOfQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekOfInterval/index.js":{"bytes":2669,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addWeeks/index.js","kind":"import-statement","original":"../addWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js","kind":"import-statement","original":"../startOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekendOfInterval/index.js":{"bytes":1541,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachDayOfInterval/index.js","kind":"import-statement","original":"../eachDayOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSunday/index.js","kind":"import-statement","original":"../isSunday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWeekend/index.js","kind":"import-statement","original":"../isWeekend/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMonth/index.js":{"bytes":813,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekendOfMonth/index.js":{"bytes":1406,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekendOfInterval/index.js","kind":"import-statement","original":"../eachWeekendOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMonth/index.js","kind":"import-statement","original":"../startOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfMonth/index.js","kind":"import-statement","original":"../endOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfYear/index.js":{"bytes":851,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfYear/index.js":{"bytes":869,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekendOfYear/index.js":{"bytes":1135,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekendOfInterval/index.js","kind":"import-statement","original":"../eachWeekendOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfYear/index.js","kind":"import-statement","original":"../endOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfYear/index.js","kind":"import-statement","original":"../startOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachYearOfInterval/index.js":{"bytes":1814,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfDecade/index.js":{"bytes":1107,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfHour/index.js":{"bytes":780,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfWeek/index.js":{"bytes":2905,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfISOWeek/index.js":{"bytes":871,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfWeek/index.js","kind":"import-statement","original":"../endOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfISOWeekYear/index.js":{"bytes":1304,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeekYear/index.js","kind":"import-statement","original":"../getISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeek/index.js","kind":"import-statement","original":"../startOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfMinute/index.js":{"bytes":801,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfQuarter/index.js":{"bytes":931,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfSecond/index.js":{"bytes":802,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfToday/index.js":{"bytes":587,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfDay/index.js","kind":"import-statement","original":"../endOfDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfTomorrow/index.js":{"bytes":758,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfYesterday/index.js":{"bytes":764,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js":{"bytes":1131,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js","kind":"import-statement","original":"../addMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCDayOfYear/index.js":{"bytes":498,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js":{"bytes":425,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeekYear/index.js":{"bytes":958,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js","kind":"import-statement","original":"../startOfUTCISOWeek/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeekYear/index.js":{"bytes":502,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeekYear/index.js","kind":"import-statement","original":"../getUTCISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js","kind":"import-statement","original":"../startOfUTCISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeek/index.js":{"bytes":722,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js","kind":"import-statement","original":"../startOfUTCISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeekYear/index.js","kind":"import-statement","original":"../startOfUTCISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js":{"bytes":1799,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeekYear/index.js":{"bytes":2426,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js","kind":"import-statement","original":"../startOfUTCWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeekYear/index.js":{"bytes":1746,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeekYear/index.js","kind":"import-statement","original":"../getUTCWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js","kind":"import-statement","original":"../startOfUTCWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeek/index.js":{"bytes":728,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js","kind":"import-statement","original":"../startOfUTCWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeekYear/index.js","kind":"import-statement","original":"../startOfUTCWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js":{"bytes":243,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/lightFormatters/index.js":{"bytes":3122,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js","kind":"import-statement","original":"../../addLeadingZeros/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/formatters/index.js":{"bytes":24159,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCDayOfYear/index.js","kind":"import-statement","original":"../../../_lib/getUTCDayOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeek/index.js","kind":"import-statement","original":"../../../_lib/getUTCISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeekYear/index.js","kind":"import-statement","original":"../../../_lib/getUTCISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeek/index.js","kind":"import-statement","original":"../../../_lib/getUTCWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeekYear/index.js","kind":"import-statement","original":"../../../_lib/getUTCWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js","kind":"import-statement","original":"../../addLeadingZeros/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/lightFormatters/index.js","kind":"import-statement","original":"../lightFormatters/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/longFormatters/index.js":{"bytes":1917,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/protectedTokens/index.js":{"bytes":1369,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatDistance/index.js":{"bytes":1824,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildFormatLongFn/index.js":{"bytes":365,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatLong/index.js":{"bytes":771,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildFormatLongFn/index.js","kind":"import-statement","original":"../../../_lib/buildFormatLongFn/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatRelative/index.js":{"bytes":350,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildLocalizeFn/index.js":{"bytes":1088,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/localize/index.js":{"bytes":3846,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildLocalizeFn/index.js","kind":"import-statement","original":"../../../_lib/buildLocalizeFn/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchFn/index.js":{"bytes":1405,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchPatternFn/index.js":{"bytes":669,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/match/index.js":{"bytes":3089,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchFn/index.js","kind":"import-statement","original":"../../../_lib/buildMatchFn/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchPatternFn/index.js","kind":"import-statement","original":"../../../_lib/buildMatchPatternFn/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/index.js":{"bytes":820,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatDistance/index.js","kind":"import-statement","original":"./_lib/formatDistance/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatLong/index.js","kind":"import-statement","original":"./_lib/formatLong/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatRelative/index.js","kind":"import-statement","original":"./_lib/formatRelative/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/localize/index.js","kind":"import-statement","original":"./_lib/localize/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/match/index.js","kind":"import-statement","original":"./_lib/match/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js":{"bytes":86,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/index.js","kind":"import-statement","original":"../../locale/en-US/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/format/index.js":{"bytes":28718,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js","kind":"import-statement","original":"../isValid/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js","kind":"import-statement","original":"../subMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/formatters/index.js","kind":"import-statement","original":"../_lib/format/formatters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/longFormatters/index.js","kind":"import-statement","original":"../_lib/format/longFormatters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/protectedTokens/index.js","kind":"import-statement","original":"../_lib/protectedTokens/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js","kind":"import-statement","original":"../_lib/defaultLocale/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/assign/index.js":{"bytes":347,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/cloneObject/index.js":{"bytes":117,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/assign/index.js","kind":"import-statement","original":"../assign/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistance/index.js":{"bytes":8990,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js","kind":"import-statement","original":"../compareAsc/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMonths/index.js","kind":"import-statement","original":"../differenceInMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInSeconds/index.js","kind":"import-statement","original":"../differenceInSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js","kind":"import-statement","original":"../_lib/defaultLocale/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/cloneObject/index.js","kind":"import-statement","original":"../_lib/cloneObject/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/assign/index.js","kind":"import-statement","original":"../_lib/assign/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistanceStrict/index.js":{"bytes":7883,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js","kind":"import-statement","original":"../compareAsc/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/cloneObject/index.js","kind":"import-statement","original":"../_lib/cloneObject/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/assign/index.js","kind":"import-statement","original":"../_lib/assign/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js","kind":"import-statement","original":"../_lib/defaultLocale/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistanceToNow/index.js":{"bytes":4443,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistance/index.js","kind":"import-statement","original":"../formatDistance/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistanceToNowStrict/index.js":{"bytes":3042,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistanceStrict/index.js","kind":"import-statement","original":"../formatDistanceStrict/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDuration/index.js":{"bytes":3506,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js","kind":"import-statement","original":"../_lib/defaultLocale/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatISO/index.js":{"bytes":4696,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js","kind":"import-statement","original":"../_lib/addLeadingZeros/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatISO9075/index.js":{"bytes":4046,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js","kind":"import-statement","original":"../isValid/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js","kind":"import-statement","original":"../_lib/addLeadingZeros/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatISODuration/index.js":{"bytes":2156,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatRFC3339/index.js":{"bytes":3604,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js","kind":"import-statement","original":"../isValid/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js","kind":"import-statement","original":"../_lib/addLeadingZeros/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatRFC7231/index.js":{"bytes":1877,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js","kind":"import-statement","original":"../isValid/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js","kind":"import-statement","original":"../_lib/addLeadingZeros/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatRelative/index.js":{"bytes":5098,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js","kind":"import-statement","original":"../differenceInCalendarDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/format/index.js","kind":"import-statement","original":"../format/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js","kind":"import-statement","original":"../_lib/defaultLocale/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js","kind":"import-statement","original":"../subMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/fromUnixTime/index.js":{"bytes":812,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDate/index.js":{"bytes":691,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDay/index.js":{"bytes":700,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDayOfYear/index.js":{"bytes":881,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfYear/index.js","kind":"import-statement","original":"../startOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js","kind":"import-statement","original":"../differenceInCalendarDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDaysInMonth/index.js":{"bytes":911,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isLeapYear/index.js":{"bytes":738,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDaysInYear/index.js":{"bytes":826,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isLeapYear/index.js","kind":"import-statement","original":"../isLeapYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDecade/index.js":{"bytes":717,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDefaultOptions/index.js":{"bytes":913,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/assign/index.js","kind":"import-statement","original":"../_lib/assign/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getHours/index.js":{"bytes":665,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISODay/index.js":{"bytes":853,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeek/index.js":{"bytes":1212,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeek/index.js","kind":"import-statement","original":"../startOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeekYear/index.js","kind":"import-statement","original":"../startOfISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeeksInYear/index.js":{"bytes":1328,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeekYear/index.js","kind":"import-statement","original":"../startOfISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addWeeks/index.js","kind":"import-statement","original":"../addWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getMilliseconds/index.js":{"bytes":755,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getMinutes/index.js":{"bytes":690,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getMonth/index.js":{"bytes":646,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getOverlappingDaysInIntervals/index.js":{"bytes":2451,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getSeconds/index.js":{"bytes":698,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getTime/index.js":{"bytes":739,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getUnixTime/index.js":{"bytes":697,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getTime/index.js","kind":"import-statement","original":"../getTime/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeekYear/index.js":{"bytes":4203,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js","kind":"import-statement","original":"../startOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeekYear/index.js":{"bytes":3514,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeekYear/index.js","kind":"import-statement","original":"../getWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js","kind":"import-statement","original":"../startOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeek/index.js":{"bytes":2364,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js","kind":"import-statement","original":"../startOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeekYear/index.js","kind":"import-statement","original":"../startOfWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeekOfMonth/index.js":{"bytes":2815,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDate/index.js","kind":"import-statement","original":"../getDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDay/index.js","kind":"import-statement","original":"../getDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMonth/index.js","kind":"import-statement","original":"../startOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfMonth/index.js":{"bytes":897,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeeksInMonth/index.js":{"bytes":1459,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarWeeks/index.js","kind":"import-statement","original":"../differenceInCalendarWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfMonth/index.js","kind":"import-statement","original":"../lastDayOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMonth/index.js","kind":"import-statement","original":"../startOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getYear/index.js":{"bytes":598,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/hoursToMilliseconds/index.js":{"bytes":733,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/hoursToMinutes/index.js":{"bytes":683,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/hoursToSeconds/index.js":{"bytes":684,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/intervalToDuration/index.js":{"bytes":2517,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js","kind":"import-statement","original":"../compareAsc/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/add/index.js","kind":"import-statement","original":"../add/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInDays/index.js","kind":"import-statement","original":"../differenceInDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInHours/index.js","kind":"import-statement","original":"../differenceInHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMinutes/index.js","kind":"import-statement","original":"../differenceInMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMonths/index.js","kind":"import-statement","original":"../differenceInMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInSeconds/index.js","kind":"import-statement","original":"../differenceInSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInYears/index.js","kind":"import-statement","original":"../differenceInYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/intlFormat/index.js":{"bytes":3968,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/intlFormatDistance/index.js":{"bytes":8981,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js","kind":"import-statement","original":"../differenceInCalendarDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarMonths/index.js","kind":"import-statement","original":"../differenceInCalendarMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarQuarters/index.js","kind":"import-statement","original":"../differenceInCalendarQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarWeeks/index.js","kind":"import-statement","original":"../differenceInCalendarWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarYears/index.js","kind":"import-statement","original":"../differenceInCalendarYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInHours/index.js","kind":"import-statement","original":"../differenceInHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMinutes/index.js","kind":"import-statement","original":"../differenceInMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInSeconds/index.js","kind":"import-statement","original":"../differenceInSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isAfter/index.js":{"bytes":906,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isBefore/index.js":{"bytes":915,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isEqual/index.js":{"bytes":900,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isExists/index.js":{"bytes":898,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isFirstDayOfMonth/index.js":{"bytes":706,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isFriday/index.js":{"bytes":610,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isFuture/index.js":{"bytes":851,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Setter.js":{"bytes":5576,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js":{"bytes":1366,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Setter.js","kind":"import-statement","original":"./Setter.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/EraParser.js":{"bytes":4816,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js":{"bytes":1171,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js":{"bytes":3536,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../../constants/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"./constants.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/YearParser.js":{"bytes":5705,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalWeekYearParser.js":{"bytes":5611,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeekYear/index.js","kind":"import-statement","original":"../../../_lib/getUTCWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js","kind":"import-statement","original":"../../../_lib/startOfUTCWeek/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOWeekYearParser.js":{"bytes":4604,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js","kind":"import-statement","original":"../../../_lib/startOfUTCISOWeek/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ExtendedYearParser.js":{"bytes":4395,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/QuarterParser.js":{"bytes":5579,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneQuarterParser.js":{"bytes":5649,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/MonthParser.js":{"bytes":5822,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneMonthParser.js":{"bytes":5892,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCWeek/index.js":{"bytes":470,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeek/index.js","kind":"import-statement","original":"../getUTCWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalWeekParser.js":{"bytes":4874,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCWeek/index.js","kind":"import-statement","original":"../../../_lib/setUTCWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js","kind":"import-statement","original":"../../../_lib/startOfUTCWeek/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCISOWeek/index.js":{"bytes":476,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeek/index.js","kind":"import-statement","original":"../getUTCISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOWeekParser.js":{"bytes":4854,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCISOWeek/index.js","kind":"import-statement","original":"../../../_lib/setUTCISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js","kind":"import-statement","original":"../../../_lib/startOfUTCISOWeek/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DateParser.js":{"bytes":5206,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayOfYearParser.js":{"bytes":5031,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCDay/index.js":{"bytes":1880,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayParser.js":{"bytes":5655,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCDay/index.js","kind":"import-statement","original":"../../../_lib/setUTCDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalDayParser.js":{"bytes":6265,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCDay/index.js","kind":"import-statement","original":"../../../_lib/setUTCDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneLocalDayParser.js":{"bytes":6347,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCDay/index.js","kind":"import-statement","original":"../../../_lib/setUTCDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCISODay/index.js":{"bytes":601,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISODayParser.js":{"bytes":6229,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/setUTCISODay/index.js","kind":"import-statement","original":"../../../_lib/setUTCISODay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/AMPMParser.js":{"bytes":5020,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/AMPMMidnightParser.js":{"bytes":5076,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayPeriodParser.js":{"bytes":5108,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour1to12Parser.js":{"bytes":4892,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour0to23Parser.js":{"bytes":4673,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour0To11Parser.js":{"bytes":4812,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour1To24Parser.js":{"bytes":4725,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/MinuteParser.js":{"bytes":4627,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/SecondParser.js":{"bytes":4624,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/FractionOfSecondParser.js":{"bytes":4412,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOTimezoneWithZParser.js":{"bytes":4925,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOTimezoneParser.js":{"bytes":4873,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/constants.js","kind":"import-statement","original":"../constants.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/TimestampSecondsParser.js":{"bytes":4252,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/TimestampMillisecondsParser.js":{"bytes":4280,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Parser.js","kind":"import-statement","original":"../Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/utils.js","kind":"import-statement","original":"../utils.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/index.js":{"bytes":5795,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/EraParser.js","kind":"import-statement","original":"./EraParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/YearParser.js","kind":"import-statement","original":"./YearParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalWeekYearParser.js","kind":"import-statement","original":"./LocalWeekYearParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOWeekYearParser.js","kind":"import-statement","original":"./ISOWeekYearParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ExtendedYearParser.js","kind":"import-statement","original":"./ExtendedYearParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/QuarterParser.js","kind":"import-statement","original":"./QuarterParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneQuarterParser.js","kind":"import-statement","original":"./StandAloneQuarterParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/MonthParser.js","kind":"import-statement","original":"./MonthParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneMonthParser.js","kind":"import-statement","original":"./StandAloneMonthParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalWeekParser.js","kind":"import-statement","original":"./LocalWeekParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOWeekParser.js","kind":"import-statement","original":"./ISOWeekParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DateParser.js","kind":"import-statement","original":"./DateParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayOfYearParser.js","kind":"import-statement","original":"./DayOfYearParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayParser.js","kind":"import-statement","original":"./DayParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/LocalDayParser.js","kind":"import-statement","original":"./LocalDayParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/StandAloneLocalDayParser.js","kind":"import-statement","original":"./StandAloneLocalDayParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISODayParser.js","kind":"import-statement","original":"./ISODayParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/AMPMParser.js","kind":"import-statement","original":"./AMPMParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/AMPMMidnightParser.js","kind":"import-statement","original":"./AMPMMidnightParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/DayPeriodParser.js","kind":"import-statement","original":"./DayPeriodParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour1to12Parser.js","kind":"import-statement","original":"./Hour1to12Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour0to23Parser.js","kind":"import-statement","original":"./Hour0to23Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour0To11Parser.js","kind":"import-statement","original":"./Hour0To11Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/Hour1To24Parser.js","kind":"import-statement","original":"./Hour1To24Parser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/MinuteParser.js","kind":"import-statement","original":"./MinuteParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/SecondParser.js","kind":"import-statement","original":"./SecondParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/FractionOfSecondParser.js","kind":"import-statement","original":"./FractionOfSecondParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOTimezoneWithZParser.js","kind":"import-statement","original":"./ISOTimezoneWithZParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/ISOTimezoneParser.js","kind":"import-statement","original":"./ISOTimezoneParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/TimestampSecondsParser.js","kind":"import-statement","original":"./TimestampSecondsParser.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/TimestampMillisecondsParser.js","kind":"import-statement","original":"./TimestampMillisecondsParser.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/index.js":{"bytes":35179,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js","kind":"import-statement","original":"../_lib/defaultLocale/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js","kind":"import-statement","original":"../subMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/assign/index.js","kind":"import-statement","original":"../_lib/assign/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/longFormatters/index.js","kind":"import-statement","original":"../_lib/format/longFormatters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/protectedTokens/index.js","kind":"import-statement","original":"../_lib/protectedTokens/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/Setter.js","kind":"import-statement","original":"./_lib/Setter.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/_lib/parsers/index.js","kind":"import-statement","original":"./_lib/parsers/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isMatch/index.js":{"bytes":22186,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/index.js","kind":"import-statement","original":"../parse/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js","kind":"import-statement","original":"../isValid/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isMonday/index.js":{"bytes":600,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isPast/index.js":{"bytes":830,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfHour/index.js":{"bytes":786,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameHour/index.js":{"bytes":1213,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfHour/index.js","kind":"import-statement","original":"../startOfHour/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameWeek/index.js":{"bytes":1787,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js","kind":"import-statement","original":"../startOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameISOWeek/index.js":{"bytes":1148,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameWeek/index.js","kind":"import-statement","original":"../isSameWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameISOWeekYear/index.js":{"bytes":1167,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeekYear/index.js","kind":"import-statement","original":"../startOfISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameMinute/index.js":{"bytes":1308,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMinute/index.js","kind":"import-statement","original":"../startOfMinute/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameMonth/index.js":{"bytes":1156,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameQuarter/index.js":{"bytes":1194,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfQuarter/index.js","kind":"import-statement","original":"../startOfQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfSecond/index.js":{"bytes":814,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameSecond/index.js":{"bytes":1572,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfSecond/index.js","kind":"import-statement","original":"../startOfSecond/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameYear/index.js":{"bytes":895,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisHour/index.js":{"bytes":933,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameHour/index.js","kind":"import-statement","original":"../isSameHour/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisISOWeek/index.js":{"bytes":1015,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameISOWeek/index.js","kind":"import-statement","original":"../isSameISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisMinute/index.js":{"bytes":959,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameMinute/index.js","kind":"import-statement","original":"../isSameMinute/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisMonth/index.js":{"bytes":914,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameMonth/index.js","kind":"import-statement","original":"../isSameMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisQuarter/index.js":{"bytes":929,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameQuarter/index.js","kind":"import-statement","original":"../isSameQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisSecond/index.js":{"bytes":967,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameSecond/index.js","kind":"import-statement","original":"../isSameSecond/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisWeek/index.js":{"bytes":1483,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameWeek/index.js","kind":"import-statement","original":"../isSameWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisYear/index.js":{"bytes":896,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameYear/index.js","kind":"import-statement","original":"../isSameYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThursday/index.js":{"bytes":624,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isToday/index.js":{"bytes":818,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameDay/index.js","kind":"import-statement","original":"../isSameDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isTomorrow/index.js":{"bytes":894,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"../addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameDay/index.js","kind":"import-statement","original":"../isSameDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isTuesday/index.js":{"bytes":617,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWednesday/index.js":{"bytes":631,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWithinInterval/index.js":{"bytes":1700,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subDays/index.js":{"bytes":1004,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"../addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isYesterday/index.js":{"bytes":901,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameDay/index.js","kind":"import-statement","original":"../isSameDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subDays/index.js","kind":"import-statement","original":"../subDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfDecade/index.js":{"bytes":896,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfWeek/index.js":{"bytes":2921,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfISOWeek/index.js":{"bytes":911,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfWeek/index.js","kind":"import-statement","original":"../lastDayOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfISOWeekYear/index.js":{"bytes":1271,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeekYear/index.js","kind":"import-statement","original":"../getISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeek/index.js","kind":"import-statement","original":"../startOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfQuarter/index.js":{"bytes":1200,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfYear/index.js":{"bytes":874,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lightFormat/index.js":{"bytes":6042,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/lightFormatters/index.js","kind":"import-statement","original":"../_lib/format/lightFormatters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js","kind":"import-statement","original":"../_lib/getTimezoneOffsetInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js","kind":"import-statement","original":"../isValid/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js","kind":"import-statement","original":"../subMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/milliseconds/index.js":{"bytes":2012,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/millisecondsToHours/index.js":{"bytes":889,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/millisecondsToMinutes/index.js":{"bytes":909,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/millisecondsToSeconds/index.js":{"bytes":903,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/minutesToHours/index.js":{"bytes":807,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/minutesToMilliseconds/index.js":{"bytes":756,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/minutesToSeconds/index.js":{"bytes":710,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/monthsToQuarters/index.js":{"bytes":834,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/monthsToYears/index.js":{"bytes":788,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js":{"bytes":1011,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"../addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDay/index.js","kind":"import-statement","original":"../getDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextFriday/index.js":{"bytes":641,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js","kind":"import-statement","original":"../nextDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextMonday/index.js":{"bytes":641,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js","kind":"import-statement","original":"../nextDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextSaturday/index.js":{"bytes":655,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js","kind":"import-statement","original":"../nextDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextSunday/index.js":{"bytes":641,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js","kind":"import-statement","original":"../nextDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextThursday/index.js":{"bytes":656,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js","kind":"import-statement","original":"../nextDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextTuesday/index.js":{"bytes":648,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js","kind":"import-statement","original":"../nextDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextWednesday/index.js":{"bytes":662,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js","kind":"import-statement","original":"../nextDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parseISO/index.js":{"bytes":8428,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parseJSON/index.js":{"bytes":2461,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js":{"bytes":1052,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDay/index.js","kind":"import-statement","original":"../getDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subDays/index.js","kind":"import-statement","original":"../subDays/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousFriday/index.js":{"bytes":683,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js","kind":"import-statement","original":"../previousDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousMonday/index.js":{"bytes":683,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js","kind":"import-statement","original":"../previousDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousSaturday/index.js":{"bytes":697,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js","kind":"import-statement","original":"../previousDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousSunday/index.js":{"bytes":683,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js","kind":"import-statement","original":"../previousDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousThursday/index.js":{"bytes":697,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js","kind":"import-statement","original":"../previousDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousTuesday/index.js":{"bytes":690,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js","kind":"import-statement","original":"../previousDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousWednesday/index.js":{"bytes":704,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js","kind":"import-statement","original":"../previousDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/quartersToMonths/index.js":{"bytes":720,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/quartersToYears/index.js":{"bytes":825,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/roundToNearestMinutes/index.js":{"bytes":2543,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/roundingMethods/index.js","kind":"import-statement","original":"../_lib/roundingMethods/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/secondsToHours/index.js":{"bytes":811,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/secondsToMilliseconds/index.js":{"bytes":744,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/secondsToMinutes/index.js":{"bytes":832,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setMonth/index.js":{"bytes":1292,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDaysInMonth/index.js","kind":"import-statement","original":"../getDaysInMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/set/index.js":{"bytes":3272,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setMonth/index.js","kind":"import-statement","original":"../setMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setDate/index.js":{"bytes":928,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setDay/index.js":{"bytes":3083,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"../addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setDayOfYear/index.js":{"bytes":946,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setDefaultOptions/index.js":{"bytes":2647,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setHours/index.js":{"bytes":862,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setISODay/index.js":{"bytes":1137,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"../addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISODay/index.js","kind":"import-statement","original":"../getISODay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setISOWeek/index.js":{"bytes":1093,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeek/index.js","kind":"import-statement","original":"../getISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setMilliseconds/index.js":{"bytes":988,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setMinutes/index.js":{"bytes":898,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setQuarter/index.js":{"bytes":1033,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setMonth/index.js","kind":"import-statement","original":"../setMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setSeconds/index.js":{"bytes":898,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setWeek/index.js":{"bytes":2223,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeek/index.js","kind":"import-statement","original":"../getWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setWeekYear/index.js":{"bytes":3896,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js","kind":"import-statement","original":"../differenceInCalendarDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeekYear/index.js","kind":"import-statement","original":"../startOfWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js","kind":"import-statement","original":"../_lib/defaultOptions/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setYear/index.js":{"bytes":1006,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfDecade/index.js":{"bytes":864,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"../toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfToday/index.js":{"bytes":601,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfDay/index.js","kind":"import-statement","original":"../startOfDay/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfTomorrow/index.js":{"bytes":761,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfYesterday/index.js":{"bytes":767,"imports":[],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMonths/index.js":{"bytes":1025,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js","kind":"import-statement","original":"../addMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/sub/index.js":{"bytes":2976,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subDays/index.js","kind":"import-statement","original":"../subDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMonths/index.js","kind":"import-statement","original":"../subMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subBusinessDays/index.js":{"bytes":1162,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addBusinessDays/index.js","kind":"import-statement","original":"../addBusinessDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subHours/index.js":{"bytes":1026,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addHours/index.js","kind":"import-statement","original":"../addHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMinutes/index.js":{"bytes":1053,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMinutes/index.js","kind":"import-statement","original":"../addMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subQuarters/index.js":{"bytes":1060,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addQuarters/index.js","kind":"import-statement","original":"../addQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subSeconds/index.js":{"bytes":1057,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addSeconds/index.js","kind":"import-statement","original":"../addSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subWeeks/index.js":{"bytes":1014,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addWeeks/index.js","kind":"import-statement","original":"../addWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subYears/index.js":{"bytes":1014,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js","kind":"import-statement","original":"../_lib/toInteger/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addYears/index.js","kind":"import-statement","original":"../addYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/weeksToDays/index.js":{"bytes":656,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/yearsToMonths/index.js":{"bytes":674,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/yearsToQuarters/index.js":{"bytes":689,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js","kind":"import-statement","original":"../_lib/requiredArgs/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"../constants/index.js"}],"format":"esm"},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/index.js":{"bytes":16572,"imports":[{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/add/index.js","kind":"import-statement","original":"./add/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addBusinessDays/index.js","kind":"import-statement","original":"./addBusinessDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js","kind":"import-statement","original":"./addDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addHours/index.js","kind":"import-statement","original":"./addHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addISOWeekYears/index.js","kind":"import-statement","original":"./addISOWeekYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js","kind":"import-statement","original":"./addMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMinutes/index.js","kind":"import-statement","original":"./addMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js","kind":"import-statement","original":"./addMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addQuarters/index.js","kind":"import-statement","original":"./addQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addSeconds/index.js","kind":"import-statement","original":"./addSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addWeeks/index.js","kind":"import-statement","original":"./addWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addYears/index.js","kind":"import-statement","original":"./addYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/areIntervalsOverlapping/index.js","kind":"import-statement","original":"./areIntervalsOverlapping/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/clamp/index.js","kind":"import-statement","original":"./clamp/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/closestIndexTo/index.js","kind":"import-statement","original":"./closestIndexTo/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/closestTo/index.js","kind":"import-statement","original":"./closestTo/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareAsc/index.js","kind":"import-statement","original":"./compareAsc/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/compareDesc/index.js","kind":"import-statement","original":"./compareDesc/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/daysToWeeks/index.js","kind":"import-statement","original":"./daysToWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInBusinessDays/index.js","kind":"import-statement","original":"./differenceInBusinessDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarDays/index.js","kind":"import-statement","original":"./differenceInCalendarDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarISOWeekYears/index.js","kind":"import-statement","original":"./differenceInCalendarISOWeekYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarISOWeeks/index.js","kind":"import-statement","original":"./differenceInCalendarISOWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarMonths/index.js","kind":"import-statement","original":"./differenceInCalendarMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarQuarters/index.js","kind":"import-statement","original":"./differenceInCalendarQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarWeeks/index.js","kind":"import-statement","original":"./differenceInCalendarWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInCalendarYears/index.js","kind":"import-statement","original":"./differenceInCalendarYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInDays/index.js","kind":"import-statement","original":"./differenceInDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInHours/index.js","kind":"import-statement","original":"./differenceInHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInISOWeekYears/index.js","kind":"import-statement","original":"./differenceInISOWeekYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMilliseconds/index.js","kind":"import-statement","original":"./differenceInMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMinutes/index.js","kind":"import-statement","original":"./differenceInMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInMonths/index.js","kind":"import-statement","original":"./differenceInMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInQuarters/index.js","kind":"import-statement","original":"./differenceInQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInSeconds/index.js","kind":"import-statement","original":"./differenceInSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInWeeks/index.js","kind":"import-statement","original":"./differenceInWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/differenceInYears/index.js","kind":"import-statement","original":"./differenceInYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachDayOfInterval/index.js","kind":"import-statement","original":"./eachDayOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachHourOfInterval/index.js","kind":"import-statement","original":"./eachHourOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachMinuteOfInterval/index.js","kind":"import-statement","original":"./eachMinuteOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachMonthOfInterval/index.js","kind":"import-statement","original":"./eachMonthOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachQuarterOfInterval/index.js","kind":"import-statement","original":"./eachQuarterOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekOfInterval/index.js","kind":"import-statement","original":"./eachWeekOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekendOfInterval/index.js","kind":"import-statement","original":"./eachWeekendOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekendOfMonth/index.js","kind":"import-statement","original":"./eachWeekendOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachWeekendOfYear/index.js","kind":"import-statement","original":"./eachWeekendOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/eachYearOfInterval/index.js","kind":"import-statement","original":"./eachYearOfInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfDay/index.js","kind":"import-statement","original":"./endOfDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfDecade/index.js","kind":"import-statement","original":"./endOfDecade/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfHour/index.js","kind":"import-statement","original":"./endOfHour/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfISOWeek/index.js","kind":"import-statement","original":"./endOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfISOWeekYear/index.js","kind":"import-statement","original":"./endOfISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfMinute/index.js","kind":"import-statement","original":"./endOfMinute/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfMonth/index.js","kind":"import-statement","original":"./endOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfQuarter/index.js","kind":"import-statement","original":"./endOfQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfSecond/index.js","kind":"import-statement","original":"./endOfSecond/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfToday/index.js","kind":"import-statement","original":"./endOfToday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfTomorrow/index.js","kind":"import-statement","original":"./endOfTomorrow/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfWeek/index.js","kind":"import-statement","original":"./endOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfYear/index.js","kind":"import-statement","original":"./endOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/endOfYesterday/index.js","kind":"import-statement","original":"./endOfYesterday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/format/index.js","kind":"import-statement","original":"./format/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistance/index.js","kind":"import-statement","original":"./formatDistance/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistanceStrict/index.js","kind":"import-statement","original":"./formatDistanceStrict/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistanceToNow/index.js","kind":"import-statement","original":"./formatDistanceToNow/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDistanceToNowStrict/index.js","kind":"import-statement","original":"./formatDistanceToNowStrict/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatDuration/index.js","kind":"import-statement","original":"./formatDuration/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatISO/index.js","kind":"import-statement","original":"./formatISO/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatISO9075/index.js","kind":"import-statement","original":"./formatISO9075/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatISODuration/index.js","kind":"import-statement","original":"./formatISODuration/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatRFC3339/index.js","kind":"import-statement","original":"./formatRFC3339/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatRFC7231/index.js","kind":"import-statement","original":"./formatRFC7231/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/formatRelative/index.js","kind":"import-statement","original":"./formatRelative/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/fromUnixTime/index.js","kind":"import-statement","original":"./fromUnixTime/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDate/index.js","kind":"import-statement","original":"./getDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDay/index.js","kind":"import-statement","original":"./getDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDayOfYear/index.js","kind":"import-statement","original":"./getDayOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDaysInMonth/index.js","kind":"import-statement","original":"./getDaysInMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDaysInYear/index.js","kind":"import-statement","original":"./getDaysInYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDecade/index.js","kind":"import-statement","original":"./getDecade/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getDefaultOptions/index.js","kind":"import-statement","original":"./getDefaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getHours/index.js","kind":"import-statement","original":"./getHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISODay/index.js","kind":"import-statement","original":"./getISODay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeek/index.js","kind":"import-statement","original":"./getISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeekYear/index.js","kind":"import-statement","original":"./getISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getISOWeeksInYear/index.js","kind":"import-statement","original":"./getISOWeeksInYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getMilliseconds/index.js","kind":"import-statement","original":"./getMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getMinutes/index.js","kind":"import-statement","original":"./getMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getMonth/index.js","kind":"import-statement","original":"./getMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getOverlappingDaysInIntervals/index.js","kind":"import-statement","original":"./getOverlappingDaysInIntervals/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getQuarter/index.js","kind":"import-statement","original":"./getQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getSeconds/index.js","kind":"import-statement","original":"./getSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getTime/index.js","kind":"import-statement","original":"./getTime/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getUnixTime/index.js","kind":"import-statement","original":"./getUnixTime/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeek/index.js","kind":"import-statement","original":"./getWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeekOfMonth/index.js","kind":"import-statement","original":"./getWeekOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeekYear/index.js","kind":"import-statement","original":"./getWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getWeeksInMonth/index.js","kind":"import-statement","original":"./getWeeksInMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/getYear/index.js","kind":"import-statement","original":"./getYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/hoursToMilliseconds/index.js","kind":"import-statement","original":"./hoursToMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/hoursToMinutes/index.js","kind":"import-statement","original":"./hoursToMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/hoursToSeconds/index.js","kind":"import-statement","original":"./hoursToSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/intervalToDuration/index.js","kind":"import-statement","original":"./intervalToDuration/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/intlFormat/index.js","kind":"import-statement","original":"./intlFormat/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/intlFormatDistance/index.js","kind":"import-statement","original":"./intlFormatDistance/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isAfter/index.js","kind":"import-statement","original":"./isAfter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isBefore/index.js","kind":"import-statement","original":"./isBefore/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isDate/index.js","kind":"import-statement","original":"./isDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isEqual/index.js","kind":"import-statement","original":"./isEqual/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isExists/index.js","kind":"import-statement","original":"./isExists/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isFirstDayOfMonth/index.js","kind":"import-statement","original":"./isFirstDayOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isFriday/index.js","kind":"import-statement","original":"./isFriday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isFuture/index.js","kind":"import-statement","original":"./isFuture/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isLastDayOfMonth/index.js","kind":"import-statement","original":"./isLastDayOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isLeapYear/index.js","kind":"import-statement","original":"./isLeapYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isMatch/index.js","kind":"import-statement","original":"./isMatch/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isMonday/index.js","kind":"import-statement","original":"./isMonday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isPast/index.js","kind":"import-statement","original":"./isPast/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameDay/index.js","kind":"import-statement","original":"./isSameDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameHour/index.js","kind":"import-statement","original":"./isSameHour/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameISOWeek/index.js","kind":"import-statement","original":"./isSameISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameISOWeekYear/index.js","kind":"import-statement","original":"./isSameISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameMinute/index.js","kind":"import-statement","original":"./isSameMinute/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameMonth/index.js","kind":"import-statement","original":"./isSameMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameQuarter/index.js","kind":"import-statement","original":"./isSameQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameSecond/index.js","kind":"import-statement","original":"./isSameSecond/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameWeek/index.js","kind":"import-statement","original":"./isSameWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSameYear/index.js","kind":"import-statement","original":"./isSameYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSaturday/index.js","kind":"import-statement","original":"./isSaturday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isSunday/index.js","kind":"import-statement","original":"./isSunday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisHour/index.js","kind":"import-statement","original":"./isThisHour/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisISOWeek/index.js","kind":"import-statement","original":"./isThisISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisMinute/index.js","kind":"import-statement","original":"./isThisMinute/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisMonth/index.js","kind":"import-statement","original":"./isThisMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisQuarter/index.js","kind":"import-statement","original":"./isThisQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisSecond/index.js","kind":"import-statement","original":"./isThisSecond/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisWeek/index.js","kind":"import-statement","original":"./isThisWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThisYear/index.js","kind":"import-statement","original":"./isThisYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isThursday/index.js","kind":"import-statement","original":"./isThursday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isToday/index.js","kind":"import-statement","original":"./isToday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isTomorrow/index.js","kind":"import-statement","original":"./isTomorrow/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isTuesday/index.js","kind":"import-statement","original":"./isTuesday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js","kind":"import-statement","original":"./isValid/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWednesday/index.js","kind":"import-statement","original":"./isWednesday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWeekend/index.js","kind":"import-statement","original":"./isWeekend/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isWithinInterval/index.js","kind":"import-statement","original":"./isWithinInterval/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isYesterday/index.js","kind":"import-statement","original":"./isYesterday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfDecade/index.js","kind":"import-statement","original":"./lastDayOfDecade/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfISOWeek/index.js","kind":"import-statement","original":"./lastDayOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfISOWeekYear/index.js","kind":"import-statement","original":"./lastDayOfISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfMonth/index.js","kind":"import-statement","original":"./lastDayOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfQuarter/index.js","kind":"import-statement","original":"./lastDayOfQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfWeek/index.js","kind":"import-statement","original":"./lastDayOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lastDayOfYear/index.js","kind":"import-statement","original":"./lastDayOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/lightFormat/index.js","kind":"import-statement","original":"./lightFormat/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/max/index.js","kind":"import-statement","original":"./max/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/milliseconds/index.js","kind":"import-statement","original":"./milliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/millisecondsToHours/index.js","kind":"import-statement","original":"./millisecondsToHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/millisecondsToMinutes/index.js","kind":"import-statement","original":"./millisecondsToMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/millisecondsToSeconds/index.js","kind":"import-statement","original":"./millisecondsToSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/min/index.js","kind":"import-statement","original":"./min/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/minutesToHours/index.js","kind":"import-statement","original":"./minutesToHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/minutesToMilliseconds/index.js","kind":"import-statement","original":"./minutesToMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/minutesToSeconds/index.js","kind":"import-statement","original":"./minutesToSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/monthsToQuarters/index.js","kind":"import-statement","original":"./monthsToQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/monthsToYears/index.js","kind":"import-statement","original":"./monthsToYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextDay/index.js","kind":"import-statement","original":"./nextDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextFriday/index.js","kind":"import-statement","original":"./nextFriday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextMonday/index.js","kind":"import-statement","original":"./nextMonday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextSaturday/index.js","kind":"import-statement","original":"./nextSaturday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextSunday/index.js","kind":"import-statement","original":"./nextSunday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextThursday/index.js","kind":"import-statement","original":"./nextThursday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextTuesday/index.js","kind":"import-statement","original":"./nextTuesday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/nextWednesday/index.js","kind":"import-statement","original":"./nextWednesday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parse/index.js","kind":"import-statement","original":"./parse/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parseISO/index.js","kind":"import-statement","original":"./parseISO/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/parseJSON/index.js","kind":"import-statement","original":"./parseJSON/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousDay/index.js","kind":"import-statement","original":"./previousDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousFriday/index.js","kind":"import-statement","original":"./previousFriday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousMonday/index.js","kind":"import-statement","original":"./previousMonday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousSaturday/index.js","kind":"import-statement","original":"./previousSaturday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousSunday/index.js","kind":"import-statement","original":"./previousSunday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousThursday/index.js","kind":"import-statement","original":"./previousThursday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousTuesday/index.js","kind":"import-statement","original":"./previousTuesday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/previousWednesday/index.js","kind":"import-statement","original":"./previousWednesday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/quartersToMonths/index.js","kind":"import-statement","original":"./quartersToMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/quartersToYears/index.js","kind":"import-statement","original":"./quartersToYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/roundToNearestMinutes/index.js","kind":"import-statement","original":"./roundToNearestMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/secondsToHours/index.js","kind":"import-statement","original":"./secondsToHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/secondsToMilliseconds/index.js","kind":"import-statement","original":"./secondsToMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/secondsToMinutes/index.js","kind":"import-statement","original":"./secondsToMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/set/index.js","kind":"import-statement","original":"./set/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setDate/index.js","kind":"import-statement","original":"./setDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setDay/index.js","kind":"import-statement","original":"./setDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setDayOfYear/index.js","kind":"import-statement","original":"./setDayOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setDefaultOptions/index.js","kind":"import-statement","original":"./setDefaultOptions/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setHours/index.js","kind":"import-statement","original":"./setHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setISODay/index.js","kind":"import-statement","original":"./setISODay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setISOWeek/index.js","kind":"import-statement","original":"./setISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setISOWeekYear/index.js","kind":"import-statement","original":"./setISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setMilliseconds/index.js","kind":"import-statement","original":"./setMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setMinutes/index.js","kind":"import-statement","original":"./setMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setMonth/index.js","kind":"import-statement","original":"./setMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setQuarter/index.js","kind":"import-statement","original":"./setQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setSeconds/index.js","kind":"import-statement","original":"./setSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setWeek/index.js","kind":"import-statement","original":"./setWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setWeekYear/index.js","kind":"import-statement","original":"./setWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/setYear/index.js","kind":"import-statement","original":"./setYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfDay/index.js","kind":"import-statement","original":"./startOfDay/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfDecade/index.js","kind":"import-statement","original":"./startOfDecade/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfHour/index.js","kind":"import-statement","original":"./startOfHour/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeek/index.js","kind":"import-statement","original":"./startOfISOWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfISOWeekYear/index.js","kind":"import-statement","original":"./startOfISOWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMinute/index.js","kind":"import-statement","original":"./startOfMinute/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfMonth/index.js","kind":"import-statement","original":"./startOfMonth/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfQuarter/index.js","kind":"import-statement","original":"./startOfQuarter/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfSecond/index.js","kind":"import-statement","original":"./startOfSecond/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfToday/index.js","kind":"import-statement","original":"./startOfToday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfTomorrow/index.js","kind":"import-statement","original":"./startOfTomorrow/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeek/index.js","kind":"import-statement","original":"./startOfWeek/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfWeekYear/index.js","kind":"import-statement","original":"./startOfWeekYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfYear/index.js","kind":"import-statement","original":"./startOfYear/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/startOfYesterday/index.js","kind":"import-statement","original":"./startOfYesterday/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/sub/index.js","kind":"import-statement","original":"./sub/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subBusinessDays/index.js","kind":"import-statement","original":"./subBusinessDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subDays/index.js","kind":"import-statement","original":"./subDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subHours/index.js","kind":"import-statement","original":"./subHours/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subISOWeekYears/index.js","kind":"import-statement","original":"./subISOWeekYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js","kind":"import-statement","original":"./subMilliseconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMinutes/index.js","kind":"import-statement","original":"./subMinutes/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMonths/index.js","kind":"import-statement","original":"./subMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subQuarters/index.js","kind":"import-statement","original":"./subQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subSeconds/index.js","kind":"import-statement","original":"./subSeconds/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subWeeks/index.js","kind":"import-statement","original":"./subWeeks/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subYears/index.js","kind":"import-statement","original":"./subYears/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js","kind":"import-statement","original":"./toDate/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/weeksToDays/index.js","kind":"import-statement","original":"./weeksToDays/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/yearsToMonths/index.js","kind":"import-statement","original":"./yearsToMonths/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/yearsToQuarters/index.js","kind":"import-statement","original":"./yearsToQuarters/index.js"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/constants/index.js","kind":"import-statement","original":"./constants/index.js"}],"format":"esm"},"src/components/Transactions/views.tsx":{"bytes":10531,"imports":[{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/index.js","kind":"import-statement","original":"date-fns"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"./index.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/Transactions/index.ts":{"bytes":2272,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"preact","kind":"import-statement","external":true},{"path":"src/components/Transactions/state.ts","kind":"import-statement","original":"./state.js"},{"path":"src/components/Transactions/views.tsx","kind":"import-statement","original":"./views.js"}],"format":"esm"},"src/hooks/bank-state.ts":{"bytes":7737,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"}],"format":"esm"},"src/pages/OperationState/state.ts":{"bytes":5989,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/context/settings.ts","kind":"import-statement","original":"../../context/settings.js"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../../hooks/account.js"},{"path":"src/hooks/bank-state.ts","kind":"import-statement","original":"../../hooks/bank-state.js"},{"path":"src/hooks/preferences.ts","kind":"import-statement","original":"../../hooks/preferences.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"./index.js","kind":"import-statement","external":true}],"format":"esm"},"../../node_modules/.pnpm/qrcode-generator@1.4.4/node_modules/qrcode-generator/qrcode.js":{"bytes":56694,"imports":[],"format":"cjs"},"src/components/QR.tsx":{"bytes":1236,"imports":[{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/qrcode-generator@1.4.4/node_modules/qrcode-generator/qrcode.js","kind":"import-statement","original":"qrcode-generator"}],"format":"esm"},"src/pages/WithdrawalConfirmationQuestion.tsx":{"bytes":23092,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/core/dist/index.mjs","kind":"import-statement","original":"swr"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"src/pages/LoginForm.tsx","kind":"import-statement","original":"./LoginForm.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"./SolveMFA.js"}],"format":"esm"},"src/pages/OperationState/views.tsx":{"bytes":28349,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/components/QR.tsx","kind":"import-statement","original":"../../components/QR.js"},{"path":"src/hooks/preferences.ts","kind":"import-statement","original":"../../hooks/preferences.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"../SolveMFA.js"},{"path":"src/pages/WithdrawalConfirmationQuestion.tsx","kind":"import-statement","original":"../WithdrawalConfirmationQuestion.js"},{"path":"./index.js","kind":"import-statement","external":true}],"format":"esm"},"src/pages/OperationState/index.ts":{"bytes":3705,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"preact","kind":"import-statement","external":true},{"path":"src/pages/OperationState/state.ts","kind":"import-statement","original":"./state.js"},{"path":"src/pages/OperationState/views.tsx","kind":"import-statement","original":"./views.js"},{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true}],"format":"esm"},"src/pages/WalletWithdrawForm.tsx":{"bytes":11010,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/dist/compat.module.js","kind":"import-statement","original":"preact/compat"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/context/settings.ts","kind":"import-statement","original":"../context/settings.js"},{"path":"src/hooks/bank-state.ts","kind":"import-statement","original":"../hooks/bank-state.js"},{"path":"src/hooks/preferences.ts","kind":"import-statement","original":"../hooks/preferences.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils.js"},{"path":"src/pages/OperationState/index.ts","kind":"import-statement","original":"./OperationState/index.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"./PaytoWireTransferForm.js"},{"path":"./regional/CreateCashout.js","kind":"import-statement","external":true}],"format":"esm"},"src/pages/PaymentOptions.tsx":{"bytes":8246,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../hooks/bank-state.js","kind":"import-statement","external":true},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"./PaytoWireTransferForm.js"},{"path":"src/pages/WalletWithdrawForm.tsx","kind":"import-statement","original":"./WalletWithdrawForm.js"},{"path":"./regional/CreateCashout.js","kind":"import-statement","external":true}],"format":"esm"},"src/pages/AccountPage/views.tsx":{"bytes":3519,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"src/components/Transactions/index.ts","kind":"import-statement","original":"../../components/Transactions/index.js"},{"path":"../../hooks/bank-state.js","kind":"import-statement","external":true},{"path":"src/hooks/preferences.ts","kind":"import-statement","original":"../../hooks/preferences.js"},{"path":"src/pages/PaymentOptions.tsx","kind":"import-statement","original":"../PaymentOptions.js"},{"path":"./index.js","kind":"import-statement","external":true},{"path":"@gnu-taler/web-util/browser","kind":"import-statement","external":true},{"path":"src/context/settings.ts","kind":"import-statement","original":"../../context/settings.js"}],"format":"esm"},"src/pages/AccountPage/index.ts":{"bytes":3596,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"preact","kind":"import-statement","external":true},{"path":"src/pages/LoginForm.tsx","kind":"import-statement","original":"../LoginForm.js"},{"path":"src/pages/AccountPage/state.ts","kind":"import-statement","original":"./state.js"},{"path":"src/pages/AccountPage/views.tsx","kind":"import-statement","original":"./views.js"},{"path":"../regional/CreateCashout.js","kind":"import-statement","external":true}],"format":"esm"},"src/pages/BankFrame.tsx":{"bytes":14468,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/context/settings.ts","kind":"import-statement","original":"../context/settings.js"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../hooks/account.js"},{"path":"src/hooks/bank-state.ts","kind":"import-statement","original":"../hooks/bank-state.js"},{"path":"src/hooks/preferences.ts","kind":"import-statement","original":"../hooks/preferences.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"}],"format":"esm"},"src/hooks/form.ts":{"bytes":3386,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"}],"format":"esm"},"src/pages/admin/ConversionClassList.tsx":{"bytes":11799,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../../hooks/regional.js"}],"format":"esm"},"src/pages/ProfileNavigation.tsx":{"bytes":8321,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"@gnu-taler/web-util/browser","kind":"import-statement","external":true}],"format":"esm"},"src/pages/regional/ConversionConfig.tsx":{"bytes":46895,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/form.ts","kind":"import-statement","original":"../../hooks/form.js"},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../../hooks/regional.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../../utils.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"../PaytoWireTransferForm.js"},{"path":"src/pages/ProfileNavigation.tsx","kind":"import-statement","original":"../ProfileNavigation.js"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"src/pages/admin/ConversionClassList.tsx","kind":"import-statement","original":"../admin/ConversionClassList.js"}],"format":"esm"},"src/pages/ConversionRateClassDetails.tsx":{"bytes":52570,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/form.ts","kind":"import-statement","original":"../hooks/form.js"},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../hooks/regional.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../utils.js"},{"path":"src/pages/admin/ConversionClassList.tsx","kind":"import-statement","original":"./admin/ConversionClassList.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"./PaytoWireTransferForm.js"},{"path":"src/pages/regional/ConversionConfig.tsx","kind":"import-statement","original":"./regional/ConversionConfig.js"},{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true}],"format":"esm"},"src/pages/admin/ConversionRateClassForm.tsx":{"bytes":23827,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../../utils.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"../PaytoWireTransferForm.js"}],"format":"esm"},"src/pages/NewConversionRateClass.tsx":{"bytes":3523,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"src/pages/admin/ConversionRateClassForm.tsx","kind":"import-statement","original":"./admin/ConversionRateClassForm.js"}],"format":"esm"},"src/pages/PublicHistoriesPage.tsx":{"bytes":2978,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/components/Transactions/index.ts","kind":"import-statement","original":"../components/Transactions/index.js"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../hooks/account.js"}],"format":"esm"},"src/pages/ShowNotifications.tsx":{"bytes":1650,"imports":[{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"}],"format":"esm"},"src/pages/WireTransfer.tsx":{"bytes":3445,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../hooks/account.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"src/pages/LoginForm.tsx","kind":"import-statement","original":"./LoginForm.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"./PaytoWireTransferForm.js"},{"path":"@gnu-taler/web-util/browser","kind":"import-statement","external":true},{"path":"src/pages/regional/CreateCashout.tsx","kind":"import-statement","original":"./regional/CreateCashout.js"}],"format":"esm"},"src/pages/QrCodeSection.tsx":{"bytes":5877,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/components/QR.tsx","kind":"import-statement","original":"../components/QR.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../hooks/session.js"},{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true}],"format":"esm"},"src/pages/WithdrawalQRCode.tsx":{"bytes":10835,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../hooks/account.js"},{"path":"src/pages/QrCodeSection.tsx","kind":"import-statement","original":"./QrCodeSection.js"},{"path":"src/pages/WithdrawalConfirmationQuestion.tsx","kind":"import-statement","original":"./WithdrawalConfirmationQuestion.js"}],"format":"esm"},"src/pages/WithdrawalOperationPage.tsx":{"bytes":2218,"imports":[{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"src/hooks/bank-state.ts","kind":"import-statement","original":"../hooks/bank-state.js"},{"path":"@gnu-taler/web-util/browser","kind":"import-statement","external":true},{"path":"src/pages/WithdrawalQRCode.tsx","kind":"import-statement","original":"./WithdrawalQRCode.js"},{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"}],"format":"esm"},"src/components/Cashouts/state.ts":{"bytes":1399,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../../hooks/regional.js"},{"path":"./index.js","kind":"import-statement","external":true}],"format":"esm"},"src/components/Cashouts/views.tsx":{"bytes":6946,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/index.js","kind":"import-statement","original":"date-fns"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"./index.js","kind":"import-statement","external":true},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../../hooks/regional.js"}],"format":"esm"},"src/components/Cashouts/index.ts":{"bytes":2283,"imports":[{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"preact","kind":"import-statement","external":true},{"path":"src/components/Cashouts/state.ts","kind":"import-statement","original":"./state.js"},{"path":"src/components/Cashouts/views.tsx","kind":"import-statement","original":"./views.js"}],"format":"esm"},"src/pages/account/CashoutListForAccount.tsx":{"bytes":2801,"imports":[{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"src/components/Cashouts/index.ts","kind":"import-statement","original":"../../components/Cashouts/index.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/pages/ProfileNavigation.tsx","kind":"import-statement","original":"../ProfileNavigation.js"},{"path":"src/pages/regional/CreateCashout.tsx","kind":"import-statement","original":"../regional/CreateCashout.js"},{"path":"@gnu-taler/web-util/browser","kind":"import-statement","external":true}],"format":"esm"},"src/pages/admin/AccountForm.tsx":{"bytes":30364,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../../utils.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"../PaytoWireTransferForm.js"},{"path":"src/pages/rnd.ts","kind":"import-statement","original":"../rnd.js"}],"format":"esm"},"src/pages/account/ShowAccountDetails.tsx":{"bytes":23170,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../../hooks/account.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/pages/admin/AccountForm.tsx","kind":"import-statement","original":"../admin/AccountForm.js"},{"path":"src/pages/LoginForm.tsx","kind":"import-statement","original":"../LoginForm.js"},{"path":"src/pages/ProfileNavigation.tsx","kind":"import-statement","original":"../ProfileNavigation.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"../SolveMFA.js"}],"format":"esm"},"src/pages/account/UpdateAccountPassword.tsx":{"bytes":11966,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../../utils.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"../PaytoWireTransferForm.js"},{"path":"src/pages/ProfileNavigation.tsx","kind":"import-statement","original":"../ProfileNavigation.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"../SolveMFA.js"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"}],"format":"esm"},"src/pages/admin/AccountList.tsx":{"bytes":9917,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../../hooks/regional.js"}],"format":"esm"},"src/pages/admin/AdminHome.tsx":{"bytes":27939,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/index.js","kind":"import-statement","original":"date-fns"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/components/Transactions/index.ts","kind":"import-statement","original":"../../components/Transactions/index.js"},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../../hooks/regional.js"},{"path":"src/pages/WireTransfer.tsx","kind":"import-statement","original":"../WireTransfer.js"},{"path":"src/pages/admin/AccountList.tsx","kind":"import-statement","original":"./AccountList.js"},{"path":"src/pages/admin/ConversionClassList.tsx","kind":"import-statement","original":"./ConversionClassList.js"}],"format":"esm"},"src/pages/admin/CreateNewAccount.tsx":{"bytes":6341,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/pages/admin/AccountForm.tsx","kind":"import-statement","original":"./AccountForm.js"}],"format":"esm"},"src/pages/admin/DownloadStats.tsx":{"bytes":23162,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/pages/admin/AdminHome.tsx","kind":"import-statement","original":"./AdminHome.js"}],"format":"esm"},"src/pages/admin/RemoveAccount.tsx":{"bytes":9062,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"../../hooks/account.js"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"../../hooks/session.js"},{"path":"src/utils.ts","kind":"import-statement","original":"../../utils.js"},{"path":"src/pages/LoginForm.tsx","kind":"import-statement","original":"../LoginForm.js"},{"path":"src/pages/PaytoWireTransferForm.tsx","kind":"import-statement","original":"../PaytoWireTransferForm.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"../SolveMFA.js"},{"path":"@gnu-taler/taler-util","kind":"import-statement","external":true}],"format":"esm"},"src/pages/regional/ShowCashoutDetails.tsx":{"bytes":6485,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"../../hooks/regional.js"}],"format":"esm"},"src/Routing.tsx":{"bytes":20906,"imports":[{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"src/hooks/session.ts","kind":"import-statement","original":"./hooks/session.js"},{"path":"src/pages/AccountPage/index.ts","kind":"import-statement","original":"./pages/AccountPage/index.js"},{"path":"src/pages/BankFrame.tsx","kind":"import-statement","original":"./pages/BankFrame.js"},{"path":"src/pages/ConversionRateClassDetails.tsx","kind":"import-statement","original":"./pages/ConversionRateClassDetails.js"},{"path":"src/pages/LoginForm.tsx","kind":"import-statement","original":"./pages/LoginForm.js"},{"path":"src/pages/NewConversionRateClass.tsx","kind":"import-statement","original":"./pages/NewConversionRateClass.js"},{"path":"src/pages/PublicHistoriesPage.tsx","kind":"import-statement","original":"./pages/PublicHistoriesPage.js"},{"path":"src/pages/RegistrationPage.tsx","kind":"import-statement","original":"./pages/RegistrationPage.js"},{"path":"src/pages/ShowNotifications.tsx","kind":"import-statement","original":"./pages/ShowNotifications.js"},{"path":"src/pages/SolveMFA.tsx","kind":"import-statement","original":"./pages/SolveMFA.js"},{"path":"src/pages/WireTransfer.tsx","kind":"import-statement","original":"./pages/WireTransfer.js"},{"path":"src/pages/WithdrawalOperationPage.tsx","kind":"import-statement","original":"./pages/WithdrawalOperationPage.js"},{"path":"src/pages/account/CashoutListForAccount.tsx","kind":"import-statement","original":"./pages/account/CashoutListForAccount.js"},{"path":"src/pages/account/ShowAccountDetails.tsx","kind":"import-statement","original":"./pages/account/ShowAccountDetails.js"},{"path":"src/pages/account/UpdateAccountPassword.tsx","kind":"import-statement","original":"./pages/account/UpdateAccountPassword.js"},{"path":"src/pages/admin/AdminHome.tsx","kind":"import-statement","original":"./pages/admin/AdminHome.js"},{"path":"src/pages/admin/CreateNewAccount.tsx","kind":"import-statement","original":"./pages/admin/CreateNewAccount.js"},{"path":"src/pages/admin/DownloadStats.tsx","kind":"import-statement","original":"./pages/admin/DownloadStats.js"},{"path":"src/pages/admin/RemoveAccount.tsx","kind":"import-statement","original":"./pages/admin/RemoveAccount.js"},{"path":"src/pages/regional/ConversionConfig.tsx","kind":"import-statement","original":"./pages/regional/ConversionConfig.js"},{"path":"src/pages/regional/CreateCashout.tsx","kind":"import-statement","original":"./pages/regional/CreateCashout.js"},{"path":"src/pages/regional/ShowCashoutDetails.tsx","kind":"import-statement","original":"./pages/regional/ShowCashoutDetails.js"}],"format":"esm"},"src/i18n/strings.ts":{"bytes":372765,"imports":[],"format":"esm"},"src/settings.ts":{"bytes":3744,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"}],"format":"esm"},"src/app.tsx":{"bytes":7346,"imports":[{"path":"../taler-util/lib/index.browser.js","kind":"import-statement","original":"@gnu-taler/taler-util"},{"path":"../web-util/lib/index.browser.mjs","kind":"import-statement","original":"@gnu-taler/web-util/browser"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js","kind":"import-statement","original":"preact/hooks"},{"path":"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/core/dist/index.mjs","kind":"import-statement","original":"swr"},{"path":"src/Routing.tsx","kind":"import-statement","original":"./Routing.js"},{"path":"src/context/settings.ts","kind":"import-statement","original":"./context/settings.js"},{"path":"src/hooks/account.ts","kind":"import-statement","original":"./hooks/account.js"},{"path":"src/hooks/regional.ts","kind":"import-statement","original":"./hooks/regional.js"},{"path":"src/i18n/strings.ts","kind":"import-statement","original":"./i18n/strings.js"},{"path":"src/pages/BankFrame.tsx","kind":"import-statement","original":"./pages/BankFrame.js"},{"path":"src/settings.ts","kind":"import-statement","original":"./settings.js"}],"format":"esm"},"src/scss/main.css":{"bytes":68027,"imports":[{"path":"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e","kind":"url-token","external":true},{"path":"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e","kind":"url-token","external":true},{"path":"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e","kind":"url-token","external":true},{"path":"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e","kind":"url-token","external":true}]},"src/index.tsx":{"bytes":1265,"imports":[{"path":"src/app.tsx","kind":"import-statement","original":"./app.js"},{"path":"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js","kind":"import-statement","original":"preact"},{"path":"src/scss/main.css","kind":"import-statement","original":"./scss/main.css"}],"format":"esm"}},"outputs":{"dist/prod/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":5700161},"dist/prod/index.js":{"imports":[],"exports":[],"entryPoint":"src/index.tsx","cssBundle":"dist/prod/index.css","inputs":{"../../node_modules/.pnpm/big-integer@1.6.52/node_modules/big-integer/BigInteger.js":{"bytesInOutput":22411},"../../node_modules/.pnpm/jed@1.1.1/node_modules/jed/jed.js":{"bytesInOutput":16648},"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/dist/preact.module.js":{"bytesInOutput":10093},"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/hooks/dist/hooks.module.js":{"bytesInOutput":3462},"../../node_modules/.pnpm/preact@10.11.3/node_modules/preact/compat/dist/compat.module.js":{"bytesInOutput":9336},"../../node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.min.js":{"bytesInOutput":787},"../../node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store/shim/index.js":{"bytesInOutput":51},"../../node_modules/.pnpm/qrcode-generator@1.4.4/node_modules/qrcode-generator/qrcode.js":{"bytesInOutput":21729},"../taler-util/lib/nacl-fast.js":{"bytesInOutput":18092},"../taler-util/lib/prng-browser.js":{"bytesInOutput":273},"../taler-util/lib/punycode.js":{"bytesInOutput":2339},"../taler-util/lib/whatwg-url.js":{"bytesInOutput":21535},"../taler-util/lib/url.js":{"bytesInOutput":377},"../taler-util/lib/helpers.js":{"bytesInOutput":641},"../taler-util/lib/logging.js":{"bytesInOutput":2797},"../taler-util/lib/codec.js":{"bytesInOutput":4009},"../taler-util/lib/CancellationToken.js":{"bytesInOutput":1714},"../taler-util/lib/taler-error-codes.js":{"bytesInOutput":64691},"../taler-util/lib/time.js":{"bytesInOutput":7667},"../taler-util/lib/errors.js":{"bytesInOutput":1122},"../taler-util/lib/http-common.js":{"bytesInOutput":3679},"../taler-util/lib/libtool-version.js":{"bytesInOutput":571},"../taler-util/lib/types-taler-common.js":{"bytesInOutput":1045},"../taler-util/lib/operation.js":{"bytesInOutput":1260},"../taler-util/lib/amounts.js":{"bytesInOutput":7642},"../taler-util/lib/index.js":{"bytesInOutput":0},"../taler-util/lib/http-impl.missing.js":{"bytesInOutput":69},"../taler-util/lib/http.js":{"bytesInOutput":32},"../taler-util/lib/base64.js":{"bytesInOutput":515},"../taler-util/lib/taler-crypto.js":{"bytesInOutput":7012},"../taler-util/lib/sha256.js":{"bytesInOutput":3374},"../taler-util/lib/kdf.js":{"bytesInOutput":432},"../taler-util/lib/taler_signatures.js":{"bytesInOutput":4257},"../taler-util/lib/result.js":{"bytesInOutput":387},"../taler-util/lib/bech32.js":{"bytesInOutput":1906},"../taler-util/lib/segwit_addr.js":{"bytesInOutput":1098},"../taler-util/lib/bitcoin.js":{"bytesInOutput":819},"../taler-util/lib/iban.js":{"bytesInOutput":4062},"../taler-util/lib/payto.js":{"bytesInOutput":7234},"../taler-util/lib/types-taler-exchange.js":{"bytesInOutput":9848},"../taler-util/lib/http-client/utils.js":{"bytesInOutput":548},"../taler-util/lib/bank-api-client.js":{"bytesInOutput":101},"../taler-util/lib/types-taler-wallet.js":{"bytesInOutput":3127},"../taler-util/lib/types-taler-merchant.js":{"bytesInOutput":25872},"../taler-util/lib/contract-terms.js":{"bytesInOutput":4051},"../taler-util/lib/fnutils.js":{"bytesInOutput":166},"../taler-util/lib/http-status-codes.js":{"bytesInOutput":2586},"../taler-util/lib/types-taler-bank-conversion.js":{"bytesInOutput":1024},"../taler-util/lib/http-client/bank-conversion.js":{"bytesInOutput":2450},"../taler-util/lib/types-taler-corebank.js":{"bytesInOutput":6904},"../taler-util/lib/taleruri.js":{"bytesInOutput":17064},"../taler-util/lib/http-client/bank-core.js":{"bytesInOutput":17860},"../taler-util/lib/types-taler-bank-integration.js":{"bytesInOutput":972},"../taler-util/lib/http-client/bank-integration.js":{"bytesInOutput":1766},"../taler-util/lib/types-taler-revenue.js":{"bytesInOutput":498},"../taler-util/lib/http-client/bank-revenue.js":{"bytesInOutput":879},"../taler-util/lib/types-taler-wire-gateway.js":{"bytesInOutput":2397},"../taler-util/lib/http-client/bank-wire.js":{"bytesInOutput":3627},"../taler-util/lib/types-taler-prepared-transfer.js":{"bytesInOutput":1017},"../taler-util/lib/http-client/bank-prepared.js":{"bytesInOutput":1174},"../taler-util/lib/types-taler-challenger.js":{"bytesInOutput":1870},"../taler-util/lib/http-client/challenger.js":{"bytesInOutput":3160},"../taler-util/lib/types-donau.js":{"bytesInOutput":699},"../taler-util/lib/http-client/donau-client.js":{"bytesInOutput":3431},"../taler-util/lib/http-client/exchange-client.js":{"bytesInOutput":13189},"../taler-util/lib/http-client/mailbox.js":{"bytesInOutput":2455},"../taler-util/lib/http-client/merchant.js":{"bytesInOutput":40535},"../taler-util/lib/i18n.js":{"bytesInOutput":1135},"../taler-util/lib/promises.js":{"bytesInOutput":208},"../taler-util/lib/longpool-queue.js":{"bytesInOutput":728},"../taler-util/lib/notifications.js":{"bytesInOutput":1334},"../taler-util/lib/timer.js":{"bytesInOutput":637},"../taler-util/lib/observability.js":{"bytesInOutput":865},"../taler-util/lib/performance.js":{"bytesInOutput":2639},"../taler-util/lib/RequestThrottler.js":{"bytesInOutput":1329},"../taler-util/lib/ReserveTransaction.js":{"bytesInOutput":113},"../taler-util/lib/TaskThrottler.js":{"bytesInOutput":39},"../taler-util/lib/types-taler-wallet-transactions.js":{"bytesInOutput":2077},"../taler-util/lib/transaction-test-data.js":{"bytesInOutput":1652},"../taler-util/lib/types-taler-mailbox.js":{"bytesInOutput":655},"../taler-util/lib/taler-account-properties.js":{"bytesInOutput":599},"../taler-util/lib/taler-signatures.js":{"bytesInOutput":540},"../taler-util/lib/aml/properties.js":{"bytesInOutput":847},"../taler-util/lib/aml/events.js":{"bytesInOutput":1568},"../taler-util/lib/aml/reporting.js":{"bytesInOutput":1127},"../taler-util/lib/index.browser.js":{"bytesInOutput":5},"../web-util/lib/index.browser.mjs":{"bytesInOutput":221476},"src/app.tsx":{"bytesInOutput":2007},"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/core/dist/index.mjs":{"bytesInOutput":3263},"../../node_modules/.pnpm/swr@2.0.3_react@18.3.1/node_modules/swr/_internal/dist/index.mjs":{"bytesInOutput":4930},"src/Routing.tsx":{"bytesInOutput":9841},"src/pages/LoginForm.tsx":{"bytesInOutput":4726},"src/utils.ts":{"bytesInOutput":2981},"src/pages/PaytoWireTransferForm.tsx":{"bytesInOutput":12908},"src/pages/SolveMFA.tsx":{"bytesInOutput":8046},"src/pages/regional/CreateCashout.tsx":{"bytesInOutput":13357},"src/hooks/account.ts":{"bytesInOutput":2242},"src/hooks/regional.ts":{"bytesInOutput":6323},"src/pages/RegistrationPage.tsx":{"bytesInOutput":7273},"src/context/settings.ts":{"bytesInOutput":107},"src/hooks/preferences.ts":{"bytesInOutput":874},"src/pages/rnd.ts":{"bytesInOutput":27481},"src/hooks/session.ts":{"bytesInOutput":1925},"src/pages/AccountPage/state.ts":{"bytesInOutput":1096},"src/pages/AccountPage/views.tsx":{"bytesInOutput":1141},"src/components/Transactions/state.ts":{"bytesInOutput":632},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/toInteger/index.js":{"bytesInOutput":119},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/requiredArgs/index.js":{"bytesInOutput":122},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/toDate/index.js":{"bytesInOutput":815},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addDays/index.js":{"bytesInOutput":115},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMonths/index.js":{"bytesInOutput":256},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/addMilliseconds/index.js":{"bytesInOutput":84},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultOptions/index.js":{"bytesInOutput":34},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getTimezoneOffsetInMilliseconds/index.js":{"bytesInOutput":210},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isDate/index.js":{"bytesInOutput":389},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/isValid/index.js":{"bytesInOutput":106},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMilliseconds/index.js":{"bytesInOutput":61},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCDayOfYear/index.js":{"bytesInOutput":162},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeek/index.js":{"bytesInOutput":142},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeekYear/index.js":{"bytesInOutput":279},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCISOWeekYear/index.js":{"bytesInOutput":125},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCISOWeek/index.js":{"bytesInOutput":117},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeek/index.js":{"bytesInOutput":585},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeekYear/index.js":{"bytesInOutput":775},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/startOfUTCWeekYear/index.js":{"bytesInOutput":518},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/getUTCWeek/index.js":{"bytesInOutput":123},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/addLeadingZeros/index.js":{"bytesInOutput":94},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/lightFormatters/index.js":{"bytesInOutput":756},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/formatters/index.js":{"bytesInOutput":7233},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/format/longFormatters/index.js":{"bytesInOutput":742},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/protectedTokens/index.js":{"bytesInOutput":999},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatDistance/index.js":{"bytesInOutput":1109},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildFormatLongFn/index.js":{"bytesInOutput":190},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatLong/index.js":{"bytesInOutput":429},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/formatRelative/index.js":{"bytesInOutput":190},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildLocalizeFn/index.js":{"bytesInOutput":431},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/localize/index.js":{"bytesInOutput":2023},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchFn/index.js":{"bytesInOutput":630},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/_lib/buildMatchPatternFn/index.js":{"bytesInOutput":333},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/_lib/match/index.js":{"bytesInOutput":1906},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/locale/en-US/index.js":{"bytesInOutput":148},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/_lib/defaultLocale/index.js":{"bytesInOutput":10},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/format/index.js":{"bytesInOutput":2089},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/index.js":{"bytesInOutput":0},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subDays/index.js":{"bytesInOutput":61},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/subMonths/index.js":{"bytesInOutput":61},"../../node_modules/.pnpm/date-fns@2.29.3/node_modules/date-fns/esm/sub/index.js":{"bytesInOutput":610},"src/components/Transactions/views.tsx":{"bytesInOutput":4370},"src/components/Transactions/index.ts":{"bytesInOutput":75},"src/pages/PaymentOptions.tsx":{"bytesInOutput":2709},"src/pages/WalletWithdrawForm.tsx":{"bytesInOutput":4819},"src/hooks/bank-state.ts":{"bytesInOutput":1872},"src/pages/OperationState/state.ts":{"bytesInOutput":2004},"src/pages/OperationState/views.tsx":{"bytesInOutput":13417},"src/components/QR.tsx":{"bytesInOutput":269},"src/pages/WithdrawalConfirmationQuestion.tsx":{"bytesInOutput":8885},"src/pages/OperationState/index.ts":{"bytesInOutput":196},"src/pages/AccountPage/index.ts":{"bytesInOutput":102},"src/pages/BankFrame.tsx":{"bytesInOutput":6489},"src/pages/ConversionRateClassDetails.tsx":{"bytesInOutput":24736},"src/hooks/form.ts":{"bytesInOutput":295},"src/pages/admin/ConversionClassList.tsx":{"bytesInOutput":4750},"src/pages/regional/ConversionConfig.tsx":{"bytesInOutput":22820},"src/pages/ProfileNavigation.tsx":{"bytesInOutput":4013},"src/pages/NewConversionRateClass.tsx":{"bytesInOutput":1597},"src/pages/admin/ConversionRateClassForm.tsx":{"bytesInOutput":2249},"src/pages/PublicHistoriesPage.tsx":{"bytesInOutput":823},"src/pages/ShowNotifications.tsx":{"bytesInOutput":370},"src/pages/WireTransfer.tsx":{"bytesInOutput":1005},"src/pages/WithdrawalOperationPage.tsx":{"bytesInOutput":388},"src/pages/WithdrawalQRCode.tsx":{"bytesInOutput":5538},"src/pages/QrCodeSection.tsx":{"bytesInOutput":2474},"src/pages/account/CashoutListForAccount.tsx":{"bytesInOutput":641},"src/components/Cashouts/state.ts":{"bytesInOutput":268},"src/components/Cashouts/views.tsx":{"bytesInOutput":2828},"src/components/Cashouts/index.ts":{"bytesInOutput":85},"src/pages/account/ShowAccountDetails.tsx":{"bytesInOutput":10929},"src/pages/admin/AccountForm.tsx":{"bytesInOutput":13331},"src/pages/account/UpdateAccountPassword.tsx":{"bytesInOutput":5368},"src/pages/admin/AdminHome.tsx":{"bytesInOutput":13798},"src/pages/admin/AccountList.tsx":{"bytesInOutput":3932},"src/pages/admin/CreateNewAccount.tsx":{"bytesInOutput":3181},"src/pages/admin/DownloadStats.tsx":{"bytesInOutput":11544},"src/pages/admin/RemoveAccount.tsx":{"bytesInOutput":4069},"src/pages/regional/ShowCashoutDetails.tsx":{"bytesInOutput":2744},"src/i18n/strings.ts":{"bytesInOutput":349748},"src/settings.ts":{"bytesInOutput":829},"src/index.tsx":{"bytesInOutput":288},"src/scss/main.css":{"bytesInOutput":0}},"bytes":1341372},"dist/prod/index.css.map":{"imports":[],"exports":[],"inputs":{},"bytes":112320},"dist/prod/index.css":{"imports":[{"path":"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e","kind":"url-token","external":true},{"path":"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e","kind":"url-token","external":true},{"path":"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e","kind":"url-token","external":true},{"path":"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e","kind":"url-token","external":true}],"inputs":{"src/scss/main.css":{"bytesInOutput":53628}},"bytes":53667}}}����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������libeufin-1.6.8/contrib/wallet-core/bank/index.html��������������������������������������������������0000664�0001750�0001750�00000006330�15204341712�022332� 0����������������������������������������������������������������������������������������������������ustar �grothoff������������������������grothoff��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� Bank
    libeufin-1.6.8/contrib/nexus.conf0000664000175000017500000001047115221677432017230 0ustar grothoffgrothoff[paths] LIBEUFIN_NEXUS_HOME = /var/lib/libeufin-nexus [nexus-ebics] # Currency used by the bank where Nexus is client. CURRENCY = # Base URL of the bank server. HOST_BASE_URL = # EBICS host ID. HOST_ID = # EBICS user ID, as assigned by the bank. USER_ID = # EBICS partner ID, as assigned by the bank. PARTNER_ID = # EBICS partner ID, as assigned by the bank. SYSTEM_ID = # IBAN of the bank account that is associated with the EBICS subscriber IBAN = # BIC of the bank account that is associated with the EBICS subscriber BIC = # Legal entity that is associated with the EBICS subscriber NAME = # File that holds the bank EBICS keys. BANK_PUBLIC_KEYS_FILE = ${LIBEUFIN_NEXUS_HOME}/bank-ebics-keys.json # File that holds the client/Nexus EBICS keys. CLIENT_PRIVATE_KEYS_FILE = ${LIBEUFIN_NEXUS_HOME}/client-ebics-keys.json # Identifies the EBICS + ISO20022 style used by the bank. # Typically, it is named after the bank itself. # This can either be postfinance, gls, raiffeisen, maerki_baumann or valiant. BANK_DIALECT = postfinance # Specify the account type and therefore the indexing behavior. # This can either can be normal or exchange. # Exchange accounts bounce invalid incoming Taler transactions. ACCOUNT_TYPE = exchange # QR IBAN of a QR virtual bank account linked to the configured bank account that can be used for QR BILL # QR_IBAN = CH4431999123000889012 [nexus-setup] # Bank encryption public key hash # BANK_ENCRYPTION_PUB_KEY_HASH = # Bank authentication public key hash # BANK_AUTHENTICATION_PUB_KEY_HASH = [libeufin-nexusdb-postgres] # Where are the SQL files to setup our tables? SQL_DIR = $DATADIR/sql/ # DB connection string CONFIG = postgres:///libeufin [nexus-fetch] # How often should ebics-fetch run when the bank does not support real time notification FREQUENCY = 30m # At what time of day should ebics-fetch perform a checkpoint CHECKPOINT_TIME_OF_DAY = 19:00 # Ignore all transactions prior to a certain date, useful when you want to use an existing account with old transactions that should not be bounced. # IGNORE_TRANSACTIONS_BEFORE = YYYY-MM-DD # Ignore all malformed transactions prior to a certain date, useful when you want to import old transactions without bouncing the malformed ones a second time # IGNORE_BOUNCES_BEFORE = YYYY-MM-DD # Whether to deduce the fee paid by the exchange account from the bounced amount # BOUNCE_DEDUCE_FEE = NO # An additional fee to deduce from the bounced amount # BOUNCE_FEE = KUDOS:0 # Bounce transactions coming from account not matching this regex # RESTRICTION_PAYTO_REGEX = payto://iban/CH.* [nexus-submit] # How often should ebics-fetch submit pending transactions FREQUENCY = 30m # Whether to wait for manual acknowledgement before submitting transactions # MANUAL_ACK = NO [nexus-httpd] # How "libeufin-nexus serve" serves its API, this can either be tcp or unix SERVE = tcp # Port on which the HTTP server listens, e.g. 9967. Only used if SERVE is tcp. PORT = 8080 # Which IP address should we bind to? E.g. ``127.0.0.1`` or ``::1``for loopback. Can also be given as a hostname. Only used if SERVE is tcp. BIND_TO = 0.0.0.0 # Which unix domain path should we bind to? Only used if SERVE is unix. # UNIXPATH = libeufin-nexus.sock # What should be the file access permissions for UNIXPATH? Only used if SERVE is unix. # UNIXPATH_MODE = 660 [nexus-httpd-wire-gateway-api] # Whether to serve the Wire Gateway API and the Prepared Transfer API ENABLED = NO # Authentication scheme, this can either can be basic, bearer or none. AUTH_METHOD = bearer # User name for basic authentication scheme # USERNAME = # Password for basic authentication scheme # PASSWORD = # Token for bearer authentication scheme TOKEN = [nexus-httpd-revenue-api] # Whether to serve the Revenue API ENABLED = NO # Authentication scheme, this can either can be basic, bearer or none. AUTH_METHOD = bearer # User name for basic authentication scheme # USERNAME = # Password for basic authentication scheme # PASSWORD = # Token for bearer authentication scheme TOKEN = [nexus-httpd-observability-api] # Whether to serve the Observability API ENABLED = NO # Authentication scheme, this can either can be basic, bearer or none. AUTH_METHOD = bearer # User name for basic authentication scheme # USERNAME = # Password for basic authentication scheme # PASSWORD = # Token for bearer authentication scheme TOKEN = libeufin-1.6.8/contrib/ibangen.py0000755000175000017500000000215014674637415017200 0ustar grothoffgrothoff#!/usr/bin/env python3 # Copyright (c) 2020 Taler Systems S.A. # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. import click import random def complete_iban(s): n = int("".join([str(int(x, 26)) for x in (s[4:] + s[0:2] + "00")])) c = 98 - (n % 97) return (s[:2] + str(c).ljust(2, "0") + s[4:]).upper() @click.command() def geniban(): bban = "12345678" accno = "".join((str(random.randint(0, 9)) for _ in range(10))) iban = complete_iban("DE00" + bban + accno) print(iban) if __name__ == '__main__': geniban() libeufin-1.6.8/contrib/docker-launcher/0000775000175000017500000000000015236145704020260 5ustar grothoffgrothofflibeufin-1.6.8/contrib/docker-launcher/launch-bank.sh0000755000175000017500000000026714674637415023017 0ustar grothoffgrothoff#!/bin/bash service postgresql start sudo -u postgres createuser -s root createdb libeufinbank libeufin-bank dbinit -c /libeufin-bank.conf libeufin-bank serve -c /libeufin-bank.conf libeufin-1.6.8/contrib/docker-launcher/README0000644000175000017500000000013714674637415021151 0ustar grothoffgrothoffThis Docker image is meant for debugging purposes. It installs and launches the libeufin-bank. libeufin-1.6.8/contrib/docker-launcher/libeufin-bank.conf0000644000175000017500000000053014760713600023626 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS DEFAULT_CUSTOMER_DEBT_LIMIT = KUDOS:200 DEFAULT_ADMIN_DEBT_LIMIT = KUDOS:2000 REGISTRATION_BONUS = KUDOS:100 REGISTRATION_BONUS_ENABLED = yes MAX_AUTH_TOKEN_DURATION = 1d SERVE = tcp PORT = 8080 [libeufin-bankdb-postgres] SQL_DIR = /usr/local/share/taler/sql/libeufin-bank/ CONFIG = postgresql:///libeufinbanklibeufin-1.6.8/contrib/docker-launcher/Dockerfile0000644000175000017500000000127014674637415022262 0ustar grothoffgrothoffFROM debian:stable RUN apt-get update RUN apt-get install -y openjdk-17-jre git curl postgresql python3-pip # Installation RUN git clone git://git.taler.net/libeufin WORKDIR /libeufin RUN ./bootstrap RUN ./configure --prefix=/usr/local RUN make install WORKDIR / COPY launch-bank.sh /launch-bank.sh COPY libeufin-bank.conf /libeufin-bank.conf RUN apt-get install -y sudo RUN grep -v ^host.*all /etc/postgresql/15/main/pg_hba.conf > /tmp/pg_hba_buf.txt RUN echo "host libeufincheck all 127.0.0.1/32 trust" >> /tmp/pg_hba_buf.txt RUN echo "host libeufincheck all ::1/128 trust" >> /tmp/pg_hba_buf.txt RUN cp /tmp/pg_hba_buf.txt /etc/postgresql/15/main/pg_hba.conf ENTRYPOINT ["/launch-bank.sh"] libeufin-1.6.8/contrib/bump-version0000755000175000017500000000371214707664064017576 0ustar grothoffgrothoff#!/usr/bin/env python3 import sys import re import argparse import subprocess import textwrap def shget(cmd): return subprocess.run(cmd, shell=True, encoding="utf-8", capture_output=True).stdout.strip() parser = argparse.ArgumentParser( description="Bump the libeufin version.") parser.add_argument("new_version") parser.add_argument("--dry", action="store_true") args = parser.parse_args() new_version = args.new_version dry = args.dry version = sys.argv[1] # Bump version of "debian/changelog" with open("debian/changelog") as deb_changelog: while True: line = deb_changelog.readline() if line == "": break if line.strip() == "": continue m = re.match(r".*\((.*)\).*", line) break deb_current_version = m.group(1) deb_bump = " [!]" if deb_current_version != version else "" print(f"debian/control: {deb_current_version} -> {version}{deb_bump}") if not dry and deb_current_version != version: name = shget("git config user.name") email = shget("git config user.email") date = shget("date -R") entry_r = f"""\ libeufin ({new_version}) unstable; urgency=low * Release version {new_version} -- {name} <{email}> {date} """ entry = textwrap.dedent(entry_r) with open("debian/changelog") as f: old_changelog = f.read() new_changelog = entry + "\n" + old_changelog with open("debian/changelog", "w") as f: f.write(new_changelog) # Bump version in build.gradle with open("build.gradle") as f: contents = f.read() gradle_pat = r'version.*=.*"(.*)"' m = re.search(gradle_pat, contents) gradle_current_version = m.group(1) new_contents = re.sub(gradle_pat, f'version = "{new_version}"', contents) gradle_bump = " [!]" if gradle_current_version != version else "" print(f"build.gradle: {gradle_current_version} -> {version}{gradle_bump}") if not dry: with open("build.gradle", "w") as f: f.write(new_contents) libeufin-1.6.8/build.gradle0000664000175000017500000000464015236113361016027 0ustar grothoffgrothoff// This file is in the public domain. plugins { id("org.jetbrains.kotlin.jvm") version "2.4.0" id("org.jetbrains.dokka") version "2.2.0" id("idea") id("java-library") } group = "tech.libeufin" version = "1.6.8" if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)){ throw new GradleException( "This build must be run with java 17 " + "or later (your version is java ${JavaVersion.current()})") } allprojects { ext { set("kotlin_version", "2.4.0") set("ktor_version", "3.5.0") set("clikt_version", "5.1.0") set("coroutines_version", "1.11.0") set("postgres_version", "42.7.11") set("junixsocket_version", "2.10.1") set("shadow_version", "9.4.3") set("prometheus_version", "1.6.1") } repositories { mavenCentral() } } subprojects { apply plugin: 'org.jetbrains.dokka' tasks.withType(Test) { // Invalidate tests cache when editing SQL logic inputs.dir("$rootDir/database-versioning").withPathSensitivity(PathSensitivity.RELATIVE) // Or when editing ISO20022 test samples inputs.dir("$rootDir/libeufin-nexus/sample").withPathSensitivity(PathSensitivity.RELATIVE) inputs.dir("$rootDir/testbench/sample").withPathSensitivity(PathSensitivity.RELATIVE) def failedTests = [] afterTest { desc, result -> if (result.resultType == TestResult.ResultType.FAILURE) { failedTests << "${desc.className}.${desc.name}" } } afterSuite { desc, result -> if (desc.parent == null && !failedTests.isEmpty()) { logger.lifecycle("") logger.lifecycle("==== FAILED TESTS ====") failedTests.each { logger.lifecycle(it) } logger.lifecycle("======================") } } testLogging { events "failed" exceptionFormat = 'full' } } } ext.getVersionWithGitHash = { -> def gitHash = 'git rev-parse --short HEAD'.execute().text.trim() return "v${project.version}-git-$gitHash" } task libeufinVersion { doLast { println getVersionWithGitHash() } } dependencies { dokka(project(":libeufin-common:")) dokka(project(":libeufin-bank:")) dokka(project(":libeufin-nexus:")) dokka(project(":libeufin-ebics:")) dokka(project(":libeufin-ebisync:")) }libeufin-1.6.8/gradlew.bat0000664000175000017500000000544015221677432015674 0ustar grothoffgrothoff@rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @rem SPDX-License-Identifier: Apache-2.0 @rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem gradlew startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables, and ensure extensions are enabled setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute echo. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 "%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 "%COMSPEC%" /c exit 1 :execute @rem Setup the command line @rem Execute gradlew @rem endlocal doesn't take effect until after the line is parsed and variables are expanded @rem which allows us to clear the local environment before executing the java command endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel :exitWithErrorLevel @rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts "%COMSPEC%" /c exit %ERRORLEVEL% libeufin-1.6.8/gradle.properties0000644000175000017500000000035515037632640017126 0ustar grothoffgrothoffkotlin.code.style=official org.gradle.caching=true #org.gradle.parallel=true #org.gradle.configuration-cache=true org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=truelibeufin-1.6.8/bootstrap0000755000175000017500000000114514674637415015526 0ustar grothoffgrothoff#!/bin/sh # Bootstrap the repository. Used when the repository is checked out from git. # When using the source tarball, running this script is not necessary. set -eu if ! git --version >/dev/null; then echo "git not installed" exit 1 fi if ! python3 --version >/dev/null; then echo "python3 not installed" exit 1 fi # Make sure that "git pull" et al. also update # submodules to avoid accidental rollbacks. git config --local submodule.recurse true git submodule sync git submodule update --init ./contrib/check-prebuilt rm -f ./configure cp build-system/taler-build-scripts/configure ./configure libeufin-1.6.8/libeufin-ebics/0000775000175000017500000000000015236145704016432 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/0000775000175000017500000000000015236145704017221 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/main/0000775000175000017500000000000015236145704020145 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/main/kotlin/0000775000175000017500000000000015236145704021445 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/0000775000175000017500000000000015236145704022370 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/0000775000175000017500000000000015236145704024165 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/0000775000175000017500000000000015236145704025252 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/cli.kt0000664000175000017500000000210515122266731026355 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.path fun CliktCommand.ebicsLogOption() = option( "--debug-ebics", help = "Log EBICS transactions steps and payload at log_dir", metavar = "log_dir" ).path()libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/pdf.kt0000664000175000017500000000754615122266731026375 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import com.itextpdf.kernel.pdf.PdfDocument import com.itextpdf.kernel.pdf.PdfWriter import com.itextpdf.layout.Document import com.itextpdf.layout.element.AreaBreak import com.itextpdf.layout.element.Paragraph import tech.libeufin.common.crypto.CryptoUtil import java.io.ByteArrayOutputStream import java.security.interfaces.RSAPrivateCrtKey import java.time.LocalDateTime import java.time.format.DateTimeFormatter /** * Generate the PDF document with all the client public keys * to be sent on paper to the bank. */ fun generateKeysPdf( clientKeys: ClientPrivateKeysFile, cfg: EbicsHostConfig ): ByteArray { val po = ByteArrayOutputStream() val pdfWriter = PdfWriter(po) val pdfDoc = PdfDocument(pdfWriter) val date = LocalDateTime.now() val dateStr = date.format(DateTimeFormatter.ISO_LOCAL_DATE) fun formatHex(ba: ByteArray): String { var out = "" for (i in ba.indices) { val b = ba[i] if (i > 0 && i % 16 == 0) { out += "\n" } out += java.lang.String.format("%02X", b) out += " " } return out } fun writeCommon(doc: Document) { doc.add( Paragraph( """ Datum: $dateStr Host-ID: ${cfg.hostId} User-ID: ${cfg.userId} Partner-ID: ${cfg.partnerId} ES version: A006 """.trimIndent() ) ) } fun writeKey(doc: Document, priv: RSAPrivateCrtKey) { val pub = CryptoUtil.RSAPublicFromPrivate(priv) val hash = CryptoUtil.getEbicsPublicKeyHash(pub) doc.add(Paragraph("Exponent:\n${formatHex(pub.publicExponent.toByteArray())}")) doc.add(Paragraph("Modulus:\n${formatHex(pub.modulus.toByteArray())}")) doc.add(Paragraph("SHA-256 hash:\n${formatHex(hash)}")) } fun writeSigLine(doc: Document) { doc.add(Paragraph("Ort / Datum: ________________")) doc.add(Paragraph("Firma / Name: ________________")) doc.add(Paragraph("Unterschrift: ________________")) } Document(pdfDoc).use { it.add(Paragraph("Signaturschlüssel").setFontSize(24f)) writeCommon(it) it.add(Paragraph("Öffentlicher Schlüssel (Public key for the electronic signature)")) writeKey(it, clientKeys.signature_private_key) it.add(Paragraph("\n")) writeSigLine(it) it.add(AreaBreak()) it.add(Paragraph("Authentifikationsschlüssel").setFontSize(24f)) writeCommon(it) it.add(Paragraph("Öffentlicher Schlüssel (Public key for the identification and authentication signature)")) writeKey(it, clientKeys.authentication_private_key) it.add(Paragraph("\n")) writeSigLine(it) it.add(AreaBreak()) it.add(Paragraph("Verschlüsselungsschlüssel").setFontSize(24f)) writeCommon(it) it.add(Paragraph("Öffentlicher Schlüssel (Public encryption key)")) writeKey(it, clientKeys.encryption_private_key) it.add(Paragraph("\n")) writeSigLine(it) } pdfWriter.flush() return po.toByteArray() }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/xml.kt0000664000175000017500000003313315122266731026413 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2020-2025 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import tech.libeufin.common.decodeBase64 import org.w3c.dom.Document import org.w3c.dom.Node import org.w3c.dom.NodeList import org.w3c.dom.Element import org.xml.sax.InputSource import java.io.InputStream import java.io.StringWriter import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.util.UUID import java.time.Instant import java.time.ZoneId import java.time.LocalDate import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.security.PrivateKey import java.security.PublicKey import javax.xml.XMLConstants import javax.xml.crypto.* import javax.xml.crypto.dom.DOMURIReference import javax.xml.crypto.dsig.* import javax.xml.crypto.dsig.dom.DOMSignContext import javax.xml.crypto.dsig.dom.DOMValidateContext import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec import javax.xml.crypto.dsig.spec.TransformParameterSpec import javax.xml.parsers.DocumentBuilderFactory import javax.xml.transform.OutputKeys import javax.xml.transform.TransformerFactory import javax.xml.transform.dom.DOMSource import javax.xml.transform.stream.StreamResult import javax.xml.stream.XMLOutputFactory import javax.xml.stream.XMLStreamWriter import javax.xml.xpath.XPath import javax.xml.xpath.XPathConstants import javax.xml.xpath.XPathFactory fun Instant.xmlDate(): String = DateTimeFormatter.ISO_DATE.withZone(ZoneId.of("UTC")).format(this) fun Instant.xmlDateTime(): String = DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.of("UTC")).format(this) interface XmlBuilder { fun el(path: String, lambda: XmlBuilder.() -> Unit = {}) fun el(path: String, content: String) { el(path) { text(content) } } fun attr(namespace: String, name: String, value: String) fun attr(name: String, value: String) fun text(content: String) companion object { fun toBytes(root: String, f: XmlBuilder.() -> Unit): ByteArray { val factory = XMLOutputFactory.newFactory() val stream = StringWriter() val writer = factory.createXMLStreamWriter(stream) /** * NOTE: commenting out because it wasn't obvious how to output the * "standalone = 'yes' directive". Manual forge was therefore preferred. */ stream.write("") XmlStreamBuilder(writer).el(root) { this.f() } writer.writeEndDocument() return stream.buffer.toString().toByteArray() } fun toDom(root: String, schema: String?, f: XmlBuilder.() -> Unit): Document { val factory = DocumentBuilderFactory.newInstance() factory.isNamespaceAware = true val builder = factory.newDocumentBuilder() val doc = builder.newDocument() doc.xmlVersion = "1.0" doc.xmlStandalone = true val root = doc.createElementNS(schema, root) doc.appendChild(root) XmlDOMBuilder(doc, schema, root).f() doc.normalize() return doc } } } private class XmlStreamBuilder(private val w: XMLStreamWriter): XmlBuilder { override fun el(path: String, lambda: XmlBuilder.() -> Unit) { path.splitToSequence('/').forEach { w.writeStartElement(it) } lambda() path.splitToSequence('/').forEach { w.writeEndElement() } } override fun attr(namespace: String, name: String, value: String) { w.writeAttribute(namespace, name, value) } override fun attr(name: String, value: String) { w.writeAttribute(name, value) } override fun text(content: String) { w.writeCharacters(content) } } private class XmlDOMBuilder(private val doc: Document, private val schema: String?, private var node: Element): XmlBuilder { override fun el(path: String, lambda: XmlBuilder.() -> Unit) { val current = node path.splitToSequence('/').forEach { val new = doc.createElementNS(schema, it) node.appendChild(new) node = new } lambda() node = current } override fun attr(namespace: String, name: String, value: String) { node.setAttributeNS(namespace, name, value) } override fun attr(name: String, value: String) { node.setAttribute(name, value) } override fun text(content: String) { node.appendChild(doc.createTextNode(content)) } } private fun Element.childrenByTag(tag: String, signed: Boolean): Sequence = sequence { for (i in 0..childNodes.length) { val el = childNodes.item(i) if (el is Element && el.localName == tag && (!signed || el.getAttribute("authenticate") == "true")) { yield(el) } } } class XmlDestructor internal constructor(private val el: Element) { fun each(path: String, signed: Boolean = false, f: XmlDestructor.() -> Unit) { el.childrenByTag(path, signed).forEach { f(XmlDestructor(it)) } } fun map(path: String, signed: Boolean = false, f: XmlDestructor.() -> T): List { return el.childrenByTag(path, signed).map { f(XmlDestructor(it)) }.toList() } fun one(tag: String, signed: Boolean = false): XmlDestructor { val children = el.childrenByTag(tag, signed).iterator() if (!children.hasNext()) { throw Exception("expected unique '${el.tagName}.$tag', got none") } val child = children.next() if (children.hasNext()) { throw Exception("expected unique '${el.tagName}.$tag', got ${children.asSequence().count() + 1}") } return XmlDestructor(child) } fun opt(tag: String, signed: Boolean = false): XmlDestructor? { val children = el.childrenByTag(tag, signed).iterator() if (!children.hasNext()) { return null } val child = children.next() if (children.hasNext()) { throw Exception("expected optional '${el.tagName}.$tag', got ${children.asSequence().count() + 1}") } return XmlDestructor(child) } fun one(path: String, signed: Boolean = false, f: XmlDestructor.() -> T): T = f(one(path, signed)) fun opt(path: String, signed: Boolean = false, f: XmlDestructor.() -> T): T? = opt(path, signed)?.run(f) fun uuid(): UUID = UUID.fromString(text()) fun text(): String = el.textContent fun base64(): ByteArray = el.textContent.decodeBase64() fun bool(): Boolean = el.textContent.toBoolean() fun float(): Float = el.textContent.toFloat() fun date(): LocalDate = LocalDate.parse(text(), DateTimeFormatter.ISO_DATE) fun dateTime(): LocalDateTime = LocalDateTime.parse(text(), DateTimeFormatter.ISO_DATE_TIME) inline fun > enum(): T = java.lang.Enum.valueOf(T::class.java, text()) fun optAttr(index: String): String? { val attr = el.getAttribute(index) if (attr == "") { return null } else { return attr } } fun attr(index: String): String { val attr = optAttr(index) if (attr == null) { throw Exception("missing attribute '$index' at '${el.tagName}'") } return attr } companion object { fun parse(xml: String, root: String, f: XmlDestructor.() -> T): T { val inputStream = ByteArrayInputStream(xml.toByteArray()) return parse(inputStream, root, f) } fun parse(xml: InputStream, root: String, f: XmlDestructor.() -> T): T { val doc = XMLUtil.parseIntoDom(xml) return parse(doc, root, f) } fun parse(doc: Document, root: String, f: XmlDestructor.() -> T): T { if (doc.documentElement.localName != root) { throw Exception("expected root '$root' got '${doc.documentElement.localName}'") } val destr = XmlDestructor(doc.documentElement) return f(destr) } } } /** * This URI dereferencer allows handling the resource reference used for * XML signatures in EBICS. */ private class EbicsSigUriDereferencer : URIDereferencer { override fun dereference(myRef: URIReference?, myCtx: XMLCryptoContext?): Data { if (myRef !is DOMURIReference) throw Exception("invalid type") if (myRef.uri != "#xpointer(//*[@authenticate='true'])") throw Exception("invalid EBICS XML signature URI: '${myRef.uri}'") val xp: XPath = XPathFactory.newInstance().newXPath() val nodeSet = xp.compile("//*[@authenticate='true']/descendant-or-self::node()").evaluate( myRef.here.ownerDocument, XPathConstants.NODESET ) if (nodeSet !is NodeList) throw Exception("invalid type") if (nodeSet.length <= 0) { throw Exception("no nodes to sign") } val nodeList = ArrayList() for (i in 0 until nodeSet.length) { val node = nodeSet.item(i) nodeList.add(node) } return NodeSetData { nodeList.iterator() } } } /** * Helpers for dealing with XML in EBICS. */ object XMLUtil { fun convertDomToBytes(document: Document): ByteArray { val w = ByteArrayOutputStream() val transformer = TransformerFactory.newInstance().newTransformer() transformer.setOutputProperty(OutputKeys.STANDALONE, "yes") transformer.transform(DOMSource(document), StreamResult(w)) return w.toByteArray() } /** Parse [xml] into a XML DOM */ fun parseIntoDom(xml: InputStream): Document { val factory = DocumentBuilderFactory.newInstance().apply { // Enable secure processing setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) // Disable all external access setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "") setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "") isNamespaceAware = true } val builder = factory.newDocumentBuilder() return xml.use { builder.parse(InputSource(it)) } } /** Sign an EBICS document with the authentication and identity signature */ fun signEbicsDocument( doc: Document, signingPriv: PrivateKey ) { val authSigNode = XPathFactory.newInstance().newXPath() .evaluate("/*[1]/*[local-name()='AuthSignature']", doc, XPathConstants.NODE) if (authSigNode !is Node) throw java.lang.Exception("sign: no AuthSignature") val fac = XMLSignatureFactory.getInstance("DOM") val c14n = fac.newTransform(CanonicalizationMethod.INCLUSIVE, null as TransformParameterSpec?) val ref: Reference = fac.newReference( "#xpointer(//*[@authenticate='true'])", fac.newDigestMethod(DigestMethod.SHA256, null), listOf(c14n), null, null ) val canon: CanonicalizationMethod = fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, null as C14NMethodParameterSpec?) val signatureMethod = fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null) val si: SignedInfo = fac.newSignedInfo(canon, signatureMethod, listOf(ref)) val sig: XMLSignature = fac.newXMLSignature(si, null) val dsc = DOMSignContext(signingPriv, authSigNode) dsc.defaultNamespacePrefix = "ds" dsc.uriDereferencer = EbicsSigUriDereferencer() dsc.setProperty("javax.xml.crypto.dsig.cacheReference", true) sig.sign(dsc) val innerSig = authSigNode.firstChild while (innerSig.hasChildNodes()) { authSigNode.appendChild(innerSig.firstChild) } authSigNode.removeChild(innerSig) } /** Check an EBICS document signature */ fun verifyEbicsDocument( doc: Document, signingPub: PublicKey ) { // Find SignedInfo val sigInfos = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "SignedInfo"); if (sigInfos.length == 0) { throw Exception("missing SignedInfo") } else if (sigInfos.length != 1) { throw Exception("many SignedInfo") } val sigInfo = sigInfos.item(0) // Rename AuthSignature val authSig = sigInfo.parentNode doc.renameNode(authSig, XMLSignature.XMLNS, "${sigInfo.prefix}:Signature") // Check signature val fac = XMLSignatureFactory.getInstance("DOM") val dvc = DOMValidateContext(signingPub, authSig) dvc.setProperty("javax.xml.crypto.dsig.cacheReference", true) dvc.uriDereferencer = EbicsSigUriDereferencer() val sig = fac.unmarshalXMLSignature(dvc) if (!sig.validate(dvc)) { throw Exception("bank signature did not verify") } } }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/db/0000775000175000017500000000000015236145704025637 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/db/Database.kt0000664000175000017500000000233215122266731027701 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.db import kotlinx.coroutines.flow.Flow import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.common.db.* import tech.libeufin.common.* import tech.libeufin.ebics.EbicsDAO import java.util.* import java.util.concurrent.ConcurrentHashMap private val logger: Logger = LoggerFactory.getLogger("libeufin-ebisync-db") class Database( dbConfig: DatabaseConfig ): DbPool(dbConfig, "libeufin-ebisync") { // DAOs val ebics = EbicsDAO(this) }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/keys.kt0000664000175000017500000001740215122266731026567 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import kotlinx.serialization.Contextual import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.descriptors.PrimitiveKind import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encodeToString import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModule import tech.libeufin.common.Base32Crockford import tech.libeufin.common.crypto.CryptoUtil import java.nio.file.* import java.security.interfaces.RSAPrivateCrtKey import java.security.interfaces.RSAPublicKey import kotlin.io.path.* val JSON = Json { this.serializersModule = SerializersModule { contextual(RSAPrivateCrtKey::class) { RSAPrivateCrtKeySerializer } contextual(RSAPublicKey::class) { RSAPublicKeySerializer } } } /** * Converts base 32 representation of RSA public keys and vice versa. */ object RSAPublicKeySerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("RSAPublicKey", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: RSAPublicKey) { encoder.encodeString(Base32Crockford.encode(value.encoded)) } // Caller must handle exceptions here. override fun deserialize(decoder: Decoder): RSAPublicKey { val fieldValue = decoder.decodeString() val bytes = Base32Crockford.decode(fieldValue) return CryptoUtil.loadRSAPublic(bytes) } } /** * Converts base 32 representation of RSA private keys and vice versa. */ object RSAPrivateCrtKeySerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("RSAPrivateCrtKey", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: RSAPrivateCrtKey) { encoder.encodeString(Base32Crockford.encode(value.encoded)) } // Caller must handle exceptions here. override fun deserialize(decoder: Decoder): RSAPrivateCrtKey { val fieldValue = decoder.decodeString() val bytes = Base32Crockford.decode(fieldValue) return CryptoUtil.loadRSAPrivate(bytes) } } /** * Structure of the JSON filethat contains the client * private keys on disk. */ @Serializable data class ClientPrivateKeysFile( @Contextual val signature_private_key: RSAPrivateCrtKey, @Contextual val encryption_private_key: RSAPrivateCrtKey, @Contextual val authentication_private_key: RSAPrivateCrtKey, var submitted_ini: Boolean, var submitted_hia: Boolean ) /** * Structure of the JSON file that contains the bank * public keys on disk. */ @Serializable data class BankPublicKeysFile( @Contextual val bank_encryption_public_key: RSAPublicKey, @Contextual val bank_authentication_public_key: RSAPublicKey, var accepted: Boolean ) /** * Generates new client private keys. * * @return [ClientPrivateKeysFile] */ fun generateNewKeys(): ClientPrivateKeysFile = ClientPrivateKeysFile( authentication_private_key = CryptoUtil.genRSAPrivate(2048), encryption_private_key = CryptoUtil.genRSAPrivate(2048), signature_private_key = CryptoUtil.genRSAPrivate(2048), submitted_hia = false, submitted_ini = false ) internal inline fun persistJsonFile(obj: T, path: Path, name: String) { val content = try { JSON.encodeToString(obj) } catch (e: Exception) { throw Exception("Could not encode $name", e) } val parent = try { path.parent ?: path.absolute().parent } catch (e: Exception) { throw Exception("Could not write $name at '$path'", e) } try { // Write to temp file then rename to enable atomicity when possible val tmp = Files.createTempFile(parent, "tmp_", "_${path.fileName}") tmp.writeText(content) tmp.moveTo(path, StandardCopyOption.REPLACE_EXISTING) } catch (e: Exception) { when { !parent.isWritable() -> throw Exception("Could not write $name at '$path': permission denied on '$parent'") !path.isWritable() -> throw Exception("Could not write $name at '$path': permission denied") else -> throw Exception("Could not write $name at '$path'", e) } } } /** * Persist the bank keys file to disk * * @param location the keys file location */ fun persistBankKeys(keys: BankPublicKeysFile, location: Path) = persistJsonFile(keys, location, "bank public keys") /** * Persist the client keys file to disk * * @param location the keys file location */ fun persistClientKeys(keys: ClientPrivateKeysFile, location: Path) = persistJsonFile(keys, location, "client private keys") inline fun loadJsonFile(path: Path, name: String): T? { val content = try { path.readText() } catch (e: Exception) { when (e) { is NoSuchFileException -> return null is AccessDeniedException -> throw Exception("Could not read $name at '$path': permission denied") else -> throw Exception("Could not read $name at '$path'", e) } } return try { JSON.decodeFromString(content) } catch (e: Exception) { throw Exception("Could not decode $name at '$path'", e) } } /** * Load the bank keys file from disk. * * @param location the keys file location. * @return the internal JSON representation of the keys file, * or null if the file does not exist */ fun loadBankKeys(location: Path): BankPublicKeysFile? = loadJsonFile(location, "bank public keys") /** * Load the client keys file from disk. * * @param location the keys file location. * @return the internal JSON representation of the keys file, * or null if the file does not exist */ fun loadClientKeys(location: Path): ClientPrivateKeysFile? = loadJsonFile(location, "client private keys") /** * Load client and bank keys from disk. * Checks that the keying process has been fully completed. * * Helps to fail before starting to talk EBICS to the bank. * * @param cfg configuration handle. * @return both client and bank keys */ fun expectFullKeys(cfg: EbicsKeysConfig, setupCmd: String): Pair { val clientKeys = loadClientKeys(cfg.clientPrivateKeysPath) if (clientKeys == null) { throw Exception("Missing client private keys file at '${cfg.clientPrivateKeysPath}', run '$setupCmd' first") } else if (!clientKeys.submitted_ini || !clientKeys.submitted_hia) { throw Exception("Unsubmitted client private keys, run '$setupCmd' first") } val bankKeys = loadBankKeys(cfg.bankPublicKeysPath) if (bankKeys == null) { throw Exception("Missing bank public keys at '${cfg.bankPublicKeysPath}', run '$setupCmd' first") } else if (!bankKeys.accepted) { throw Exception("Unaccepted bank public keys, run '$setupCmd' until accepting the bank keys") } return Pair(clientKeys, bankKeys) }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/ws.kt0000664000175000017500000001551715122266731026252 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import io.ktor.client.* import io.ktor.client.plugins.websocket.* import io.ktor.client.request.* import io.ktor.http.* import io.ktor.serialization.kotlinx.* import io.ktor.websocket.* import kotlinx.coroutines.* import kotlinx.coroutines.channels.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.* import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.common.* private val wsLog: Logger = LoggerFactory.getLogger("libeufin-ebics-ws") @Serializable data class WssParams( val URL: String, val TOKEN: String, val OTT: String, val VALIDITY: String, val PARTNERID: String, val USERID: String? = null, ) @Serializable data class WssNotificationClass( val NAME: String, val VERS: String, val TIMESTAMP: String, ) @Serializable data class WssNotificationBTF( val SERVICE: String, val SCOPE: String? = null, val OPTION: String? = null, val CONTTYPE: String? = null, val MSGNAME: String, val VARIANT: String? = null, val VERSION: String? = null, val FORMAT: String? = null, ) @Serializable data class WssNewData( val MCLASS: List, val PARTNERID: String, val USERID: String? = null, val BTF: List, val ORDERTYPE: List? = null ): WssNotification @Serializable data class WssInfo( val LANG: String, val FREE: String ) @Serializable data class WssGeneralInfo( val MCLASS: List, val INFO: List ): WssNotification @Serializable(with = WssNotification.Serializer::class) sealed interface WssNotification { companion object Serializer : JsonContentPolymorphicSerializer(WssNotification::class) { override fun selectDeserializer(element: JsonElement) = when { "INFO" in element.jsonObject -> WssGeneralInfo.serializer() else -> WssNewData.serializer() } } } /** Download EBICS real-time notifications websocket params */ suspend fun EbicsClient.wssParams(): WssParams = download(EbicsOrder.V3.WSS_PARAMS) { stream -> Json.decodeFromStream(stream) } /** Receive a JSON message from a websocket session */ private suspend inline fun DefaultClientWebSocketSession.receiveJson(): T { val frame = incoming.receive() val content = frame.readBytes() val msg = Json.decodeFromStream(kotlinx.serialization.serializer(), content.inputStream()) return msg } /** Connect to the EBICS real-time notifications websocket */ suspend fun WssParams.connect(client: HttpClient, lambda: suspend (WssNotification) -> Unit) { val client = client.config { install(WebSockets) { contentConverter = KotlinxWebsocketSerializationConverter(Json) } } // TODO check PARTNERID and USERID match conf ? val credentials = buildString { // Username append(PARTNERID) if (USERID != null) { append('_') append(USERID) } // Password append(':') append(TOKEN) }.encodeBase64() client.wss(URL.replace("https://", "wss://"), request = { headers { append(HttpHeaders.Authorization, "Basic $credentials") } }) { while (true) { wsLog.trace("wait for ws msg") // TODO use receiveDeserialized from ktor when it works val msg = receiveJson() wsLog.trace("received: {}", msg) lambda(msg) } } } suspend fun listenForNotification(client: EbicsClient): ReceiveChannel>? { val channel = Channel>() val backoff = ExpoBackoffDecorr( 30 * 1000, // 30 seconds 30 * 60 * 1000 // 30 min ) kotlin.concurrent.thread(isDaemon = true) { runBlocking { while (true) { try { // Try to get params val params = try { client.wssParams() } catch (e: EbicsError) { if ( // Expected EBICS error (e is EbicsError.Code && e.technicalCode == EbicsReturnCode.EBICS_INVALID_ORDER_IDENTIFIER) || // Netzbon HTTP error (e is EbicsError.HTTP && e.status == HttpStatusCode.BadRequest) ) { // Failure is expected if this wss is not supported wsLog.info("Real-time EBICS notifications is not supported") return@runBlocking } else throw e } wsLog.info("Listening to real-time EBICS notifications") wsLog.trace("{}", params) params.connect(client.client) { msg -> backoff.reset() when (msg) { is WssGeneralInfo -> { for (info in msg.INFO) { wsLog.info("info: {}", info.FREE) } } is WssNewData -> { val orders = msg.BTF.map { EbicsOrder.V3( type = "BTD", service = it.SERVICE, scope = it.SCOPE, message = it.MSGNAME, version = it.VERSION, container = it.CONTTYPE, option = it.OPTION ) } channel.send(orders) } } } } catch (e: Exception) { e.fmtLog(wsLog) delay(backoff.next()) } } } } return channel }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/test/0000775000175000017500000000000015236145704026231 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/test/TxCheck.kt0000664000175000017500000000665715122266731030136 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics.test import io.ktor.client.* import tech.libeufin.common.* import tech.libeufin.ebics.* import org.slf4j.Logger import org.slf4j.LoggerFactory data class TxCheckResult( var concurrentFetchAndFetch: Boolean = false, var concurrentFetchAndSubmit: Boolean = false, var concurrentSubmitAndSubmit: Boolean = false, var idempotentClose: Boolean = false ) /** * Test EBICS implementation's transactions semantic: * - Can two fetch transactions run concurrently ? * - Can a fetch & submit transactions run concurrently ? * - Can two submit transactions run concurrently ? * - Is closing a submit transaction idempotent */ suspend fun txCheck( client: HttpClient, cfg: EbicsHostConfig, clientKeys: ClientPrivateKeysFile, bankKeys: BankPublicKeysFile, fetchOrder: EbicsOrder, submitOrder: EbicsOrder ): TxCheckResult { val result = TxCheckResult() val fetch = EbicsBTS(cfg, bankKeys, clientKeys, fetchOrder) val submit = EbicsBTS(cfg, bankKeys, clientKeys, submitOrder) val ebicsLogger = EbicsLogger(null).tx("test").step("step") suspend fun EbicsBTS.close(id: String, phase: String, ebicsLogger: StepLogger) { val xml = downloadReceipt(id, false) postBTS(client, xml, phase, ebicsLogger) } val firstTxId = fetch.postBTS(client, fetch.downloadInitialization(null, null), "Init first fetch", ebicsLogger) .transactionID!! try { try { val id = fetch.postBTS(client, fetch.downloadInitialization(null, null), "Init second fetch", ebicsLogger).transactionID!! result.concurrentFetchAndFetch = true fetch.close(id, "Init second fetch", ebicsLogger) } catch (e: EbicsError.Code) {} var paylod = prepareUploadPayload(cfg, clientKeys, bankKeys, ByteArray(2000000).rand()) try { val submitId = submit.postBTS(client, submit.uploadInitialization(paylod), "Init first submit", ebicsLogger). transactionID!! result.concurrentFetchAndSubmit = true submit.postBTS(client, submit.uploadTransfer(submitId, paylod, 1), "Submit first upload", ebicsLogger) try { submit.postBTS(client, submit.uploadInitialization(paylod), "Init second submit", ebicsLogger) result.concurrentSubmitAndSubmit = true } catch (e: EbicsError.Code) {} } catch (e: EbicsError.Code) {} } finally { fetch.close(firstTxId, "Close first fetch", ebicsLogger) } try { fetch.close(firstTxId, "Close first fetch a second time", ebicsLogger) result.idempotentClose = true } catch (e: Exception) { logger.debug { e.fmt() } } return result }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/test/ebics.kt0000664000175000017500000004446115122266731027665 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics.test import org.w3c.dom.Document import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test import io.ktor.http.* import io.ktor.http.content.* import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.ebics.* import kotlin.io.path.* import kotlin.test.* import java.security.interfaces.RSAPrivateCrtKey import java.security.interfaces.RSAPublicKey import java.time.LocalDate class EbicsState { private val bankSignKey: RSAPrivateCrtKey = CryptoUtil.genRSAPrivate(2048) private val bankEncKey: RSAPrivateCrtKey = CryptoUtil.genRSAPrivate(2048) private val bankAuthKey: RSAPrivateCrtKey = CryptoUtil.genRSAPrivate(2048) private var clientSignPub: RSAPublicKey? = null private var clientEncrPub: RSAPublicKey? = null private var clientAuthPub: RSAPublicKey? = null private var transactionId: String? = null private var orderId: String? = null companion object { private val HEV_OK = XmlBuilder.toBytes("ebicsHEVResponse") { attr("xmlns", "http://www.ebics.org/H000") el("SystemReturnCode") { el("ReturnCode", "000000") el("ReportText", "[EBICS_OK] OK") } el("VersionNumber") { attr("ProtocolVersion", "H005") text("03.00") } } private val KEY_OK = XmlBuilder.toBytes("ebicsKeyManagementResponse") { attr("xmlns", "http://www.ebics.org/H005") el("header") { attr("authenticate", "true") el("mutable") { el("ReturnCode", "000000") el("ReportText", "[EBICS_OK] OK") } } el("body") { el("ReturnCode") { attr("authenticate", "true") text("000000") } } } private fun parseUnsecureRequest(body: String, order: String, root: String, parse: XmlDestructor.() -> Unit) { XmlDestructor.parse(body, "ebicsUnsecuredRequest") { val adminOrder = one("header").one("static").one("OrderDetails").one("AdminOrderType").text() assertEquals(adminOrder, order) val chunk = one("body").one("DataTransfer").one("OrderData").base64() val deflated = chunk.inputStream().inflate() XmlDestructor.parse(deflated, root) { parse() } } } } private fun signedResponse(doc: Document): ByteArray { XMLUtil.signEbicsDocument(doc, bankAuthKey) return XMLUtil.convertDomToBytes(doc) } private fun ebicsResponsePayload(payload: ByteArray, last: Boolean = true): ByteArray { transactionId = randEbicsId() val deflated = payload.inputStream().deflate() val (transactionKey, encryptedTransactionKey) = CryptoUtil.genEbicsE002Key(clientEncrPub!!) val encrypted = CryptoUtil.encryptEbicsE002(transactionKey, deflated) val doc = XmlBuilder.toDom("ebicsResponse", "http://www.ebics.org/H005") { attr("http://www.w3.org/2000/xmlns/", "xmlns", "http://www.ebics.org/H005") el("header") { attr("authenticate", "true") el("static") { el("TransactionID", transactionId!!) el("NumSegments", "1") } el("mutable") { el("TransactionPhase", "Initialisation") el("SegmentNumber") { attr("lastSegment", last.toString()) text("1") } el("ReturnCode", "000000") el("ReportText", "[EBICS_OK] OK") } } el("AuthSignature") el("body") { el("DataTransfer") { el("DataEncryptionInfo") { attr("authenticate", "true") el("EncryptionPubKeyDigest") { attr("Version", "E002") attr("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256") text(CryptoUtil.getEbicsPublicKeyHash(clientEncrPub!!).encodeBase64()) } el("TransactionKey", encryptedTransactionKey.encodeBase64()) } el("OrderData", encrypted.encodeBase64()) } el("ReturnCode") { attr("authenticate", "true") text("000000") } } } return signedResponse(doc) } private fun ebicsResponseNoData(): ByteArray { val doc = XmlBuilder.toDom("ebicsResponse", "http://www.ebics.org/H005") { attr("http://www.w3.org/2000/xmlns/", "xmlns", "http://www.ebics.org/H005") el("header") { attr("authenticate", "true") el("static") el("mutable") { el("TransactionPhase", "Initialisation") el("ReturnCode", "000000") el("ReportText", "[EBICS_OK] OK") } } el("AuthSignature") el("body") { el("ReturnCode") { attr("authenticate", "true") text("090005") } } } return signedResponse(doc) } fun hev(body: String): ByteArray { val hostId = XmlDestructor.parse(body, "ebicsHEVRequest") { one("HostID").text() } return HEV_OK } fun ini(body: String): ByteArray { parseUnsecureRequest(body, "INI", "SignaturePubKeyOrderData") { clientSignPub = one("SignaturePubKeyInfo") { val version = one("SignatureVersion").text() assertEquals(version, "A006") rsaPubKey() } } return KEY_OK } fun hia(body: String): ByteArray { parseUnsecureRequest(body, "HIA", "HIARequestOrderData") { clientAuthPub = one("AuthenticationPubKeyInfo") { val version = one("AuthenticationVersion").text() assertEquals(version, "X002") rsaPubKey() } clientEncrPub = one("EncryptionPubKeyInfo") { val version = one("EncryptionVersion").text() assertEquals(version, "E002") rsaPubKey() } } return KEY_OK } fun hpb(body: String): ByteArray { // Parse HPB request XmlDestructor.parse(body, "ebicsNoPubKeyDigestsRequest") { val order = one("header").one("static").one("OrderDetails").one("AdminOrderType").text() assertEquals(order, "HPB") } val payload = XmlBuilder.toBytes("HPBResponseOrderData") { el("AuthenticationPubKeyInfo") { el("PubKeyValue") { el("RSAKeyValue") { el("Modulus", bankAuthKey.modulus.encodeBase64()) el("Exponent", bankAuthKey.publicExponent.encodeBase64()) } } el("AuthenticationVersion", "X002") } el("EncryptionPubKeyInfo") { el("PubKeyValue") { el("RSAKeyValue") { el("Modulus", bankEncKey.modulus.encodeBase64()) el("Exponent", bankEncKey.publicExponent.encodeBase64()) } } el("EncryptionVersion", "E002") } }.inputStream().deflate() val (transactionKey, encryptedTransactionKey) = CryptoUtil.genEbicsE002Key(clientEncrPub!!) val encrypted = CryptoUtil.encryptEbicsE002(transactionKey, payload) return XmlBuilder.toBytes("ebicsKeyManagementResponse") { attr("xmlns:ds", "http://www.w3.org/2000/09/xmldsig#") attr("xmlns", "http://www.ebics.org/H005") el("header") { attr("authenticate", "true") el("mutable") { el("ReturnCode", "000000") el("ReportText", "[EBICS_OK] OK") } } el("body") { el("DataTransfer") { el("DataEncryptionInfo") { attr("authenticate", "true") el("EncryptionPubKeyDigest") { attr("Version", "E002") attr("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256") text(CryptoUtil.getEbicsPublicKeyHash(clientEncrPub!!).encodeBase64()) } el("TransactionKey", encryptedTransactionKey.encodeBase64()) } el("OrderData", encrypted.encodeBase64()) } el("ReturnCode") { attr("authenticate", "true") text("000000") } } } } private fun receipt(body: String, ok: Boolean): ByteArray { XmlDestructor.parse(body, "ebicsRequest") { one("header") { val id = one("static").one("TransactionID").text() assertEquals(id, transactionId) val phase = one("mutable").one("TransactionPhase").text() assertEquals(phase, "Receipt") } val code = one("body").one("TransferReceipt").one("ReceiptCode").text() assertEquals(code, if (ok) { "0" } else { "1" }) } val response = signedResponse(XmlBuilder.toDom("ebicsResponse", "http://www.ebics.org/H005") { attr("http://www.w3.org/2000/xmlns/", "xmlns", "http://www.ebics.org/H005") el("header") { attr("authenticate", "true") el("static") { el("TransactionID", transactionId!!) } el("mutable") { el("TransactionPhase", "Receipt") el("ReturnCode", "000000") el("ReportText", "[EBICS_OK] OK") } } el("AuthSignature") el("body") { el("ReturnCode") { attr("authenticate", "true") text("000000") } } }) transactionId = null return response } fun receiptOk(body: String): ByteArray = receipt(body, true) fun receiptErr(body: String): ByteArray = receipt(body, false) fun hkd(body: String): ByteArray { XmlDestructor.parse(body, "ebicsRequest") { one("header") { val adminOrder = one("static").one("OrderDetails").one("AdminOrderType").text() assertEquals(adminOrder, "HKD") val phase = one("mutable").one("TransactionPhase").text() assertEquals(phase, "Initialisation") } } return ebicsResponsePayload( XmlBuilder.toBytes("HKDResponseOrderData") { el("PartnerInfo") { el("AddressInfo") el("OrderInfo") { el("AdminOrderType", "BTD") el("Service") { el("ServiceName", "STM") el("Scope", "CH") el("Container") { attr("containerType", "ZIP") } el("MsgName") { attr("version", "08") text("camt.052") } } el("Description") } el("OrderInfo") { el("AdminOrderType", "BTU") el("Service") { el("ServiceName", "SCT") el("MsgName") { text("pain.001") } } el("Description", "Direct Debit") } el("OrderInfo") { el("AdminOrderType", "BTU") el("Service") { el("ServiceName", "SCI") el("Scope", "DE") el("MsgName") { text("pain.001") } } el("Description", "Instant Direct Debit") } } } ) } fun haa(body: String): ByteArray { XmlDestructor.parse(body, "ebicsRequest") { one("header") { val adminOrder = one("static").one("OrderDetails").one("AdminOrderType").text() assertEquals(adminOrder, "HAA") val phase = one("mutable").one("TransactionPhase").text() assertEquals(phase, "Initialisation") } } return ebicsResponsePayload( XmlBuilder.toBytes("HAAResponseOrderData") { el("Service") { el("ServiceName", "STM") el("Scope", "CH") el("Container") { attr("containerType", "ZIP") } el("MsgName") { attr("version", "08") text("camt.052") } } } ) } private fun btdDateCheck(body: String, pinned: LocalDate?): ByteArray { XmlDestructor.parse(body, "ebicsRequest") { one("header") { one("static").one("OrderDetails") { val adminOrder = one("AdminOrderType").text() assertEquals(adminOrder, "BTD") val start = one("BTDOrderParams").opt("DateRange")?.opt("Start")?.date() assertEquals(start, pinned) } val phase = one("mutable").one("TransactionPhase").text() assertEquals(phase, "Initialisation") } } return ebicsResponseNoData() } fun btdNoData(body: String): ByteArray = btdDateCheck(body, null) fun btdNoDataNow(body: String): ByteArray = btdDateCheck(body, LocalDate.now()) fun btdNoDataPinned(body: String): ByteArray = btdDateCheck(body, LocalDate.parse("2024-06-05")) fun btuInit(body: String): ByteArray { XmlDestructor.parse(body, "ebicsRequest") { one("header") { one("static").one("OrderDetails") { val adminOrder = one("AdminOrderType").text() assertEquals(adminOrder, "BTU") } val phase = one("mutable").one("TransactionPhase").text() assertEquals(phase, "Initialisation") } } transactionId = randEbicsId() orderId = randEbicsId() val doc = XmlBuilder.toDom("ebicsResponse", "http://www.ebics.org/H005") { attr("http://www.w3.org/2000/xmlns/", "xmlns", "http://www.ebics.org/H005") el("header") { attr("authenticate", "true") el("static") { el("TransactionID", transactionId!!) } el("mutable") { el("TransactionPhase", "Initialisation") el("OrderID", orderId!!) el("ReturnCode", "000000") el("ReportText", "[EBICS_OK] OK") } } el("AuthSignature") el("body") { el("ReturnCode") { attr("authenticate", "true") text("000000") } } } return signedResponse(doc) } fun btuPayload(body: String): ByteArray { lateinit var segment: String XmlDestructor.parse(body, "ebicsRequest") { one("header") { one("static") { val txid = one("TransactionID").text() assertEquals(txid, transactionId) } one("mutable") { val phase = one("TransactionPhase").text() assertEquals(phase, "Transfer") segment = one("SegmentNumber").text() } } } val doc = XmlBuilder.toDom("ebicsResponse", "http://www.ebics.org/H005") { attr("http://www.w3.org/2000/xmlns/", "xmlns", "http://www.ebics.org/H005") el("header") { attr("authenticate", "true") el("static") { el("TransactionID", transactionId!!) } el("mutable") { el("TransactionPhase", "Transfer") el("SegmentNumber", segment) el("OrderID", orderId!!) el("ReturnCode", "000000") el("ReportText", "[EBICS_OK] OK") } } el("AuthSignature") el("body") { el("ReturnCode") { attr("authenticate", "true") text("000000") } } } return signedResponse(doc) } fun badRequest(body: String): ByteArray { throw BadRequest } fun initializeTx(body: String): ByteArray = ebicsResponsePayload(ByteArray(0), false) fun failure(body: String): ByteArray { throw Exception("Not reachable") } }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/EbicsConstants.kt0000664000175000017500000000767015122266731030544 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics // TODO import missing using a script @Suppress("SpellCheckingInspection") enum class EbicsReturnCode(val code: String) { EBICS_OK("000000"), EBICS_DOWNLOAD_POSTPROCESS_DONE("011000"), EBICS_DOWNLOAD_POSTPROCESS_SKIPPED("011001"), EBICS_TX_SEGMENT_NUMBER_UNDERRUN("011101"), EBICS_AUTHENTICATION_FAILED("061001"), EBICS_INVALID_REQUEST("061002"), EBICS_INTERNAL_ERROR("061099"), EBICS_TX_RECOVERY_SYNC("061101"), EBICS_AUTHORISATION_ORDER_IDENTIFIER_FAILED("090003"), EBICS_INVALID_ORDER_DATA_FORMAT("090004"), EBICS_NO_DOWNLOAD_DATA_AVAILABLE("090005"), // Transaction administration EBICS_INVALID_USER_OR_USER_STATE("091002"), EBICS_USER_UNKNOWN("091003"), EBICS_INVALID_USER_STATE("091004"), EBICS_INVALID_ORDER_IDENTIFIER("091005"), EBICS_UNSUPPORTED_ORDER_TYPE("091006"), EBICS_INVALID_XML("091010"), EBICS_TX_UNKNOWN_TXID("091101"), EBICS_TX_ABORT("091102"), EBICS_TX_MESSAGE_REPLAY("091102"), EBICS_TX_SEGMENT_NUMBER_EXCEEDED("091104"), EBICS_INVALID_ORDER_PARAMS("091112"), EBICS_INVALID_REQUEST_CONTENT("091113"), EBICS_ORDERID_UNKNOWN("091114"), EBICS_ORDERID_ALREADY_FINAL("091115"), EBICS_PROCESSING_ERROR("091116"), EBICS_ORDER_ALREADY_EXISTS("091122"), // Key-Management errors EBICS_KEYMGMT_UNSUPPORTED_VERSION_SIGNATURE("091201"), EBICS_KEYMGMT_UNSUPPORTED_VERSION_AUTHENTICATION("091202"), EBICS_KEYMGMT_UNSUPPORTED_VERSION_ENCRYPTION("091203"), EBICS_KEYMGMT_KEYLENGTH_ERROR_SIGNATURE("091204"), EBICS_KEYMGMT_KEYLENGTH_ERROR_AUTHENTICATION("091205"), EBICS_KEYMGMT_KEYLENGTH_ERROR_ENCRYPTION("091206"), EBICS_X509_CERTIFICATE_EXPIRED("091208"), EBICS_X509_CERTIFICATE_NOT_VALID_YET("091209"), EBICS_X509_WRONG_KEY_USAGE("091210"), EBICS_X509_WRONG_ALGORITHM("091211"), EBICS_X509_INVALID_THUMBPRINT("091212"), EBICS_X509_CTL_INVALID("091213"), EBICS_X509_UNKNOWN_CERTIFICATE_AUTHORITY("091214"), EBICS_X509_INVALID_POLICY("091215"), EBICS_X509_INVALID_BASIC_CONSTRAINTS("091216"), EBICS_ONLY_X509_SUPPORT("091217"), EBICS_KEYMGMT_DUPLICATE_KEY("091218"), EBICS_CERTIFICATE_VALIDATION_ERROR("091219"), // Pre-erification errors EBICS_SIGNATURE_VERIFICATION_FAILED("091301"), EBICS_ACCOUNT_AUTHORISATION_FAILED("091302"), EBICS_AMOUNT_CHECK_FAILED("091303"), EBICS_SIGNER_UNKNOWN("091304"), EBICS_INVALID_SIGNER_STATE("091305"), EBICS_DUPLICATE_SIGNATURE("091306"); enum class Kind { Information, Note, Warning, Error } fun kind(): Kind { return when (val errorClass = code.substring(0..1)) { "00" -> Kind.Information "01" -> Kind.Note "03" -> Kind.Warning "06", "09" -> Kind.Error else -> throw Exception("Unknown EBICS status code error class: $errorClass") } } companion object { fun lookup(code: String): EbicsReturnCode { for (x in entries) { if (x.code == code) { return x } } throw Exception( "Unknown EBICS status code: $code" ) } } }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/order.kt0000664000175000017500000001274415122266731026733 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics sealed class EbicsOrder(val schema: String) { data class V2_5( val type: String, val attribute: String ): EbicsOrder("H004") data class V3( val type: String, val service: String? = null, val scope: String? = null, val message: String? = null, val version: String? = null, val container: String? = null, val option: String? = null ): EbicsOrder("H005") { companion object { val WSS_PARAMS = V3( type = "BTD", service = "OTH", scope = "DE", message = "wssparam" ) val HAC = V3(type = "HAC") val HKD = V3(type = "HKD") val HAA = V3(type = "HAA") } } fun description(): String = buildString { when (this@EbicsOrder) { is V2_5 -> { append(type) append('-') append(attribute) } is V3 -> { append(type) for (part in sequenceOf(service, scope, option, container)) { if (part != null) { append('-') append(part) } } if (message != null) { append('-') append(message) if (version != null) { append('.') append(version) } } } } } fun doc(): OrderDoc? { return when (this) { is V2_5 -> { when (this.type) { "HAC" -> OrderDoc.acknowledgement "Z01" -> OrderDoc.status "Z52" -> OrderDoc.report "Z53" -> OrderDoc.statement "Z54" -> OrderDoc.notification else -> null } } is V3 -> { when (this.type) { "HAC" -> OrderDoc.acknowledgement "BTD" -> when (this.message) { "pain.002" -> OrderDoc.status "camt.052" -> OrderDoc.report "camt.053" -> OrderDoc.statement "camt.054" -> OrderDoc.notification else -> null } else -> null } } } } /** Check if EBICS order is a downloadable one */ fun isDownload(): Boolean = when (this) { is V2_5 -> this.type in setOf("HAC", "Z01", "Z52", "Z53", "Z54") is V3 -> this.type == "HAC" || ( this.type=="BTD" && this.message in setOf("pain.002", "camt.052", "camt.053", "camt.054") ) } /** Check if EBICS order is an uploadable one */ fun isUpload(): Boolean = when (this) { is V2_5 -> false is V3 -> this.type == "BTU" } /** Check if two EBICS order match ignoring the message version */ fun match(other: EbicsOrder): Boolean = when (this) { is V2_5 -> other is V2_5 && type == other.type && attribute == other.attribute is V3 -> other is V3 && type == other.type && service == other.service && scope == other.scope && message == other.message && container == other.container && option == other.option } } enum class OrderDoc { /// EBICS acknowledgement - CustomerAcknowledgement HAC pain.002 acknowledgement, /// Payment status - CustomerPaymentStatusReport pain.002 status, /// Account intraday reports - BankToCustomerAccountReport camt.052 report, /// Account statements - BankToCustomerStatement camt.053 statement, /// Debit & credit notifications - BankToCustomerDebitCreditNotification camt.054 notification; fun shortDescription(): String = when (this) { acknowledgement -> "EBICS acknowledgement" status -> "Payment status" report -> "Account intraday reports" statement -> "Account statements" notification -> "Debit & credit notifications" } fun fullDescription(): String = when (this) { acknowledgement -> "EBICS acknowledgement - CustomerAcknowledgement HAC pain.002" status -> "Payment status - CustomerPaymentStatusReport pain.002" report -> "Account intraday reports - BankToCustomerAccountReport camt.052" statement -> "Account statements - BankToCustomerStatement camt.053" notification -> "Debit & credit notifications - BankToCustomerDebitCreditNotification camt.054" } }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/EBicsLogger.kt0000664000175000017500000001142115157551657027750 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import tech.libeufin.common.* import tech.libeufin.ebics.EbicsOrder import java.io.* import java.nio.file.* import java.time.* import java.time.format.DateTimeFormatter import kotlin.io.* import kotlin.io.path.* import io.ktor.client.statement.* /** Log EBICS transactions steps and payload if [path] is not null */ class EbicsLogger(private val dir: Path?) { init { if (dir != null) { try { // Create logging directory if missing dir.createDirectories() } catch (e: Exception) { throw Exception("Failed to init EBICS debug logging directory", e) } logger.info("Logging to '$dir'") } } /** Create a new [name] EBICS transaction logger */ fun tx(name: String): TxLogger { if (dir == null) return TxLogger(null) val utcDateTime = Instant.now().atOffset(ZoneOffset.UTC) val txDir = dir // yyyy-MM-dd per day directory .resolve(utcDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE)) // HH:mm:ss.SSS-name per transaction directory .resolve("${utcDateTime.format(TIME_WITH_MS)}-$name") txDir.createDirectories() return TxLogger(txDir) } /** Create a new [order] EBICS transaction logger */ fun tx(order: EbicsOrder): TxLogger { if (dir == null) return TxLogger(null) return tx(order.description()) } companion object { private val TIME_WITH_MS = DateTimeFormatter.ofPattern("HH:mm:ss.SSS") } } /** Log EBICS transaction steps and payload */ class TxLogger internal constructor( private val dir: Path? ) { /** Create a new [name] EBICS transaction step logger*/ fun step(name: String? = null) = StepLogger(dir, name) /** Log a [stream] EBICS transaction payload of [type] */ fun payload(stream: InputStream, type: String = "xml"): InputStream { if (dir == null) return stream return payload(stream.readBytes(), type).inputStream() } /** Log a [content] EBICS transaction payload of [type] */ fun payload(content: ByteArray, type: String = "xml"): ByteArray { if (dir == null) return content val type = type.lowercase() if (type == "zip") { val payloadDir = dir.resolve("payload") payloadDir.createDirectory() content.inputStream().unzipEach { fileName, xmlContent -> xmlContent.use { Files.copy(it, payloadDir.resolve(fileName)) } } } else { dir.resolve("payload.$type").writeBytes(content, StandardOpenOption.CREATE_NEW) } return content } } /** Log EBICS transaction protocol step */ class StepLogger internal constructor( private val dir: Path?, name: String? ) { private val prefix = if (name != null) "$name-" else "" /** Log a protocol step [request] */ fun logRequest(request: ByteArray) { dir?.resolve("${prefix}request.xml")?.writeBytes(request, StandardOpenOption.CREATE_NEW) } /** Log a protocol step failure */ suspend fun logFailure(res: HttpResponse) { if (dir != null) { // TODO reduce allocation // TODO silent io error val bytes = buildString { append("${res.version} ${res.status}\n") for ((k, vs) in res.headers.entries()) { for (v in vs) { append("${k}: ${v}\n") } } append('\n') }.toByteArray() + res.readRawBytes() dir.resolve("${prefix}failure") .writeBytes(bytes, StandardOpenOption.CREATE_NEW) } } /** Log a protocol step [response] */ fun logResponse(response: InputStream): InputStream { if (dir == null) return response val bytes = response.readBytes() dir.resolve("${prefix}response.xml") .writeBytes(bytes, StandardOpenOption.CREATE_NEW) return bytes.inputStream() } }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/EbicsCommon.kt0000664000175000017500000003567615157551657030043 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import io.ktor.client.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.utils.io.jvm.javaio.* import org.slf4j.Logger import org.slf4j.LoggerFactory import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.withContext import org.w3c.dom.Document import org.xml.sax.SAXException import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import java.io.InputStream import java.io.SequenceInputStream import java.security.interfaces.RSAPrivateCrtKey import java.time.Instant import java.util.* internal val logger: Logger = LoggerFactory.getLogger("libeufin-ebics") /** Supported documents that can be downloaded via EBICS */ enum class SupportedDocument { PAIN_002, PAIN_002_LOGS, CAMT_053, CAMT_052, CAMT_054 } /** EBICS related errors */ sealed class EbicsError(msg: String, cause: Throwable? = null): Exception(msg, cause) { /** Network errors */ class Network(msg: String, cause: Throwable): EbicsError(msg, cause) /** Http errors */ class HTTP(msg: String, val status: HttpStatusCode): EbicsError(msg) /** EBICS protocol & XML format error */ class Protocol(msg: String, cause: Throwable? = null): EbicsError(msg, cause) /** EBICS protocol & XML format error */ class Code(msg: String, val technicalCode: EbicsReturnCode, val bankCode: EbicsReturnCode): EbicsError(msg) } /** POST an EBICS request [msg] to [bankUrl] returning a parsed XML response */ suspend fun HttpClient.postToBank( bankUrl: String, msg: ByteArray, phase: String, stepLogger: StepLogger ): Document { stepLogger.logRequest(msg) val res = try { post(urlString = bankUrl) { contentType(ContentType.Text.Xml) setBody(msg) } } catch (e: Exception) { throw EbicsError.Network("$phase: failed to contact bank", e) } if (res.status != HttpStatusCode.OK) { stepLogger.logFailure(res) throw EbicsError.HTTP("$phase: bank HTTP error: ${res.status}", res.status) } try { val bodyStream = res.bodyAsChannel().toInputStream() val loggedStream = stepLogger.logResponse(bodyStream) return XMLUtil.parseIntoDom(loggedStream) } catch (e: SAXException) { throw EbicsError.Protocol("$phase: invalid XML bank response", e) } catch (e: Exception) { throw EbicsError.Network("$phase: failed read bank response", e) } } /** POST an EBICS BTS request [xmlReq] using [client] returning a validated and parsed XML response */ suspend fun EbicsBTS.postBTS( client: HttpClient, xmlReq: ByteArray, phase: String, stepLogger: StepLogger ): BTSResponse { val doc = client.postToBank(cfg.baseUrl, xmlReq, phase, stepLogger) try { XMLUtil.verifyEbicsDocument( doc, bankKeys.bank_authentication_public_key ) } catch (e: Exception) { throw EbicsError.Protocol("$phase ${order.description()}: invalid signature", e) } val response = try { EbicsBTS.parseResponse(doc) } catch (e: Exception) { throw EbicsError.Protocol("$phase ${order.description()}: invalid ebics response", e) } logger.debug { buildString { append(phase) response.content.transactionID?.let { append(" for ") append(it) } append(": ") append(response.technicalCode) append(" & ") append(response.bankCode) } } return response.okOrFail(phase) } /** High level EBICS client */ class EbicsClient( val cfg: EbicsHostConfig, val client: HttpClient, val dao: EbicsDAO, val ebicsLogger: EbicsLogger, val clientKeys: ClientPrivateKeysFile, val bankKeys: BankPublicKeysFile ) { /** * Performs an EBICS download transaction of [order] between [startDate] and [endDate]. * Download content is passed to [processing] * * It conducts init -> transfer -> processing -> receipt phases. * * Cancellations and failures are handled. */ suspend fun download( order: EbicsOrder, startDate: Instant? = null, endDate: Instant? = null, peek: Boolean = false, processing: suspend (InputStream) -> T, ): T { val description = order.description() logger.debug { buildString { append("Download order ") append(description) if (startDate != null) { append(" from ") append(startDate) if (endDate != null) { append(" to ") append(endDate) } } } } val impl = EbicsBTS(cfg, bankKeys, clientKeys, order) // Close interrupted val interruptedLog = ebicsLogger.tx("INTD") while (true) { val tId = dao.first() if (tId == null) break val xml = impl.downloadReceipt(tId, false) try { impl.postBTS(client, xml, "Closing interrupted transaction ${tId}", interruptedLog.step(tId)) } catch (e: Exception) { when (e) { // Transaction already closed or expired - EBICS protocol error is EbicsError.Code if e.technicalCode == EbicsReturnCode.EBICS_TX_UNKNOWN_TXID -> {} // Transaction already closed or expired - HTTP protocol error for non compliant banks is EbicsError.HTTP if e.status == HttpStatusCode.BadRequest -> {} // Unexpected error else -> throw e } logger.debug("${e.fmt()}") } dao.remove(tId) } val txLog = ebicsLogger.tx(order) // We need to run the logic in a non-cancelable context because we need to send // a receipt for each open download transaction, otherwise we'll be stuck in an // error loop until the pending transaction timeout. val (tId, initContent) = withContext(NonCancellable) { // Init phase val initReq = impl.downloadInitialization(startDate, endDate) val initContent = impl.postBTS(client, initReq, "Download init $description", txLog.step("init")) val tId = requireNotNull(initContent.transactionID) { "Download init $description: missing transaction ID" } dao.register(tId) Pair(tId, initContent) } val howManySegments = requireNotNull(initContent.numSegments) { "Download init $description: missing num segments" } val firstSegment = requireNotNull(initContent.segment) { "Download init $description: missing OrderData" } val dataEncryptionInfo = requireNotNull(initContent.dataEncryptionInfo) { "Download init $description: missing EncryptionInfo" } // Transfer phase val segments = mutableListOf(firstSegment) for (x in 2 .. howManySegments) { val transReq = impl.downloadTransfer(x, howManySegments, tId) val transResp = impl.postBTS(client, transReq, "Download transfer $description", txLog.step("transfer$x")) val segment = requireNotNull(transResp.segment) { "Download transfer: missing encrypted segment" } segments.add(segment) } // Decompress encrypted chunks val payloadStream = try { decryptAndDecompressPayload( clientKeys.encryption_private_key, dataEncryptionInfo, segments ) } catch (e: Exception) { throw EbicsError.Protocol("invalid chunks", e) } val container = when (order) { is EbicsOrder.V2_5 -> "rax" // TODO infer ? is EbicsOrder.V3 -> order.container ?: "xml" } val loggedStream = txLog.payload(payloadStream, container) // Run business logic val res = runCatching { processing(loggedStream) } // First send a proper EBICS transaction receipt val xml = impl.downloadReceipt(tId, res.isSuccess && !peek) impl.postBTS(client, xml, "Download receipt $description", txLog.step("receipt")) runCatching { dao.remove(tId) } // Then throw business logic exception if any return res.getOrThrow() } /** * Performs an EBICS upload transaction of [order] using [payload]. * * It conducts init -> upload phases. * * Returns upload orderID */ suspend fun upload( order: EbicsOrder, payload: ByteArray, ): String { val description = order.description(); logger.debug { "Upload order $description" } val txLog = ebicsLogger.tx(order) val impl = EbicsBTS(cfg, bankKeys, clientKeys, order) val preparedPayload = prepareUploadPayload(cfg, clientKeys, bankKeys, payload) txLog.payload(payload, "xml") // Init phase val initXml = impl.uploadInitialization(preparedPayload) val initResp = impl.postBTS(client, initXml, "Upload init $description", txLog.step("init")) val tId = requireNotNull(initResp.transactionID) { "Upload init $description: missing transaction ID" } val orderId = requireNotNull(initResp.orderID) { "Upload init $description: missing order ID" } // Transfer phase for (i in 1..preparedPayload.segments.size) { val transferXml = impl.uploadTransfer(tId, preparedPayload, i) impl.postBTS(client, transferXml, "Upload transfer $description", txLog.step("transfer$i")) } return orderId } } suspend fun HEV( client: HttpClient, cfg: EbicsHostConfig, ebicsLogger: EbicsLogger ): List { logger.info("Doing administrative request HEV") val txLog = ebicsLogger.tx("HEV") val req = EbicsAdministrative.HEV(cfg) val xml = client.postToBank(cfg.baseUrl, req, "HEV", txLog.step()) return EbicsAdministrative.parseHEV(xml).okOrFail("HEV") } suspend fun keyManagement( cfg: EbicsHostConfig, privs: ClientPrivateKeysFile, client: HttpClient, ebicsLogger: EbicsLogger, order: EbicsKeyMng.Order, ebics3: Boolean ): EbicsResponse { logger.info("Doing key request $order") val txLog = ebicsLogger.tx(order.name) // TODO is this still necessary ? val req = EbicsKeyMng(cfg, privs, ebics3).request(order) val xml = client.postToBank(cfg.baseUrl, req, order.name, txLog.step()) return EbicsKeyMng.parseResponse(xml, privs.encryption_private_key) } class PreparedUploadData( val transactionKey: ByteArray, val userSignatureDataEncrypted: String, val dataDigest: ByteArray, val segments: List ) /** Signs, encrypts and format EBICS BTS payload */ fun prepareUploadPayload( cfg: EbicsHostConfig, clientKeys: ClientPrivateKeysFile, bankKeys: BankPublicKeysFile, payload: ByteArray, ): PreparedUploadData { val payloadDigest = CryptoUtil.digestEbicsOrderA006(payload) val innerSignedEbicsXml = XmlBuilder.toBytes("UserSignatureData") { attr("xmlns", "http://www.ebics.org/S002") el("OrderSignatureData") { el("SignatureVersion", "A006") el("SignatureValue", CryptoUtil.signEbicsA006( payloadDigest, clientKeys.signature_private_key, ).encodeBase64()) el("PartnerID", cfg.partnerId) el("UserID", cfg.userId) } } // Generate ephemeral transaction key val (transactionKey, encryptedTransactionKey) = CryptoUtil.genEbicsE002Key(bankKeys.bank_encryption_public_key) // Compress and encrypt order signature val orderSignature = CryptoUtil.encryptEbicsE002( transactionKey, innerSignedEbicsXml.inputStream().deflate() ).encodeBase64() // Compress and encrypt payload val encrypted = CryptoUtil.encryptEbicsE002( transactionKey, payload.inputStream().deflate() ) // Chunks of 1MB and encode segments val segments = encrypted.encodeBase64().chunked(1000000) return PreparedUploadData( encryptedTransactionKey, orderSignature, payloadDigest, segments ) } /** Decrypts and decompresses EBICS BTS payload */ fun decryptAndDecompressPayload( clientEncryptionKey: RSAPrivateCrtKey, encryptionInfo: DataEncryptionInfo, segments: List ): InputStream { val transactionKey = CryptoUtil.decryptEbicsE002Key(clientEncryptionKey, encryptionInfo.transactionKey) return SequenceInputStream(Collections.enumeration(segments.map { it.inputStream() })) // Aggregate .run { CryptoUtil.decryptEbicsE002( transactionKey, this ) }.inflate() } /** Generate a secure random nonce of [size] bytes */ fun getNonce(size: Int): ByteArray { return ByteArray(size / 8).secureRand() } private val EBICS_ID_ALPHABET = ('A'..'Z') + ('0'..'9') fun randEbicsId(): String { return List(34) { EBICS_ID_ALPHABET.random() }.joinToString("") } class DataEncryptionInfo( val transactionKey: ByteArray, val bankPubDigest: ByteArray ) class EbicsResponse( val technicalCode: EbicsReturnCode, val bankCode: EbicsReturnCode, internal val content: T ) { /** Checks that return codes are both EBICS_OK */ fun ok(): T? { return if (technicalCode.kind() != EbicsReturnCode.Kind.Error && bankCode.kind() != EbicsReturnCode.Kind.Error) { content } else { null } } /** Checks that return codes are both EBICS_OK or throw an exception */ fun okOrFail(phase: String): T { if (technicalCode.kind() == EbicsReturnCode.Kind.Error) { throw EbicsError.Code("$phase has technical error: $technicalCode", technicalCode, bankCode) } else if (bankCode.kind() == EbicsReturnCode.Kind.Error) { throw EbicsError.Code("$phase has bank error: $bankCode", technicalCode, bankCode) } else { return content } } }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/EbicsAdministrative.kt0000664000175000017500000001376115122266731031551 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import org.w3c.dom.Document import java.io.InputStream data class VersionNumber(val number: Float, val schema: String) { override fun toString(): String = "$number:$schema" } data class HKD( val partner: PartnerInfo, val users: List ) data class PartnerInfo( val name: String?, val accounts: List, val orders: List ) data class OrderInfo( val order: EbicsOrder, val description: String, ) data class AccountInfo( val currency: String, val iban: String, val bic: String ) data class UserInfo( val id: String, val status: UserStatus, val permissions: List, ) data class HAA( val orders: List ) enum class UserStatus(val description: String) { Ready("Subscriber is permitted access"), New("Subscriber is established, pending access permission"), INI("Subscriber has sent INI file, but no HIA file yet"), HIA("Subscriber has sent HIA order, but no INI file yet"), Initialised("Subscriber has sent both HIA order and INI file"), SuspendedFailedAttempts("Suspended after several failed attempts, new initialisation via INI and HIA possible"), SuspendedSPR("Suspended after SPR order, new initialisation via INI and HIA possible"), SuspendedBank("Suspended by bank, new initialisation via INI and HIA is not possible, suspension can only be revoked by the bank"), } object EbicsAdministrative { fun HEV(cfg: EbicsHostConfig): ByteArray { return XmlBuilder.toBytes("ebicsHEVRequest") { attr("xmlns", "http://www.ebics.org/H000") el("HostID", cfg.hostId) } } fun parseHEV(doc: Document): EbicsResponse> { return XmlDestructor.parse(doc, "ebicsHEVResponse") { val technicalCode = one("SystemReturnCode") { EbicsReturnCode.lookup(one("ReturnCode").text()) } val versions = map("VersionNumber") { VersionNumber(text().toFloat(), attr("ProtocolVersion")) } EbicsResponse( technicalCode = technicalCode, bankCode = EbicsReturnCode.EBICS_OK, content = versions ) } } private fun XmlDestructor.ebicsOrder(type: String): EbicsOrder = EbicsOrder.V3( type = type, service = opt("ServiceName")?.text(), scope = opt("Scope")?.text(), option = opt("ServiceOption")?.text(), container = opt("Container")?.attr("containerType"), message = opt("MsgName")?.text(), version = opt("MsgName")?.optAttr("version"), ) fun parseHKD(stream: InputStream): HKD { fun XmlDestructor.order(): EbicsOrder { val type = one("AdminOrderType").text() return opt("Service") { ebicsOrder(type) } ?: EbicsOrder.V3(type) } return XmlDestructor.parse(stream, "HKDResponseOrderData") { val partnerInfo = one("PartnerInfo") { val name = one("AddressInfo").opt("Name")?.text() val accounts = map("AccountInfo") { var currency = attr("Currency") lateinit var iban: String lateinit var bic: String each("AccountNumber") { if (attr("international") == "true") { iban = text() } } each("BankCode") { if (attr("international") == "true") { bic = text() } } AccountInfo(currency, iban, bic) } val orders = map("OrderInfo") { OrderInfo( order = order(), description = one("Description").text() ) } PartnerInfo(name, accounts, orders) } val usersInfo = map("UserInfo") { val (id, status) = one("UserID") { val id = text() val status = when (val status = attr("Status")) { "1" -> UserStatus.Ready "2" -> UserStatus.New "3" -> UserStatus.INI "4" -> UserStatus.HIA "5" -> UserStatus.Initialised "6" -> UserStatus.SuspendedFailedAttempts // 7 is not applicable per spec "8" -> UserStatus.SuspendedSPR "9" -> UserStatus.SuspendedBank else -> throw Exception("Unknown user statte $status") } Pair(id, status) } val permissions = map("Permission") { order() } UserInfo(id, status, permissions) } HKD(partnerInfo, usersInfo) } } fun parseHAA(stream: InputStream): HAA { return XmlDestructor.parse(stream, "HAAResponseOrderData") { val orders = map("Service") { ebicsOrder("BTD") } HAA(orders) } } } libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/http.kt0000664000175000017500000000452715122266731026577 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import io.ktor.http.* import io.ktor.http.content.* import io.ktor.client.* import io.ktor.client.request.* import io.ktor.client.plugins.* import io.ktor.client.engine.mock.* import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter /** Use for unit testing */ var MOCK_ENGINE: MockEngine? = null /** Create an HTTP client for EBICS requests */ fun httpClient(): HttpClient = MOCK_ENGINE?.let { HttpClient(it) } ?: HttpClient { install(HttpTimeout) { // It can take a lot of time for the bank to generate documents socketTimeoutMillis = 5 * 60 * 1000 } } /** Gets an HTTP client whose requests are going to be served by 'handler' */ fun getMockedClient( handler: MockRequestHandleScope.(HttpRequestData) -> HttpResponseData ): HttpClient = HttpClient(MockEngine) { followRedirects = false engine { addHandler { request -> handler(request) } } } private lateinit var steps: Iterator<(String) -> ByteArray> object BadRequest: Exception() fun setMock(sequences: Sequence<(String) -> ByteArray>) { steps = sequences.iterator() if (MOCK_ENGINE == null) { val cfg: MockEngineConfig = MockEngineConfig() cfg.addHandler { req -> val body = String((req.body as OutgoingContent.ByteArrayContent).bytes()) val handler = steps.next() try { val res = handler(body) respond(res) } catch (e: BadRequest) { respondBadRequest() } } MOCK_ENGINE = MockEngine(cfg) } }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/EbicsDAO.kt0000664000175000017500000000303715122266731027164 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import tech.libeufin.common.db.DbPool /** Data access logic for EBICS transaction */ class EbicsDAO(private val db: DbPool) { /** Register a pending transaction */ suspend fun register(id: String) = db.serializable( "INSERT INTO pending_ebics_transactions (tx_id) VALUES (?) ON CONFLICT DO NOTHING" ) { bind(id) executeUpdate() } /** Remove pending transaction */ suspend fun remove(id: String) = db.serializable( "DELETE FROM pending_ebics_transactions WHERE tx_id = ?" ) { bind(id) executeUpdate() } /** Get first pending transaction */ suspend fun first(): String? = db.serializable( "SELECT tx_id FROM pending_ebics_transactions LIMIT 1" ) { oneOrNull { it.getString(1) } } }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/config.kt0000664000175000017500000000214715122266731027061 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import java.nio.file.Path interface EbicsKeysConfig { val clientPrivateKeysPath: Path val bankPublicKeysPath: Path } interface EbicsSetupConfig { val bankAuthPubKey: ByteArray? val bankEncPubKey: ByteArray? } interface EbicsHostConfig { val baseUrl: String val hostId: String val userId: String val partnerId: String }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/EbicsBTS.kt0000664000175000017500000003150115157551657027222 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import org.w3c.dom.Document import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.decodeBase64 import tech.libeufin.common.encodeBase64 import tech.libeufin.common.encodeHex import tech.libeufin.common.encodeUpHex import java.time.Instant /** EBICS protocol for business transactions */ class EbicsBTS( val cfg: EbicsHostConfig, val bankKeys: BankPublicKeysFile, val clientKeys: ClientPrivateKeysFile, val order: EbicsOrder ) { /* ----- Download ----- */ fun downloadInitialization(startDate: Instant?, endDate: Instant?): ByteArray { val nonce = getNonce(128) return signedRequest { el("header") { attr("authenticate", "true") el("static") { el("HostID", cfg.hostId) el("Nonce", nonce.encodeHex()) el("Timestamp", Instant.now().xmlDateTime()) el("PartnerID", cfg.partnerId) el("UserID", cfg.userId) // SystemID // Product el("OrderDetails") { when (order) { is EbicsOrder.V2_5 -> { el("OrderType", order.type) el("OrderAttribute", order.attribute) el("StandardOrderParams") { if (startDate != null) { el("DateRange") { el("Start", startDate.xmlDate()) el("End", (endDate ?: Instant.now()).xmlDate()) } } } } is EbicsOrder.V3 -> { el("AdminOrderType", order.type) if (order.type == "BTD") { el("BTDOrderParams") { service(order) if (startDate != null) { el("DateRange") { el("Start", startDate.xmlDate()) el("End", (endDate ?: Instant.now()).xmlDate()) } } } } else { el("StandardOrderParams") } } } } bankDigest() } el("mutable/TransactionPhase", "Initialisation") } el("AuthSignature") el("body") } } fun downloadTransfer( nbSegment: Int, segmentNumber: Int, transactionId: String ): ByteArray { return signedRequest { el("header") { attr("authenticate", "true") el("static") { el("HostID", cfg.hostId) el("TransactionID", transactionId) } el("mutable") { el("TransactionPhase", "Transfer") el("SegmentNumber") { attr("lastSegment", if (nbSegment == segmentNumber) "true" else "false") text(segmentNumber.toString()) } } } el("AuthSignature") el("body") } } fun downloadReceipt( transactionId: String, success: Boolean ): ByteArray { return signedRequest { el("header") { attr("authenticate", "true") el("static") { el("HostID", cfg.hostId) el("TransactionID", transactionId) } el("mutable") { el("TransactionPhase", "Receipt") } } el("AuthSignature") el("body/TransferReceipt") { attr("authenticate", "true") el("ReceiptCode", if (success) "0" else "1") } } } /* ----- Upload ----- */ fun uploadInitialization(uploadData: PreparedUploadData): ByteArray { val nonce = getNonce(128) return signedRequest { el("header") { attr("authenticate", "true") el("static") { el("HostID", cfg.hostId) el("Nonce", nonce.encodeUpHex()) el("Timestamp", Instant.now().xmlDateTime()) el("PartnerID", cfg.partnerId) el("UserID", cfg.userId) // SystemID // Product el("OrderDetails") { when (order) { is EbicsOrder.V2_5 -> { // TODO } is EbicsOrder.V3 -> { el("AdminOrderType", order.type) el("BTUOrderParams") { service(order) el("SignatureFlag") } } } } bankDigest() el("NumSegments", uploadData.segments.size.toString()) } el("mutable/TransactionPhase", "Initialisation") } el("AuthSignature") el("body") { el("DataTransfer") { el("DataEncryptionInfo") { attr("authenticate", "true") el("EncryptionPubKeyDigest") { attr("Version", "E002") attr("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256") text(CryptoUtil.getEbicsPublicKeyHash(bankKeys.bank_encryption_public_key).encodeBase64()) } el("TransactionKey", uploadData.transactionKey.encodeBase64()) } el("SignatureData") { attr("authenticate", "true") text(uploadData.userSignatureDataEncrypted) } el("DataDigest") { attr("SignatureVersion", "A006") text(uploadData.dataDigest.encodeBase64()) } } } } } fun uploadTransfer( transactionId: String, uploadData: PreparedUploadData, segmentNumber: Int ): ByteArray { return signedRequest { el("header") { attr("authenticate", "true") el("static") { el("HostID", cfg.hostId) el("TransactionID", transactionId) } el("mutable") { el("TransactionPhase", "Transfer") el("SegmentNumber") { attr("lastSegment", if (uploadData.segments.size == segmentNumber) "true" else "false") text(segmentNumber.toString()) } } } el("AuthSignature") el("body/DataTransfer/OrderData", uploadData.segments[segmentNumber-1]) } } /* ----- Helpers ----- */ /** Generate a signed ebicsRequest */ private fun signedRequest(lambda: XmlBuilder.() -> Unit): ByteArray { val doc = XmlBuilder.toDom("ebicsRequest", "urn:org:ebics:${order.schema}") { attr("http://www.w3.org/2000/xmlns/", "xmlns", "urn:org:ebics:${order.schema}") attr("http://www.w3.org/2000/xmlns/", "xmlns:ds", "http://www.w3.org/2000/09/xmldsig#") attr("Version", order.schema) attr("Revision", "1") lambda() } XMLUtil.signEbicsDocument( doc, clientKeys.authentication_private_key ) return XMLUtil.convertDomToBytes(doc) } private fun XmlBuilder.bankDigest() { el("BankPubKeyDigests") { el("Authentication") { attr("Version", "X002") attr("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256") text(CryptoUtil.getEbicsPublicKeyHash(bankKeys.bank_authentication_public_key).encodeBase64()) } el("Encryption") { attr("Version", "E002") attr("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256") text(CryptoUtil.getEbicsPublicKeyHash(bankKeys.bank_encryption_public_key).encodeBase64()) } // Signature } el("SecurityMedium", "0000") } private fun XmlBuilder.service(order: EbicsOrder.V3) { el("Service") { el("ServiceName", order.service!!) if (order.scope != null) { el("Scope", order.scope) } if (order.option != null) { el("ServiceOption", order.option) } if (order.container != null) { el("Container") { attr("containerType", order.container) } } el("MsgName") { if (order.version != null) attr("version", order.version) text(order.message!!) } } } companion object { fun parseResponse(doc: Document): EbicsResponse { return XmlDestructor.parse(doc, "ebicsResponse") { var transactionID: String? = null var numSegments: Int? = null lateinit var technicalCode: EbicsReturnCode lateinit var bankCode: EbicsReturnCode var orderID: String? = null var segmentNumber: Int? = null var segment: ByteArray? = null var dataEncryptionInfo: DataEncryptionInfo? = null one("header", signed = true) { one("static") { transactionID = opt("TransactionID")?.text() numSegments = opt("NumSegments")?.text()?.toInt() } one("mutable") { segmentNumber = opt("SegmentNumber")?.text()?.toInt() orderID = opt("OrderID")?.text() technicalCode = EbicsReturnCode.lookup(one("ReturnCode").text()) } } one("body") { opt("DataTransfer") { segment = one("OrderData").base64() dataEncryptionInfo = opt("DataEncryptionInfo", signed = true) { DataEncryptionInfo( one("TransactionKey").base64(), one("EncryptionPubKeyDigest").base64() ) } } bankCode = EbicsReturnCode.lookup(one("ReturnCode", signed = true).text()) } EbicsResponse( bankCode = bankCode, technicalCode = technicalCode, content = BTSResponse( transactionID = transactionID, orderID = orderID, segment = segment, dataEncryptionInfo = dataEncryptionInfo, numSegments = numSegments, segmentNumber = segmentNumber ) ) } } } } class BTSResponse( val transactionID: String?, val orderID: String?, val dataEncryptionInfo: DataEncryptionInfo?, val segment: ByteArray?, val segmentNumber: Int?, val numSegments: Int? )libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/setup.kt0000664000175000017500000002274315122266731026760 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import io.ktor.client.HttpClient import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.encodeUpHex import tech.libeufin.common.fmtChunkByTwo import tech.libeufin.ebics.EbicsKeyMng.Order.* import java.time.Instant import kotlin.io.path.Path import kotlin.io.path.writeBytes import java.nio.file.FileAlreadyExistsException import java.nio.file.Path import java.nio.file.StandardOpenOption /** Load client private keys at [path] or create new ones if missing */ private fun loadOrGenerateClientKeys(path: Path): ClientPrivateKeysFile { // If exists load from disk val current = loadClientKeys(path) if (current != null) return current // Else create new keys val newKeys = generateNewKeys() persistClientKeys(newKeys, path) logger.info("New client private keys created at '$path'") return newKeys } /** * Asks the user to accept the bank public keys. * * @param bankKeys bank public keys, in format stored on disk. * @return true if the user accepted, false otherwise. */ fun askUserToAcceptKeys(bankKeys: BankPublicKeysFile, cfg: EbicsSetupConfig): Boolean { val encHash = CryptoUtil.getEbicsPublicKeyHash(bankKeys.bank_encryption_public_key) val authHash = CryptoUtil.getEbicsPublicKeyHash(bankKeys.bank_authentication_public_key) val authPubKey = cfg.bankAuthPubKey val encPubKey = cfg.bankEncPubKey if (authPubKey != null && encPubKey != null) { if (encHash.contentEquals(encPubKey) && authHash.contentEquals(authPubKey)) { logger.info("Accepting bank keys matching config hashes") return true } throw Exception(buildString { append("Bank keys does not match config hashes\nBank encryption key: ") append(encHash.encodeUpHex().fmtChunkByTwo()) append("\nConfig encryption key: ") append(encPubKey.encodeUpHex().fmtChunkByTwo()) append("\nBank authentication key: ") append(authHash.encodeUpHex().fmtChunkByTwo()) append("\nConfig authentication key: ") append(authPubKey.encodeUpHex().fmtChunkByTwo()) }) } println("The bank has the following keys:") println("Encryption key: ${encHash.encodeUpHex().fmtChunkByTwo()}") println("Authentication key: ${authHash.encodeUpHex().fmtChunkByTwo()}") print("type 'yes, accept' to accept them: ") val userResponse: String? = readlnOrNull() return userResponse == "yes, accept" } /** * Mere collector of the PDF generation steps. Fails the * process if a problem occurs. * * @param privs client private keys. * @param cfg configuration handle. */ private fun makePdf(privs: ClientPrivateKeysFile, cfg: EbicsHostConfig) { val pdf = generateKeysPdf(privs, cfg) val path = Path("/tmp/libeufin-ebics-keys.pdf") try { path.writeBytes(pdf, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING) } catch (e: Exception) { throw Exception("Could not write PDF to '$path'", e) } println("PDF file with keys created at '$path'") } /** Perform an EBICS public key management [order] using [client] and update on disk state */ private suspend fun submitClientKeys( keyCfg: EbicsKeysConfig, hostCfg: EbicsHostConfig, privs: ClientPrivateKeysFile, client: HttpClient, ebicsLogger: EbicsLogger, order: EbicsKeyMng.Order, ebics3: Boolean ) { require(order != HPB) { "Only INI & HIA are supported for client keys" } val resp = keyManagement(hostCfg, privs, client, ebicsLogger, order, ebics3) if (resp.technicalCode == EbicsReturnCode.EBICS_INVALID_USER_OR_USER_STATE || resp.technicalCode == EbicsReturnCode.EBICS_INVALID_USER_STATE) { throw Exception("$order status code ${resp.technicalCode}: either your IDs are incorrect, or you already have keys registered with this bank") } val orderData = resp.okOrFail(order.name) when (order) { INI -> privs.submitted_ini = true HIA -> privs.submitted_hia = true HPB -> {} } try { persistClientKeys(privs, keyCfg.clientPrivateKeysPath) } catch (e: Exception) { throw Exception("Could not update the $order state on disk", e) } } /** Perform an EBICS private key management HPB using [client] */ private suspend fun fetchPrivateKeys( cfg: EbicsHostConfig, privs: ClientPrivateKeysFile, client: HttpClient, ebicsLogger: EbicsLogger, ebics3: Boolean ): BankPublicKeysFile { val order = HPB val resp = keyManagement(cfg, privs, client, ebicsLogger, order, ebics3) if (resp.technicalCode == EbicsReturnCode.EBICS_AUTHENTICATION_FAILED) { throw Exception("$order status code ${resp.technicalCode}: could not download bank keys, send client keys (and/or related PDF document with --generate-registration-pdf) to the bank") } val orderData = requireNotNull(resp.okOrFail(order.name)) { "$order: missing order data" } val (authPub, encPub) = EbicsKeyMng.parseHpbOrder(orderData) return BankPublicKeysFile( bank_authentication_public_key = authPub, bank_encryption_public_key = encPub, accepted = false ) } suspend fun ebicsSetup( client: HttpClient, ebicsLogger: EbicsLogger, keyCfg: EbicsKeysConfig, hostCfg: EbicsHostConfig, setupCfg: EbicsSetupConfig, forceKeysResubmission: Boolean, generateRegistrationPdf: Boolean, autoAcceptKeys: Boolean, ebics3: Boolean ): Pair{ val clientKeys = loadOrGenerateClientKeys(keyCfg.clientPrivateKeysPath) var bankKeys = loadBankKeys(keyCfg.bankPublicKeysPath) // Check EBICS 3 support val versions = HEV(client, hostCfg, ebicsLogger) logger.debug("HEV: {}", versions) if (!versions.contains(VersionNumber(3.0f, "H005")) && !versions.contains(VersionNumber(3.02f, "H005"))) { throw Exception("EBICS 3 is not supported by your bank") } // Privs exist. Upload their pubs val keysNotSub = !clientKeys.submitted_ini if (!clientKeys.submitted_ini || forceKeysResubmission) submitClientKeys(keyCfg, hostCfg, clientKeys, client, ebicsLogger, INI, ebics3) // Eject PDF if the keys were submitted for the first time, or the user asked. if (keysNotSub || generateRegistrationPdf) makePdf(clientKeys, hostCfg) if (!clientKeys.submitted_hia || forceKeysResubmission) submitClientKeys(keyCfg, hostCfg, clientKeys, client, ebicsLogger, HIA, ebics3) val fetchedBankKeys = fetchPrivateKeys(hostCfg, clientKeys, client, ebicsLogger, ebics3) if (bankKeys == null) { // Accept bank keys logger.info("Bank keys stored at ${keyCfg.bankPublicKeysPath}") try { persistBankKeys(fetchedBankKeys, keyCfg.bankPublicKeysPath) } catch (e: Exception) { throw Exception("Could not store bank keys on disk", e) } bankKeys = fetchedBankKeys } else { // Check current bank keys if (bankKeys.bank_encryption_public_key != fetchedBankKeys.bank_encryption_public_key) { throw Exception(buildString { append("On disk bank encryption key stored at ") append(keyCfg.bankPublicKeysPath) append(" doesn't match server key\nDisk: ") append(CryptoUtil.getEbicsPublicKeyHash(bankKeys.bank_encryption_public_key).encodeUpHex().fmtChunkByTwo()) append("\nServer: ") append(CryptoUtil.getEbicsPublicKeyHash(fetchedBankKeys.bank_encryption_public_key).encodeUpHex().fmtChunkByTwo()) }) } else if (bankKeys.bank_authentication_public_key != fetchedBankKeys.bank_authentication_public_key) { throw Exception(buildString { append("On disk bank authentication key stored at ") append(keyCfg.bankPublicKeysPath) append(" doesn't match server key\nDisk: ") append(CryptoUtil.getEbicsPublicKeyHash(bankKeys.bank_authentication_public_key).encodeUpHex().fmtChunkByTwo()) append("\nServer: ") append(CryptoUtil.getEbicsPublicKeyHash(fetchedBankKeys.bank_authentication_public_key).encodeUpHex().fmtChunkByTwo()) }) } } if (!bankKeys.accepted) { // Finishing the setup by accepting the bank keys. if (autoAcceptKeys) bankKeys.accepted = true else bankKeys.accepted = askUserToAcceptKeys(bankKeys, setupCfg) if (!bankKeys.accepted) { throw Exception("Cannot successfully finish the setup without accepting the bank keys") } try { persistBankKeys(bankKeys, keyCfg.bankPublicKeysPath) } catch (e: Exception) { throw Exception("Could not set bank keys as accepted on disk", e) } } return Pair(clientKeys, bankKeys) }libeufin-1.6.8/libeufin-ebics/src/main/kotlin/tech/libeufin/ebics/EbicsKeyMng.kt0000664000175000017500000001745715122266731027766 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebics import org.w3c.dom.Document import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.decodeBase64 import tech.libeufin.common.deflate import tech.libeufin.common.encodeBase64 import tech.libeufin.common.encodeUpHex import tech.libeufin.ebics.EbicsKeyMng.Order.* import java.io.InputStream import java.security.interfaces.RSAPrivateCrtKey import java.security.interfaces.RSAPublicKey import java.time.Instant /** EBICS protocol for key management */ class EbicsKeyMng( private val cfg: EbicsHostConfig, private val clientKeys: ClientPrivateKeysFile, private val ebics3: Boolean ) { private val schema = if (ebics3) "H005" else "H004" enum class Order { INI, HIA, HPB } fun request(order: Order): ByteArray { val (name, securityMedium, orderAttribute) = when (order) { INI, HIA -> Triple("ebicsUnsecuredRequest", "0200", "DZNNN") HPB -> Triple("ebicsNoPubKeyDigestsRequest", "0000", "DZHNN") } val data = when (order) { INI -> XMLOrderData("SignaturePubKeyOrderData", "http://www.ebics.org/S00${if (ebics3) 2 else 1}") { el("SignaturePubKeyInfo") { RSAKeyXml(clientKeys.signature_private_key) el("SignatureVersion", "A006") } } HIA -> XMLOrderData("HIARequestOrderData", "urn:org:ebics:$schema") { el("AuthenticationPubKeyInfo") { RSAKeyXml(clientKeys.authentication_private_key) el("AuthenticationVersion", "X002") } el("EncryptionPubKeyInfo") { RSAKeyXml(clientKeys.encryption_private_key) el("EncryptionVersion", "E002") } } HPB -> null } val sign = order == HPB val doc = XmlBuilder.toDom(name, "urn:org:ebics:$schema") { attr("http://www.w3.org/2000/xmlns/", "xmlns", "urn:org:ebics:$schema") attr("http://www.w3.org/2000/xmlns/", "xmlns:ds", "http://www.w3.org/2000/09/xmldsig#") attr("Version", schema) attr("Revision", "1") el("header") { attr("authenticate", "true") el("static") { el("HostID", cfg.hostId) if (order == HPB) { el("Nonce", getNonce(128).encodeUpHex()) el("Timestamp", Instant.now().xmlDateTime()) } el("PartnerID", cfg.partnerId) el("UserID", cfg.userId) el("OrderDetails") { if (ebics3) { el("AdminOrderType", order.name) } else { el("OrderType", order.name) el("OrderAttribute", orderAttribute) } } el("SecurityMedium", securityMedium) } el("mutable") } if (sign) el("AuthSignature") el("body") { if (data != null) el("DataTransfer/OrderData", data) } } if (sign) XMLUtil.signEbicsDocument(doc, clientKeys.authentication_private_key) return XMLUtil.convertDomToBytes(doc) } private fun XmlBuilder.RSAKeyXml(key: RSAPrivateCrtKey) { if (ebics3) { val cert = CryptoUtil.X509CertificateFromRSAPrivate(key, "LibEuFin EBICS") el("ds:X509Data") { el("ds:X509Certificate", cert.encoded.encodeBase64()) } } else { el("PubKeyValue") { el("ds:RSAKeyValue") { el("ds:Modulus", key.modulus.encodeBase64()) el("ds:Exponent", key.publicExponent.encodeBase64()) } } } } private fun XMLOrderData(name: String, schema: String, build: XmlBuilder.() -> Unit): String { return XmlBuilder.toBytes(name) { attr("xmlns:ds", "http://www.w3.org/2000/09/xmldsig#") attr("xmlns", schema) build() el("PartnerID", cfg.partnerId) el("UserID", cfg.userId) }.inputStream().deflate().encodeBase64() } companion object { fun parseResponse(doc: Document, clientEncryptionKey: RSAPrivateCrtKey): EbicsResponse { return XmlDestructor.parse(doc, "ebicsKeyManagementResponse") { lateinit var technicalCode: EbicsReturnCode lateinit var bankCode: EbicsReturnCode var payload: InputStream? = null one("header", signed = true) { one("mutable") { technicalCode = EbicsReturnCode.lookup(one("ReturnCode").text()) } } one("body") { bankCode = EbicsReturnCode.lookup(one("ReturnCode", signed = true).text()) payload = opt("DataTransfer") { val descriptionInfo = one("DataEncryptionInfo", signed = true) { DataEncryptionInfo( one("TransactionKey").base64(), one("EncryptionPubKeyDigest").base64() ) } val chunk = one("OrderData").base64() decryptAndDecompressPayload( clientEncryptionKey, descriptionInfo, listOf(chunk) ) } } EbicsResponse( technicalCode = technicalCode, bankCode, content = payload ) } } fun parseHpbOrder(data: InputStream): Pair { return XmlDestructor.parse(data, "HPBResponseOrderData") { val authPub = one("AuthenticationPubKeyInfo") { val version = one("AuthenticationVersion").text() require(version == "X002") { "Expected authentication version X002 got unsupported $version" } rsaPubKey() } val encPub = one("EncryptionPubKeyInfo") { val version = one("EncryptionVersion").text() require(version == "E002") { "Expected encryption version E002 got unsupported $version" } rsaPubKey() } Pair(authPub, encPub) } } } } fun XmlDestructor.rsaPubKey(): RSAPublicKey { val cert = opt("X509Data")?.one("X509Certificate")?.text()?.decodeBase64() return if (cert != null) { CryptoUtil.RSAPublicFromCertificate(cert) } else { one("PubKeyValue").one("RSAKeyValue") { CryptoUtil.RSAPublicFromComponents( one("Modulus").base64(), one("Exponent").base64(), ) } } }libeufin-1.6.8/libeufin-ebics/src/test/0000775000175000017500000000000015236145704020200 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/test/kotlin/0000775000175000017500000000000015236145704021500 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/test/kotlin/EbicsTest.kt0000664000175000017500000000661315122266731023731 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.w3c.dom.Document import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test import kotlinx.coroutines.runBlocking import io.ktor.http.* import io.ktor.http.content.* import io.ktor.client.engine.mock.* import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.ebics.* import tech.libeufin.ebics.test.* import kotlin.io.path.* import kotlin.test.* import java.time.LocalDate @OptIn(kotlin.io.path.ExperimentalPathApi::class) class EbicsTest { private val ebicsLogger = EbicsLogger(null).tx("test").step("step") // POSTs an EBICS message to the mock bank. Tests // the main branches: unreachable bank, non-200 status // code, and 200. @Test fun postMessage() {runBlocking { assertFailsWith { getMockedClient { respondError(HttpStatusCode.NotFound) }.postToBank("http://ignored.example.com/", ByteArray(0), "Test", ebicsLogger) }.run { assertEquals(HttpStatusCode.NotFound, status) assertEquals("Test: bank HTTP error: 404 Not Found", message) } assertFailsWith { getMockedClient { throw Exception("Simulate failure") }.postToBank("http://ignored.example.com/", ByteArray(0), "Test", ebicsLogger) }.run { assertEquals("Test: failed to contact bank", message) assertEquals("Simulate failure", cause!!.message) } assertFailsWith { getMockedClient { respondOk("") }.postToBank("http://ignored.example.com/", ByteArray(0), "Test", ebicsLogger) }.run { assertEquals("Test: invalid XML bank response", message) assertEquals("Attribute name \"broken\" associated with an element type \"ebics\" must be followed by the ' = ' character.", cause!!.message) } getMockedClient { respondOk("") }.postToBank("http://ignored.example.com/", ByteArray(0), "Test", ebicsLogger) }} // Tests that internal repr. of keys lead to valid PDF. // Mainly tests that the function does not throw any error. @Test fun keysPdf() { val pdf = generateKeysPdf(generateNewKeys(), object: EbicsHostConfig { override val baseUrl = "https://isotest.postfinance.ch/ebicsweb/ebicsweb" override val hostId = "PFEBICS" override val userId = "PFC00563" override val partnerId = "PFC00563" }) Path("/tmp/libeufin-nexus-test-keys.pdf").writeBytes(pdf) } }libeufin-1.6.8/libeufin-ebics/src/test/kotlin/MySerializers.kt0000664000175000017500000000367415122266731024652 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.Base32Crockford import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.ebics.ClientPrivateKeysFile import tech.libeufin.ebics.JSON import kotlin.test.assertEquals class MySerializers { // Testing deserialization of RSA private keys. @Test fun rsaPrivDeserialization() { val s = Base32Crockford.encode(CryptoUtil.genRSAPrivate(2048).encoded) val a = Base32Crockford.encode(CryptoUtil.genRSAPrivate(2048).encoded) val e = Base32Crockford.encode(CryptoUtil.genRSAPrivate(2048).encoded) val obj = JSON.decodeFromString(""" { "signature_private_key": "$s", "authentication_private_key": "$a", "encryption_private_key": "$e", "submitted_ini": true, "submitted_hia": true } """.trimIndent()) assertEquals(obj.signature_private_key, CryptoUtil.loadRSAPrivate(Base32Crockford.decode(s))) assertEquals(obj.authentication_private_key, CryptoUtil.loadRSAPrivate(Base32Crockford.decode(a))) assertEquals(obj.encryption_private_key, CryptoUtil.loadRSAPrivate(Base32Crockford.decode(e))) } }libeufin-1.6.8/libeufin-ebics/src/test/kotlin/XmlTest.kt0000664000175000017500000001250515122266731023441 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import kotlin.test.* import org.w3c.dom.Document import org.junit.Test import tech.libeufin.ebics.* import tech.libeufin.common.asUtf8 import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.decodeBase64 import tech.libeufin.ebics.XMLUtil import java.security.KeyPairGenerator class XmlCombinatorsTest { fun testBuilder(expected: String, root: String, builder: XmlBuilder.() -> Unit): Document { val toBytes = XmlBuilder.toBytes(root, builder) val toDom = XmlBuilder.toDom(root, null, builder) //assertEquals(expected, toString) TODO fix empty tag being closed only with toString assertEquals(expected, XMLUtil.convertDomToBytes(toDom).asUtf8()) return toDom } @Test fun testWithModularity() { fun module(base: XmlBuilder) { base.el("module") } testBuilder( "", "root" ) { module(this) } } @Test fun testWithIterable() { testBuilder( "111222333444555666777888999101010", "iterable" ) { el("endOfDocument") { for (i in 1..10) el("e$i/e$i$i", "$i$i$i") } } } @Test fun testBasicXmlBuilding() { testBuilder( "", "ebicsRequest" ) { attr("version", "H004") el("a/b/c") { attr("attribute-of", "c") el("d/e/f") { attr("nested", "true") el("g/h") } } el("one_more") } } @Test fun signed() { val trapped = XmlBuilder.toDom("document", "urn:org:ebics:test") { el("order") { text("not signed") } el("order") { attr("authenticate", "true") text("signed") } el("order") { attr("authenticate", "false") text("not signed 2") } } XmlDestructor.parse(trapped, "document") { assertEquals(3, map("order") { text() }.size) one("order", signed = true) { assertEquals("signed", text()) } } } } class XmlUtilTest { @Test fun basicSigningTest() { val doc = XMLUtil.parseIntoDom(""" Hello World """.trimIndent().toByteArray().inputStream()) val kpg = KeyPairGenerator.getInstance("RSA") kpg.initialize(2048) val pair = kpg.genKeyPair() val otherPair = kpg.genKeyPair() XMLUtil.signEbicsDocument(doc, pair.private) XMLUtil.verifyEbicsDocument(doc, pair.public) assertFails { XMLUtil.verifyEbicsDocument(doc, otherPair.public) } } @Test fun multiAuthSigningTest() { val doc = XMLUtil.parseIntoDom(""" Hello World Another one! """.trimIndent().toByteArray().inputStream()) val kpg = KeyPairGenerator.getInstance("RSA") kpg.initialize(2048) val pair = kpg.genKeyPair() XMLUtil.signEbicsDocument(doc, pair.private) XMLUtil.verifyEbicsDocument(doc, pair.public) } @Test fun testRefSignature() { val classLoader = ClassLoader.getSystemClassLoader() val docText = classLoader.getResourceAsStream("signature1/doc.xml") val doc = XMLUtil.parseIntoDom(docText) val keyStream = classLoader.getResourceAsStream("signature1/public_key.txt") val keyBytes = keyStream.decodeBase64().readAllBytes() val key = CryptoUtil.loadRSAPublic(keyBytes) XMLUtil.verifyEbicsDocument(doc, key) } }libeufin-1.6.8/libeufin-ebics/src/test/kotlin/WsTest.kt0000664000175000017500000001366615122266731023303 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.HttpHeaders import io.ktor.serialization.kotlinx.* import io.ktor.server.application.* import io.ktor.server.routing.* import io.ktor.server.testing.* import io.ktor.server.websocket.* import io.ktor.websocket.* import kotlinx.coroutines.channels.ClosedReceiveChannelException import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.decodeFromJsonElement import kotlinx.serialization.json.encodeToJsonElement import tech.libeufin.ebics.* import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertIs class WsTest { // WSS params example from the spec val PARAMS_EXAMPLE = """ { "URL": "https://bankmitwebsocket.de", "TOKEN": "550e8400-e29b-11d4-a716-446655440000", "OTT": "N", "VALIDITY": "2019-03-21T10:35:22Z", "PARTNERID": "K1234567", "USERID": "USER4711" } """ // Authorization header example from the spec val AUTH_EXAMPLE = "Basic SzEyMzQ1NjdfVVNFUjQ3MTE6NTUwZTg0MDAtZTI5Yi0xMWQ0LWE3MTYtNDQ2NjU1NDQwMDAw" // Notifications examples from the spec val NOTIFICATION_EXAMPLES = sequenceOf( """ { "MCLASS": [ { "NAME": "EBICS-HAA", "VERS": "1.0", "TIMESTAMP": "2019-05-13T12:21:50Z" } ], "PARTNERID": "K1234567", "USERID": "USER471", "BTF": [ { "SERVICE": "REP", "SCOPE": "DE", "CONTTYPE": "ZIP", "MSGNAME": "camt.054" } ], "ORDERTYPE": [ "C5N" ] } """, """ { "MCLASS": [ { "NAME": "EBICS-HAA", "VERS": "1.0", "TIMESTAMP": "2019-05-13T12:21:53Z" } ], "PARTNERID": "K1234567", "USERID": "USER471", "BTF": [ { "SERVICE": "REP", "SCOPE": "DE", "CONTTYPE": "ZIP", "MSGNAME": "camt.052" }, { "SERVICE": "REP", "SCOPE": "DE", "OPTION": "SCI", "CONTTYPE": "ZIP", "MSGNAME": "pain.002" } ], "ORDERTYPE": [ "C52", "CIZ" ] } """, """ { "MCLASS": [ { "NAME": "INFO", "VERS": "1.0", "TIMESTAMP": "2019-03-25T12:25:34Z" } ], "INFO": [ { "LANG": "EN", "FREE": " The EBICS-Service is limited on 30.03.2019 from 10:00 a.m. - 11:00a.m. due to maintenance work " } ] } """ ) /** Test JSON serialization roudtrip */ inline fun roundtrip(raw: String): B { val json: JsonObject = Json.decodeFromString(raw) val decoded: B = Json.decodeFromJsonElement(json) val encoded = Json.encodeToJsonElement(decoded) assertEquals(json, encoded) return decoded } /** Test our serialization implementation works with spec examples */ @Test fun serialization() { roundtrip(PARAMS_EXAMPLE) for (raw in NOTIFICATION_EXAMPLES) { roundtrip(raw) } } /** Test our implementation works with spec examples */ @Test fun wss() { val params: WssParams = Json.decodeFromString(PARAMS_EXAMPLE) testApplication { externalServices { hosts(params.URL.replace("https://", "wss://")) { install(WebSockets) { contentConverter = KotlinxWebsocketSerializationConverter(Json) } routing { webSocket("/") { assertEquals(AUTH_EXAMPLE, call.request.headers[HttpHeaders.Authorization]) // Send all examples for (example in NOTIFICATION_EXAMPLES) { send(example) } close(CloseReason(CloseReason.Codes.NORMAL, "Test done")) } } } } var count = 0 try { params.connect(client) { msg -> count++ // Check message number and type assert(count <= 3) if (count == 3) { assertIs(msg) } else { assertIs(msg) } } } catch (e: ClosedReceiveChannelException) { // Expected } // Check receive all messages assertEquals(3, count) } } }libeufin-1.6.8/libeufin-ebics/src/test/kotlin/Keys.kt0000664000175000017500000000707115122266731022756 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.fmtChunkByTwo import tech.libeufin.ebics.* import kotlin.io.path.Path import kotlin.io.path.deleteIfExists import kotlin.io.path.notExists import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue class PublicKeys { // Tests intermittent spaces in public keys fingerprint. @Test fun splitTest() { assertEquals("0099887766".fmtChunkByTwo(), "00 99 88 77 66") // even assertEquals("ZZYYXXWWVVU".fmtChunkByTwo(), "ZZ YY XX WW VV U") // odd } // Tests loading the bank public keys from disk. @Test fun loadBankKeys() { // artificially creating the keys. val fileContent = BankPublicKeysFile( accepted = true, bank_authentication_public_key = CryptoUtil.genRSAPublic(2028), bank_encryption_public_key = CryptoUtil.genRSAPublic(2028) ) // storing them on disk. persistBankKeys(fileContent, Path("/tmp/nexus-tests-bank-keys.json")) // loading them and check that values are the same. val fromDisk = loadBankKeys(Path("/tmp/nexus-tests-bank-keys.json")) assertNotNull(fromDisk) assertTrue { fromDisk.accepted && fromDisk.bank_encryption_public_key == fileContent.bank_encryption_public_key && fromDisk.bank_authentication_public_key == fileContent.bank_authentication_public_key } } @Test fun loadNotFound() { assertNull(loadBankKeys(Path("/tmp/highly-unlikely-to-be-found.json"))) } } class PrivateKeys { val f = Path("/tmp/nexus-privs-test.json") init { f.deleteIfExists() } /** * Tests whether loading keys from disk yields the same * values that were stored to the file. */ @Test fun load() { assert(f.notExists()) val clientKeys = generateNewKeys() persistClientKeys(clientKeys, f) // Artificially storing this to the file. val fromDisk = loadClientKeys(f) // loading it via the tested routine. assertNotNull(fromDisk) // Checking the values from disk match the initial object. assertTrue { clientKeys.authentication_private_key == fromDisk.authentication_private_key && clientKeys.encryption_private_key == fromDisk.encryption_private_key && clientKeys.signature_private_key == fromDisk.signature_private_key && clientKeys.submitted_ini == fromDisk.submitted_ini && clientKeys.submitted_hia == fromDisk.submitted_hia } } // Testing failure on file not found. @Test fun loadNotFound() { assertNull(loadClientKeys(Path("/tmp/highly-unlikely-to-be-found.json"))) } }libeufin-1.6.8/libeufin-ebics/src/test/resources/0000775000175000017500000000000015236145704022212 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/test/resources/signature1/0000775000175000017500000000000015236145704024274 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebics/src/test/resources/signature1/public_key.txt0000664000175000017500000000061015122266731027156 0ustar grothoffgrothoffMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqpUpetHZYdMjnaG544iSLZ5SnxlV4F/eQsIckG3mvMaXCQsY4rUTfJyle/fTZ0xGbjCUXCsbl1wkz8eB6chaX2LsHYDGiu/xNnU1nddAVB+5kkA5AIGncT9NVhdOgmpnZY/tae9qtZfCPAvbI0sGYQHea0pwyJ/hUnRJiMOjSRgIXALIvGVNqxe4U5ffLXFIUapTK2hOuhUH9BwDSK+mVR6gw0vDT05Z38sEpTeKUqJywL5cPSFIV+AN4ErSvsXNkTKUcbDxhGzOh/oTjTkz1kFFKe4ijPkSRkpK2sJMyAIretBKOK8SDICnsSrIh0YAcd6yTHQ3CeEjW4t0ZBULOQIDAQABlibeufin-1.6.8/libeufin-ebics/src/test/resources/signature1/doc.xml0000664000175000017500000000236115122266731025563 0ustar grothoffgrothoff qiFUoCn9kE0zSidyraO2Br/wn3/XyvWObJZ0aLIBXyA=LupLyRUJIuk0kCRwpFj4fpen2MI7Jw0BI944agwzXHfSDfq0Pp8h3sub6eSsKIAq7ekT3z+mlfMc VFaKRi4B7kv4ja/URiYCKKbChQU2+kMGDvsncx9VcpcFrqAbWPmE9JXD2W2YW9OSkJ1tAZxZlZwS A8KcvluV1wGEBuakHL2t3GqFPQEfKW4l8GYTjHh/w9jBve5d8tvMOjGtoyNemZGrVlzBxO9+hwbw 8UFUCDA00dCjFDUHOnyAbBYsGzoaQyZprDn3iYDvlBz243zAN98PIKDclxlUEmkuF+JhrhCRjT9l +JJxrELGHaDkFVadR4kaPdWPsbDaV0/2Fzc4Qg== Hello World libeufin-1.6.8/libeufin-ebics/build.gradle0000664000175000017500000000251315140725607020712 0ustar grothoffgrothoffplugins { id("kotlin") id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version" } version = rootProject.version java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } compileKotlin.kotlinOptions.jvmTarget = "17" compileTestKotlin.kotlinOptions.jvmTarget = "17" sourceSets.main.java.srcDirs = ["src/main/kotlin"] dependencies { // Core language libraries implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") implementation(project(":libeufin-common")) // Command line parsing implementation("com.github.ajalt.clikt:clikt:$clikt_version") implementation("org.postgresql:postgresql:$postgres_version") // Ktor client library implementation("io.ktor:ktor-client-cio:$ktor_version") implementation("io.ktor:ktor-client-mock:$ktor_version") implementation("io.ktor:ktor-client-websockets:$ktor_version") // PDF generation implementation("com.itextpdf:itext-core:9.5.0") // Serialization implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") // Unit testing implementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version") testImplementation("io.ktor:ktor-server-test-host:$ktor_version") testImplementation("io.ktor:ktor-server-cio:$ktor_version") }libeufin-1.6.8/Makefile0000664000175000017500000001217515122266731015216 0ustar grothoffgrothoff# This Makefile has been placed under the public domain -include build-system/config.mk # Default target, must be at the top. # Should be changed with care to not break (Debian) packaging. all: build git-archive-all = ./build-system/taler-build-scripts/archive-with-submodules/git_archive_all.py git_tag=$(shell git describe --tags) gradle_version=$(shell ./gradlew -q libeufinVersion) define versions_check = if test $(git_tag) != $(gradle_version); \ then echo WARNING: Project version from Gradle: $(gradle_version) differs from current Git tag: $(git_tag); fi endef # Absolute DESTDIR or empty string if DESTDIR unset/empty abs_destdir=$(abspath $(DESTDIR)) share_dir=$(abs_destdir)$(prefix)/share man_dir=$(share_dir)/man bin_dir=$(abs_destdir)$(prefix)/bin lib_dir=$(abs_destdir)$(prefix)/lib # While the gradle command sounds like it's installing something, # it's like a destdir install that only touches the source tree. .PHONY: build build: ./gradlew libeufin-bank:installShadowDist libeufin-nexus:installShadowDist libeufin-ebisync:installShadowDist .PHONY: dist dist: $(call versions_check) mkdir -p build/distributions $(git-archive-all) --include ./configure build/distributions/libeufin-$(gradle_version)-sources.tar.gz .PHONY: deb deb: dpkg-buildpackage -rfakeroot -b -uc -us .PHONY: install-nobuild-files install-nobuild-files: install -m 644 -D -t $(share_dir)/libeufin/config.d contrib/currencies.conf install -m 644 -D -t $(share_dir)/libeufin/config.d contrib/bank.conf install -m 644 -D -t $(share_dir)/libeufin/config.d contrib/nexus.conf install -m 644 -D -t $(share_dir)/libeufin/sql database-versioning/versioning.sql install -m 644 -D -t $(share_dir)/libeufin/sql database-versioning/libeufin-bank*.sql install -m 644 -D -t $(share_dir)/libeufin/sql database-versioning/libeufin-nexus*.sql install -m 644 -D -t $(share_dir)/libeufin/sql database-versioning/libeufin-conversion*.sql install -m 644 -D -t $(share_dir)/libeufin-ebisync/config.d libeufin-ebisync/ebisync.conf install -m 644 -D -t $(share_dir)/libeufin-ebisync/sql database-versioning/versioning.sql install -m 644 -D -t $(share_dir)/libeufin-ebisync/sql database-versioning/libeufin-ebisync*.sql install -D -t $(bin_dir) contrib/libeufin-dbconfig install -D -t $(bin_dir) contrib/libeufin-ebisync-dbconfig install -D -t $(bin_dir) contrib/libeufin-tan-*.sh install -d $(share_dir)/libeufin/spa cp contrib/wallet-core/bank/* $(share_dir)/libeufin/spa/ install -d $(share_dir)/libeufin-ebisync/spa cp libeufin-ebisync/src/spa/* $(share_dir)/libeufin-ebisync/spa/ .PHONY: install install: build install-nobuild-files # Install libeufin-bank install -D -t $(bin_dir) libeufin-bank/build/install/libeufin-bank-shadow/bin/libeufin-bank install -m 644 -D -t $(man_dir)/man1 doc/prebuilt/man/libeufin-bank.1 install -m 644 -D -t $(man_dir)/man5 doc/prebuilt/man/libeufin-bank.conf.5 install -m 644 -D -t $(lib_dir) libeufin-bank/build/install/libeufin-bank-shadow/lib/libeufin-bank-all.jar # Install libeufin-nexus install -D -t $(bin_dir) libeufin-nexus/build/install/libeufin-nexus-shadow/bin/libeufin-nexus install -m 644 -D -t $(man_dir)/man1 doc/prebuilt/man/libeufin-nexus.1 install -m 644 -D -t $(man_dir)/man5 doc/prebuilt/man/libeufin-nexus.conf.5 install -m 644 -D -t $(lib_dir) libeufin-nexus/build/install/libeufin-nexus-shadow/lib/libeufin-nexus-all.jar # Install libeufin-ebisync install -D -t $(bin_dir) libeufin-ebisync/build/install/libeufin-ebisync-shadow/bin/libeufin-ebisync install -m 644 -D -t $(lib_dir) libeufin-ebisync/build/install/libeufin-ebisync-shadow/lib/libeufin-ebisync-all.jar .PHONY: assemble assemble: ./gradlew assemble .PHONY: check check: install-nobuild-files ./gradlew check .PHONY: bank-test bank-test: install-nobuild-files ./gradlew :libeufin-bank:test --tests $(test) -i .PHONY: nexus-test nexus-test: install-nobuild-files ./gradlew :libeufin-nexus:test --tests $(test) -i .PHONY: common-test common-test: install-nobuild-files ./gradlew :libeufin-common:test --tests $(test) -i .PHONY: ebics-test ebics-test: install-nobuild-files ./gradlew :libeufin-ebics:test --tests $(test) -i .PHONY: testbench-test testbench-test: install-nobuild-files ./gradlew :testbench:test --tests $(test) -i .PHONY: ebisync-test ebisync-test: install-nobuild-files ./gradlew :libeufin-ebisync:test --tests $(test) -i .PHONY: nexus-testbench nexus-testbench: install-nobuild-files ./gradlew :testbench:install && \ cd testbench && \ ./build/install/libeufin-testbench-test/bin/libeufin-testbench-test nexus $(platform) .PHONY: ebisync-testbench ebisync-testbench: install-nobuild-files ./gradlew :testbench:install && \ cd testbench && \ ./build/install/libeufin-testbench-test/bin/libeufin-testbench-test ebisync $(platform) .PHONY: doc doc: ./gradlew :dokkaGeneratePublicationHtml echo "Open build/dokka/html/index.html" .PHONY: ci ci: contrib/ci/run-all-jobs.sh .PHONY: bank-bench-db bank-bench-db: install-nobuild-files ./gradlew cleanTest :libeufin-bank:test --tests Bench.benchDb -i --no-build-cache .PHONY: nexus-bench-db nexus-bench-db: install-nobuild-files ./gradlew cleanTest :libeufin-nexus:test --tests Bench.benchDb -i --no-build-cache libeufin-1.6.8/build-system/0000775000175000017500000000000015236145704016173 5ustar grothoffgrothofflibeufin-1.6.8/build-system/taler-build-scripts/0000775000175000017500000000000015236145704022064 5ustar grothoffgrothofflibeufin-1.6.8/build-system/taler-build-scripts/bootstrap.template0000775000175000017500000000056215122323605025634 0ustar grothoffgrothoff#!/bin/sh # Bootstrap the repository. Used when the repository is checked out from git. # When using the source tarball, running this script is not necessary. set -eu if ! git --version >/dev/null; then echo "git not installed" exit 1 fi git submodule sync git submodule update --init rm -f ./configure cp build-system/taler-build-scripts/configure ./configure libeufin-1.6.8/build-system/taler-build-scripts/semver.py0000664000175000017500000013375015122323605023740 0ustar grothoffgrothoff# -*- coding: utf-8 -*- # Copyright (c) The python-semanticversion project # This code is distributed under the two-clause BSD License. import functools import re import warnings def _has_leading_zero(value): return (value and value[0] == '0' and value.isdigit() and value != '0') class MaxIdentifier(object): __slots__ = [] def __repr__(self): return 'MaxIdentifier()' def __eq__(self, other): return isinstance(other, self.__class__) @functools.total_ordering class NumericIdentifier(object): __slots__ = ['value'] def __init__(self, value): self.value = int(value) def __repr__(self): return 'NumericIdentifier(%r)' % self.value def __eq__(self, other): if isinstance(other, NumericIdentifier): return self.value == other.value return NotImplemented def __lt__(self, other): if isinstance(other, MaxIdentifier): return True elif isinstance(other, AlphaIdentifier): return True elif isinstance(other, NumericIdentifier): return self.value < other.value else: return NotImplemented @functools.total_ordering class AlphaIdentifier(object): __slots__ = ['value'] def __init__(self, value): self.value = value.encode('ascii') def __repr__(self): return 'AlphaIdentifier(%r)' % self.value def __eq__(self, other): if isinstance(other, AlphaIdentifier): return self.value == other.value return NotImplemented def __lt__(self, other): if isinstance(other, MaxIdentifier): return True elif isinstance(other, NumericIdentifier): return False elif isinstance(other, AlphaIdentifier): return self.value < other.value else: return NotImplemented class Version(object): version_re = re.compile(r'^(\d+)\.(\d+)\.(\d+)(?:-([0-9a-zA-Z.-]+))?(?:\+([0-9a-zA-Z.-]+))?$') partial_version_re = re.compile(r'^(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:-([0-9a-zA-Z.-]*))?(?:\+([0-9a-zA-Z.-]*))?$') def __init__( self, version_string=None, major=None, minor=None, patch=None, prerelease=None, build=None, partial=False): if partial: warnings.warn( "Partial versions will be removed in 3.0; use SimpleSpec('1.x.x') instead.", DeprecationWarning, stacklevel=2, ) has_text = version_string is not None has_parts = not (major is minor is patch is prerelease is build is None) if not has_text ^ has_parts: raise ValueError("Call either Version('1.2.3') or Version(major=1, ...).") if has_text: major, minor, patch, prerelease, build = self.parse(version_string, partial) else: # Convenience: allow to omit prerelease/build. prerelease = tuple(prerelease or ()) if not partial: build = tuple(build or ()) self._validate_kwargs(major, minor, patch, prerelease, build, partial) self.major = major self.minor = minor self.patch = patch self.prerelease = prerelease self.build = build self.partial = partial @classmethod def _coerce(cls, value, allow_none=False): if value is None and allow_none: return value return int(value) def next_major(self): if self.prerelease and self.minor == self.patch == 0: return Version( major=self.major, minor=0, patch=0, partial=self.partial, ) else: return Version( major=self.major + 1, minor=0, patch=0, partial=self.partial, ) def next_minor(self): if self.prerelease and self.patch == 0: return Version( major=self.major, minor=self.minor, patch=0, partial=self.partial, ) else: return Version( major=self.major, minor=self.minor + 1, patch=0, partial=self.partial, ) def next_patch(self): if self.prerelease: return Version( major=self.major, minor=self.minor, patch=self.patch, partial=self.partial, ) else: return Version( major=self.major, minor=self.minor, patch=self.patch + 1, partial=self.partial, ) def truncate(self, level='patch'): """Return a new Version object, truncated up to the selected level.""" if level == 'build': return self elif level == 'prerelease': return Version( major=self.major, minor=self.minor, patch=self.patch, prerelease=self.prerelease, partial=self.partial, ) elif level == 'patch': return Version( major=self.major, minor=self.minor, patch=self.patch, partial=self.partial, ) elif level == 'minor': return Version( major=self.major, minor=self.minor, patch=None if self.partial else 0, partial=self.partial, ) elif level == 'major': return Version( major=self.major, minor=None if self.partial else 0, patch=None if self.partial else 0, partial=self.partial, ) else: raise ValueError("Invalid truncation level `%s`." % level) @classmethod def coerce(cls, version_string, partial=False): """Coerce an arbitrary version string into a semver-compatible one. The rule is: - If not enough components, fill minor/patch with zeroes; unless partial=True - If more than 3 dot-separated components, extra components are "build" data. If some "build" data already appeared, append it to the extra components Examples: >>> Version.coerce('0.1') Version(0, 1, 0) >>> Version.coerce('0.1.2.3') Version(0, 1, 2, (), ('3',)) >>> Version.coerce('0.1.2.3+4') Version(0, 1, 2, (), ('3', '4')) >>> Version.coerce('0.1+2-3+4_5') Version(0, 1, 0, (), ('2-3', '4-5')) """ base_re = re.compile(r'^\d+(?:\.\d+(?:\.\d+)?)?') match = base_re.match(version_string) if not match: raise ValueError( "Version string lacks a numerical component: %r" % version_string ) version = version_string[:match.end()] if not partial: # We need a not-partial version. while version.count('.') < 2: version += '.0' # Strip leading zeros in components # Version is of the form nn, nn.pp or nn.pp.qq version = '.'.join( # If the part was '0', we end up with an empty string. part.lstrip('0') or '0' for part in version.split('.') ) if match.end() == len(version_string): return Version(version, partial=partial) rest = version_string[match.end():] # Cleanup the 'rest' rest = re.sub(r'[^a-zA-Z0-9+.-]', '-', rest) if rest[0] == '+': # A 'build' component prerelease = '' build = rest[1:] elif rest[0] == '.': # An extra version component, probably 'build' prerelease = '' build = rest[1:] elif rest[0] == '-': rest = rest[1:] if '+' in rest: prerelease, build = rest.split('+', 1) else: prerelease, build = rest, '' elif '+' in rest: prerelease, build = rest.split('+', 1) else: prerelease, build = rest, '' build = build.replace('+', '.') if prerelease: version = '%s-%s' % (version, prerelease) if build: version = '%s+%s' % (version, build) return cls(version, partial=partial) @classmethod def parse(cls, version_string, partial=False, coerce=False): """Parse a version string into a Version() object. Args: version_string (str), the version string to parse partial (bool), whether to accept incomplete input coerce (bool), whether to try to map the passed in string into a valid Version. """ if not version_string: raise ValueError('Invalid empty version string: %r' % version_string) if partial: version_re = cls.partial_version_re else: version_re = cls.version_re match = version_re.match(version_string) if not match: raise ValueError('Invalid version string: %r' % version_string) major, minor, patch, prerelease, build = match.groups() if _has_leading_zero(major): raise ValueError("Invalid leading zero in major: %r" % version_string) if _has_leading_zero(minor): raise ValueError("Invalid leading zero in minor: %r" % version_string) if _has_leading_zero(patch): raise ValueError("Invalid leading zero in patch: %r" % version_string) major = int(major) minor = cls._coerce(minor, partial) patch = cls._coerce(patch, partial) if prerelease is None: if partial and (build is None): # No build info, strip here return (major, minor, patch, None, None) else: prerelease = () elif prerelease == '': prerelease = () else: prerelease = tuple(prerelease.split('.')) cls._validate_identifiers(prerelease, allow_leading_zeroes=False) if build is None: if partial: build = None else: build = () elif build == '': build = () else: build = tuple(build.split('.')) cls._validate_identifiers(build, allow_leading_zeroes=True) return (major, minor, patch, prerelease, build) @classmethod def _validate_identifiers(cls, identifiers, allow_leading_zeroes=False): for item in identifiers: if not item: raise ValueError( "Invalid empty identifier %r in %r" % (item, '.'.join(identifiers)) ) if item[0] == '0' and item.isdigit() and item != '0' and not allow_leading_zeroes: raise ValueError("Invalid leading zero in identifier %r" % item) @classmethod def _validate_kwargs(cls, major, minor, patch, prerelease, build, partial): if ( major != int(major) or minor != cls._coerce(minor, partial) or patch != cls._coerce(patch, partial) or prerelease is None and not partial or build is None and not partial ): raise ValueError( "Invalid kwargs to Version(major=%r, minor=%r, patch=%r, " "prerelease=%r, build=%r, partial=%r" % ( major, minor, patch, prerelease, build, partial )) if prerelease is not None: cls._validate_identifiers(prerelease, allow_leading_zeroes=False) if build is not None: cls._validate_identifiers(build, allow_leading_zeroes=True) def __iter__(self): return iter((self.major, self.minor, self.patch, self.prerelease, self.build)) def __str__(self): version = '%d' % self.major if self.minor is not None: version = '%s.%d' % (version, self.minor) if self.patch is not None: version = '%s.%d' % (version, self.patch) if self.prerelease or (self.partial and self.prerelease == () and self.build is None): version = '%s-%s' % (version, '.'.join(self.prerelease)) if self.build or (self.partial and self.build == ()): version = '%s+%s' % (version, '.'.join(self.build)) return version def __repr__(self): return '%s(%r%s)' % ( self.__class__.__name__, str(self), ', partial=True' if self.partial else '', ) def __hash__(self): # We don't include 'partial', since this is strictly equivalent to having # at least a field being `None`. return hash((self.major, self.minor, self.patch, self.prerelease, self.build)) @property def precedence_key(self): if self.prerelease: prerelease_key = tuple( NumericIdentifier(part) if re.match(r'^[0-9]+$', part) else AlphaIdentifier(part) for part in self.prerelease ) else: prerelease_key = ( MaxIdentifier(), ) return ( self.major, self.minor, self.patch, prerelease_key, ) def __cmp__(self, other): if not isinstance(other, self.__class__): return NotImplemented if self < other: return -1 elif self > other: return 1 elif self == other: return 0 else: return NotImplemented def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented return ( self.major == other.major and self.minor == other.minor and self.patch == other.patch and (self.prerelease or ()) == (other.prerelease or ()) and (self.build or ()) == (other.build or ()) ) def __ne__(self, other): if not isinstance(other, self.__class__): return NotImplemented return tuple(self) != tuple(other) def __lt__(self, other): if not isinstance(other, self.__class__): return NotImplemented return self.precedence_key < other.precedence_key def __le__(self, other): if not isinstance(other, self.__class__): return NotImplemented return self.precedence_key <= other.precedence_key def __gt__(self, other): if not isinstance(other, self.__class__): return NotImplemented return self.precedence_key > other.precedence_key def __ge__(self, other): if not isinstance(other, self.__class__): return NotImplemented return self.precedence_key >= other.precedence_key class SpecItem(object): """A requirement specification.""" KIND_ANY = '*' KIND_LT = '<' KIND_LTE = '<=' KIND_EQUAL = '==' KIND_SHORTEQ = '=' KIND_EMPTY = '' KIND_GTE = '>=' KIND_GT = '>' KIND_NEQ = '!=' KIND_CARET = '^' KIND_TILDE = '~' KIND_COMPATIBLE = '~=' # Map a kind alias to its full version KIND_ALIASES = { KIND_SHORTEQ: KIND_EQUAL, KIND_EMPTY: KIND_EQUAL, } re_spec = re.compile(r'^(<|<=||=|==|>=|>|!=|\^|~|~=)(\d.*)$') def __init__(self, requirement_string, _warn=True): if _warn: warnings.warn( "The `SpecItem` class will be removed in 3.0.", DeprecationWarning, stacklevel=2, ) kind, spec = self.parse(requirement_string) self.kind = kind self.spec = spec self._clause = Spec(requirement_string).clause @classmethod def parse(cls, requirement_string): if not requirement_string: raise ValueError("Invalid empty requirement specification: %r" % requirement_string) # Special case: the 'any' version spec. if requirement_string == '*': return (cls.KIND_ANY, '') match = cls.re_spec.match(requirement_string) if not match: raise ValueError("Invalid requirement specification: %r" % requirement_string) kind, version = match.groups() if kind in cls.KIND_ALIASES: kind = cls.KIND_ALIASES[kind] spec = Version(version, partial=True) if spec.build is not None and kind not in (cls.KIND_EQUAL, cls.KIND_NEQ): raise ValueError( "Invalid requirement specification %r: build numbers have no ordering." % requirement_string ) return (kind, spec) @classmethod def from_matcher(cls, matcher): if matcher == Always(): return cls('*', _warn=False) elif matcher == Never(): return cls('<0.0.0-', _warn=False) elif isinstance(matcher, Range): return cls('%s%s' % (matcher.operator, matcher.target), _warn=False) def match(self, version): return self._clause.match(version) def __str__(self): return '%s%s' % (self.kind, self.spec) def __repr__(self): return '' % (self.kind, self.spec) def __eq__(self, other): if not isinstance(other, SpecItem): return NotImplemented return self.kind == other.kind and self.spec == other.spec def __hash__(self): return hash((self.kind, self.spec)) def compare(v1, v2): return Version(v1).__cmp__(Version(v2)) def match(spec, version): return Spec(spec).match(Version(version)) def validate(version_string): """Validates a version string against the SemVer specification.""" try: Version.parse(version_string) return True except ValueError: return False DEFAULT_SYNTAX = 'simple' class BaseSpec(object): """A specification of compatible versions. Usage: >>> Spec('>=1.0.0', syntax='npm') A version matches a specification if it matches any of the clauses of that specification. Internally, a Spec is AnyOf( AllOf(Matcher, Matcher, Matcher), AllOf(...), ) """ SYNTAXES = {} @classmethod def register_syntax(cls, subclass): syntax = subclass.SYNTAX if syntax is None: raise ValueError("A Spec needs its SYNTAX field to be set.") elif syntax in cls.SYNTAXES: raise ValueError( "Duplicate syntax for %s: %r, %r" % (syntax, cls.SYNTAXES[syntax], subclass) ) cls.SYNTAXES[syntax] = subclass return subclass def __init__(self, expression): super(BaseSpec, self).__init__() self.expression = expression self.clause = self._parse_to_clause(expression) @classmethod def parse(cls, expression, syntax=DEFAULT_SYNTAX): """Convert a syntax-specific expression into a BaseSpec instance.""" return cls.SYNTAXES[syntax](expression) @classmethod def _parse_to_clause(cls, expression): """Converts an expression to a clause.""" raise NotImplementedError() def filter(self, versions): """Filter an iterable of versions satisfying the Spec.""" for version in versions: if self.match(version): yield version def match(self, version): """Check whether a Version satisfies the Spec.""" return self.clause.match(version) def select(self, versions): """Select the best compatible version among an iterable of options.""" options = list(self.filter(versions)) if options: return max(options) return None def __contains__(self, version): """Whether `version in self`.""" if isinstance(version, Version): return self.match(version) return False def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented return self.clause == other.clause def __hash__(self): return hash(self.clause) def __str__(self): return self.expression def __repr__(self): return '<%s: %r>' % (self.__class__.__name__, self.expression) class Clause(object): __slots__ = [] def match(self, version): raise NotImplementedError() def __and__(self, other): raise NotImplementedError() def __or__(self, other): raise NotImplementedError() def __eq__(self, other): raise NotImplementedError() def prettyprint(self, indent='\t'): """Pretty-print the clause. """ return '\n'.join(self._pretty()).replace('\t', indent) def _pretty(self): """Actual pretty-printing logic. Yields: A list of string. Indentation is performed with \t. """ yield repr(self) def __ne__(self, other): return not self == other def simplify(self): return self class AnyOf(Clause): __slots__ = ['clauses'] def __init__(self, *clauses): super(AnyOf, self).__init__() self.clauses = frozenset(clauses) def match(self, version): return any(c.match(version) for c in self.clauses) def simplify(self): subclauses = set() for clause in self.clauses: simplified = clause.simplify() if isinstance(simplified, AnyOf): subclauses |= simplified.clauses elif simplified == Never(): continue else: subclauses.add(simplified) if len(subclauses) == 1: return subclauses.pop() return AnyOf(*subclauses) def __hash__(self): return hash((AnyOf, self.clauses)) def __iter__(self): return iter(self.clauses) def __eq__(self, other): return isinstance(other, self.__class__) and self.clauses == other.clauses def __and__(self, other): if isinstance(other, AllOf): return other & self elif isinstance(other, Matcher) or isinstance(other, AnyOf): return AllOf(self, other) else: return NotImplemented def __or__(self, other): if isinstance(other, AnyOf): clauses = list(self.clauses | other.clauses) elif isinstance(other, Matcher) or isinstance(other, AllOf): clauses = list(self.clauses | set([other])) else: return NotImplemented return AnyOf(*clauses) def __repr__(self): return 'AnyOf(%s)' % ', '.join(sorted(repr(c) for c in self.clauses)) def _pretty(self): yield 'AnyOF(' for clause in self.clauses: lines = list(clause._pretty()) for line in lines[:-1]: yield '\t' + line yield '\t' + lines[-1] + ',' yield ')' class AllOf(Clause): __slots__ = ['clauses'] def __init__(self, *clauses): super(AllOf, self).__init__() self.clauses = frozenset(clauses) def match(self, version): return all(clause.match(version) for clause in self.clauses) def simplify(self): subclauses = set() for clause in self.clauses: simplified = clause.simplify() if isinstance(simplified, AllOf): subclauses |= simplified.clauses elif simplified == Always(): continue else: subclauses.add(simplified) if len(subclauses) == 1: return subclauses.pop() return AllOf(*subclauses) def __hash__(self): return hash((AllOf, self.clauses)) def __iter__(self): return iter(self.clauses) def __eq__(self, other): return isinstance(other, self.__class__) and self.clauses == other.clauses def __and__(self, other): if isinstance(other, Matcher) or isinstance(other, AnyOf): clauses = list(self.clauses | set([other])) elif isinstance(other, AllOf): clauses = list(self.clauses | other.clauses) else: return NotImplemented return AllOf(*clauses) def __or__(self, other): if isinstance(other, AnyOf): return other | self elif isinstance(other, Matcher): return AnyOf(self, AllOf(other)) elif isinstance(other, AllOf): return AnyOf(self, other) else: return NotImplemented def __repr__(self): return 'AllOf(%s)' % ', '.join(sorted(repr(c) for c in self.clauses)) def _pretty(self): yield 'AllOF(' for clause in self.clauses: lines = list(clause._pretty()) for line in lines[:-1]: yield '\t' + line yield '\t' + lines[-1] + ',' yield ')' class Matcher(Clause): __slots__ = [] def __and__(self, other): if isinstance(other, AllOf): return other & self elif isinstance(other, Matcher) or isinstance(other, AnyOf): return AllOf(self, other) else: return NotImplemented def __or__(self, other): if isinstance(other, AnyOf): return other | self elif isinstance(other, Matcher) or isinstance(other, AllOf): return AnyOf(self, other) else: return NotImplemented class Never(Matcher): __slots__ = [] def match(self, version): return False def __hash__(self): return hash((Never,)) def __eq__(self, other): return isinstance(other, self.__class__) def __and__(self, other): return self def __or__(self, other): return other def __repr__(self): return 'Never()' class Always(Matcher): __slots__ = [] def match(self, version): return True def __hash__(self): return hash((Always,)) def __eq__(self, other): return isinstance(other, self.__class__) def __and__(self, other): return other def __or__(self, other): return self def __repr__(self): return 'Always()' class Range(Matcher): OP_EQ = '==' OP_GT = '>' OP_GTE = '>=' OP_LT = '<' OP_LTE = '<=' OP_NEQ = '!=' # <1.2.3 matches 1.2.3-a1 PRERELEASE_ALWAYS = 'always' # <1.2.3 does not match 1.2.3-a1 PRERELEASE_NATURAL = 'natural' # 1.2.3-a1 is only considered if target == 1.2.3-xxx PRERELEASE_SAMEPATCH = 'same-patch' # 1.2.3 matches 1.2.3+* BUILD_IMPLICIT = 'implicit' # 1.2.3 matches only 1.2.3, not 1.2.3+4 BUILD_STRICT = 'strict' __slots__ = ['operator', 'target', 'prerelease_policy', 'build_policy'] def __init__(self, operator, target, prerelease_policy=PRERELEASE_NATURAL, build_policy=BUILD_IMPLICIT): super(Range, self).__init__() if target.build and operator not in (self.OP_EQ, self.OP_NEQ): raise ValueError( "Invalid range %s%s: build numbers have no ordering." % (operator, target)) self.operator = operator self.target = target self.prerelease_policy = prerelease_policy self.build_policy = self.BUILD_STRICT if target.build else build_policy def match(self, version): if self.build_policy != self.BUILD_STRICT: version = version.truncate('prerelease') if version.prerelease: same_patch = self.target.truncate() == version.truncate() if self.prerelease_policy == self.PRERELEASE_SAMEPATCH and not same_patch: return False if self.operator == self.OP_EQ: if self.build_policy == self.BUILD_STRICT: return ( self.target.truncate('prerelease') == version.truncate('prerelease') and version.build == self.target.build ) return version == self.target elif self.operator == self.OP_GT: return version > self.target elif self.operator == self.OP_GTE: return version >= self.target elif self.operator == self.OP_LT: if ( version.prerelease and self.prerelease_policy == self.PRERELEASE_NATURAL and version.truncate() == self.target.truncate() and not self.target.prerelease ): return False return version < self.target elif self.operator == self.OP_LTE: return version <= self.target else: assert self.operator == self.OP_NEQ if self.build_policy == self.BUILD_STRICT: return not ( self.target.truncate('prerelease') == version.truncate('prerelease') and version.build == self.target.build ) if ( version.prerelease and self.prerelease_policy == self.PRERELEASE_NATURAL and version.truncate() == self.target.truncate() and not self.target.prerelease ): return False return version != self.target def __hash__(self): return hash((Range, self.operator, self.target, self.prerelease_policy)) def __eq__(self, other): return ( isinstance(other, self.__class__) and self.operator == other.operator and self.target == other.target and self.prerelease_policy == other.prerelease_policy ) def __str__(self): return '%s%s' % (self.operator, self.target) def __repr__(self): policy_part = ( '' if self.prerelease_policy == self.PRERELEASE_NATURAL else ', prerelease_policy=%r' % self.prerelease_policy ) + ( '' if self.build_policy == self.BUILD_IMPLICIT else ', build_policy=%r' % self.build_policy ) return 'Range(%r, %r%s)' % ( self.operator, self.target, policy_part, ) @BaseSpec.register_syntax class SimpleSpec(BaseSpec): SYNTAX = 'simple' @classmethod def _parse_to_clause(cls, expression): return cls.Parser.parse(expression) class Parser: NUMBER = r'\*|0|[1-9][0-9]*' NAIVE_SPEC = re.compile(r"""^ (?P<|<=||=|==|>=|>|!=|\^|~|~=) (?P{nb})(?:\.(?P{nb})(?:\.(?P{nb}))?)? (?:-(?P[a-z0-9A-Z.-]*))? (?:\+(?P[a-z0-9A-Z.-]*))? $ """.format(nb=NUMBER), re.VERBOSE, ) @classmethod def parse(cls, expression): blocks = expression.split(',') clause = Always() for block in blocks: if not cls.NAIVE_SPEC.match(block): raise ValueError("Invalid simple block %r" % block) clause &= cls.parse_block(block) return clause PREFIX_CARET = '^' PREFIX_TILDE = '~' PREFIX_COMPATIBLE = '~=' PREFIX_EQ = '==' PREFIX_NEQ = '!=' PREFIX_GT = '>' PREFIX_GTE = '>=' PREFIX_LT = '<' PREFIX_LTE = '<=' PREFIX_ALIASES = { '=': PREFIX_EQ, '': PREFIX_EQ, } EMPTY_VALUES = ['*', 'x', 'X', None] @classmethod def parse_block(cls, expr): if not cls.NAIVE_SPEC.match(expr): raise ValueError("Invalid simple spec component: %r" % expr) prefix, major_t, minor_t, patch_t, prerel, build = cls.NAIVE_SPEC.match(expr).groups() prefix = cls.PREFIX_ALIASES.get(prefix, prefix) major = None if major_t in cls.EMPTY_VALUES else int(major_t) minor = None if minor_t in cls.EMPTY_VALUES else int(minor_t) patch = None if patch_t in cls.EMPTY_VALUES else int(patch_t) if major is None: # '*' target = Version(major=0, minor=0, patch=0) if prefix not in (cls.PREFIX_EQ, cls.PREFIX_GTE): raise ValueError("Invalid simple spec: %r" % expr) elif minor is None: target = Version(major=major, minor=0, patch=0) elif patch is None: target = Version(major=major, minor=minor, patch=0) else: target = Version( major=major, minor=minor, patch=patch, prerelease=prerel.split('.') if prerel else (), build=build.split('.') if build else (), ) if (major is None or minor is None or patch is None) and (prerel or build): raise ValueError("Invalid simple spec: %r" % expr) if build is not None and prefix not in (cls.PREFIX_EQ, cls.PREFIX_NEQ): raise ValueError("Invalid simple spec: %r" % expr) if prefix == cls.PREFIX_CARET: # Accept anything with the same most-significant digit if target.major: high = target.next_major() elif target.minor: high = target.next_minor() else: high = target.next_patch() return Range(Range.OP_GTE, target) & Range(Range.OP_LT, high) elif prefix == cls.PREFIX_TILDE: assert major is not None # Accept any higher patch in the same minor # Might go higher if the initial version was a partial if minor is None: high = target.next_major() else: high = target.next_minor() return Range(Range.OP_GTE, target) & Range(Range.OP_LT, high) elif prefix == cls.PREFIX_COMPATIBLE: assert major is not None # ~1 is 1.0.0..2.0.0; ~=2.2 is 2.2.0..3.0.0; ~=1.4.5 is 1.4.5..1.5.0 if minor is None or patch is None: # We got a partial version high = target.next_major() else: high = target.next_minor() return Range(Range.OP_GTE, target) & Range(Range.OP_LT, high) elif prefix == cls.PREFIX_EQ: if major is None: return Range(Range.OP_GTE, target) elif minor is None: return Range(Range.OP_GTE, target) & Range(Range.OP_LT, target.next_major()) elif patch is None: return Range(Range.OP_GTE, target) & Range(Range.OP_LT, target.next_patch()) elif build == '': return Range(Range.OP_EQ, target, build_policy=Range.BUILD_STRICT) else: return Range(Range.OP_EQ, target) elif prefix == cls.PREFIX_NEQ: assert major is not None if minor is None: # !=1.x => <1.0.0 || >=2.0.0 return Range(Range.OP_LT, target) | Range(Range.OP_GTE, target.next_major()) elif patch is None: # !=1.2.x => <1.2.0 || >=1.3.0 return Range(Range.OP_LT, target) | Range(Range.OP_GTE, target.next_minor()) elif prerel == '': # !=1.2.3- return Range(Range.OP_NEQ, target, prerelease_policy=Range.PRERELEASE_ALWAYS) elif build == '': # !=1.2.3+ or !=1.2.3-a2+ return Range(Range.OP_NEQ, target, build_policy=Range.BUILD_STRICT) else: return Range(Range.OP_NEQ, target) elif prefix == cls.PREFIX_GT: assert major is not None if minor is None: # >1.x => >=2.0 return Range(Range.OP_GTE, target.next_major()) elif patch is None: return Range(Range.OP_GTE, target.next_minor()) else: return Range(Range.OP_GT, target) elif prefix == cls.PREFIX_GTE: return Range(Range.OP_GTE, target) elif prefix == cls.PREFIX_LT: assert major is not None if prerel == '': # <1.2.3- return Range(Range.OP_LT, target, prerelease_policy=Range.PRERELEASE_ALWAYS) return Range(Range.OP_LT, target) else: assert prefix == cls.PREFIX_LTE assert major is not None if minor is None: # <=1.x => <2.0 return Range(Range.OP_LT, target.next_major()) elif patch is None: return Range(Range.OP_LT, target.next_minor()) else: return Range(Range.OP_LTE, target) class LegacySpec(SimpleSpec): def __init__(self, *expressions): warnings.warn( "The Spec() class will be removed in 3.1; use SimpleSpec() instead.", PendingDeprecationWarning, stacklevel=2, ) if len(expressions) > 1: warnings.warn( "Passing 2+ arguments to SimpleSpec will be removed in 3.0; concatenate them with ',' instead.", DeprecationWarning, stacklevel=2, ) expression = ','.join(expressions) super(LegacySpec, self).__init__(expression) @property def specs(self): return list(self) def __iter__(self): warnings.warn( "Iterating over the components of a SimpleSpec object will be removed in 3.0.", DeprecationWarning, stacklevel=2, ) try: clauses = list(self.clause) except TypeError: # Not an iterable clauses = [self.clause] for clause in clauses: yield SpecItem.from_matcher(clause) Spec = LegacySpec @BaseSpec.register_syntax class NpmSpec(BaseSpec): SYNTAX = 'npm' @classmethod def _parse_to_clause(cls, expression): return cls.Parser.parse(expression) class Parser: JOINER = '||' HYPHEN = ' - ' NUMBER = r'x|X|\*|0|[1-9][0-9]*' PART = r'[a-zA-Z0-9.-]*' NPM_SPEC_BLOCK = re.compile(r""" ^(?:v)? # Strip optional initial v (?P<|<=|>=|>|=|\^|~|) # Operator, can be empty (?P{nb})(?:\.(?P{nb})(?:\.(?P{nb}))?)? (?:-(?P{part}))? # Optional re-release (?:\+(?P{part}))? # Optional build $""".format(nb=NUMBER, part=PART), re.VERBOSE, ) @classmethod def range(cls, operator, target): return Range(operator, target, prerelease_policy=Range.PRERELEASE_SAMEPATCH) @classmethod def parse(cls, expression): result = Never() groups = expression.split(cls.JOINER) for group in groups: group = group.strip() if not group: group = '>=0.0.0' subclauses = [] if cls.HYPHEN in group: low, high = group.split(cls.HYPHEN, 2) subclauses = cls.parse_simple('>=' + low) + cls.parse_simple('<=' + high) else: blocks = group.split(' ') for block in blocks: if not cls.NPM_SPEC_BLOCK.match(block): raise ValueError("Invalid NPM block in %r: %r" % (expression, block)) subclauses.extend(cls.parse_simple(block)) prerelease_clauses = [] non_prerel_clauses = [] for clause in subclauses: if clause.target.prerelease: if clause.operator in (Range.OP_GT, Range.OP_GTE): prerelease_clauses.append(Range( operator=Range.OP_LT, target=Version( major=clause.target.major, minor=clause.target.minor, patch=clause.target.patch + 1, ), prerelease_policy=Range.PRERELEASE_ALWAYS, )) elif clause.operator in (Range.OP_LT, Range.OP_LTE): prerelease_clauses.append(Range( operator=Range.OP_GTE, target=Version( major=clause.target.major, minor=clause.target.minor, patch=0, prerelease=(), ), prerelease_policy=Range.PRERELEASE_ALWAYS, )) prerelease_clauses.append(clause) non_prerel_clauses.append(cls.range( operator=clause.operator, target=clause.target.truncate(), )) else: non_prerel_clauses.append(clause) if prerelease_clauses: result |= AllOf(*prerelease_clauses) result |= AllOf(*non_prerel_clauses) return result PREFIX_CARET = '^' PREFIX_TILDE = '~' PREFIX_EQ = '=' PREFIX_GT = '>' PREFIX_GTE = '>=' PREFIX_LT = '<' PREFIX_LTE = '<=' PREFIX_ALIASES = { '': PREFIX_EQ, } PREFIX_TO_OPERATOR = { PREFIX_EQ: Range.OP_EQ, PREFIX_LT: Range.OP_LT, PREFIX_LTE: Range.OP_LTE, PREFIX_GTE: Range.OP_GTE, PREFIX_GT: Range.OP_GT, } EMPTY_VALUES = ['*', 'x', 'X', None] @classmethod def parse_simple(cls, simple): match = cls.NPM_SPEC_BLOCK.match(simple) prefix, major_t, minor_t, patch_t, prerel, build = match.groups() prefix = cls.PREFIX_ALIASES.get(prefix, prefix) major = None if major_t in cls.EMPTY_VALUES else int(major_t) minor = None if minor_t in cls.EMPTY_VALUES else int(minor_t) patch = None if patch_t in cls.EMPTY_VALUES else int(patch_t) if build is not None and prefix not in [cls.PREFIX_EQ]: # Ignore the 'build' part when not comparing to a specific part. build = None if major is None: # '*', 'x', 'X' target = Version(major=0, minor=0, patch=0) if prefix not in [cls.PREFIX_EQ, cls.PREFIX_GTE]: raise ValueError("Invalid expression %r" % simple) prefix = cls.PREFIX_GTE elif minor is None: target = Version(major=major, minor=0, patch=0) elif patch is None: target = Version(major=major, minor=minor, patch=0) else: target = Version( major=major, minor=minor, patch=patch, prerelease=prerel.split('.') if prerel else (), build=build.split('.') if build else (), ) if (major is None or minor is None or patch is None) and (prerel or build): raise ValueError("Invalid NPM spec: %r" % simple) if prefix == cls.PREFIX_CARET: if target.major: # ^1.2.4 => >=1.2.4 <2.0.0 ; ^1.x => >=1.0.0 <2.0.0 high = target.truncate().next_major() elif target.minor: # ^0.1.2 => >=0.1.2 <0.2.0 high = target.truncate().next_minor() elif minor is None: # ^0.x => >=0.0.0 <1.0.0 high = target.truncate().next_major() elif patch is None: # ^0.2.x => >=0.2.0 <0.3.0 high = target.truncate().next_minor() else: # ^0.0.1 => >=0.0.1 <0.0.2 high = target.truncate().next_patch() return [cls.range(Range.OP_GTE, target), cls.range(Range.OP_LT, high)] elif prefix == cls.PREFIX_TILDE: assert major is not None if minor is None: # ~1.x => >=1.0.0 <2.0.0 high = target.next_major() else: # ~1.2.x => >=1.2.0 <1.3.0; ~1.2.3 => >=1.2.3 <1.3.0 high = target.next_minor() return [cls.range(Range.OP_GTE, target), cls.range(Range.OP_LT, high)] elif prefix == cls.PREFIX_EQ: if major is None: return [cls.range(Range.OP_GTE, target)] elif minor is None: return [cls.range(Range.OP_GTE, target), cls.range(Range.OP_LT, target.next_major())] elif patch is None: return [cls.range(Range.OP_GTE, target), cls.range(Range.OP_LT, target.next_minor())] else: return [cls.range(Range.OP_EQ, target)] elif prefix == cls.PREFIX_GT: assert major is not None if minor is None: # >1.x return [cls.range(Range.OP_GTE, target.next_major())] elif patch is None: # >1.2.x => >=1.3.0 return [cls.range(Range.OP_GTE, target.next_minor())] else: return [cls.range(Range.OP_GT, target)] elif prefix == cls.PREFIX_GTE: return [cls.range(Range.OP_GTE, target)] elif prefix == cls.PREFIX_LT: assert major is not None return [cls.range(Range.OP_LT, target)] else: assert prefix == cls.PREFIX_LTE assert major is not None if minor is None: # <=1.x => <2.0.0 return [cls.range(Range.OP_LT, target.next_major())] elif patch is None: # <=1.2.x => <1.3.0 return [cls.range(Range.OP_LT, target.next_minor())] else: return [cls.range(Range.OP_LTE, target)] libeufin-1.6.8/build-system/taler-build-scripts/LICENSE0000664000175000017500000000120015122323605023052 0ustar grothoffgrothoffCopyright (C) 2019 by GNUnet eV Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. libeufin-1.6.8/build-system/taler-build-scripts/configure.py.template0000664000175000017500000000155315122323605026225 0ustar grothoffgrothoff# This configure.py file is places in the public domain. # Configure the build directory. # This file is invoked by './configure' and should usually not be invoked # manually. import talerbuildconfig as tbc import sys import shutil if getattr(tbc, "serialversion", 0) < 2: print("talerbuildconfig outdated, please update the build-common submodule and/or bootstrap") sys.exit(1) b = tbc.BuildConfig() # Enable the --prefix option b.enable_prefix() # Enable generation of the "config.mk" include file for the main "Makefile" b.enable_configmk() # Declare dependencies b.add_tool(tbc.PosixTool("find")) b.add_tool(tbc.NodeJsTool(version_spec=">=12")) b.add_tool(tbc.GenericTool("npm")) b.add_tool(tbc.GenericTool("pnpm", hint="Use 'sudo npm install -g pnpm' to install.")) b.run() print("copying Makefile") shutil.copyfile("build-system/Makefile", "Makefile") libeufin-1.6.8/build-system/taler-build-scripts/pyvercheck.py0000664000175000017500000000054115122323605024571 0ustar grothoffgrothoff# This file is placed in the public domain. # Detect the Python version in a portable way. # import sys sys.stderr.write("info: running with python " + str(sys.version_info) + "\n") if sys.version_info.major < 3 or sys.version_info.minor < 7: sys.stderr.write("error: python>=3.7 must be available as the python3 executable\n") sys.exit(1) libeufin-1.6.8/build-system/taler-build-scripts/.gitignore0000664000175000017500000000002615122323605024042 0ustar grothoffgrothoffconfig.mk __pycache__ libeufin-1.6.8/build-system/taler-build-scripts/testconfigure.py0000664000175000017500000000070515122323605025311 0ustar grothoffgrothofffrom talerbuildconfig import * b = BuildConfig() b.enable_prefix() b.enable_configmk() b.add_tool(YarnTool()) b.add_tool(BrowserTool()) b.add_tool(PyBabelTool()) b.add_tool(NodeJsTool(version_spec=">=12.0.0")) b.add_tool(PythonTool()) b.add_tool(PosixTool("find")) b.add_tool(PosixTool("xargs")) b.add_tool(PosixTool("msgmerge")) b.use(Option("foo", help="What is foo?")) b.use(Option("bar", help="What is bar?", required=False, default="42")) b.run() libeufin-1.6.8/build-system/taler-build-scripts/talerbuildconfig.py0000664000175000017500000004363715122323605025760 0ustar grothoffgrothoff# This file is part of TALER # (C) 2019 GNUnet e.V. # # Authors: # Author: ng0 # Author: Florian Dold # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE # LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF # THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD import sys if not (sys.version_info.major == 3 and sys.version_info.minor >= 7): print("This script requires Python 3.7 or higher!") print("You are using Python {}.{}.".format(sys.version_info.major, sys.version_info.minor)) sys.exit(1) from abc import ABC import argparse import os import sys import shlex import shutil import logging import subprocess from dataclasses import dataclass import semver from pathlib import Path """ This module aims to replicate a small GNU Coding Standards configure script, tailored at projects in GNU Taler. We hope it can be of use outside of GNU Taler, hence it is dedicated to the public domain ('0BSD'). It takes a couple of arguments on the commandline equivalent to configure by autotools, in addition some environment variables xan take precedence over the switches. In the absence of switches, /usr/local is assumed as the PREFIX. When all data from tests are gathered, it generates a config.mk Makefile fragment, which is the processed by a Makefile (usually) in GNU Make format. """ # Should be incremented each time we add some functionality serialversion = 2 # TODO: We need a smallest version argument. class Tool(ABC): def args(self, parser): ... def check(self, buildconfig): ... class Plugin(ABC): def args(self, parser): ... class BuildConfig: def __init__(self): # Pairs of (key, value) for config.mk variables self.make_variables = [] self.tools = [] self.tool_results = {} self.plugins = [] self.args = None self.prefix_enabled = False self.configmk_enabled = False self.configmk_dotfile = False def add_tool(self, tool): """Deprecated. Prefer the 'use' method.""" if isinstance(tool, Tool): self.tools.append(tool) else: raise Exception("Not a 'Tool' instance: " + repr(tool)) def use(self, plugin): if isinstance(plugin, Plugin): self.plugins.append(plugin) elif isinstance(plugin, Tool): self.tools.append(plugin) else: raise Exception("Not a 'Plugin' or 'Tool' instance: " + repr(plugin)) def _set_tool(self, name, value, version=None): self.tool_results[name] = (value, version) def enable_prefix(self): """If enabled, process the --prefix argument.""" self.prefix_enabled = True def _warn(self, msg): print("Warning", msg) def _error(self, msg): print("Error", msg) def enable_configmk(self, dotfile=False): """If enabled, output the config.mk makefile fragment.""" self.configmk_enabled = True self.configmk_dotfile = dotfile def run(self): parser = argparse.ArgumentParser() if self.prefix_enabled: parser.add_argument( "--prefix", type=str, default="/usr/local", help="Directory prefix for installation", ) for tool in self.tools: tool.args(parser) for plugin in self.plugins: plugin.args(parser) args = self.args = parser.parse_args() for plugin in self.plugins: res = plugin.run(self) for tool in self.tools: res = tool.check(self) if not res: print(f"Error: tool '{tool.name}' not available") if hasattr(tool, "hint"): print(f"Hint: {tool.hint}") sys.exit(1) if hasattr(tool, "version_spec"): sv = semver.SimpleSpec(tool.version_spec) path, version = self.tool_results[tool.name] if not sv.match(semver.Version(version)): print(f"Error: Tool '{tool.name}' has version '{version}', but we require '{tool.version_spec}'") sys.exit(1) for tool in self.tools: path, version = self.tool_results[tool.name] if version is None: print(f"found {tool.name} as {path}") else: print(f"found {tool.name} as {path} (version {version})") if self.configmk_enabled: if self.configmk_dotfile: d = Path(".") cf = d / ".config.mk" else: d = Path(os.environ.get("TALERBUILDSYSTEMDIR", ".")) cf = d / "config.mk" d.mkdir(parents=True, exist_ok=True) print(f"writing {cf}") with open(cf, "w") as f: f.write("# this makefile fragment is autogenerated by configure.py\n") if self.prefix_enabled: f.write(f"prefix = {args.prefix}\n") for tool in self.tools: path, version = self.tool_results[tool.name] f.write(f"{tool.name} = {path}\n") for plugin in self.plugins: d = plugin.get_configmk(self) for k, v in d.items(): f.write(f"{k} = {v}\n") def existence(name): return shutil.which(name) is not None class Option(Plugin): def __init__(self, optname, help, required=True, default=None): self.optname = optname self.help = help self.default = default self.required = required self._arg = None def args(self, parser): parser.add_argument("--" + self.optname, action="store") def run(self, buildconfig): arg = getattr(buildconfig.args, self.optname) if arg is None: if self.required: print(f"required option '--{self.optname}' missing") sys.exit(1) else: arg = self.default self._arg = arg def get_configmk(self, buildconfig): key = "opt_" + self.optname return {"opt_" + self.optname: self._arg} class YarnTool(Tool): name = "yarn" description = "The yarn package manager for node" def args(self, parser): parser.add_argument("--with-yarn", action="store") def check(self, buildconfig): yarn_arg = buildconfig.args.with_yarn if yarn_arg is not None: buildconfig._set_tool("yarn", yarn_arg) return True if existence("yarn"): p1 = subprocess.run( ["yarn", "help"], stderr=subprocess.STDOUT, stdout=subprocess.PIPE ) if "No such file or directory" in p1.stdout.decode("utf-8"): if existence("cmdtest"): buildconfig._warn( "cmdtest is installed, this can lead to known issues with yarn." ) buildconfig._error( "You seem to have the wrong kind of 'yarn' installed.\n" "Please remove the conflicting binary before proceeding" ) return False yarn_version = tool_version("yarn --version") buildconfig._set_tool("yarn", "yarn", yarn_version) return True elif existence("yarnpkg"): yarn_version = tool_version("yarnpkg --version") buildconfig._set_tool("yarn", "yarnpkg", yarn_version) return True return False def tool_version(name): return subprocess.getstatusoutput(name)[1] class EmscriptenTool: def args(self, parser): pass def check(self, buildconfig): if existence("emcc"): emscripten_version = tool_version("emcc --version") buildconfig._set_tool("emcc", "emcc", emscripten_version) return True return False class PyToxTool(Tool): name ="tox" def args(self, parser): parser.add_argument( "--with-tox", type=str, help="name of the tox executable" ) def check(self, buildconfig): # No suffix. Would probably be cheaper to do this in # the dict as well. We also need to check the python # version it was build against (TODO). if existence("tox"): import tox mypytox_version = tox.__version__ buildconfig._set_tool("tox", "tox", mypytox_version) return True else: # Has suffix, try suffix. We know the names in advance, # so use a dictionary and iterate over it. Use enough names # to safe updating this for another couple of years. version_dict = { "3.0": "tox-3.0", "3.1": "tox-3.1", "3.2": "tox-3.2", "3.3": "tox-3.3", "3.4": "tox-3.4", "3.5": "tox-3.5", "3.6": "tox-3.6", "3.7": "tox-3.7", "3.8": "tox-3.8", "3.9": "tox-3.9", "4.0": "tox-4.0", } for key, value in version_dict.items(): if existence(value): # FIXME: This version reporting is slightly off # FIXME: and only maps to the suffix. import tox mypytox_version = tox.__version__ buildconfig._set_tool("tox", value, mypytox_version) return True class YapfTool(Tool): name ="yapf" def args(self, parser): parser.add_argument( "--with-yapf", type=str, help="name of the yapf executable" ) def check(self, buildconfig): # No suffix. Would probably be cheaper to do this in # the dict as well. We also need to check the python # version it was build against (TODO). if existence("yapf"): import yapf myyapf_version = yapf.__version__ buildconfig._set_tool("yapf", "yapf", myyapf_version) return True else: # Has suffix, try suffix. We know the names in advance, # so use a dictionary and iterate over it. Use enough names # to safe updating this for another couple of years. version_dict = { "3.0": "yapf3.0", "3.1": "yapf3.1", "3.2": "yapf3.2", "3.3": "yapf3.3", "3.4": "yapf3.4", "3.5": "yapf3.5", "3.6": "yapf3.6", "3.7": "yapf3.7", "3.8": "yapf3.8", "3.9": "yapf3.9", "4.0": "yapf4.0", "4.1": "yapf4.1", "4.2": "yapf4.2", "4.3": "yapf4.3", "4.4": "yapf4.4", "4.5": "yapf4.5", "4.6": "yapf4.6", "4.7": "yapf4.7", "4.8": "yapf4.8", "4.9": "yapf4.9", "5.0": "yapf5.0", "5.1": "yapf5.1", } for key, value in version_dict.items(): if existence(value): # FIXME: This version reporting is slightly off # FIXME: and only maps to the suffix. import yapf myyapf_version = yapf.__version__ buildconfig._set_tool("yapf", value, myyapf_version) return True class PyBabelTool(Tool): name = "pybabel" def args(self, parser): parser.add_argument( "--with-pybabel", type=str, help="name of the pybabel executable" ) def check(self, buildconfig): # No suffix. Would probably be cheaper to do this in # the dict as well. We also need to check the python # version it was build against (TODO). if existence("pybabel"): import babel pybabel_version = babel.__version__ buildconfig._set_tool("pybabel", "pybabel", pybabel_version) return True else: # Has suffix, try suffix. We know the names in advance, # so use a dictionary and iterate over it. Use enough names # to safe updating this for another couple of years. # # Food for thought: If we only accept python 3.7 or higher, # is checking pybabel + pybabel-3.[0-9]* too much and could # be broken down to pybabel + pybabel-3.7 and later names? version_dict = { "3.0": "pybabel-3.0", "3.1": "pybabel-3.1", "3.2": "pybabel-3.2", "3.3": "pybabel-3.3", "3.4": "pybabel-3.4", "3.5": "pybabel-3.5", "3.6": "pybabel-3.6", "3.7": "pybabel-3.7", "3.8": "pybabel-3.8", "3.9": "pybabel-3.9", "4.0": "pybabel-4.0", } for key, value in version_dict.items(): if existence(value): # FIXME: This version reporting is slightly off # FIXME: and only maps to the suffix. pybabel_version = key buildconfig._set_tool("pybabel", value, pybabel_version) return True class PythonTool(Tool): # This exists in addition to the files in sh, so that # the Makefiles can use this value instead. name = "python" def args(self, parser): parser.add_argument( "--with-python", type=str, help="name of the python executable" ) def check(self, buildconfig): # No suffix. Would probably be cheaper to do this in # the dict as well. We need at least version 3.7. if existence("python") and (shlex.split(subprocess.getstatusoutput("python --version")[1])[1] >= '3.7'): # python might not be python3. It might not even be # python 3.x. python_version = shlex.split(subprocess.getstatusoutput("python --version")[1])[1] if python_version >= '3.7': buildconfig._set_tool("python", "python", python_version) return True else: # Has suffix, try suffix. We know the names in advance, # so use a dictionary and iterate over it. Use enough names # to safe updating this for another couple of years. # # Food for thought: If we only accept python 3.7 or higher, # is checking pybabel + pybabel-3.[0-9]* too much and could # be broken down to pybabel + pybabel-3.7 and later names? version_dict = { "3.7": "python3.7", "3.8": "python3.8", "3.9": "python3.9", "3.10": "python3.10", "3.11": "python3.11", "3.12": "python3.12", "3.13": "python3.13", "3.14": "python3.14", } for key, value in version_dict.items(): if existence(value): python3_version = key buildconfig._set_tool("python", value, python3_version) return True # TODO: Make this really optional, not use a hack ("true"). class BrowserTool(Tool): name = "browser" def args(self, parser): parser.add_argument( "--with-browser", type=str, help="name of your webbrowser executable" ) def check(self, buildconfig): browser_dict = { "ice": "icecat", "ff": "firefox", "chg": "chrome", "ch": "chromium", "o": "opera", "t": "true" } if "BROWSER" in os.environ: buildconfig._set_tool("browser", os.environ["BROWSER"]) return True for value in browser_dict.values(): if existence(value): buildconfig._set_tool("browser", value) return True class NodeJsTool(Tool): name = "node" hint = "If you are using Ubuntu Linux or Debian Linux, try installing the\nnode-legacy package or symlink node to nodejs." def __init__(self, version_spec): self.version_spec = version_spec def args(self, parser): pass def check(self, buildconfig): if not existence("node"): return False if ( subprocess.getstatusoutput( "node -p 'process.exit((/v([0-9]+)/.exec(process.version)[1] >= 4) ? 0 : 5)'" )[1] != "" ): buildconfig._warn("your node version is too old, use Node 4.x or newer") return False node_version = tool_version("node --version").lstrip("v") buildconfig._set_tool("node", "node", version=node_version) return True class GenericTool(Tool): def __init__(self, name, hint=None, version_arg="-v"): self.name = name if hint is not None: self.hint = hint self.version_arg = version_arg def args(self, parser): pass def check(self, buildconfig): if not existence(self.name): return False vers = tool_version(f"{self.name} {self.version_arg}") buildconfig._set_tool(self.name, self.name, version=vers) return True class PosixTool(Tool): def __init__(self, name): self.name = name def args(self, parser): pass def check(self, buildconfig): found = existence(self.name) if found: buildconfig._set_tool(self.name, self.name) return True return False libeufin-1.6.8/build-system/taler-build-scripts/archive-with-submodules/0000775000175000017500000000000015236145704026636 5ustar grothoffgrothofflibeufin-1.6.8/build-system/taler-build-scripts/archive-with-submodules/git_archive_all.py0000775000175000017500000005745515122323605032337 0ustar grothoffgrothoff#! /usr/bin/env python3 # coding=utf-8 # The MIT License (MIT) # # Copyright (c) 2010 Ilya Kulakov # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from __future__ import print_function from __future__ import unicode_literals import logging from os import environ, extsep, path, readlink from subprocess import CalledProcessError, Popen, PIPE import sys import re __version__ = "1.22.0" try: # Python 3.2+ from os import fsdecode except ImportError: def fsdecode(filename): if not isinstance(filename, unicode): return filename.decode(sys.getfilesystemencoding(), 'strict') else: return filename try: # Python 3.2+ from os import fsencode except ImportError: def fsencode(filename): if not isinstance(filename, bytes): return filename.encode(sys.getfilesystemencoding(), 'strict') else: return filename def git_fsdecode(filename): """ Decode filename from git output into str. """ if sys.platform.startswith('win32'): return filename.decode('utf-8') else: return fsdecode(filename) def git_fsencode(filename): """ Encode filename from str into git input. """ if sys.platform.startswith('win32'): return filename.encode('utf-8') else: return fsencode(filename) try: # Python 3.6+ from os import fspath as _fspath def fspath(filename, decoder=fsdecode, encoder=fsencode): """ Convert filename into bytes or str, depending on what's the best type to represent paths for current Python and platform. """ # Python 3.6+: str can represent any path (PEP 383) # str is not required on Windows (PEP 529) # Decoding is still applied for consistency and to follow PEP 519 recommendation. return decoder(_fspath(filename)) except ImportError: def fspath(filename, decoder=fsdecode, encoder=fsencode): # Python 3.4 and 3.5: str can represent any path (PEP 383), # but str is required on Windows (no PEP 529) # # Python 2.6 and 2.7: str cannot represent any path (no PEP 383), # str is required on Windows (no PEP 529) # bytes is required on POSIX (no PEP 383) if sys.version_info > (3,): import pathlib if isinstance(filename, pathlib.PurePath): return str(filename) else: return decoder(filename) elif sys.platform.startswith('win32'): return decoder(filename) else: return encoder(filename) def git_fspath(filename): """ fspath representation of git output. """ return fspath(filename, git_fsdecode, git_fsencode) class GitArchiver(object): """ GitArchiver Scan a git repository and export all tracked files, and submodules. Checks for .gitattributes files in each directory and uses 'export-ignore' pattern entries for ignore files in the archive. >>> archiver = GitArchiver(main_repo_abspath='my/repo/path') >>> archiver.create('output.zip') """ TARFILE_FORMATS = { 'tar': 'w', 'tbz2': 'w:bz2', 'tgz': 'w:gz', 'txz': 'w:xz', 'bz2': 'w:bz2', 'gz': 'w:gz', 'xz': 'w:xz' } ZIPFILE_FORMATS = ('zip',) LOG = logging.getLogger('GitArchiver') def __init__(self, prefix='', exclude=True, force_sub=False, extra=None, main_repo_abspath=None, git_version=None): """ @param prefix: Prefix used to prepend all paths in the resulting archive. Extra file paths are only prefixed if they are not relative. E.g. if prefix is 'foo' and extra is ['bar', '/baz'] the resulting archive will look like this: / baz foo/ bar @param exclude: Determines whether archiver should follow rules specified in .gitattributes files. @param force_sub: Determines whether submodules are initialized and updated before archiving. @param extra: List of extra paths to include in the resulting archive. @param main_repo_abspath: Absolute path to the main repository (or one of subdirectories). If given path is path to a subdirectory (but not a submodule directory!) it will be replaced with abspath to top-level directory of the repository. If None, current cwd is used. @param git_version: Version of Git that determines whether various workarounds are on. If None, tries to resolve via Git's CLI. """ self._check_attr_gens = {} self._ignored_paths_cache = {} if git_version is None: git_version = self.get_git_version() if git_version is not None and git_version < (1, 6, 1): raise ValueError("git of version 1.6.1 and higher is required") self.git_version = git_version if main_repo_abspath is None: main_repo_abspath = path.abspath('') elif not path.isabs(main_repo_abspath): raise ValueError("main_repo_abspath must be an absolute path") self.main_repo_abspath = self.resolve_git_main_repo_abspath(main_repo_abspath) self.prefix = fspath(prefix) self.exclude = exclude self.extra = [fspath(e) for e in extra] if extra is not None else [] self.force_sub = force_sub def create(self, output_path, dry_run=False, output_format=None, compresslevel=None): """ Create the archive at output_file_path. Type of the archive is determined either by extension of output_file_path or by output_format. Supported formats are: gz, zip, bz2, xz, tar, tgz, txz @param output_path: Output file path. @param dry_run: Determines whether create should do nothing but print what it would archive. @param output_format: Determines format of the output archive. If None, format is determined from extension of output_file_path. @param compresslevel: Optional compression level. Interpretation depends on the output format. """ output_path = fspath(output_path) if output_format is None: file_name, file_ext = path.splitext(output_path) output_format = file_ext[len(extsep):].lower() self.LOG.debug("Output format is not explicitly set, determined format is {0}.".format(output_format)) if not dry_run: if output_format in self.ZIPFILE_FORMATS: from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED if compresslevel is not None: if sys.version_info > (3, 7): archive = ZipFile(path.abspath(output_path), 'w', compresslevel=compresslevel) else: raise ValueError("Compression level for zip archives requires Python 3.7+") else: archive = ZipFile(path.abspath(output_path), 'w') def add_file(file_path, arcname): if not path.islink(file_path): archive.write(file_path, arcname, ZIP_DEFLATED) else: i = ZipInfo(arcname) i.create_system = 3 i.external_attr = 0xA1ED0000 archive.writestr(i, readlink(file_path)) elif output_format in self.TARFILE_FORMATS: import tarfile mode = self.TARFILE_FORMATS[output_format] if compresslevel is not None: try: archive = tarfile.open(path.abspath(output_path), mode, compresslevel=compresslevel) except TypeError: raise ValueError("{0} cannot be compressed".format(output_format)) else: archive = tarfile.open(path.abspath(output_path), mode) def add_file(file_path, arcname): archive.add(file_path, arcname) else: raise ValueError("unknown format: {0}".format(output_format)) def archiver(file_path, arcname): self.LOG.debug(fspath("{0} => {1}").format(file_path, arcname)) add_file(file_path, arcname) else: archive = None def archiver(file_path, arcname): self.LOG.info(fspath("{0} => {1}").format(file_path, arcname)) self.archive_all_files(archiver) if archive is not None: archive.close() def is_file_excluded(self, repo_abspath, repo_file_path): """ Checks whether file at a given path is excluded. @param repo_abspath: Absolute path to the git repository. @param repo_file_path: Path to a file relative to repo_abspath. @return: True if file should be excluded. Otherwise False. """ if not self.exclude: return False cache = self._ignored_paths_cache.setdefault(repo_abspath, {}) if repo_file_path not in cache: next(self._check_attr_gens[repo_abspath]) attrs = self._check_attr_gens[repo_abspath].send(repo_file_path) export_ignore_attr = attrs['export-ignore'] if export_ignore_attr == b'set': cache[repo_file_path] = True elif export_ignore_attr == b'unset': cache[repo_file_path] = False else: repo_file_dir_path = path.dirname(repo_file_path) if repo_file_dir_path: cache[repo_file_path] = self.is_file_excluded(repo_abspath, repo_file_dir_path) else: cache[repo_file_path] = False return cache[repo_file_path] def archive_all_files(self, archiver): """ Archive all files using archiver. @param archiver: Callable that accepts 2 arguments: abspath to file on the system and relative path within archive. """ for file_path in self.extra: archiver(path.abspath(file_path), path.join(self.prefix, file_path)) for file_path in self.walk_git_files(): archiver(path.join(self.main_repo_abspath, file_path), path.join(self.prefix, file_path)) def walk_git_files(self, repo_path=fspath('')): """ An iterator method that yields a file path relative to main_repo_abspath for each file that should be included in the archive. Skips those that match the exclusion patterns found in any discovered .gitattributes files along the way. Recurs into submodules as well. @param repo_path: Path to the git submodule repository relative to main_repo_abspath. @return: Generator to traverse files under git control relative to main_repo_abspath. """ repo_abspath = path.join(self.main_repo_abspath, fspath(repo_path)) assert repo_abspath not in self._check_attr_gens self._check_attr_gens[repo_abspath] = self.check_git_attr(repo_abspath, ['export-ignore']) try: repo_file_paths = self.list_repo_files(repo_abspath) for repo_file_path in repo_file_paths: repo_file_abspath = path.join(repo_abspath, repo_file_path) # absolute file path main_repo_file_path = path.join(repo_path, repo_file_path) # relative to main_repo_abspath if not path.islink(repo_file_abspath) and path.isdir(repo_file_abspath): continue if self.is_file_excluded(repo_abspath, repo_file_path): continue yield main_repo_file_path if self.force_sub: self.run_git_shell('git submodule init', repo_abspath) self.run_git_shell('git submodule update', repo_abspath) try: repo_gitmodules_abspath = path.join(repo_abspath, fspath(".gitmodules")) with open(repo_gitmodules_abspath) as f: lines = f.readlines() for l in lines: m = re.match("^\\s*path\\s*=\\s*(.*)\\s*$", l) if m: repo_submodule_path = fspath(m.group(1)) # relative to repo_path main_repo_submodule_path = path.join(repo_path, repo_submodule_path) # relative to main_repo_abspath if self.is_file_excluded(repo_abspath, repo_submodule_path): continue for main_repo_submodule_file_path in self.walk_git_files(main_repo_submodule_path): repo_submodule_file_path = path.relpath(main_repo_submodule_file_path, repo_path) # relative to repo_path if self.is_file_excluded(repo_abspath, repo_submodule_file_path): continue yield main_repo_submodule_file_path except IOError: pass finally: self._check_attr_gens[repo_abspath].close() del self._check_attr_gens[repo_abspath] def check_git_attr(self, repo_abspath, attrs): """ Generator that returns git attributes for received paths relative to repo_abspath. >>> archiver = GitArchiver(...) >>> g = archiver.check_git_attr('repo_path', ['export-ignore']) >>> next(g) >>> attrs = g.send('relative_path') >>> print(attrs['export-ignore']) @param repo_abspath: Absolute path to a git repository. @param attrs: Attributes to check """ def make_process(): env = dict(environ, GIT_FLUSH='1') cmd = 'git check-attr --stdin -z {0}'.format(' '.join(attrs)) return Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, cwd=repo_abspath, env=env) def read_attrs(process, repo_file_path): process.stdin.write(repo_file_path + b'\0') process.stdin.flush() # For every attribute check-attr will output: NUL NUL NUL path, attr, info = b'', b'', b'' nuls_count = 0 nuls_expected = 3 * len(attrs) while nuls_count != nuls_expected: b = process.stdout.read(1) if b == b'' and process.poll() is not None: raise RuntimeError("check-attr exited prematurely") elif b == b'\0': nuls_count += 1 if nuls_count % 3 == 0: yield path, attr, info path, attr, info = b'', b'', b'' elif nuls_count % 3 == 0: path += b elif nuls_count % 3 == 1: attr += b elif nuls_count % 3 == 2: info += b def read_attrs_old(process, repo_file_path): """ Compatibility with versions 1.8.5 and below that do not recognize -z for output. """ process.stdin.write(repo_file_path + b'\0') process.stdin.flush() # For every attribute check-attr will output: : : \n # where is c-quoted path, attr, info = b'', b'', b'' lines_count = 0 lines_expected = len(attrs) while lines_count != lines_expected: line = process.stdout.readline() info_start = line.rfind(b': ') if info_start == -1: raise RuntimeError("unexpected output of check-attr: {0}".format(line)) attr_start = line.rfind(b': ', 0, info_start) if attr_start == -1: raise RuntimeError("unexpected output of check-attr: {0}".format(line)) path = line[:attr_start] attr = line[attr_start + 2:info_start] # trim leading ": " info = line[info_start + 2:len(line) - 1] # trim leading ": " and trailing \n yield path, attr, info lines_count += 1 if not attrs: return process = make_process() if self.git_version is None or self.git_version > (1, 8, 5): reader = read_attrs else: reader = read_attrs_old try: while True: repo_file_path = yield repo_file_path = git_fsencode(fspath(repo_file_path)) repo_file_attrs = {} for path, attr, value in reader(process, repo_file_path): attr = attr.decode('utf-8') repo_file_attrs[attr] = value yield repo_file_attrs finally: process.stdin.close() process.wait() def resolve_git_main_repo_abspath(self, abspath): """ Return absolute path to the repo for a given path. """ try: main_repo_abspath = self.run_git_shell('git rev-parse --show-toplevel', cwd=abspath).rstrip() return path.abspath(git_fspath(main_repo_abspath)) except CalledProcessError as e: raise ValueError("{0} is not part of a git repository ({1})".format(abspath, e.returncode)) @classmethod def run_git_shell(cls, cmd, cwd=None): """ Run git shell command, read output and decode it into a unicode string. @param cmd: Command to be executed. @param cwd: Working directory. @return: Output of the command. @raise CalledProcessError: Raises exception if return code of the command is non-zero. """ p = Popen(cmd, shell=True, stdout=PIPE, cwd=cwd) output, _ = p.communicate() if p.returncode: if sys.version_info > (2, 6): raise CalledProcessError(returncode=p.returncode, cmd=cmd, output=output) else: raise CalledProcessError(returncode=p.returncode, cmd=cmd) return output @classmethod def get_git_version(cls): """ Return version of git current shell points to. If version cannot be parsed None is returned. """ try: output = cls.run_git_shell('git version') except CalledProcessError: cls.LOG.warning("Unable to get Git version.") return None try: version = output.split()[2] except IndexError: cls.LOG.warning("Unable to parse Git version \"%s\".", output) return None try: return tuple(int(v) if v.isdigit() else 0 for v in version.split(b'.')) except ValueError: cls.LOG.warning("Unable to parse Git version \"%s\".", version) return None @classmethod def list_repo_files(cls, repo_abspath): repo_file_paths = cls.run_git_shell( 'git ls-files -z --cached --full-name --no-empty-directory', cwd=repo_abspath ) repo_file_paths = repo_file_paths.split(b'\0')[:-1] if sys.platform.startswith('win32'): repo_file_paths = (git_fspath(p.replace(b'/', b'\\')) for p in repo_file_paths) else: repo_file_paths = map(git_fspath, repo_file_paths) return repo_file_paths def main(argv=None): if argv is None: argv = sys.argv from optparse import OptionParser, SUPPRESS_HELP parser = OptionParser( usage="usage: %prog [-v] [-C BASE_REPO] [--prefix PREFIX] [--no-export-ignore]" " [--force-submodules] [--include EXTRA1 ...] [--dry-run] [-0 | ... | -9] OUTPUT_FILE", version="%prog {0}".format(__version__) ) parser.add_option('--prefix', type='string', dest='prefix', default=None, help="""prepend PREFIX to each filename in the archive; defaults to OUTPUT_FILE name""") parser.add_option('-C', type='string', dest='base_repo', default=None, help="""use BASE_REPO as the main git repository to archive; defaults to the current directory when empty""") parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='enable verbose mode') parser.add_option('--no-export-ignore', '--no-exclude', action='store_false', dest='exclude', default=True, help="ignore the [-]export-ignore attribute in .gitattributes") parser.add_option('--force-submodules', action='store_true', dest='force_sub', help='force `git submodule init && git submodule update` at each level before iterating submodules') parser.add_option('--include', '--extra', action='append', dest='extra', default=[], help="additional files to include in the archive") parser.add_option('--dry-run', action='store_true', dest='dry_run', help="show files to be archived without actually creating the archive") for i in range(10): parser.add_option('-{0}'.format(i), action='store_const', const=i, dest='compresslevel', help=SUPPRESS_HELP) options, args = parser.parse_args(argv[1:]) if len(args) != 1: parser.error("You must specify exactly one output file") output_file_path = args[0] if path.isdir(output_file_path): parser.error("You cannot use directory as output") # avoid tarbomb if options.prefix is not None: options.prefix = path.join(options.prefix, '') else: output_name = path.basename(output_file_path) output_name = re.sub( '(\\.zip|\\.tar|\\.tbz2|\\.tgz|\\.txz|\\.bz2|\\.gz|\\.xz|\\.tar\\.bz2|\\.tar\\.gz|\\.tar\\.xz)$', '', output_name ) or "Archive" options.prefix = path.join(output_name, '') try: handler = logging.StreamHandler(sys.stdout) handler.setFormatter(logging.Formatter('%(message)s')) GitArchiver.LOG.addHandler(handler) GitArchiver.LOG.setLevel(logging.DEBUG if options.verbose else logging.INFO) archiver = GitArchiver(options.prefix, options.exclude, options.force_sub, options.extra, path.abspath(options.base_repo) if options.base_repo is not None else None ) archiver.create(output_file_path, options.dry_run, compresslevel=options.compresslevel) except Exception as e: parser.exit(2, "{0}\n".format(e)) return 0 if __name__ == '__main__': sys.exit(main()) libeufin-1.6.8/build-system/taler-build-scripts/README0000664000175000017500000000077415122323605022744 0ustar grothoffgrothoffShared build-system files for (some) parts of Taler. A repository using these build-system files should be structured as follows: - bootstrap (copied/adjusted from bootstrap.template) - build-system (directory containing build system "stuff") --| configure.py (copied/adjusted from configure.py.template) --| taler-build-scripts (git submodule of taler-build-scripts) Directory Structure: -------------------- conf: - contains mixed configuration data, mostly for linters and editors libeufin-1.6.8/build-system/taler-build-scripts/coverage.sh0000664000175000017500000000054015122323605024202 0ustar grothoffgrothoff#!/bin/sh # Run from 'taler-exchange/' top-level directory to generate # code coverage data. TOP=`pwd` mkdir -p doc/coverage/ lcov -d $TOP -z make check lcov -d $TOP -c --no-external -o doc/coverage/coverage.info lcov -r doc/coverage/coverage.info **/test_* **/perf_* -o doc/coverage/rcoverage.info genhtml -o doc/coverage doc/coverage/rcoverage.info libeufin-1.6.8/build-system/taler-build-scripts/Makefile.inc0000664000175000017500000000221315122323605024262 0ustar grothoffgrothoff# This file has to be copied into the directory one level above. # This also means (obviously): this file is excluded from including # itself. BUILDCOMMON_SHLIB_FILES = \ build-common/LICENSE BUILDCOMMON_CONF_FILES = \ build-common/conf/.dir-locals.el \ build-common/conf/.prettierrc \ build-common/conf/.style.yapf \ build-common/conf/.vscode/settings.json \ build-common/conf/.vscode/tasks.json \ build-common/conf/.yarnrc \ build-common/conf/uncrustify-mode.el \ build-common/conf/uncrustify.cfg \ build-common/conf/uncrustify.el \ build-common/conf/uncrustify.sh \ build-common/conf/uncrustify_precommit BUILDCOMMON_BUILD_FILES = \ build-common/bootstrap.template \ build-common/configure \ build-common/configure.py.template \ build-common/talerbuildconfig.py \ build-common/testconfigure.py BUILDCOMMON_DOC_FILES = \ build-common/README BUILDCOMMON_SCRIPT_FILES = \ build-common/coverage.sh BUILD_COMMON_FILES = \ $(BUILDCOMMON_SHLIB_FILES) \ $(BUILDCOMMON_CONF_FILES) \ $(BUILDCOMMON_BUILD_FILES) \ $(BUILDCOMMON_DOC_FILES) \ $(BUILDCOMMON_SCRIPT_FILES) libeufin-1.6.8/build-system/taler-build-scripts/configure0000775000175000017500000000404515122323605023766 0ustar grothoffgrothoff#!/bin/sh # This file is part of GNU Taler. # (C) 2020 Taler Systems S.A. # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE # LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF # THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # This script checks if a suitable python3 executable is installed and then # executes the actual configure logic written in Python. build_system_dir=build-system if ! test -d "$build_system_dir"; then # Maybe this is not a top-level configure invocation # For monorepos, try location from top-level build_system_dir=../../build-system fi if ! test -d "$build_system_dir"; then echo "fatal error: build-system directory not found" >&2 echo "hint: are you running this script from the right directory?" >&2 exit 1 fi scriptpath=$build_system_dir/taler-build-scripts if ! test -d "$build_system_dir"; then echo "fatal error: taler-build-scripts directory not found at $scriptpath" >&2 echo "hint: did you run './bootstrap'?" >&2 exit 1 fi export TALERBUILDSYSTEMDIR=$build_system_dir # Check that the python3 executable is on the PATH. # This follows PEP 394 (https://www.python.org/dev/peps/pep-0394/). if ! python3 --version >/dev/null 2>&1; then echo "error: python3 not found" >&2 exit 1 fi # Let python3 check that its own version is okay for us. python3 "$scriptpath/pyvercheck.py" || exit $? # Allow Python to find libraries that are checked into the build system git. export PYTHONPATH="$scriptpath:${PYTHONPATH:-}" # Call configure.py, assuming all went well. python3 $TALERBUILDSYSTEMDIR/configure.py "$@" libeufin-1.6.8/build-system/taler-build-scripts/conf/0000775000175000017500000000000015236145704023011 5ustar grothoffgrothofflibeufin-1.6.8/build-system/taler-build-scripts/conf/uncrustify-mode.el0000775000175000017500000001251115122323605026463 0ustar grothoffgrothoff;;; uncrustify-mode.el --- Minor mode to automatically uncrustify. ;; Copyright (C) 2012 tabi ;; Author: Tabito Ohtani ;; Version: 0.01 ;; Keywords: uncrustify ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Installation: ;; drop requirements and this file into a directory in your `load-path', ;; and put these lines into your .emacs file. ;; (require 'uncrusfify-mode) ;; (add-hook 'c-mode-common-hook ;; '(lambda () ;; (uncrustify-mode 1))) ;;; ChangeLog: ;; * 0.0.1: ;; Initial version. ;; case (eval-when-compile (require 'cl)) ;;; Variables: (defcustom uncrustify-config-path "~/.uncrustify.cfg" "uncrustify config file path" :group 'uncrustify :type 'file) (make-variable-buffer-local 'uncrustify-config-path) (defcustom uncrustify-bin "uncrustify -q" "The command to run uncrustify." :group 'uncrustify) ;;; Functions: (defun uncrustify-get-lang-from-mode (&optional mode) "uncrustify lang option" (let ((m (or mode major-mode))) (case m ('c-mode "C") ('c++-mode "CPP") ('d-mode "D") ('java-mode "JAVA") ('objc-mode "OC") (t nil)))) (defun uncrustify-point->line (point) "Get the line number that POINT is on." ;; I'm not bothering to use save-excursion because I think I'm ;; calling this function from inside other things that are likely to ;; use that and all I really need to do is restore my current ;; point. So that's what I'm doing manually. (let ((line 1) (original-point (point))) (goto-char (point-min)) (while (< (point) point) (incf line) (forward-line)) (goto-char original-point) line)) (defun uncrustify-invoke-command (lang start-in end-in) "Run uncrustify on the current region or buffer." (if lang (let ((start (or start-in (point-min))) (end (or end-in (point-max))) (original-line (uncrustify-point->line (point))) (cmd (concat uncrustify-bin " -c " uncrustify-config-path " -l " lang)) (out-buf (get-buffer-create "*uncrustify-out*")) (error-buf (get-buffer-create "*uncrustify-errors*"))) (with-current-buffer error-buf (erase-buffer)) (with-current-buffer out-buf (erase-buffer)) ;; Inexplicably, save-excursion doesn't work to restore the ;; point. I'm using it to restore the mark and point and manually ;; navigating to the proper new-line. (let ((result (save-excursion (let ((ret (shell-command-on-region start end cmd t t error-buf nil))) (if (and (numberp ret) (zerop ret)) ;; Success! Clean up. (progn (message "Success! uncrustify modify buffer.") (kill-buffer error-buf) t) ;; Oops! Show our error and give back the text that ;; shell-command-on-region stole. (progn (undo) (with-current-buffer error-buf (message "uncrustify error: <%s> <%s>" ret (buffer-string))) nil)))))) ;; This goto-line is outside the save-excursion because it'd get ;; removed otherwise. I hate this bug. It makes things so ugly. (goto-line original-line) (not result))) (message "uncrustify not support this mode : %s" major-mode))) (defun uncrustify () (interactive) (save-restriction (widen) (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (region-beginning) (region-end)))) (defun uncrustify-buffer () (interactive) (save-restriction (widen) (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (point-min) (point-max)))) ;;; mode (defun uncrustify-write-hook () "Uncrustifys a buffer during `write-file-hooks' for `uncrustify-mode'. if uncrustify returns not nil then the buffer isn't saved." (if uncrustify-mode (save-restriction (widen) (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (point-min) (point-max))))) ;;;###autoload (define-minor-mode uncrustify-mode "Automatically `uncrustify' when saving." :lighter " Uncrustify" (if (not (uncrustify-get-lang-from-mode)) (message "uncrustify not support this mode : %s" major-mode) (if (version<= "24" emacs-version) (if uncrustify-mode (add-hook 'write-file-hooks 'uncrustify-write-hook nil t) (remove-hook 'uncrustify-write-hook t)) (make-local-hook 'write-file-hooks) (funcall (if uncrustify-mode #'add-hook #'remove-hook) 'write-file-hooks 'uncrustify-write-hook)))) (provide 'uncrustify-mode) ;;; uncrustify-mode.el ends here libeufin-1.6.8/build-system/taler-build-scripts/conf/.style.yapf0000664000175000017500000000014215122323605025075 0ustar grothoffgrothoff[style] based_on_style = pep8 coalesce_brackets=True column_limit=80 dedent_closing_brackets=True libeufin-1.6.8/build-system/taler-build-scripts/conf/uncrustify.sh0000775000175000017500000000056115122323605025555 0ustar grothoffgrothoff#!/usr/bin/env bash set -eu DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" if ! uncrustify --version >/dev/null; then echo "you need to install uncrustify for indentation" exit 1 fi find "$DIR/../src" \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) \ -exec uncrustify -c "$DIR/uncrustify.cfg" --replace --no-backup {} + \ || true libeufin-1.6.8/build-system/taler-build-scripts/conf/uncrustify.cfg0000664000175000017500000000272615122323605025704 0ustar grothoffgrothoffinput_tab_size = 2 output_tab_size = 2 indent_columns = 2 indent_with_tabs = 0 indent_case_brace = 2 indent_label=0 code_width=80 #cmd_width=80 # Leave most comments alone for now cmt_indent_multi=false sp_cmt_cpp_start=add sp_not=add sp_func_call_user_paren_paren=remove sp_inside_fparen=remove sp_after_cast=add ls_for_split_full=true ls_func_split_full=true ls_code_width=true # Arithmetic operations in wrapped expressions should be at the start # of the line. pos_arith=lead # Fully parenthesize boolean exprs mod_full_paren_if_bool=true # Braces should be on their own line nl_fdef_brace=add nl_enum_brace=add nl_struct_brace=add nl_union_brace=add nl_if_brace=add nl_brace_else=add nl_elseif_brace=add nl_while_brace=add nl_switch_brace=add # no newline between "else" and "if" nl_else_if=remove nl_func_paren=remove nl_assign_brace=remove # No extra newlines that cause noisy diffs nl_start_of_file=remove # If there's no new line, it's not a text file! nl_end_of_file=add sp_inside_paren = remove sp_arith = add sp_arith_additive = add # We want spaces before and after "=" sp_before_assign = add sp_after_assign = add # we want "char *foo;" sp_after_ptr_star = remove sp_between_ptr_star = remove # we want "if (foo) { ... }" sp_before_sparen = add sp_inside_fparen = remove # add space before function call and decl: "foo (x)" sp_func_call_paren = add sp_func_proto_paren = add sp_func_proto_paren_empty = add sp_func_def_paren = add sp_func_def_paren_empty = add libeufin-1.6.8/build-system/taler-build-scripts/conf/.prettierrc0000664000175000017500000000012515122323605025163 0ustar grothoffgrothoff{ "trailingComma": "all", "tabWidth": 2, "semi": true, "singleQuote": false }libeufin-1.6.8/build-system/taler-build-scripts/conf/uncrustify.el0000664000175000017500000000070715122323605025542 0ustar grothoffgrothoff;; suggested integration of uncrustify for Emacs ;; This assumes that the 'uncrustify-mode.el' is ;; installed to '~/.emacs.d/load-path/'. Feel free ;; to put it elsewhere and adjust the load path below! ;; adding the following to ~/.emacs will then run ;; uncrustify whenever saving a C buffer. (add-to-list 'load-path "~/.emacs.d/load-path/") (require 'uncrustify-mode) (add-hook 'c-mode-common-hook '(lambda () (uncrustify-mode 1))) libeufin-1.6.8/build-system/taler-build-scripts/conf/.vscode/0000775000175000017500000000000015236145704024352 5ustar grothoffgrothofflibeufin-1.6.8/build-system/taler-build-scripts/conf/.vscode/tasks.json0000664000175000017500000000222115122323605026357 0ustar grothoffgrothoff{ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ { "type": "typescript", "tsconfig": "tsconfig.json", "option": "watch", "problemMatcher": [ "$tsc-watch" ], "group": "build", "isBackground": true, "promptOnClose": false }, { "type": "typescript", "tsconfig": "tsconfig.json", "problemMatcher": [ "$tsc" ], "group": "build" }, { "label": "tslint", "type": "shell", "command": "make lint", "problemMatcher": { "owner": "tslint", "applyTo": "allDocuments", "fileLocation": "absolute", "severity": "warning", "pattern": "$tslint5" }, "group": "build" }, { "label": "My Task", "type": "shell", "command": "echo Hello" } ] }libeufin-1.6.8/build-system/taler-build-scripts/conf/.vscode/settings.json0000664000175000017500000000373315122323605027103 0ustar grothoffgrothoff// Place your settings in this file to overwrite default and user settings. { // Use latest language servicesu "typescript.tsdk": "./node_modules/typescript/lib", // Defines space handling after a comma delimiter "typescript.format.insertSpaceAfterCommaDelimiter": true, // Defines space handling after a semicolon in a for statement "typescript.format.insertSpaceAfterSemicolonInForStatements": true, // Defines space handling after a binary operator "typescript.format.insertSpaceBeforeAndAfterBinaryOperators": true, // Defines space handling after keywords in control flow statement "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": true, // Defines space handling after function keyword for anonymous functions "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true, // Defines space handling after opening and before closing non empty parenthesis "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, // Defines space handling after opening and before closing non empty brackets "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, // Defines whether an open brace is put onto a new line for functions or not "typescript.format.placeOpenBraceOnNewLineForFunctions": false, // Defines whether an open brace is put onto a new line for control blocks or not "typescript.format.placeOpenBraceOnNewLineForControlBlocks": false, // Files hidden in the explorer "files.exclude": { // include the defaults from VS Code "**/.git": true, "**/.DS_Store": true, // exclude .js and .js.map files, when in a TypeScript project "**/*.js": { "when": "$(basename).ts" }, "**/*?.js": { "when": "$(basename).tsx" }, "**/*.js.map": true }, "tslint.enable": true, "editor.wrappingIndent": "same", "editor.tabSize": 2 }libeufin-1.6.8/build-system/taler-build-scripts/conf/uncrustify_precommit0000775000175000017500000000121515122323605027220 0ustar grothoffgrothoff#!/bin/sh # use as .git/hooks/pre-commit exec 1>&2 RET=0 changed=$(git diff --cached --name-only) crustified="" for f in $changed; do if echo $f | grep \\.[c,h]\$ > /dev/null then # compare result of uncrustify with changes # # only change any of the invocations here if # they are portable across all cmp and shell # implementations ! uncrustify -q -c uncrustify.cfg -f $f | cmp -s $f - if test $? = 1 ; then crustified=" $crustified $f" RET=1 fi fi done if [ $RET = 1 ]; then echo "Run" echo "uncrustify --no-backup -c uncrustify.cfg ${crustified}" echo "before committing." fi exit $RET libeufin-1.6.8/build-system/taler-build-scripts/conf/.yarnrc0000664000175000017500000000012415122323605024275 0ustar grothoffgrothoffyarn-offline-mirror "./npm-packages-offline-cache" yarn-offline-mirror-pruning true libeufin-1.6.8/build-system/taler-build-scripts/conf/.dir-locals.el0000664000175000017500000000103715122323605025433 0ustar grothoffgrothoff;; Per-directory local variables for GNU Emacs 23 and later. ((nil . ((fill-column . 78) (tab-width . 4) (indent-tabs-mode . nil) (show-trailing-whitespace . t) (c-basic-offset . 2) (ispell-check-comments . exclusive) (ispell-local-dictionary . "american") (safe-local-variable-values '((c-default-style . "gnu") (sentence-end-double-space . f) (eval add-hook 'prog-mode-hook #'flyspell-prog-mode) (flyspell-issue-message-flag . f) ; avoid messages for every word ))))) libeufin-1.6.8/build-system/configure.py0000644000175000017500000000027214674637415020537 0ustar grothoffgrothoff# This configure.py.template file is in the public domain. from talerbuildconfig import * b = BuildConfig() b.enable_prefix() b.enable_configmk() b.add_tool(PosixTool("find")) b.run() libeufin-1.6.8/gradle/0000775000175000017500000000000015236145704015010 5ustar grothoffgrothofflibeufin-1.6.8/gradle/wrapper/0000775000175000017500000000000015236145704016470 5ustar grothoffgrothofflibeufin-1.6.8/gradle/wrapper/gradle-wrapper.jar0000664000175000017500000013651615221677432022120 0ustar grothoffgrothoffPK! META-INF/LICENSEUTZ[s6~ϯhfgFI}RcU73>B$(aC,@Z=(Nu=֢swJ|gr]ΩW//e6vn(}g퇡͛0ݛro^X݈wwnas[;|\[7z>!ōuP_ymfD3iDd'8l*QU6VNªޚj,qEổv D[JlbJ ȷfA{[ z{Xiջ ̡SVJPG!ao\Z1 `ӝKj'qKϔ;< i,IJz1^ jxk0`MSiUА]JӶ⠇= ⽱G?@$Fͼʼn+}KAgKB Fy)'Np_7{X!{EӾd9h&rAr%պkʖ( pU.H[ՁJ HL.Ì3qk7;ν&Qy|x [<',6[ )՞FZoUך,hMh*8Xwe3) EgVGghCpJG~_hFeq7¹;3pP~ִr/;:$DEM4c-`bz@/䘐6Ƅ2?"' NPn*-pc2(!iL8R@w1tXHn RhXJJ2B@70-/k2-dqPOagXa E+ 1de#XQ 4Fq^ (Q*VF?DcnE\8u5@ ̴Q+14>O ><0rA%lfJ Xw]}~I|zw$W Zc~^Z UV5Gȃ3n тqV]k"[˒Dh3:}) .Ҩ bL$H2lZN"KQMm7n;h#3ZLjDe}5yu^f^˰H5腭l(uD>[_`FWPhd!R+%u -+Y Tr;*,!%H+ȵrL 6 8n9:cKxi'BTS0!(hFJ&v(rzC(Ȱ#j{K|v':;d)On@dSe ("$}R:ඥ{sF›ѷs *]<~`Vb3rqz,GeURd!38@z5eB5A#L<5e3_V' єga`Xq|t q k}#!ЙK'X}[N#Y>B9'la5sG+X Z!P$PqCt-z>k= l/ѦAP /؁qe f죰MӁʈ]^f+ܺ7;^Ք ҡ审 6IdtA8wڂL-PbYc/0ScN |~ V8 (͈?hz6jE,O_8 vS&ñ?Zb 4e ͨϔh%/*+V|Ѻ Ċ໹X|24[yLvB:p %Ha@ Ċ 3 % sunDC>!R e-Bd6ˆ*bGd&%-5P8"?S8ި*Uch$bpyid03\L&VA<džy⢉RWALN_+P?G24 ˽h•L}A"MMV$T"yu6K VMpd8K&*q4N8{jvMx蠊:rzJ/I.H|x"aV6zvt>x:aͧKki `ZG^2.7T_2LwXFH57B9pR|io`? L=2xhviPCXxte9ٍ_1} ŹYd48Rg#c_A4T=‚'XɥPMӨ XxG MNj!|5PRuKZ| v9$nR-V"5/i V$wI+-j6/'νƹ@lL,7=܋Oz_n:{/??;op:I4JISќT:BKȞC,~y^/W/߮ ݯB }`e|\akansՖo Y{TӭpW8 5H5DB79Dx;S&3{V,?9}r<_b@`a'v6j 7Y@C>2ԮJu]b2ʍ/7zK<"[-9)8 .k4m'ZtWҗ\n=}bW H`xr^h@h8|gUmtɚcĘ;3|bpx ؝1A73e FT-W#c  [ r8HOq^FQ%is0kZ! /H:KO{t=,|-ro OAi9l+Zԑ+1G#ŝj;jIY0OAAW-p_造V2 NotMv9!@`%nQIQ~&=196uMjhWx0\ږ(hŔΣO+fx{d#H6dEcF.PK 'PK! META-INF/MANIFEST.MFUT- 0{ [RB۸j Ɛa)eSLvJ厳j &fGJ"v#b9'֐OUmo)*R ZG))1A?D~6Dn\_]Zֶ) 8PKjZPK!1 org/gradle/cli/CommandLineArgumentException.classUTMOJ1xImREZ46.n>oIP,(:}~92xlfr.c.efsmD3,E=I\%U(m0; ^̙f9Y,0{^~mr}G؆6[ZAӝFSZܗ]l8+,=A+uxoqiYA !fxnղ, xu^ )m!\iG\/OL1$jN#i 15K KtKFF*4fD./Y6K+Bt3(N!K{+ *wVC&QU-yI]aHw j~Mi5ץ_g^a*=[cdsk*J@Au`( *z# }k42DW7=Tq 8.ⲊDpUEq{ oZB# \GK'񊊛 nW9]Aԥx*^^c" Ԝڵ;B'Q pwLXMTC&{>7`\ ]ZS+gμtEZEޚO۾̛H> QHgX `hUM2H?蜧!x"ߑ8>F>>_?8CuEw͓73_0R{~ +tuqt)) *PYF6@ PKyPK!3 org/gradle/cli/CommandLineParser$AfterOptions.classUTSmOP~.uc.VPE ILH0bڻ]n;!?hhGO,=<9O=fa+)\?<̭͐3Бѡa$aR(Ø䨨 %K=[2n\y[Ix1^ˆ d /NKuL c 7yқgzf p!+G* t~ҭJJF+nba@}n6{Šh2ŜGFa4BUO`Jȣ#/I49FdӅ1oR% \@OL0V|[8/yZȦzTVvq;s):H~,k@/PKbZPK!< org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.classUTUmSW~.,UK[a ,)D!|#c33l.ʾdv7NG~3VioԳqM/&ssy9웷_8mm)V.:kjVa7[ :4.uiy7=U5 |1u! u ךIWd@k-k5B7^&*6` rifaqk˫馑[t,etpĚRZ`or|  ~`P}Ѱ 2x~FWwt _@Q '"t(nձ|Lnr%?Hm 2R+r@cZEHgH/{/e C2n _18^Ÿq7+QT5 e;,;Fwzr_>2b8QygȞwTy"g*\aH,Dk:fӪ7DGL k ݯ (r_tgtEЁ@f:Op&+ W^#ALOۘ||9?.ok3\O/wlxW]{m0n);FB %="-m8I*`H)vӴJ*lC{PKlGRPK!= org/gradle/cli/CommandLineParser$KnownOptionParserState.classUTV_~I"I4 ]0F,ݘ&lff!hMz+^5m] _[?C@U]~s=y8z烣z|R`|,ƭd0uװR#x8;O:lMGHROG Ck2I3GHԸ6RN ۡ-ZEb*BA+cc)*[d}g(兤\ g|"x+'#QJWp=?_.`wh6aox"swO!˿H2BY".hEm(yt莑kox4- =|O.O% g^[V{GTGqƉėHZ$n;e0|3s*Z ~&*aors'[Y4{S8OYזF=AϗYVPPK@zƿ^:PK!< org/gradle/cli/CommandLineParser$MissingOptionArgState.classUTmOP"0E've ML3ywuvi;c|~?t Bܞ{_XaoE֎[m[u=4'x$cGN#}ͽHck CKAڰ1o<Qt\)DJ"( K  z%`N 퉺׉瞹QDnRi< jG,"ϐR V)+>]$ð񴼥ABE`ao[a9eỼqԛq6by6#~X 9#5:5 {D>9 'ΪP}`Z3fp),]Aw5 }d.\P k1>5Sĕ+ݒe6Stcz(KOL8T?516%צ%H--3TmWI)˥+ځsȆ=!QG#C (U2s ^tG` MDkk # p>a F9AJ0?I;Fre.A.1m$ބw(6h0;>SN\KfAU{ȓ<--ϥ*Ki%RUP4'd踃C7:G #X1|;[(HPZf'~Mon.gzғGT P#HaZ+(gh2dqƪ,$0&A.E 0tk&0fCP]uVߔ)9!7yth:D!"#~BZhO'.t_2VJЖaoT!gI'oCsķNc[a2]`?>j}|[H!d#P.'PKAJPK!8 org/gradle/cli/CommandLineParser$OptionParserState.classUTPMo17_%mQ8␠nV-BJJQ[d]ިRESqjo<̯ۛ ~u9 &N ARTdüHyC3a2V ,eX{ 1\VJ1ag):H1;'c/)̓o Ee( &2(Q2:(u:b41vu[g8H΢%MͷRKN@;]UxІԻ64|)4wDFl^ |yΪPKz}PK!3 org/gradle/cli/CommandLineParser$OptionString.classUTuR]oA=SHVUj&5>ħj|12,Wf^|դ&zw$3g=ΙǗoEƑpڶffxo<ro*7H t  kR\o9N&R\y/;9B@k6RiZL2IIghsB0+q# 48(.PP,,(5[ 0jPE .odxlq:pu w֥ѯ|S|SVv޼ť}bVӎ65a ˱NGl]dEdc[ZVuU-q˟~/7078L亓M3=,2]P9-8GPKKFPK!? org/gradle/cli/CommandLineParser$UnknownOptionParserState.classUTSNQ= oWԶt+$10ݽ, ݢȃ Ф`2-E$i3wfΙ3seIrkW[[zQBzˠfnm~nAgLp>udY~]C?.fFVC}HaH Ѓ^1;"~ʣ%}4~.I0 Jl.Ef€JjILdf3rFS֘N#(FZc3+n/j^-3 ȩĶ]juGXb~SC3QXw0Dx*]UԴtKdS oNStN.lM50h.r,#ە]D+mRC\JOz[tz>)VFai`\̦CPP PKfmrPK!& org/gradle/cli/CommandLineParser.classUTU]WG~7X%4eJ *Z##V $HPawHV6qwG^xl=MDGK<9ٝygyޏ_8EgOdg2' 5>WfqŬ4;i*n ]p[b)"9^\EoVNUy-B:32gNS']Q !,(u^X6EL__&Ch-E\t V9]kYrC%qn’d8x΍r0s_( B~:NNMbhze#,cv6q"W5Be`w5ze7 ܮu\iQ0=s! CB C aBKoF0}7䬄Uؚ%E;u;N=8A\K_ݭ=Fhjc}]d (tf{W#ća@W!4t< gSv_a}b {D,1ꔟ))N'q$STqD\gq ,QUпp(ԅHsp%lH…c. u]0EExH0a:2WU[괻dnX(З5-e*jVW(6դܕ^]}!\Κp\S 5|Jz}ѽ4F\NyM1tlhn .ɪR Tjnn-T/gάe%֛$G5L.Ʌ,YP"W}Q˜]JslNE2}fB~в4;&VWDB`!s]DߋXt"}04p(ѽTa8ZVNL~{mP=8iwa?uCeZϩQ׫3,h.$1۔1SmfxǛhD͛u@4YZA5FVp8~ lxh2~9 $}9D7/=N _-\Gp#ZF?"/#?_#W 4ѡ+ `m.Md4 wVp%2ʣ=?CgxI~<9]s_ߓ{0OːFc.D2Vц=$LhEh%';HXxc,?Llߒ4O< {_PK8xPK!& org/gradle/cli/ParsedCommandLine.classUTU]Sg~^ذ4QE ȇ(%k4J?MX즻FSQ8CAiU/:Ew`db߳gs_GWQ`x-%lp&#Q(b-YNzk\8}VhfgvR `1-(Ũ*bp>ymJJF k[N=ꜛ'7-Ex<{<` r(~K8C0󱼩d5hjbZP[;i]8gq::J7ptgaB@`w S|V B: 5k՟/"̪+CAU'o(u7PKbǂRPK!, org/gradle/cli/ParsedCommandLineOption.classUTmPMK@}kZ?C1h  m2M$e7) ?%N ޼ o{fw>cKe2 ܮ F܆fHi,," iXK} H{ړR^"Gf4e^ }N-iR"Ҙ1˻}.CT„t4 f&c##M~+*KF-kOv0/>ck~;0w(8 +ݚEi|l)\*(?TQrVje,-a5+/j8|c4بwޱ;oxf9~PKcSPK!3 org/gradle/internal/file/PathTraversalChecker.classUTuUwUݦ04RaiKy(hZ5PM2t2f&-=]cxN (.=ƝK=BNRJ\䞹~ݸ0ukQ H<ەarϰD.;,s7>*ndMW#R« Cbs.ONf$poXOVpU|J͝N ZC3|TnYCʨp| m%Pa\Fg$ķcwWױ~ 4bǣlXN7x+zSwq+= iؕ`O~!heOCe;X~ľ8PGn^q36;Lsu䧰_l_S|k\`4s1\è4ƈ{%=|6˅p=#Xb*A9(o:6w;fohkjA Ȥf/鷑iio 49~E%t*joV>[Ϩ.b7_Ԁ=PK VPK!A org/gradle/internal/file/locking/ExclusiveFileAccessManager.classUTeQn@}$uƴP>Q] "$T AQ9o6gڵV~?'(`lq`;y3w@C4jAvEjEKmd ŔwdHzbr.}}t4^Tfq.X7DȔ.[?aeL["m蒜^i7?gt0eQ{fA0`mPK-_&PK!1 org/gradle/util/internal/WrapperCredentials.classUTUsU&a4|P*_ZcmMȗR6HZ0E-M aտA|vx:Ou'z&s9=|xu~QEr4UjM[3d,q[\JRO\]oTѱy"Z$J- >wF%]ktӾuԗ)bT4sK3*$˭:a|thFxya|F9Cܴ*tjؚ [[Jƭ)ak7CrWIQI劷jK8MJ!>" J]SJefhPl~5WlZ8臄Cx`*pȶV.seR oI CJʹ;+pAxMWTHljao}8͚s 'Ws-wxLJgͬy*C0ۯ<CɆ%ah5È1 !18R4QbHvR'j#Q8I)lT<%O3xmup81dz8't?d8?U0JK+]qEB7>8嬚{l_3Nc'd4*vwp{JWٕ#$_bZ\v-tC?sڞ;a0H#C4h8W-M(ot0MaEP"O4>LMx@3F3RٴNQK , n0b]#t#_$|"4 6UgEg@^tVRA#DB9tB 4!|iTs*iڭκ P%"Z%8ANET =Ysj[!x=ohEV!1ЯIp 5ğ!xO/hP1#&wx?Cy)G{O]Ipl!i16 ' !WHKλ$$FHˆuMVw xcpG<G sH~*k d7I&Թ1\Qw/@Nb=,[fb|@|nթq?ǡ NlPn ֞$\Jp}09Yoў9PK=vPK!> org/gradle/util/internal/WrapperDistributionUrlConverter.classUTKo@д.[ me6)5P ,'΍3$DT[$~pP@ K5|3G>n)z^^%Ҫ,K$ }YQbFO^}U zx]5 hBїҒ*%2*Y)Zwi}$f&b#U:P%J32]\>gَXOA6S٤,ɳ=e}祏'TxuT'`~2Ѻ2/ !Fbsc v^z Y2EUs)X_< N;kvIUrݣ 3ZPZWg3!ºΒ5UdZ*lDh)?3քc^Mmj#BG 5AaoмVazȤUdn8#?c]["l*D%zB;6\v.d87eZ9˭+Wf3v/PKPK!A org/gradle/wrapper/Download$DefaultDownloadProgressListener.classUTSoG{v8$@&[c Zh KH07YAʥ7=q3RV=AO7˯Ҽ7oͼx3g+կ5nn2 m9.+w}KP<ࡠfGa 6wC1crʎwcܦ$ bߘp?kV1Cݑ>Yu4WLQMp)A5W,*8I$ŏNKXpJ}}SPq+9]knu39ZibypP#H"!ܸ{&=qwMIWIy$9yRD;"FhH<J;O0$|T&'g{9ZY-kM=?1]Lg5n53-Q&(,Vissw|?} *^z5zpsM8Y}H7Wt E:ds/n慹 >mO \q+!ĕk\ol2;I3J xHm`qXCa#~Υ𠞲P(gCIak7۱j/R) a=tl %3a%3C1,g޺=0?%fE͜7'SRjDh;j٬anͤL=~DoK陡QSE2,G`QA!˰Hv2Aĕz.=3ȅ=y+ tʹ0d9T.=M 2sԴ&ӆs隸V, %67w˼fRZdK2tneиOhi\5kdk$j@ÀhhiK-m1,1%h x0Ҋ*jgkI%~VW*j`dzQws5˾4ݯ&7Ҩ2ncOkdo3bwFTFA4gtI4 Ca1sf "6\ş}"?yʩO~/ۙ6?\]L˯&e;}*9O hv1-&rFax\2v}VRnjUWd2URQd4LOG؝)vq{L6|!+VtgOu\("LU@n4.A6v\'CH:dضcq#+j(t9X mgDudD1Yݲ x)tk[Q} e|d7Q*fԅf-ZhtFYÂ"Q] "F~w"ӇIZPǙVF 6hN^;{{f|^zRT\}Lٷ7Rr+pg}N?.Jё4,#; COkakK圾ɲ3/Z{Gѯ0MRv}Gǧ@DO g:Lgaj 9I|= iDbzL25i|DOcHq=ϡ0l:q rz_!gQ0f`e^㾜a;j5´-E,=gmP xOaOCl:CMizO.}3"N7QuNx^t<-%ر+SU$ϣ9y\24<ʴxNqGc@2s 7 }Y(M qHx)4W53((s).g"`7>&5MYo0E͒Q~_!(vN?>CTvC?À Z-o8!;g>:G>4E,I[.jfb!__{ H]rYHo$}_5_̥QGwrv0XJ;',6z3FG-k(sG _ߐu@nSҴzߙXhS~/qǟxʴ? ސ{)Zfs}pPՠpqMloyie'(, Y&$x|Zs*0k _+W^BP LWkfv6hly!SKk|\͵p"D&rR9Ci/Ӷ C^x1_;Q^:B*MZFk|}5VyS:9b6"zz 2}PC߆&)=`V :P z:WFLp.{gaH#N8{SO!8*+y 3%[gٻeTh^M7"Y@m%rg _sjқ1MWUP8dByb/\J`2zmx[m[ᑵ()} *=ƛ8v,9Rvmp {tƳ>x4Mq: ʧh2M]tΑ螯eBw8?tW;ڶ|=23,KuRE\8ؗ1eTh^ ?#hhMC7OkᓢVZbSȏL5 /`rwQ^>%}G)4k*mlXeoV%S/ފ9(o#x+M0?)WG^ f0 +VɌѓK CtYHTwу*10j|5.5Vb~#44DѦq ĺG<]P#1ڄIejv] UBf;C[PKnf╦gjLFޤ&4<Y<.^ + Pl<8J[Sgy6N;bͣtGy\ztY#W@} q <͑<ؕ[4i8\r}b=NfQr.*&UbkiPr5mj\EkO<рqE5N@34<{{{8p?O+XXb-QD>c4L>'kӯM|AWhG|^mo(]ԯ`>D)XF- , Qgs Q,/$_+XFCU~` )XFx,X=e|-^Fh t" 9$w'0+c ͞I<2m f  XЮHH+łGA"R .MbIF$KdwQ*I`PT%F\RNN#Bm2$Z\KT31Ar`eߠF0kX##6A (,bc|KpU4mz|shuh{ã|:=|;u.K%t%cpwܐNaO(]8e~`s#ic!9mHig&z-y~?$Գ|\Mto=+ָgT2P܎"aY^f(x@QVDynMT!:-S.q+jx-\b \6xڽr?Q8ēC6|p7)qܩ[ԧɧ));Vމ{w+E0] dQ"(Ieb8`b^?u(|hVk-?^W1Ojy~9"C8 PKݷf<PK!- org/gradle/wrapper/GradleUserHomeLookup.classUTR]OA=C~XQPTtU( ۍIC &>5v~ev! cF?xh/3sϜsw_(]V0'` f^}l 'V  NPK}ePK!1 org/gradle/wrapper/GradleWrapperMain$Action.classUT5N0  t3D@,` UqB ^ҴJڂ؃(x ?O>+\J]ʙMZmrxXaT"}Di&[jlw_.0gmeX:%XO7L o1y CM֑&,eۖBv>uhѕNaWzݭ֤Bxar|`RCec H~PK+bR,PK!* org/gradle/wrapper/GradleWrapperMain.classUTYy|T?g;'C2"&" 2 qM2237 UY5,Uha& R[Vh7}v7w&I&_OH9/܉'Ә۷o*n5hvWVh_8$ZB*jDU*6{7ثw'RDECI}=ި 倍/w",$zy$j<jO,/;n7W`'fZ*Tׄ#*S+Z'k֦cYf^+%Sj5dbigo|ߟL4Vme1:$Le=jrc\KXl *FB @DF94Jt3h&i8h5eH̴` 2ΠYLsh6S)nL(&G4&l\r419w$ZdMj[6NBkڙH.Dkg#Q1+mU2-s`nNpU3kR1roY92PlepJF< ?B!r2ÃtLL-KI1D{9]\JQ)f]}]=Y^bx\KtiNY]$ GZen5$ '/1vP 2Wx.T6 Bi|qM+CV\&+gyA:u/8 = yLnJŒڲ7~KW+tԤ"B}P[ǻ/Wu ]e%g'i qb.AW ? ȴY(|~bIeo;gmk{.tlN#6la&2|] kЛmGJN=a5a0 Ə("sy18P1)wSDHeZrjDtq4d q9(ND;c0X4B> a6O{]J$6ZF>kKszt MW"ۼxQz4&YpiߐIE!>X쌼c4mt;N|M*&A4.71HQ0I%Ñz_8ZaFL[;n u틨nost@l+ZN `<Ց+|2AS< ~V=S z@&SwPV%$8Na} uܰlbՀ*W٦Og M"m> t$DsZD\{})cDdz($ ˴ĴdPJ `bZq Ɖ'#SseP]+rR=dR+5|,:T{R?rP+~hAսIV J_+8z\sdAг9kTRqR m 1*i1^ϤA3|uE+:L7/cE0M&{l<V⹐Qk󄆏|DN'gX E_qڹTL:)> 1 sj8W"}h*>ټ$7H\%sHεS$2\'RDv>KMr~7N|@8ͅ(M'_ĴS8NLhаq Zgzg3ôh™eI|)ycrz&lR jD]Z3I։NN$y\l0-VQWA6w z 费7"{)&cK >:߉-h+"r+E?->qvDW3K"|-k K48(A@ӣD6>0|U7;$d`ٹ[fUEY&bUU0@ifɔfӴ)hj7as˚-͝k755Z:[6u(Xp̸%i~A&B4s"u;#l o"jT뇂 g6;pa9}qAH|7 OuQO^Q~̷mLWt4mjom_n퉡 DòVpxpxw${1:I pl\G+њZ~yVdch5;E^3"71&"Rd/Z40DI{It3Q4`*zՑ=juVRH<"H͘G#=U1S{ᨪ(g% c^!WBbc?#gԆ4m5YLBfQ]!r\;Ҟ`bWPӰ4 lu2Y 3l1bp_ۭtIԤҭۀď#1DO Y<`j!2%*SM(oƑVM]D"h: KJ2LOػzD6FV+zA92Ӽ"GI(J#c} 譣]z?c"r"1~i紁7NK$T󣌉XUf,\&k3 .;?czl8FriCViZ'̦vHI_ɻ$QHgU)Q()d>ĩM.ٯu btgfⱘ_Ek3.yX{#.yC*o *k3)/, ?LmX2̿*h7€(&ALթ4X7d-%'XSt$V{!o= =#4X.KL 60}iuY7)M];)+P?4<W4 |%uiMuh׉+e1@˭HoHnduIq\ۆtFhz;vlYxn(P%:ԭ.[22 TGg`~'qaj]f/48貖-W Q v7XvԜe!V 4/,E#H=ni^|=i񬆭ixYV4X&O ^yYKx)\6s$Yfugה 7sSUvnN2nM889 .Kk wm.xkS͹>坖/WY>Es\6͜ (# :j{2{xZ<>Z~~%5geSWlܮ!.g,!.uI ,6J\vWIN b*1=D7-v;9ma[7H %XvwO]i 5=@F4jG&G2|A?hVp0?ܙGk]'xyɲ_O%.Z0JI2r/~I4ѿiD5.8g""=ڋLW(-zh d*,Ij@sBJ6ΚQ*%6by~޲D ޤB%BOtKU(ͷVs/^ny(4h{1BKQAWn*nh!HN{Q>N3%Irn2m4t;^٦7hmkM.|g^D͵|1-43ͻh9DntyUb2ζ,s,U%B\BՖTcSr#[s-@Y Fd; Fh^|,^$ [Ù"meOw*(/2h;N3kX$ּmv[qˁ4 0f3aCuRK-E`8W 2;cmWM掴6m2fB\2ҕQW@uK:a|Xr, &oPK'g+'PK!- org/gradle/wrapper/Install$InstallCheck.classUTeJ1XZWkƻUu7((eNd[/>o^>8[OH?^laV;kRtwܰ603eċ&nHěmiMiImfS 5|5 -I"DvX>`ms-uF *iDŽt4 ,&##;#\j1(0y#2 2k(oϨ/wYhI;NZ1Q?uȋ25 /5/_ /8b5ՔjܔgbZpyn%rugϘ~hoQPKyiPK! org/gradle/wrapper/Install.classUTZ `Ցy:~IV'B09l@@ vbb;'@߱,IRJPG8 mlmhKviKʶ-(ɲ#B{o޼y|Dt';~˪Z6S}"‹D2KSM>3iƲ&b٦ߝfEcɬ^4i06Ԕ|YUͬ*'Ě KjW"eDjz,B泚W5{CI3qsC"i2-HgvfLlh̴tX2i؞XK2ղj33Nw23L'wVߩW3y{St:{3b٬9؛*_\΃I }d>أ767ٮX*U;\B"33X-t|7Բ~>7J0]QwMp[oKuȠ hi&C^O>oO3۩L(ul.͋nIsL:'- Oɉ?yش]2hkÚYh1>嬅 c ^liO'Dh5k;!iN]}S|H`MGT/E?IDLt6S̈́赙LLiPVU%h kCl0ևzVϥd>md HdFKh-3]u6yBg,͞KP* ө\, R`tJ}Ch}\:ԟH}x.9ZVnzO:3Iϩ;/t!mQ=u0?61-~cWG&5'ubD 7wZC ?jXr?"~*o_2#o}cAP2Kt犯lTlPNH7JV1]ƾ"2Ւׄ*~qvbZQK=6-_]H'%kDn Qm]b)!+skoIq*iCe0nJj\Z1T)7MCbkOm\wm"_Nzzx :ދsΥ79]RtyGw.s'įS)u϶CLMӻ43ɥέkw~_O `OZ9SH?pt23GHXL}D\Pm I}-M-ME* ƆC=f4S\lqAoo"7м4՞N'2@,3tF䞁nmO~P&BǰeE&;5㈬!qP"H0'SB Tc 3A\&Y6VZB2HhiPg2]Eqpijm<)&\h FZp,E9t?*͇$oYW*YpkCL +ҪNˆrYbBOVPR>zhrT~h'Oׄ*c1蛸s}To p}Q-eS#E 3l(o] yUu%cs5p/ܲv]zoٹqsz+wJo[lLKt9L5|粔o|n88 48Or -E6B nh独MVeuW`o_lĭ[r&S9f7ϗ6buSlф=fKVc,`zOy1dIg:;?Tn!ɊHd|Q'ٞ킡!=m!ԟ΄BNHV{Bu NN~Cl4ݓ[SE~k|挋Ym8D܅ٶӃR@,2YmvapD`M3{=fdb|~+?r##P͓qLo/{zv)c/'\rx"b(b^y|$މMԾ ||A~?߁19)<R+ZumKk@KX?)b%*wURSSHgoR?Q<4@(?Li_}*1<א^곤DG%~)cs"ȿI N@oF=a\ ԅ~%coϠf\|@DDNpi4HyZg"?1ܱ!KMA@&;_/>ʴ2T1ҾT}ٰU!R!BMJOq1p f=&a=ue%2n[~]Y)Wn[ gִ+eb~nm.'еZ͡Q-zV"u4H NdP=?ģN!?N&cW%$?_x "Z3f=^ɿ.ղ0#o~(/_N{ AeWOgh G+ZCgs˿ÞȖUL[Nv?6:<0w*w@+*VW,;܈e0uR[N^SIFU>,0*]k5 +6g-9\6 grO]!NyL~˛,O~S1T[3T&ʙ}e׻O(O-4ev&rڛ(݂nS c9A!x`"+!+R^ԐNbbQj[R*BNNoXGat{E|wWlh(4K.dw~=?r'KE<ŷ򓼦~L%G^PC4cyMtRãl|N?JM‡tnJf0ύ7;7F-F|Ίnz#/7ѮQZG3=@ hUot›#\TMƞ9M3 X-lx\v5̹|v@T+>LWj;vYǝ7X>BN~\~1 aebQ%qf98r7chEi U:E c)8mJqO IłwCp)|^IY}!$9j30Fe]qήz"S䟣QMS /#dd?p{Xk : tk>LF[]Vwp榀4~}01 t,[tVY{c t~X|b- NCq:z=pgCAuDq#AQꌐag>p6O ]HkƧg9_<:FA6:<$6q9"}F7Sp*^q9Wi-Y& :^llh<ĎCזh؏#muݍ0A3΀yUO8 |Ag5B3NGUS"(d/k D'č gѠl +9+xDk'NpP".xa}WCP Ë#47vѷ!b4AC5CQ(^("8ĝш(JDvPMSf4m,,>DAÍ^MbW:,5F_(Mp WNZ)np!5|(F`-+.\ b+qOR;yݴ0FX^-~ۣ]ȑAwߊ?驛#twP* Ax=t3MAwc^ݽsd[PYw)*GfLGCV4+~Oitf6ǏzS=:E(?Q?5A?1M)V8[*5WTMWj h("եC+ULӸkO.Ԋ#|+ <% ^<:uTiCg4u>ݣR^&$/e6@RwQF7Ť^BTM|ہ@*j ѭv[ cH|S?E9{pi/G<@i:GU7Q-Pw97[^Hlp6SEb8t)C A6`s7{Lpi@n~# fۑZaڻ$kN3_iu6`D܂#sU#BP;OFsi<r=Πx@ onZjƆ@&v@m,_uG'oR+muL"aM\Y0D},e#;d#lқ Y\;K+]7iG`;6Cѧ5=,=;My*M\na9P jFȱPpog{ːrfZl1D6JUd!pU~ʹ|/uU-;EH1c@ `0* cyq;Z wQ/HzFZX8RF ]Vh+oZ  BVA.p=c c}q >[y]c9ޝ5W=O54N˖،)fbS#?L4lJ-SŔj-S͋J/ y|bٓ`j>|8@߉aUGUQ,ЕbyLGyEH)rAƦ Y!Z>5\H 𨫢qr_t[tkTZZYPkyV#gFc}X"GQ:jԅ=DU=jsACtΝAЀ+8l=w":FOѭ8g8wHǗyMcĖ4 m:J8aW 7vv|¸ 8 B-YL$ZI 5u^OomtkzݫAM!M/i}Uӯ3>OEzY?Bu8ᐦKxM,,h= O|PC5M G}K/+V7F:PmޯmҾO=B}P=B]PPiVPi^}OJy*_t[~Bmh;m A:mҨU>F~,oUc;zې `yߪ[H$M#~rL+` M3@ը鞊: JTPƆފŲ578vU7)e6hjSAѭ۳2vzF2WWu*"y*' 8+j7zo负?*>Bpm+,WC0ɫ0 :s#4, P=@9jUWR@yN:ɱ;DAqzJO%OW/FPK ]9PK! org/gradle/wrapper/Logger.classUTkOAP U-i11$&$k0m=lR1F~BbH`;WCMa?cY`TحPp = oZ5I7ϓoH^}g zh3f}quUb'ō&d z{b) )TVM*j%LL` 3Y#j#\1U-gpn`zo0 ТPKBlq`PK!. org/gradle/wrapper/PropertiesFileHandler.classUTT[WUP&NBK)RƠB.[ P S/x29I&3\,>#}kBkֲo7bg$\\&3g_}9޿˯.cÇKocE iX2Y5[7[ffa RVҪB[w,sɘ]Iո%L,:=o$p3<$}\c(,qo?Sc0U'?5H uSRQXy-_>=E(I/ Bb::m8/)~"wX;7Ƹ&"ld-2"ܺi3{ղ!ܐ/_ٜぎ<^M]@MZRmNdw>e``(3ށi_nm}>> RRY"\T}u<.Yo?6Ew&n*J"{$ؤ&%IT򘜲5b;ۑ؎ƖFkiv"^Ovy4ܥ:fd_8>>?`:I3қޜ 7 ; q4_ඊ/c%d^oqVui%(zՕ8kApO~8|_/??Zy^׵?T?Peg|S/U-|Nɷ9%=[F퉾5%7ye~ [luVǴH7*B6+ݚ3 7nMJ7jm톍Bև>LϬw1\(['ʞ^:)85.z E8e2!JUxIޡDNIhAMktfO Yvm nzdEbsx{ŽŰ| =9|YR.ъ 6yw}8& eFHfO mtJƒiKCy^}D{nG+{F,s\F(o~<T7\kY/U^J~+t ԻFu,V~uUQCc0{O܎ͤoԮS;χ0\UD,d:`43G*D?$+tf/Y6UƙQ?i?>ƿc xN9E_Ԅ41H;Kmny 5+|K!=~-GTGBv[ Z(L=_E<^ܑ64*/ќf w#$gњD[ 3XQp"qAҋLWEߵCEl tG\B 馒3OnOq! n#)Yҁ"L!?VQg.-<x?x*Jb9:#xqݵx^?J IlPШл)xg2;!n<4.=HxFxh<9Mz H{1H-`IO)zƕ @l ƲD:5`^bgB@ +v6D}DtR6&dֆӏ&ȧHFzK\m7BhQJvss >99^ľ񗼌p]+!O-vf,yiNPIL$6yϣiw"rUfSOuf dHc 5Jorg/gradle/util/internal/WrapperDistributionUrlConverter.classUTPK!/ Lorg/gradle/wrapper/BootstrapMainStarter$1.classUTPK!^rKA xNorg/gradle/wrapper/Download$DefaultDownloadProgressListener.classUTPK!-A4 ;Rorg/gradle/wrapper/Download$ProxyAuthenticator.classUTPK!ݷf<! Uorg/gradle/wrapper/Download.classUTPK!}e- eorg/gradle/wrapper/GradleUserHomeLookup.classUTPK!+bR,1 /horg/gradle/wrapper/GradleWrapperMain$Action.classUTPK!'g+'* iorg/gradle/wrapper/GradleWrapperMain.classUTPK!yi- |org/gradle/wrapper/Install$InstallCheck.classUTPK! ]9 T~org/gradle/wrapper/Install.classUTPK!`]-YZ org/gradle/wrapper/Logger.classUTPK!Blq`& dorg/gradle/wrapper/PathAssembler.classUTPK!70f. !org/gradle/wrapper/PropertiesFileHandler.classUTPK!#IZ- org/gradle/wrapper/WrapperConfiguration.classUTPK!u ( corg/gradle/wrapper/WrapperExecutor.classUTPK"" libeufin-1.6.8/gradle/wrapper/gradle-wrapper.properties0000664000175000017500000000043115221677432023522 0ustar grothoffgrothoffdistributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists libeufin-1.6.8/README0000644000175000017500000000425714674637415014452 0ustar grothoffgrothoffInstalling LibEuFin =================== Although different versions of Java may support this project, the following steps were verified with Java 17.0.6. The following dependencies (names match Debian packages) should be available before trying the installation: - make - python3-venv - openjdk-17-jre-headless Run the following steps to install LibEuFin: $ ./bootstrap $ ./configure --prefix=$PFX $ make install If the previous step succeeded, libeufin-nexus and a command line client (libeufin-cli) should be found under $PFX/bin. Additionally, the libeufin-bank command used for testing should be found under $PFX/bin as well. Running tests ============= Tests need a PostgreSQL database called "libeufincheck". If the database setup is correct and LibEuFin is installed, the following command runs all the test cases: $ make check Launching LibEuFin ================== Launch Nexus: $ libeufin-nexus serve --with-db=jdbc:postgres://localhost:5433/$DB_NAME?user=foo&password=bar More instructions about configuring and setting Libeufin are available at this link: https://docs.taler.net/libeufin/nexus-tutorial.html Exporting a dist-file ===================== $ ./bootstrap $ make dist The TGZ file should be found at: build/distributions/libeufin-$VERSION-sources.tar.gz Exporting an archive with the three executables =============================================== Such archive contains the compiled Bank and Nexus, and the CLI script. $ ./bootstrap # Needed to silence 'GNU make' $ make exec-arch Alternatively, the same archive is produced by: $ ./gradlew execArch The archive should be found at: build/distributions/libeufin-$VERSION.zip After extracting the compressed files, run the three executable found under the "bin/" folder. User interface ============== This repository does not ship any UI, rather it downloads one from the following project along the "make deb" target: https://git.taler.net/wallet-core.git/tree/packages/bank-ui This way, the libeufin-bank Debian package provides one self-contained solution including Nginx, LibEuFin Bank, and the UI. Note: the UI an independent Web app that could even be served from a different host than the one running the backend. libeufin-1.6.8/gradlew0000775000175000017500000002072015221677432015130 0ustar grothoffgrothoff#!/bin/sh # # Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # SPDX-License-Identifier: Apache-2.0 # ############################################################################## # # gradlew start up script for POSIX generated by Gradle. # # Important for running: # # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # noncompliant, but you have some other compliant shell such as ksh or # bash, then to run this script, type that shell name before the whole # command line, like: # # ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # «${var#prefix}», «${var%suffix}», and «$( cmd )»; # * compound commands having a testable exit status, especially «case»; # * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided # by Bash, Ksh, etc; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security # problems, so this is (mostly) avoided, by progressively accumulating # options in "$@", and eventually passing that to Java. # # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # see the in-line comments for details. # # There are tweaks for specific operating systems such as AIX, CygWin, # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template # https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. # ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link app_path=$0 # Need this for daisy-chained symlinks. while APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path [ -h "$app_path" ] do ls=$( ls -ld "$app_path" ) link=${ls#*' -> '} case $link in #( /*) app_path=$link ;; #( *) app_path=$APP_HOME$link ;; esac done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum warn () { echo "$*" } >&2 die () { echo echo "$*" echo exit 1 } >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "$( uname )" in #( CYGWIN* ) cygwin=true ;; #( Darwin* ) darwin=true ;; #( MSYS* | MINGW* ) msys=true ;; #( NONSTOP* ) nonstop=true ;; esac # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD=$JAVA_HOME/jre/sh/java else JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD=java if ! command -v java >/dev/null 2>&1 then die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi # Collect all arguments for the java command, stacking in reverse order: # * args from the command line # * the main class name # * -classpath # * -D...appname settings # * --module-path (only if needed) # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) # Now convert the arguments - kludge to limit ourselves to /bin/sh for arg do if case $arg in #( -*) false ;; # don't mess with options #( /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath [ -e "$t" ] ;; #( *) false ;; esac then arg=$( cygpath --path --ignore --mixed "$arg" ) fi # Roll the args list around exactly as many times as the number of # args, so each arg winds up back in the position where it started, but # possibly modified. # # NB: a `for` loop captures its iteration list before it begins, so # changing the positional parameters here affects neither the number of # iterations, nor the values presented in `arg`. shift # remove old arg set -- "$@" "$arg" # push replacement arg done fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. if ! command -v xargs >/dev/null 2>&1 then die "xargs is not available" fi # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' exec "$JAVACMD" "$@" libeufin-1.6.8/presentation/0000775000175000017500000000000015236145704016265 5ustar grothoffgrothofflibeufin-1.6.8/presentation/.gitignore0000644000175000017500000000003314674637415020261 0ustar grothoffgrothoff*.fdb_latexmk *.fls *.pdf libeufin-1.6.8/presentation/presentation.tex0000644000175000017500000000607614674637415021543 0ustar grothoffgrothoff\documentclass[pdf, aspectratio=169]{beamer} \usepackage{graphicx} \mode{} \title{LibEuFin} \subtitle{Libre European Finance} \author{Marcello Stanisci} \newcommand{\boldred}[1]{\textcolor{red}{\textbf{#1}}} \begin{document} \begin{frame} \titlepage \end{frame} \begin{frame} \begin{center} \boldred{People} and businesses need \boldred{programmatic access} to bank accounts, and the \boldred{EU} recognized this by passing the 2nd Payment Service Directive. But it's extremely \boldred{complicated}! \end{center} \end{frame} \begin{frame}{Too many protocols..} \begin{itemize} \item EBICS: hundreds of pages, just for {\it enclosing} payloads \item ISO20022: hundreds of pages for payloads \item FinTS / HBCI: hundreds of pages \item NextGenPSD2 by Berlin Group \item Startup banks: N26 / Revoult \item 100\% proprietary: PayPal \item .. \end{itemize} \end{frame} \begin{frame}{LibEuFin} \begin{center} LibEuFin is an Open Source \boldred{service} and \boldred{API} that allows developers communities and SMEs to programmatically \boldred{access their bank accounts}. It \boldred{abstracts} over complex \boldred{legacy APIs} and provides a bank \boldred{sandbox} to make testing cheap and easy. \end{center} \end{frame} \begin{frame}{Improvements} \begin{itemize} \item \boldred{Unifies} several banking protocols into an abstraction layer. \item Enables development of FinTech apps \boldred{without "clouds" or third parties} \item \boldred{Frees} application developers from implementing \boldred{difficult cryptography} \end{itemize} \end{frame} \begin{frame}{Architecture} \includegraphics[height=0.63\textheight]{libeufin.png} \end{frame} \begin{frame}{Current status} \begin{itemize} \item One major protocol (\boldred{EBICS}) implemented \item Current code works with \boldred{real bank account} at GLS! \item Should work with all banks of the \boldred{German Credit Union} \item Ongoing \boldred{integration with Taler} (former PF project). \end{itemize} \end{frame} \begin{frame}{Challenges} \begin{itemize} \item \boldred{Slow communication} with banks. \item \boldred{Significant research} needed before starting coding. \item \boldred{Subscriber initiation} process: mixes digital and analog! \item No reliable \boldred{testing environment} available. \end{itemize} \end{frame} \begin{frame}{Successes} \begin{itemize} \item \boldred{Milestones estimation} was (almost!) accurate. \item Our approach to testing (develop \boldred{sandbox first}) was successful: real bank access worked on first try, after 4 months of development. \end{itemize} \end{frame} \begin{frame}{Future} \begin{center} LibEuFin will be \boldred{further developed} for the \boldred{next 2 years}, thanks to our employment at \boldred{Taler Systems}. \end{center} \end{frame} \begin{frame}{Where to find us} \begin{center} Web: \\ \textcolor{red}{\tt{https://libeufin.tech}} \\ e-mail: \\ \textcolor{red}{\tt{contact@libeufin.tech}} \end{center} \end{frame} \end{document} libeufin-1.6.8/presentation/libeufin.png0000644000175000017500000027737114674637415020621 0ustar grothoffgrothoffPNG  IHDRlizTXtRaw profile type exifxڭgdc ؈ف?AV5M4ꊮJp1^?+eK=8x_WKuYcQ1 ^߾}0k_u7/tgjYּsCj' 5ޫ&>ݔd;R\z:f=L&vZr7mf *c6_??<2&B(IBݑ#)wj|;[=QľrlR.?(שR,ߝI,y,|^>ɕ ֖)yOݱ0YXU8Gͦ.sv*}|{ʡALlҘKBa>NّwWŃW:'tj#]F*bHC2L*;C]1EƱ!šquPP0hQA& 澟2V@[I-R{܀)A!>Ջ"w ]HU}mU }D 5"wGݹ9j׫_/>3Nm~Pum`^Q[)jL>Cu|eT?7MS.𡝸fJaSTࢷR1tDFP]+.RߔmgH.3-CPTq@W 9 -҆v(F3Bݐ;[X ]OneDwbzaC Jd\8Dr 0ff5t̀~b0r\GmG{~9fэ Z)#5*uԵ }}-CV9@8ܱ܁g[,wI5dH/qOodpl4Ӌ^1%ָ;[) I0d NO iZC}vcfUtw .dJA9: s6)͂<#FH(:SWi`knTɾ[w]פI1vݸB}sQ^pq.; ěQ;LdIxuI,7 xɔfxdqyko/% 6ҫ$r ecudt!9*O |O(!))I.}k G/nMaӒDT=: 7ahHӅ%`'݅fq&^(%c  -I.vWQ7DZ(\ 6d(.9\R62Ant?K$ P[DۍN*a LA9KbD Fx'4 [b#0>I >٥!͕io2µ%.)`j!oRVH7C8NǛ}潂tF飈AaTGtFyֳ^rg ԈI[PdL\B"Re[J8D0}N1%;cd Y6BwUa0<$a4ޗ~qSpɌ䁙!D: Zd=("IEiP]Vc@y(!t.GĽ"éK|jDhL.͸ D"e0 XB@tHeu[:ȴ_4Eq7Xjt]kˁHӪ0yqઉ4vUv44Cʎ] L>,J) J&)Cj0!`5QSX$$^H@df<[ɐ5 M; l@G}VG{ |d+nx^` aPھO&hZz$sE2p`t޴lyUKzPU%dc9g? "x́@ky."tKKKHY+mܐhQLh5E`XWǁkIx%''K~{܆#K9I ,Z&""*(>Rp-mA ʓ2do2q!ض1f{ҸZ`XZ,UKf_j[A;*9Ң2m L !CЦ־dCI+aw] :i͖rZ+h 3: 5^ލk`*J BbzLJ$h'v1Q<&g5_͛ZB1,>:j!v$p` +xPU[~ r<-%#i 5] 멅R$xa4  . r'}c<C d<8R> !6Qo-Pr%311n rS O5-ă+# ZaEon M k' 7L E1H >6ZiP UL- hk.@M~eLUjjE"ݕH, %֔@SQn9d ;'e(61oNgX(  'P~aPZp{ #|UZc*jKo<-E 0+s,Ja.6*b0؍/z?5yg4"S;|Z(Uhy1y '  z(2&7ڄL]~xuP70"\ kNqG |`p_}E0ĺ򔪬"񢖙mT=px(EI<*Zv% 0 ǞM n9U,(N0 .cu"lk! rY֟ mmL.!6ZކVD;@ .J@^u2[37?!>A0Ǐ+sUcDUKDž/ E(0~L~fY lI>vZTi%$mւkȋQ-N CZǯhep"pϸSkT` #zF|1T:Wb4T N-HYbG(5:T[N9otEI6>|1P8hGۻY6,Ju yr}Vo2*>LL[\\R܂_Z6ahC-Q)6| K@S},Z,af`zh :[RaFfW M4ɓzTi~`*b`6b hinkk7(oZpt#ҸQMi4r(JфkvmԄMWޘ=_.{ҭt1w+!M<83eOz:_}vhpit[5u-qנVu0`X6mш{ƅ"Ho$hDQZNW ҵBY3hRSzaȰ^oV~LPZq!(@0|ȀGK_9 4]lF&8J pk^b5fÔSθ} sQJOj^ AyZ%a P f$@a|֧4[SCK{@|SZѪqTԦ2lKVOK~T͢""aZM7Fk)yxXKv⺵e$PU&kFDaG-7@o.ES tnpuzYf?Z4Pl8tAkA`kBOl,vU >XC@ qGAIfz2N C&ЊV+M7Ó:xL;.kǖzmɠ_>̴eATE zJ4V V@N`B n#NQ^1:zKW!HSPQ TCGRc:it:{`4WSu +DO_yDa[+ `R<kZ@EHk8/g 0ؚ G4ŊRWI3rޯ\BP.H,k2ȟcCiadqhdE AUqâ`CESM+kCh&FP@:3ڽ4%K}KRIcOgɾ?x2Ν:KC\C$х#6h2Z؞:tk*S[;qy1sHIim s l:gJFGš k ^';SFh#+gti:"%hr04vyGb\Erjo~5IL7m(:!KƷ( D.JIt:]Jο$3W;['[ubCKDg޵"A;|BԞo׮1Mn4}4;:Q`-4H|eH#qozI~!: U  g*CS p7}N%!hD<uuDϏ5:SnC{z(bQfI3sBio8BC 8bDłOhQJ+tz hz#}S3j\' dt.m:'q`;VYݭf$iCCPICC profilex}=H@_SE8dbATQP Vh/hҐ8 ?.κ: "ƃ~{2Ӭq@m3 a#QYƜ$%;]gs9xMAv |Rf>Iз \\4e"Olʮ)}Szּޚ8}U88F =mr bKGD pHYs  tIME$:x IDATxwWHo `APTbÂ5Ѩ1 1|5b,_c;6,bAEDPPr\mwck9|#y琉e( D dY?_|~YT$RZZ/˒-IO`6>uשO%$SNx9N=U11ѨQ;w_p'hJM4))ISo+ҥZ\}ʲc_v]@ ..]trS:xedԽAWrsuI2Dk{S~ FҽW/I{o߸q{]kx\.!K/i(wfIҘ1fk'Ig{tz|8fS8pOqFҧwos4v^NGi@bbt9j^fi M/z[o:LMZkk#F kWj_kDFV,,4LVfժʙeesd.zrӵ̴irmf#^buF2[k|Q?n$s{8ȴ4dIlӷK&tK֚ndUW׬Xa=oLffˊ sF2g}(Ǚed^zzOTm䘄#9sqm/lY5z1ƼLJJOW#`KݺUN{zqyz W|uYux*gjt}=NHlT˗KRjsuqrw4y~F.P-ZTx}{͞>Η^R^Ǝ%Ԫp=A/ n^4i=D~C*.֤IڸQl[3ftUB%l@.d`P|S9gIoدr#3Ψ5gOIڱc?+(PD|o _뮻tiW~^zI7.\Z9s4mM%_7q~\W6/W^)I_~Y=gTy-S~mX%1Qv`pLRBBݙKҶm/7mWy#mwZ5'4 yy~V˓= #W_?跿ѕ)B /+7~g")e~h'(͎.SgdW*(ᄑ]8Yfz+/~sVhW'˥ѣAEE;W&IoרQjݺR4wnq8X|j ァ"IڼYJIZW! ScfIշmh" צBQPEVHHۭR*<|'%Kc/$I=+uxHe2rNPhuVͩ֬ԩz5q^{M'k=gOXzdS]4ol[ÇW;V^|JjoZeiƺ-~}4R߾/{^L ۶… GCKzC?A<{5F3?ʗ4I?5cӕ+%iQkoTY;Oɕ3'OVZX\Sʫʂ9r:&FP@@/#NرWw_Tll_x͜ntŚ0A]*"bWzYٶ.HÇ4dnM%iT맋/:lzQw$͞SJr tEu}Mp}8*\EQ?o;՚9S-\֭k-ӽ~A<]tyG7cG{7N￯aôy,P?_ژe2rzh;4kV]j&}6mRϞ\3Ϭ^m[}.Peezm^?AP9|}N>Y˗wiq,%Kt%ԛojuR]'I YVݧBM+ƍkmm IZR2\/G]'$G[# =]]t_6tk׶ qg%֧s+@UGaʇ_%Q֜:zX㏋:TcuNV=Č}]-͛$O.\! T#A8=?;!Qsj/),9)wm`o:#y}ŧVV5eɲks@ 1i g_4v7Y]~흰^=TeR⣭OM=wo^&WWXW֮%+kDuǞ JҮloO>eSK洉k1SRgVvS(R`c ACSGcZlًf!ٷ֧Ƽ5~x!:~5/f[ɧ^sRsqFME:[%][.8p~97'7hq1q{|=Μ@Qat~ԣfzU[Y92_ˎ]ɲ4ĸ [-bBTSdea|w]ڔW).?sjܺ>' 90:T#(Џ뵥!1=?k{vh#A@M'(1y me9^\5g-'  DиNB!4f/d ͷP߃4}4hhu?دj̰쒾}1@,\^0ְOaMbv⣨QܯU5h3jpPWF nkX= ޔ>-bQu-~VFh((|Mޜ8*ҕ)*9]9>!jޑ^Np@P϶g.ձ8ڢR{sB@#0ҧ 3O^/Yl]m^:ӑUsrKanSsNYE!ʳt8/X֧{H(p %ٳ5N),hWȒqc[1%tƶ+ڶ-ۮ Q11SlKdqλwecր58K=# DzV_UC;AIb#v町KϾ_4]Q%2*ƁX:_f-0m2"3̎){LU[ DuֽK_kLJJ2e[lz@~%tM VM0!5UmJvD9\.ӧsŃzra(b׮]>w]5'::;vl.]k./TN?8mGjuh-'l:‚&93UsBߒQ)nB+++om۶ <9rd\\WyGBv:GxPw%A5;KZlQMd~Ni;CsbW-i~\! М_zB/s3&22ro|W$w%43~Pi6mZ(A5cvh۶mL> uz7]e)hݣ+!w]`Z{?/Qfm]tѿg}^֭ޢESnܸSNMCZ/ܩ9*w7|M9u暢ܤ4(Vӳ5|M@47Ƙ?{sΕ4|~ꫯ3c7HP N5T3U0Pي9aVarY߷3#m~w CWng??\3;BY /™gzyu׽;}=?I4_7kf oN>T`*|߶$ל|f'И$d=A.ŧqZ' KhnJJJ+2駟~GZl<P$TЫAʜ[.%dCr/N{/sYH3Jg+X"էڒ}ϛ_d! |_C/?waaaS%TiPvӬC\="N#OlI erwfi8Y늓}r1Gh)> ժ! IDATYha1|G@47999SN}g$-\3ΰ01],Aլjf $vhAٻe'l^=„kn=gТ92,GL-vo׹:2 44NveAh~ӯ3fHVjS|1viORTZ}c".sWxhW(X%s/QA˘#R|35{aioQf.YfI3f̛oٹs3yI4:]HoL룦(m/i]jmY3*A֒AjL|eD:\T-էAڐNjrKhn222Pƍ1cF۶mSu8 z[dY՝s)f=eϭFcoeھh@aN8 ]+ٶzLPbfg/*! ^{V|gqSO=՜],AUUC5~PASs2u$FF]{3%ɩz$eiԀ{/| o}4s׈xodߔdeNPq$fkH>\ޚp D{筷ޒtꩧ>III$(暠z7]eȍa}Yv[sNRP5%vn5sởӅ)Z)@4C~|'$ 6^HNNnN Sjvjf ;Y*pHs7yfdFTxlKTLI:1w/[cYή԰ev)SghZ}^#Z#|ίS8ڸܜ6 =ㆷDׅ)Z9w-(-ہ2gdyg~KJKKOuF$5UЬ]0Co +kѾ?}}r=#2R~k:Ow相 pY)(dum[ڻsy>VTj(O(7s=J6)w-<ߜt$D8*Pwy'$)AL:|=2Aݥ $j9$u ^\p(ʒ⢃#_r -I. 3aak=[|A#Mq49Un͙B@4K}ٹOuBIͫt}vy=1?uusWg н]k/Ƕs"|潭[3!~m.Kӂ7EСQh'N M=S)fJKe51vsWpZ,trVJKan3MeSۜ몧[&hƬi,"Ah6n8qBI/R$ةO2h,`j=:qۏ{o)k-EI}8**wf%ni]cz%"=v5)E d ?PAA7߼aIwyu]gvsUu@:EKs?AUڱvCoyvtХEfveS*#=v^\jrj{6J Ó$%=ŧR`c/"Ah>z^zwz}|Hgg4郴ly\ިƨG j_2c{(;L.Y֑=T.O7nu?%ByZpɓCӧOOIILIf'Gߑ.sI HOj{?XL! lm߾ MϘ1cРA (ϳ8O1ɒjjjk:𴿙LKR`KWK(@T\\?iʕI&Q&@;5s'p.LM~Br{W$M0owXdP w-(-(p)8v̚5;Աc<662pAB9[n_1cFv(8PTT?Pҳ>{ 'P& KƝgV+),S.%KE۱aq޸(! 1O?/iɗ^z)eiɫ0WnMxIO ExK<~_f̘1 aܞRoO^}ܶ+!:9i` }7˦9߀ӆE! pX^}'|Rرcoۦg[Kxy-]۴KhkD9 >6".ց8$?c՘?0O( JC]vpbwOvA²l{7l?kE;瞜?dׂϾAS.Ԯ5%B tMW_}wޔ ph]z2PYҎ2=$ :. iv7Uk\ؾ zh}֣r=P./\c۞ (cTXboM[#rĬ҄(y㔖:WR|~6rS ["_oM+e7oݕ+:a1! p{yI=\ 8dLo2aNJ~Q(〶vakT}EպYܗҘZpOb>3#·̓[zykPz\~%wxFەlVyGMŅ[;^;jPQ˄@dj\~?&7G]|F\ Dw}<--;x< q+.<9W1^QFͯf,HYeEU"K[us sM&)..KÚc땧UbSk Im_OyAu! ӟB6{.cv| +GcWW&"PTjRak|c8 D~fC^x!--2Р %f_sVFA፾|&"~Exu ǜSޙעf^[?M[Q=!Fd}\E_!6*X5z׿ss\|%G"AUZ-KI)=Ra;rwm ! Pג%Kh%nkzy#6(;xSH );Y7 Œ}Gx! P[AA~iEMyΈܪPїˢ\4Ą3O/\|c"9?_N /K:uiFhPNXSEET[_>*(wҀ1繄Swr@Զz뮻NRRRҟ'h`v~;T7sz+)OqcU4]Q?O>JhP.NիSu5LS*\9 Dŋs=sWS Qvpzv+WNΩ9Åm\\9hG{74#$$$P&Z'?[u^w8?$ (@o|ǒnᆑ#GR A3eAr{KVovEI~(@ӲaÆ+RRttʃ4;eDW>`jDǿp CO>dv(GPyvQ,c#KFƱu;j"{Ͷo벌lgYX FhH,U/xaG$۲dY2eYe$ٶ-ɘ<Kl˶vmhٶ$K<1EÑdCU8̟?ĈƎ;S&@sb˽%'nsƲdɄm(bfo-(Hg=T߂Vf'nw(Y Hd9 QeYrv'0T3 uqũÑ^Pp)))BӦM#A qdi ݒQ_*s*b\N<ʭٗ4?m2vUnxX&5֙r4I$(f͚5w\I7tӐ!C(ٚEy ZbM[Zz(>_lWtľW(Zia{PvT{{N3qтk׮n)4}7zh\5'ǿUt8}WGsE. ;:zli퓽\8ӧOȐSOuؑpDUdGܭ}r_-K:a@{u8|/zyP ((a[67UMSݻG(-~4e˒*{s۶ݶUݝWY#U-P{[NkS B@|xNQ$=YΗ9и|Ʊ$+YݍL;.?S{PQȲjf+fۧضQCw=kUnqܱiaۂ^yI\pѣ)G"zk/6*~UF)V}wǻCOn9up%} 5%,,2KAhx㍥KJCh HP8ќm۶M2ERRRW_Mh,9dS RN D /%''S ZX%znvL bMm))/'zTF,ɲ90f(L$۶C},޽%˒eYe#˲l;+.6bԀ0TV\ywK0`YgEh; ؟{t'^KAFsrri2FTg9F2׳mے,Y(-2r0}hVߪOI(<?&&2A߼߭tKFe%E74,8h-ZGҸq@8ۗ7+)fu֑G˫{]w|>@C3aǤћ½Nk,IJ+٫Zk@JڝyZvo>[?Z4Oㅭ/8+!%@ MphLeA}+1w_@_־rg2r~̺;#H+6媌t~kkF?`K T3|茑q,#]۶*T9%S,Kr uNn(.\Pҽ۫W/ h\ +cWJMe_,ﮕceOVz3=.EȲM{%K¨2_UP^U;vzcE޶eսNl˶vhY媜>h@(##[n M_qatE:۪mzPC48Q4%jFFm߾=JlAёΨN1A%Blٲ妛nԱc /ФK3bҳ[6 [ʢ''Qꫯ&'&&R 4Y|cUG&uL86T4k"&b%sܸqDx,jm-"4 怶^orwߙY:HkWܾiQt#7IpBFm[~mr"ܲ\zXƷ*U#kkq댤׈UZ{_{Q:g]Җ:;.A3FM4 V_*iz*4)%Am0a:Gָ*UWZY(uym${5l_b\s}loswmD2! 1?|hL40K#U;?BR5 skX\+m\=U"=(+:! VXCI1bѣ) ,Σ1Z["VA.o.tG_BQ2q総9o#~bc{,)rYX:&' 1 Ms=t$Рb:1AK-AIRLZkUl􃿤ц(+ |oSzrOc5RC4K>ƍ7b @CtiL (Ssq{=cw).Эw_5wC|LJ}1*էjsvW\B(@C %L40BJT~1'{mZ3n82碔n\ }~?g}9_p0[^#hh}_I\pOh0% S5n%dI֒mjevm?wa%ed-Djp,i /Kh@ox< ګk^J=7e ΐ[~˳_|_Q„(@cXd+"iɃ@48.Hβrt;Oױ&es~흒NDvw8w=ؖ#S{LVNBG0|'C_L4~F;?2:~)Qo8ksr.ٯܿ~DT8OxR }w%-b5G̳msS}'ۘycώ1\E& ?c I\p) U.IUzJPl8[9gi uqL_Yk,Xv쌣g:klk3qd\5`OWCɊ/_p|)hx<3ڇ IDAT?n75pąٲ,Uqwzhڋߞ%'gK Nm̶Zbv%z\E;*W OԵMIdK'A e̜_]K(hLK.>}?Ȑ!#-1L#MN 'Gqw("W]]1:>a喝k_Ͽ̎iNHw{jl$)ͭ(-*Ό/zJ'\c/rY'E ?BkNLY߯y\B D@c 8}-`[ʭ=\LjRmߗhk7ˣi.g7f}ٵM1yۮ"WyU/񹦕+2,,:x8 ,MdNzܦ3g29DܹZX|ЋQ hVi+=ǝ[..D['b#am2hxI ?>2ejTikvMo,)gȿiwϟ&ԐOGpT(;NDW9Bj[isi$(Iޒؑ|0zN:qOXm&c"|NbA?NzYwj7NKiPVzE%\ D@[|yhd & 6pĸ?{ŝ퍥,wA)"6THK4bbI.gL1ƴK%є3^I4[{(jPQA:H_:A g֦΋N u1J4@.>_ 8{xXWD=]KaBu7Ԓ%Kx<!M+osu>t ?m/l17cĀ@/Iti{p@~-qi Ye_'4 BBWz~ 111XP70 *%A5 Ha.ņw NZ=|V( :gWE{8 .Cʝ-eݷbBBٍ7xBęܡN!@(N0Zcu![V7y ;lMF,K-vw-a=#WB^e{[Xh_BCB˖-#GbABA΅'\LHPzE+$\@4)4\#\"JoZIg1A! Q!ԻlݺxwB!BHAPonk7ݴhkmaӶ/oX?n%-%fa y$ȈjMr(R~`W;BHYY? 3f >1k*Pa=V=V"5ڊk@+ 1vPc j$@tw[.|*; u,c Bڵ㏥R)!Եx$<z0x4Tu+֪uX!Bݮ棏>GGx,Bksa#\S3FAvygNh&,(BnT*_=!ԵD1AYʭ]?BR>sv{ҤIXPzi@BbOHA V}l Q!9r$##KWWW,Bk@giNU^r*&(! !z)^_3f >D` : YtV@D!P7:y'/!/0D!P/Sm6\ݞ;w.!B-.\`/p,B!! !P[~wvg% BaB!tW+VcAB! Q!-rXB聁K#P׫F‚ P?dlfB3c0X,f pp$8B۷xR)N΅0Ynh!-{m *F37T75U: Μ/˱h֘W|% >K! !hWbb"KXJeyyyUUZ&B,) \.@ 4"BМkWtߝH0,;*A*tIpH26⢢DB! !D ì_~g]d2]wm111~~~RT,D"X aps}2TkI`x\F,%"{D>Sy[guyA(z~0yH,H2 iii_~Ν;Q.lVJy'N8qs  tuuBs pcWO R wi(I]ɗԨBT<Fh4J 6ԧq ahg%H+cå`B޽{ٍ_~Gu-ŒP&Lp8j,336;;׭[n:va P(|>!ԡ%l>P~5?Eaj-[̿Upy~ ԩJ~ꚢ [PUT_kw}&v ! !uuu}9 ҵw&W_}'EҫW^r%333??o=vب({{{\Hxƽ4pi[Ln>~$$(F7U|{ s6^⤎TӘH;X;K͹>~CmX,Ůh⪪233wޝRث7\|˿⋩Sr80biiaop8"كiU"mZB'.猵o Q<f[\l0D88x .K3hn'Dm.l ćf)O^%A4yq#B qaE e7lB?^jtii&˄avf(ؑf7k1 c0z=DFZvm@@ i6 eee ѣG`͚5/Bŋׯ-))e󟱱xzRcc#{Ű%ɰ,zp9-hPQmvuc6]nxq#F k78Dm?(nۉų<&_>.Ӄ! !/xXsrr>Ez}}}=CuuR,,,|K:uŋ]qΜ9֭KNNny"L:yrBCz Mdرcz?~|xxxV^=t~'(6D)QYP[x[NOuy\ZF_8ktXuNrLPBڻw/1o<\Һk56664i҄ nv@ pvvvvvfotꊊӧOoܸ?3g9r$E 3bbbN8Q^^ZmCCDQb1+k֬ٽ{ݻف/@<;^ɡZev+'BɓlŻzEl%؅˛>tO.5*&&fΝ΄ :t.''''''ɤWgΜj:y=.\ffh|322$ of͚A=BDž7ߡӓhBABa-kײ=r()))((0Lw( v󌌌.˦8zN׺'|yGnݺus΍z'oPϠ̜X oERE) Q!yW^e^`AN I200ѱٳqqq!!!#N55"IolOT<iZ:D{~w*+W4h-_ 3fAܴÀC՛o:Щݶ V|#G3ӱCf@OJ{q[%3  %|_VCBn<ӸD7 7nܦMv4k,CQI$Iw<6///--MRIR.{q*))h4=QG$i꜓'On޼yϞ=Cx7zY+;\T;Q<!-.B4݌ h K4g7h `mp!I Go5uJsnTnY:/7o.BW[[.)D"RT*ժUN:/˥RD"bX$ >OQ!I2''gDFFq(+ V{(LJퟴZ?RTT˗/;v,u9.*sY1gMmIaK{m鎷! L[kKr G$-疋UBu0D!P=d2;vMJuԩSN9::ccokk___Y^^Ξ#vqͧ]s؅%j{W,Zzzz9sF$I$u'"ԭ-0[Nj``:GZw^lCrE07}B0,?/jzq>3@2. AI { æ-. q(pI?fT 6;+ܤy[{7u/{hnQEu?'%%m߾eҥ|>Xtzzֈ  A000\<2oF=F!i<   hJ>A@$B@I0s#81l"&tEyGw Q!7=ŋ}]~~>L0aZy4MW5&h4t:NR򲲲J%8ƍk +**(%BBB222f3(kʗ_~Hә˗?X :.ju-6֌Sl3 ƂtT*7o^ll,EW$BP(uss0`@DDP(,)))))ٿZZB(((X~_~ oy;>)X,{ psay뭷>>p{ ¸8|IޖNr~\97~O5:bp-(Ν;v;븼u7Pޡ666G>vؖ-[`fǎ0u'|ۻC|> X,s IDAT=Q$I# ={ꘘ+V3+z)giھ|OGp0(ٸq#߯wuK!88QTYf͚5!!!=\XXXGcC0{\.N`tرM6}gN>_è7Sך˫,(*C ZxܦwPq ގ^c$mOu2ϼG%x0D!P_UPP/̙3 D&tЎfl0n_o#F6?lU(vNT?Syj -B ԒJPwP'*(Bwf0V^n6 }ܢؽ{wXXشi Z cb\|?x-ڡ#vu$z=ܩ'Χ Ö-[֮]{HgPу 0D!PIOOgW?qoEm}>Ӓ˗;ah`0F`0TTT~]GGP3sIII^^^YY^/**ki>$I>Ik֬9rHhhhxxy^z%|}et\0D!PWh<ԩSeɩ:e2g;5YkаgϞuhZ! Fc/^0̦M`ʕG W&zC0D!Pר裏 $$$<< hn=,??\\\d2H$b֞;wGNNN֌Soͦ۟pimk׮UUU[nJ Hp`_$S>C@ 17>MB7 F8 @qӁ7~$p=yB\QCB]Of7,Y" ݭrgo:G"bH$JmllRH$T*Unnnrr-[nŶkXӿ{6AIRB!KJJ{***lllD"lVlVgNOvڕtҨx|)]fNׁ[m\ Hc57b][ӂcU[G[ea * msF7<:9%-QƲhl%K1ttL  (}$A @$0AۻE$I C0AE$4A4Cĵ__Boiz6^gر7nܼy󢣣b1 ì]"ȚUJ;oϏ7N&=zRTG9w}}}\nzzzUUU߭sMMZ޼yoVٳ>>>"|B>HEemp-OM/-:?$DjC1D!PUPPax}}} ݍabv Y``ELbЉ'9s&##qȑ(Nwuֱ7ϟ RرcGJռO_UVmܸɓQQQ _~%Pa6Z9L :4z&t//! !|sř!=@R"4jԨ;(JPd{|)S=aܟ~y*Ԃ m Fp8z>//Z\eeaJ_ /<ԏsĔtNv@F( Q!g5kְCł<ήˈkZ6qϟnߓٛJdd$ 򄄄IPGTnݺuƍm/ {$''O;v cp 2?ќBÌt .v+; Q!weee=z^}U'',}O*** C/..nF/kJڱcٛ!!!3fpuumD"H$ihh8|ﯧFy7`͚5&>5jPdZk"IZZgFb!CNm7o?oލ[ѭv,!3! !cǎӧOj HP(gg1Lf`0&&&o쨼{/66рFq߾}q=Zdd$_bq@@Gχv믿j+Wvi=U]W> =ZV{kN@@@4g"%J!sIq#I.N$I6/kNA7GםfP6B}^nGDD`AzLXXԩS ligV 矟~iTwygĉrNll~…ީVYl|3gNddO< )Vo%HuQ)uMS{w[P ~Ɔ6,m6 â>0D!jl''|bUPӧ'&&T+W4=m4vUq^_WWWUUURRQ__P[[sq ???uRRRt9sfϞntpp0aرcak͊]NRڵ?{X,^n]xx#@&h01wQ#lϚv%lqX`ce["mՖVrgSi GmK~"!w`d %E6U6v`$ŤfH h5ABd7~aFO(jʔ)~{}ݙ3gr9EQ&IkOR*z뭷Ǝ_BǞs"}6Z="mn-mmUu--mE[):¢ߦ A.k0D!P[ 4h9::oD|MIIIZZZ;t̟?յ8TPPf͚$fHHK/݉ﯓ'OZ Q˗/wss;vl;==x޺^{lO <_}ABM.\`,Y B/Bhhӧ z@(kd2gggGG46:jkklٲyfKYfM034MZZڛoye//qm߾]"wZ~5uNfP̌QrMg8@>CBUsEll,V~D?Qr<O(ejɓ'z'\\\ e2>v9Tcƌ3gNr;wLLLE"|0}`| e*}#{im^c aB;/ &&?(W\iFaFF֭[ٛK,/沲> --MӹSaGR+-)cI ى՛.6s\AKghB |`B!+]tݘ?>^T2[ovQm k_>|x/rС?$Ʌ >111x^ wONnw;^ гN*QW>11BJñMNbom,R IAM%B`h>}C:tO?(J"oQQQxHC v]W\`Քթ9Oʢ8[v6kf?}8|Ã>0P ~bP鍫x?" Q!de˖ ^oQr ٕ8N/y}k׮ə8qI-Zg{JP6@A830}52ݿ1uJ5;Du]HE _|~Y+0D!{ХW-afҴư@ rw QF%I466Yfƍ.]Ǐpvv3нq SE15өi*bW07d?ڛh S(=hB@ A ]:I@|ދS.| _4,Bv!vcĈXwȻ%(6ֲ~~~b[AA  믿?֎=BO~bf-Rϑ_ mԴ|r SJI_r==3K㗧1?zᯨ EC݅ *Bq.1AY {BECC_ Ă E5/a2{na4˫؛^^^'?x!F1 s{`;s {ѱk榤,^XGEE%&&I$0zz[تKX @nx-p[6ۊX{u9kBQ@31̚ɇGAb1u }E,둗[h^Dq$o!l掳_ Q!Ǐg7F+D"QϟO4I:^]_|7n}Oizҥɗ.]7nܴi^}U//OP=z488 OB](RcT߽p8}_w~u%q(&:Ds9zG. ]$Cq)3cb15F}V~ kpz E/DӐQ(\7$eC(B-w5(^z%P+HnqFooѣGb6&1 SUU{'Nď>qԨQ / .. D[lx4bۡW&^r6NGb!=$H5$HBMɋeȱW3\!c25i$\D r7O0w`jP٭84Ux/#p`ǹMCBݓsα8o(*$$$&&ԩSpԩUVUVVّ$Y[[{o?!!ϯ'D}w>s挋ƍCCCL!M j=k{EΑa;doPTsFM]VU=V-BG#%Hk#2*f{u#nQPj{Pdl ]~WBb_ ~[8??A!J*&%%%%%M<חgΜ}c'M'Nܾ}3!M"d0ɱkAmz>>mX{<0(h0}]/91]" \B|BѣpB;;;,Hbgg7eʔ+@RR{cƌ馱|_|ۇ 6o޼ p8w7"gnj[BHF[W}U-7}DPUVmy` 9!pmWˆz+>a|Du= }Pɗr0AaBѼۇ7|wy7hQ;ws=ӵ3 soСC"~> wsӣgΜh6yuIB%-`.lK>( Q!u^mJO?3BWda~' Һ~,HV\3`$"]/}z|)ɗCS^bTn+EDcF` W6 " po`kjVLPBk>}݈j<#S׎c?~|[l={O<#`2+It@`c@0`11\q.T®$$! !h_ HV_t7ިtss+))|>+P%xj'!`vͤi_BB+egg?/ 莖.]b Hy)S`AIm  X k \r*VCBu QFj[(ʣG~駍o3<eA' JX P7V3WTLPB{;v0`V5kllܰaÊ+z -[&ɰ,01iup`ǹM`A0D!PP`XW^Yn9}!C l>s(^.]b7pqsgΜYn?0cƌ5kr BX>[ IDATHpLPBݻ jgJrΜ9 ## g@! ,(^UUU[l3g:::bAv:u/cAB vcҤIXi߾}cƌy뭷|}}> !5' !eddX&++ٳ:t%KaMƆ .{<%[vYіon˫Ͷt4dk4" Q!=zj+s9!C6l5A;Sf)\Uﵭ 5 ! !zNcc㯿 ƍ QGCCk}vTFGGb, zX8Q PaQt(؍S6lؐaÆ_=!!!..kBCBY+;; j˂BCBu@jj*x?O=Ԋ+\.!(NussÂ:bĈݻwaMz0x H5h-M7m~ zИ;֖oa)S˿h m_B~(..f7kA&''߿͚5=OxSSS}فٳ]#\>< 4f,f`hH h ̘0D!Uʚ*c5s9}ڵk !1cc\CBڵk^f{wW\K/}'OƂ #"ͻ&;jJAc8 l$?WôQ ],lC9'J%*)C1D!Ѓyi>Bt:￿vڷ~?DXP?OdS/E4e#tLvxvNCBvE%WoL&Ν; ,,L,cA"ŲdɒիW| !/1en3g ( Q~j96mzGy)ڜ ?u>2Hw]*s+xEU:53qHLv)Cu7;BT!0|PY~;j!!bz1D!jvWso/oB1@ѠV+j d_H+pʨ EH  1UZF02SnrrL7W<Wv(dG< B {]pttj!7n\paDDĶm gu&.x07V\FNDp[N%LVmPră:xF!|Y$Ywnk[qg@hq-] 8f# /ZٖJǯyW<_=W#ӭI@x–C56}jmۇ! !ԿX>?… z-LPMe9jiVg܃mm)\S~$O\hLrSβА'\MmsIGڤgbjMUΏW?4*"znBԝ?mHo~0D!ڦ?R)V+++{NJO8AJ 3f-7 Yߺp?:ҖLHPyuG(oJPF2=Cl/~X@( W9_,s׷^e&ٿv}]B_hlld7|>Vrʴi?1A!!^ᣎeT[kx-(p+s9J0[_!K.\OЌP $@&yS)l[B3EA*pvG=)T!Bi^jgϮY~a?ae- ;tzb #~N Tt'z3`N_:ۣ od&kZ_՛>C :thȐ!_]SSsڵ+WdddkZ@#&r֊~-kY, ?_ H(J"KĀ)pttTDH@@MrqB(((]zueƍ$Am۶_vvv{:::N4)**Ύ=% /jl}gZxK)O$!sC_w@Ia= -Jj᪻jam몢֪Uqbp d) ~C@,crLB+R6(::zҤIt:ܹs$ ۲e:rww7nMqqb5DDDDDDǏommmʇ2e=UTV+f `~mA8TKS ո2 0c8n`?Jetu .';إ~{(P{`|X9?66611Q(:99 B TȘ2eJRRI/ .&O81l0===^xt9 H$o 6L:O*]\iovx.U9  ĭWCtt9Xqau>PbX*ɓq˗V׫WSI"&&FՈϟ3ffk׮ӦM;rHBBBPP]˽._,HB]D))Ԥ};@H4oGFga+^30Гocc-QEuZ^^`ʪu!jy'OJNjWAxܹshkjj:lذ!CL4iƍ7oTwrrR(TÇ߲e˴i `bH$*(((------++H$RT*rc-B͇(]}ʎ:nnnLfh#F$$$W׏bDGGٳGE222-Zdaaш7k]`Ĉ#FSfLE?HU>ǫ$hcO:cV`2j_+WWO}mݺU}G~ȨwR477ٳgJBMeod&Vݧ : ޫxx(j1yyy`cczIݻcZLLL\.yfzJ$lex∈z'Z䄆@rr# ͛~Ukܹsǎ999(44tϞ=_}ɀ95J━U[2b[1'LBEDEE._pذa痙 Ūe:v숁j1'O;|p;sΝ9s)5k֬;888666??֜*++ӧqqqh5kmmذaڵIII=WXѫWYf?xf"Ժb7̰]::wc? LB$9o<$Ν;;99H5innjG9z{-Z[ό3 * v`ݻwEEEeeenݺ?P-OH3oSMڵ{KKKS*Bm ],i\_9/IByGcL[Bb.QVVtR\pƼƪ>}z̙K.m?AiV>>>2ǚNT jY[k -UX,V7y3fԩS2c &ycǎPsHP+I'%R( (*/,QџdLzTDF  Ze>$FU?BZw@w_)-I`IB]100 z3TU`Ȑ!o6juE̙3gϞfjA~?>.]奫 rH$edd$&&>|Zj<̞=G:::Z6b .nݺϟ>|ÚK~?*??_]!de gPJ(%]5KBR$E)IN)EE.T.$I ԏ.$AA$U5SL$*k"o5!]QZN.v޽&QhȐ!O>ݼyի5 9}Μ9'={}VOOOW2dΝ;"d:o)//NIIya```XXfγt҆Ae0}۷VNNN<O]~u{7@)àG>%.# kpWPEjaBxVSՖcǎ޽{o<ػwki&P_N81---''󁁁PRRĤe4,qZ] _,zJ5dZxZö)meO.ƥeΒg&Q!0jԨ۷X$Iooo|VZ{E \\.'IQh^^^&M:qĩS/^lnnN|>Eݢ%TITAAfvQ+Z\5SEt eJ$;u#&Q!yElٲS N搝}+VZԴtjjndۥK솪ށl͖(.CQkgzCƻ$1Z<t0W^U(|EKյD2u/$WþD!k,---Zh/_:u ~Ν;===Ճ85T*U LkggX[[k/j%E]=PAPE$Qz6Ƥ^2~@Uς^kI~NAiE ST!iaݳkJ`BuvCEEń 8PԩWhh͛7׬Yw߹0 9~٭[TLv嚘$''Di ,pNT{6齸&nqeeDUOTa΅TNTv:Cm1ՎZ.X(B->KKK;s挽=FCE(؄C:4~x777}}}@|>d2 I!!!Vԭ[7-HGGG!PPT]Xuu5$I(bɒBPW`0 j8J z+^}I#rٔ=#]5#IB?y0U:u%˨Qn޼ zzzϟ߰aj  8P]% (RD՝E譒(}Yܽr Z#IBzxx`4(J=*nϞ=teРA$jʕogffy,aKB-@X4㩁^9ܐ2{%B5'O|'fffӦM{A`'A0Ǚ50;td0N%NוDi.j\%(emvυ uXUO B!IΆbp?ݞC|<,__|Q93!,/f%%p,= qqP^gv-<ց5?MQQu֭'O):SSS>˗666oP.;;;--K,qqqybzr[jV%J*h[2tJ_OI{uJ$4T>D2ט#.<2 -QoB+]wiΫ9VB̆WcRZAtxjLbQjM wCe«)O\%h;DYOBb*D۬>St&QvcG_wg:YUIW/`@(|X,;wN4mܸqIII[l{ݻO>$IFU!k ߓА1Rsr >\] \fee:tēQ;kkCܻwO=~sttlP/_ܺuZU(}4 BQ\%i Vp08`BM'!f͂XXfϮ%}LOZ֖gΝJ%P`k /UK_]s=èQп?H$d ?R)dC}:tZRS/!&,)S`Z8b(`0~lTjʔ)}IxuH$*ebbf΂}ՕAf=-Q*---##ַ? _t>&9Kؠ-(QiG.$ !R Ő_#GBl,tffp@@tTmB{ll Lxbb` 2B((} bFFСBy90`n^1*7A '_}sept797oBZ9]V/^XZZOFnܸqq9۷o .cX2񥥥;w |}zzz ,(ܹk_ٙI$JqviݿlѣG1jTveK|eZE~?$5D!P 8xz$v ,Xvʅ+*`f8r ?f}} (.;`.=a7)fâE0c/[66e t\maN==8p@Gd2u fφ$ض Z1J* <Ozccu3ڵk?Æ4"HyPzƃ/)>`gLl$ !W׮0p`?{ 1( cn݂,O?ʠ*x`8t ?)س'Tkc0_?ػbHKk$jǎ_}h*---y5jن ,hKL8qZW\rl^G~s0S޼y̙39fP  yT}ӡ!MqP(ؖY֡n@mn#o +K^rq GBPs[(jR={WNNй3DFBDr9ܸ$ NNzA+CBťJwjҤI|>ԨQ<ϵzrZI__ ("|r++z?uɨ(դfUt}bBA8Nddݻ?_Lf 3k( dT}‡x`YHN L:r?ڧsobB- <22ֶxx <<@! $ &FFII@Q5[]Ο?/yxŋ{xx䤤h&w^'N8f%QC\pvٷoƎesYZ54^W%QVIm=,phYN;!o& .*HaJҦ3o?beN4OFMv 4*SxTsDu\J xۖOB{jÊ -:\\Cmрx<(+˗az(/aЪے}ϰk`f$CNܺQQ믕#2q0|8= v-̟ W.SVZDDDğyE<7 A׾}/8Rdmbj{h4}tt`0@( мd1w?BH<{ 'Ts|>_®]TV6g 0j|e23MłWA$L:/́ͮYӂss06,J 01քڴy Y,05^ @ԬgϞݹsgMUgTҥ: DXx1F5jœPsĉ-,,SܕiӦ]2L KJJqFbb;lذ7 jT޸j ˽z!"hpbQzʏ ~Kpml~=}K ˳ yg>#ƔSDt{^/M?;xpQ{QQ$ !h`c66 ] XFkڎ=O+ԓÇޑvROzxx7:~!VXqʕGu̙3 2jaʚe\&mCZaqBڳI|aŃ? ː&%VtccϐeX@PbR'.M/2:d98wBAfۇabjڇ\T$N~,ӥrFBeHNQdr"*MH@!tFSOt`σcR D!\.߿g}&,Ł?Ȩ026RFٳuf1ofϞ=O>yfnnMX,G7=`e0~dzTGC?,~,A,p~Þ9-ny)m;Ywi/jt";w1B!T{>>ETON<+H?}:̙3gؠ’^B@ɠ|Q7ݚ`%Q "qNυ`5t\uN<fPD!ߜ9s Ga(ZRIIJT'>cZvܵkW__ߍ7pOxB*}Y? #GtMuw`E*%W1{"a7z)<Gxn;z/,B!m?~Xex ƘP[CmPD!X,>w\EEÇ1-LP_s\ B%> ϟ?zWvv6GoAuӃe 6!("ip54U @*%\"it J(-sK)FƱ:wF@on ܏y=&Q!ꔑqС+V`(ZFҵ@=ijjIv7o>}tii+ ֯_? j,{.tm J zaJ^ؼRFA/FJ/Hr.<W0T& }׏>&Q!sssc(Zf=LH$,n``*::ɓ;wr<01181zv\pC-|&T$$P$ @A@C'%:=0ܘfЧJ$ !{o2eJ=0-ObNN\.kɗ/_FDD^ϙ3ajHMMݻw={D"ԩSG5yd zc}zFzzի l...!tSRR^x:u–((((8}ƍ 0ue˖aXJSq րBEr('mƶ [ xK[܍~&Qw@``o~/k$*22k֬ӯ[[['7olkkkkk[c۷oرCGڳgǃ\n```=p|O&ۺ^m tȨ#P|e;BJD! ʽ{/2FHԫW/12D ҇&ZZJ`BY`PZmݾBO" ;v9' ã[n #***44Tsooovs߿njB`fPcnIBF8{߷.//iӦ:tHsfDD]vVRR9iҤt}}ŋϝ;Դlt#3ȨhP] :0BHN1ws!PMͳP.wwÇ_|Y]^.3f3fL۷o?~l6o577s52%$aT l"&Q!Q(J&N(W\%]t{ R)J́{{{O{&u 'IF<+ IDAT%r8!opi{(aF!ΝJd~ݺu;p}j5/^އݻ.\ذa@ :t :ugHdυO,U_EـzlXYҪm5uIB!Nڵ͛WX^XXP(ttt,,,,--9{`##;ϊl1\ͅ2e=Ȗ‰W≯cW!GD!H$ZhY,FM!ظ|۷o/[mϞ=}Ó!IB6$RNE_ 2dѣ,XaAaBMw+65… ?#|[u֯_[bLBD!Pprr?;nS̝;+Ԓv}P=aAaB+..NNNfݻwhpƍ{:uQUUdAaBwȑիWc(Ps ?t萟L&[|a1<j z!0SLho I m eC`U v<|&QQE$A0 ecƌ f$˗.]GGqFkkkQ>FCBY=^kxR\;S-Ѷ` 0$~IBMC&EFF>zѱgϞ{5{2h9$''9sfEEE'O^fͧ~aA:.d$YLNUg(S24l[ #OS&Q5իW{lboҤI9PgZjzձ>ADj޽ԩSh4Ϸmۖ~w߾}k׮!Ԋ_~…\ z3Ν w^HHW`ٲeXs5"V}O-6y<Jն%`b&Q9֘}ӧL8>wjrݺus133!*(***X5Vyyyqq1cRSS`ʔ)7oڵ+F5b/nd[1ިҳg4'WZ5g :tiӦj 1tD2s-[b4PÝ>}z̙"hر[n !N`KjJO<ќ>}:N}1OO&ϟ??zhB>SDr}yyyaXBD!"""ԯGimm]i`L0AD]xH__P{ii&ףG[[Z!&Q5TEEEiizӓɬIL.iiiiiiD!*VZկ_Cb(P]2337nxĉ3f VGaPP(RT=ibbeakkkDLLLtss" $ 6CZ[ gϞΝ;x!!,,2dI- '0DEEmٲC4o޼yȐ!ٳ={6zh{{{̠B% 5VZwk׮GQM$Bd2R~vugggKKK B#)({AX}4:SˀjsT|m (mA4nCa pFWwիKNԯcbbJJJ(ZX,۷/do˖-www۷ݻw1,i A|mnncR?IBMDwFŋ ={0"b222` E;wܹG=zvշo.]`XB(X,z255UTj~kff9yqOOOч+&&fݺunӻwzBBEEQaaa+Je˖-YD(A!LPrѣGo.[wQMnڴ/tqq0FҥÇ[q/O===,jo>3fPvٳׯnܸ̚5 ÂP#I,6h Nd׿nzP+Aьz>im-h[A=T`C)^F  KB*x :$)Z]\)s:R*-PbaRڵk[lvZ 8;;4Ivo۶ml6e˖=z|͍7,--15'O}_iii9cjȇB-r:O0Pvaq'IGS[fR :GIBID[ĊHy M3L)mi (THbŊ}iY&>>>>>ַn߾ㆆvTIHHXz;4GE5@ {f큁7n޽9s B$\ŠfѮY}[ {PGҙ!8=l+i#{YZhmf;L6ӧO zݻ7Ҳc@@@>}s6||8 &o߾sZXX`(i `ʔ)?|ʕVVVNNNP렀(SFM<=ݥcP  CJ}zd%w4ؐ&R)LPJ?|%[___.fff>ҥKZs_׻wǫ,ZBMIGGxC;fccӳgϼ|XcL^H|ILLLjjH$d9r$Ym߾Y*&z<~x۶m'N(//_rСC1,E*u/[! ʻ{y;ORtCO>RLP:~WkA7D/_߶mj9rdܹ#:##_~QϜ6mڍ7'OOj}kxX 633ܹ3rMMM=zddd"Z +fR:z}(r9:q霸4vfH*tϑ+m$vf2#=jz}E}:v%IlI#MYһ(T˗/'h4333333OOO{{ ϛ7]t6|򤤤cǎǯ[n۶m Pd~~~xB/^8p௿˛6mȑ#'OaA-zZ7 p-FH{1G_$*j6!iF9:L: hP(M! XnR,Vn.(N@1sːCg~УoWIjbqRRu^}n1_ÇTs~GǏF1vz7ZVV9s͛wP}rvH$t钓F,ZO`UCSj G)iN?7d*rd՛ClPrܣ6ǺfNoe"㰪}ɠyZ=q=;`~FlV6HajGQUg& >裏Iٳg۷`z?heeo߾}XwBP=G"ĤKR:#H !T"GGG E[̙~-))iӦM1,ak{˵Q*4&'+_b1e8 fy6D,$@fuTRLy>@>xt1{ 56dgYx× 5iDk“Վ¼<|raa8 .,e^޽{oڴiɒ%ɧO>}z̙I\78pB=O:XYYaXBm .x!52ڡK;v'h(2A(_bk+IBnWmlوs:6x׮JnpT;@бcG޽{e2YcW"j믋_C_~e^s8kHxdQ{5gΜ'Nh {P(P0ƅ Ο?Q(۷{zz6@ eO33A8܉lȼ,{:<#@aY/޵}6hOBۉ26(D;`ʔ)7nTݻw޽0b ###X, uuu&1Ԑ!w]瑋4C.YDp/::ݘT?KN4mذ>f]liEU(//͝2eJVV@ Xzŋmll:Oq\"v t:f7:@t24kljV k|ЪZ4;0(UK};J$8iwӢrF ^t+مhI2#!mxDAGt \L[oHD!ѣ'O͛ߓӴhׯ5jPhѢiӦyyyh[=z'O-[N]y~mBMMMAAAQQQiiiiiT*%b|>rl65L&)+Dg%H؊V#8H \X 5ϦΥٳ;YIT#/zZZɀZBӼJ0 ŽL[#h8ӧOLaas}ZgDn\"66vӦMⳲ<<$$>'"##kS D!sNsǍ|V;W\\&1]-DppKl٢'&&{쩨000ӧY}۷k8gwwwA .-RN~ֽ?ZrX<c!}{9k,..d555=rȑ#Gy666l65#+* q}cSVA~6֪w+(6f1;wV>5QIKKۺu+lnn{n33FP( NX,WWŋyfDTk&PHD!8G,m‹/ݻ[]]~ s EPPЖ-[`ٲes޽;q͛WYYPɞ={~jԩ(>1IQ_,Ϥӈם.8,:$"7h ҥz(DDEEIRry՚(wk֬SDm۶?nϕR-!6z˖-N9rرc/_TfffJJ L0aܸqNNNWभecc3rȯ*22gΜx&233?HHH4iҨQtttwUT*UB9.C)[^V~1m#>6;KiAr$uZ۷oSz򥟟ߊ+7;mnXT*O.߱c<66vŊ8gee}ņYG4Fl@  yfHT]]P2{FFFAA)SLLL4ԨT*r9iI.J 'L`aaW Z.ht.x1 cW+ANҹ\D="qKL*U(]sDjYĸ *_=p޽{7JFoy3QHD!,UUU1ACAAA?;o$ܣP(KlviBP*kС!!!N }T*裏LMM5Q>J=93Vqơ VĈ"4܂ Yu׆aGӹZf K ˒ W 5-lHW_ZWiΊq~3NN%_Q.j]a͹jy„ ۶mN:En?kbqS\]D)J$Dqʕ}?׿FctDx<xzz7^>` f3L&MMM-,,._7hSԧ iWTTU"O 2jnQ#f=%xvιj[>م7k,+$W`Au>Qz ..۷oիy7|6 / 66vڵjj[mGDyBtY&MqFWWWT;wΝ366'< Sgryee%ϝ;׿SSS###@+TZSS@Uh&&&\.ȑ#+Wr>>>FFF*H&UUUWl IDAT"avל7я Jh_:ziC:Q966;;;r\&UVVfgg慌 \.wÇuVcc&]RR*BnDh4|Ž?sNBz{{/ΊD"yӧϞ=Kno^x1qDkkkpHHQL]q1޽{PT2ŋ矱c ^xq#G(]ϟ ՐH[ejKT*?eIevjA" Q7::::qď?[(~G B.K$؜wH~,UNNN7|SQQ krtD=i/㪄HD!$t:]WWUT*WZs &N믿weee6䪭+--p®]H /LniixbD_ҥKCCCO޷o_=== BCCʓ&~vv AIIIcǎ?N.WWWϛ7}<qW=|@mKa"t^Qz7l@~N8Qg\ tիWNBR---w4|loDkvZ33Kh/^t_QQ1}qƌ]WUU8qB ԭ[7*_QQ!uuuy<Ng2R˗133333SOGBUUUׯ[ZZu-22RUj̘1nnnl6ƍj DbooO.ذaV7779rj~(q e$<:.)VoKʩOMʌ畐^  d +"ꁁJra{+.e,(h\ B J]jUAAA3LJR}olv>DLD"##c[nE~P͆L޽aÆׯ} sJ^^^@@s`k֬qqq!ǭMyyy/^xݻwߝ =z!C ƢRV۷oϏ -(( ͛7o̙={p8EEE/^@Md2o޼I>}AAAAAA4MP899 <OT="A a1'0 (@8v/)l*JVt'p*7j Wp# W2 ǁ 0 '^"p#cj߿@ 0 ǡJc|v5D!X,ڵkQvvvdkkkP+x<rL&ɓ[nM6/wL\.Gw [ndff|rݼ81].[lРA;v>|xW/_X,^n]~8N2biȐ!fͪ.,,|ٳgo߾ &LXhQ;lmmݻ:tݻ]P75224D AP}Yf@DDٳ~wT9u?k֬2GG={L2E(v !8,--5Aь322nݺu$ggg w߿s^^^EED"INNr势EEEMM )0 <&yyycƌ  SLAZaWSiԎ7a4cHA" G4{{s6E&TPZZZVΧ 4\~}FFk}3f G.>}>ܧO???>/^wǏW^Ma4`0\.Ūk8lϻRfIII\.W*x*k=|jLE1:|I``u&Nhiiy & 6 OW(R#:0ta5"hTr3gmAGA.,//OKDT{`رS*׮]Sŋ;99i}fϞ}ĉ'Oɓ'7oތfWWL81-- ð3gn߾PAPgϞ;wA4iŗgaa<]JP z"ceeTGG&mٲ̙3999vvv={\~=it昁R&QA-4*po2DXUN j0^< 13y!hղR Q-4#%8.++++++,>92 7o$`^` 2޽{"h044T ]vʕNT9s̙3Ǐ'pvubi@ pvvJLL}NrJkkATܺuܹszD,!Z+W|gP(8xѣQ-9˖-۰a3gdׯ2GR'l6[,[XX߿?11qx<6MceXT8Y#B_* +++J*EPE_Gۻv:wS*#Z TD8 6s) }Zb%DA~9iV-a:oh dT)ކh쏄լq."F.]D" C{O5^UU{-]z HIIٺu={+  gTE%}GGZ"caȂFY9oQ0M )(4#sQ5;pL6J! 0Bu"6 zU金+L\i3׭GD"b -*11ܰai"j*..&S.Aiՙ={R;w&&s),,l եiT>}Çpĉ9s搣sSə3gNBB™3gZMA۷Vl||G]fddر㹹;v)SC(ׯ_W7hA&L>9h4F#}_UrV@[^|9s̸-[7y^ *zk55xQյwo,,e`@N>@X-2 ,-DVfUU֣ OK`^( f̘A( ㏠˗;99!F'8995ST:tO?mիX,f|),,$=~'OLhGGG##:{EFZfMkZu\Aʺu֯Jkgggll*Q$IXX_hh(|׎dM2RT*RT.dҤPu5n8;;;Uat:B'Jpс\v[8}5ՆVCjuzP=.msQ`8Ds눨1.&W#]l8F^=?QּvJ>}~'CEDD*rNxyyɓ'nRm?9BÇ?#rT*={6X[[+((ݲ!>>> ._L3L8gԩL0uֵ5lZ3B҃ٳ'11qĈGQ4k׮ݾ}nΜ9cǎ MTJBJ,33366֭[ɤhIҜK.1bĈ,KCkEJ_t:ӧ/_|С_~Cm)T\ӄP,l%P0B x5igGJrʛH| ,v|'x0I%#3h|@qhqEԤF]]I'M UAg҆~BP(+W!tJZYYu֭&&&BO7o,//o YM@@ {ITXu''''''7[OTL''CN;wΙ3R[./p&ͪt5 ;R7tٴs ƢW+D.%Y>CQxP; H$52Lܤbrŋ۷  FAAAddΝ;CBB ѣM6*߲K.Qw 奥yyydl꼼 *~T T %&bf M`ULZy. ʱhohWII kzիWWxasUVVvkjjRD"!@:J7---ҵ/DIJJ ۶m۔)S<==W^j尲zɓ'wQSSAZKr29}DϑJ.ܸqhnnnoo4TEEEzzzfffyy9F +**%T*[V` z[T듖6{w^$k\DI62ʼnw;n;Jx.%nՠ|p!O @(z&j^&3>X1aj ^ S6VKdh>0Od1PWG#RyaA@ؗheHD!mRR^^^ |ݻ믿߿F"gϞYfgZ--GGӧOs8|ڵk]\\N>퍲FF%MٳgϞ9&qCBB{…ZRwR[)~~zhhuT'@0&!io4%<xYܓ*eHUUi&-ŝ;Y% U򭕷.0_D9,kӦM3f ONNNl999qqq?~xvvG^fg}T.ȣGp?~<ӧVuu5P(L|||PP_Mǭ[ z Z*>E;xL&djii1L2NW*$??ٳgeeee``Ν;ߝ\N;D=rرۚPFT-E TY ӄ,i>'#N]Yoɀ*yk{3h5DiL0aAW\r劗W^8NRRRttӧOt_uɶȺa|}}RÇ(ʶm`֬Yr={$&&޸q_~p8/F8yq2g 9àuuu\.NgXL&򄄄'N8p@h<HiC @,3LRedd<{ 0@PUUU+j<<}e˖:P{%0 ,'QWQr7i-.KǢ0^-l6gٻv"ܺu֭[M:ق 榣F$55UP^:!!^wm`ggљ(((xŋWX1nܸZ<FZZӧOsrrq͚5>>>Q۪emmm+++.sNU^z FETFFƣGHqX<iӦ?~͙'O|!aX4??CJR^^]]]v }}}T-nmIyE_2GIj};b"A^Ҥ=(Id*X9:::ǘ1c6op0 IDATaallܿ~Y[[bCCCPB/++cX0oL̙3wuss[d 9ъhCRRR\\\qiJ ѫW/WWW.=:|pbb"xyy͛70[[[sssr2]CZŋ'NX|ԩSӃQ1 W}{=,0@b"ɐN NJHH OHHqbgggX,B{ƊhuŔW/xell,СC!CPCt> EQQٳ~u,k{@*lmm8N>...diӦ3F,7lvErC7N:}۶mϞ=+**T*`ݹs'%%8-2ѣ+WJ?ӺuЌ_ O h@=rv|zU[A( ,Ӧu%J m$0D-d2{ѣG9s! ߻w-..޾}ˋ_z .Dʕ+>y򤹹y^PCt:NoR_Y.5<##ʕ+LCuwwWa2  tQ(:_ >|pX|8((.]x)SQ[Btݻ;&H֯_?rAjio0 >yyyr\CUݍ70tIuߡh;0!@P zc3><ܼy4؛5k͸qzꅪEHII9r_U\\UK;G,ZXX\|yĈUǕJ\.(**JOOOHHPdݺu 䚚ׯ[nᡉ IzzzYY Bhii ̜9d…{E)T ePݰf2ԣ,&5sй\ /Cr{}9Tp!?(ii˚1wBǏj(+,>j͈6B@0- ETZ^^G-,,,,,d2 ,ؾ};۫z!D禤DP/o533v횃CÖ]vF֭wfff\\ܹsgϞ=`===BCw={ׯU:Jٳg{'#FDJ P8h daH$&LϷ ppp@bh^H(sBrƗyHP1Sf_H+̔$xL`.RE:-+|FCMGmFHD) ѣȿ zAZ}EۢvЋOMMdw?cZZڰa̙fP;SL)))ټy3\pݻL&+++StzoظϞ=۽{ѣGՙ3gN6!.]:wΝ?1I @rL=f{TBn)OZwUD{2ӈuwxzḲD cE ¤+·Ei%!<6@ nϞ= 999** /^ZCD {*s&~g`5kD+<h8UTTQwI'<| #ܚP7ᨮ d'O߿̙3QĔaFիWvvviiBP(t:fs8.f|~AAkףX,^d~}Ͽw˗Us9H6 ???66v̙ )(1dA o ^g@JM퍍X\webY7Y#W\l^mۢ-HZ,.UBPa1aioo[n2牏#tۦiK0"Z]g^{|w?X,F..΅ .\pA:yfooo4 tRq ( F1#477Q9J$jժ#6a׮]׮]|MFIW5[jjkO.}{kU@= lp`+C\KU'sC/B |VMB%/ȹ>bP ?X'Sr'Tk(Eŋ츓B]ߙ`rXG[rJ2y`"Z @K{8.\P~9|CC!"''MN "??P!.;uTCCÎkT^^7qĜ>f͚> h `NNǏ^,7|]ruʔ)'OF .266޵kעEE3H(8x-yG?D]%l˯7 nYy' ;s3"\~'xO4%E )U&d)LJ2BS)(?bR`!ReτEhq+癙Y3 Tw}ߌBTO@@pDTMMͿ |L&ݻ駨*5556mj K.j^/ps#Wxyyu: yqhh)ʺuBti(++={6`r^^^ݺu; ϟ駟͗.]o: L>iKdƉͥt._ayG#d ]u֗e/l+">s~:_iCb*E\Xxjc+p\y/+0Iif۴VG|kb&hgD^K&{d0wb\Nz7l6{*3֟}Y+ȑ#Mʕ+}'SD8?wqW(f͊9r7<==Q$DEEufoo_R*3޷ r?|ڵ}١` A!+ rˬ0#.ݿ"lh+F5uVA."LgmEТRiXcD`&>?>Dԝ393{!u.Ϥk'|(࿎TNy7hlJT~MÇxwdffվ`ί#3$ɪUvڅa?@nŋmۦ3lذ7nX[[{Pj500of)??\۷1"kBBB.\د_Ǔ!@]S@E9SYza\M5l.<^*&8z%(dP]$Qq zUhuR([_CsPd܆}NS")Z؉+>y@4jjxo,/dO.++R=='JDC Me:7mڴk׮Knܸ|}}k?~<uRiMͫ b<O(EDiiii+ӧwplVX5xÇ::L94oHp5WY^:|99EϟDf0H1´u9|F2(4 R*Յbj~|G.E6R6ei}lfTAyc_5"PLIlz1o*?Om8`G#e+f!#U|j`0ՐHLL\._jðAݻO3}9q℁dzzz ,MVő0@tTfaKA}__ٳg8p`Æ pwwo +S]]]QQAEhBJ8^TTTXXH-GbbիW*;;`gggcvcf<)T)y.&Ɖ@ԫ#7pc'7'zi+JX[^R#VXI,zi5U.hTB[KirXh9L%AP꙰Ppwp7Ke|l*3LēF| PZ#H_,Zq\YĶ{Z0i;IP `@((cǎlRYY` W Bp˗,x$V|2l07hW?$++k)))l6{ԩ>>>u4B}J5UAd?A (,,ܽ{&N8f̘w"pa.0 u7 pBKlo esD bBU*&?p/1m$ R4I6<4wzz9 ɡ8φ5aDԝ3uxTsqEdjtmC۾?u[gi3{T @H^XRK%KVgffӧO8::jii;h+YUTTL:5446nܸnݺǛD"ttk ^4I76mJ)((سgϩS=zdee% Qʹv\ȕBrcQ ߶Z gs?+ qX![KAJ{,SoruT AP`9+ifqc TETI~Jʳn{!bmPWJ5ozī^ y9(MshEd1ڮ]HI&9::8pD7 F%͙3TP$򋥥e\\@ 4ikzNT&sJDegmmBJ|Xn߾=bǧL~z >9ְ⫣ H-}tf)})UYCIℼ08xs:$'iM(5j,틢{N[]M߼~Ŋlvph_~_~ڲm62ʹQa2ZZZl6BPkADaa*41G3Q%KIrx h: {IMSPQҚ[ǖLՓ?>mHGa:2ꫪ,i,עK |=D .1! D"c~`0TFFtFTL |&+۴'iӦo0aR[7naKKK D"Q)LAikk9rܹsz:v옇\eqЂ𸬍ԛ- ɀpЏ.V̾8e^+qpg  L*ê$*ZA%7&]/<]V`/2(Z-Ra1aiMݽ9"*>sKq65}{Ҷ0t.y:J% ŋٍ9@ М (PSeDK h.|f֭WG~ ]%&mٳgb9J$3gΐ"7d2o@@@\\ܨQlٲh"T-]{.ևv|"Gf6@)׏ɓd3_򠆏0)r1- hUTQ =],k~ (0V SO#$U%&wi!EWftL3ӹQJJUUUn kjjjddD.`V^^n1 2aȑsak `k;qȉ":fff JJJ"@]tٳgD555Ϟ=iӦۣlC\.駟^mii߻wodp.AXPehS'K6',f3O8`,%ݵr3KGLCW`((Bu*ֶ5N###_NnIII!s#?S 4 !qqq!!! .ׯO?4fT-;.L4lX|U4âshMQ f.s(,,<< 0`޽|iv~a2nnnf͒Jػ=zԈ+VݻwȑfffN GƊs=~l*KWYcǵԅ`~E'22E!Jmmmsrrf utb"144yyy @OO~СCx ///))L9`dd4o޼3fAԂEB0*C#l8`I?;((Y΃ۧk?udMt-քX"*Fl( "PQ IDAT4i>/ƬA~~ޙ;{fWܹW O: ={͕H$Legg' YNϜ90bĈ27@i_ˬ*6\y힃jLwCOWU™Kwzth7,%Ofs0j J_xADyyy$11<<>>99b͝;wݺuD'VYY)=zwEDD/X`vvv&&&@[Iʓj%ұ+6ÁXzBA)|=C"N߿sN"ܹӧ1CÏ9~zMM޽{o۶ ah{I(^G{:6~FcF6ρjITѨN;#Vݓ: yիWwMD< oήw666~/^?~<==}ɾ lMgb)zhB}r xYfM3gt=~ i:Z^R<5dXy}*E|v=Ve}mߖռq9%uu-I)-HڋkDŽiiԜuh~jOoNYYYQQQTTԂ (//ŋnnnDdllL A;ȑw3ޱcǤIXz}1 w7ydddܼy g uJ/^駟.^qkڦ(QНCz3G$H5<W 4sӽֆ5VP(qRD[}I"|; OD3f >F⌌ yjS8//ODYYY8MH^^^XXXiiӉh̘1O!PC SmȨ$-D9lc]=:w$J$QNN牨o߾ݻ7>jժ3g(++8p DU4T~AIa:b%_kfM=ݚ8hb?SUXXtR"ڰaD"]d b(UIDC1b"r$QGx:BE~9I5q3*07MMӸT@Dcǎ-((Jbl2 |ٳgbxΜ9iiiZZZl6ɓƪȗD&j@։iev[,Lo4k~]v 9m'[Yٽ{w~~H$H__OMMmٲeM6ђ%Krrr|>=~JT?*(wT,=E3tܩTT[uzTjZNs|}}%KJJO:ED...4T*H$YYY&M"3gp833.ۯ_?DCMԡƪ|@ۦwƋ?5Ujл}șN<)[瞯/Ϗǧ-ܺuѣGsURR4h-[l޼y4AUik3fd L*jC15d寶ڵU+O|tѼ}~Dᅲ-XԔl6>o#55uDEkkm۶=L2o7*3ү>TCIiy~AifH˼_e=d{yK#3Ե~رcD$ ȣttt0NNNy%K***l󵵵"h$ݿ/__Sb0t-腺(9\v/'hwu ΁}_GxҥWQHHȣGhƌB000c={э7;fmmHD{0`*>{ %l )(*kWQUs y#򊋋,55 L(A'ú*2EU/nIOMd ů- o-zmQ_^oKW/D͛D%'hH-Lu|]4jCu%G&sBRTH]4=;v؈#܆Zm7n<~޷o.] _iqJNN?>YXXvܹB6d::::::R+%Izؘ*֗jKJ n9$TsBY8g (P]+aaaSL޽.ˠΟ?uV"# :88t_f4{d":p߿)0<@N]]]e˖y{{g ={Lnݺ˗/3+l6[QQjG[3%%eղE]]]aÆ9;; 6:c%Z׾e'HZ@el0ӫ\Ɋ.3;yky'.p ^nԻKo#GL:tƌ{^dIx;w$W˗+((O:!zb8((ɠWX࠮rս{Ըmff//wÇWWWoScqX-0NHs«w^ظ~,hMず9?sj*9y-w_M6-?? MD:::/q+++333􊊊JKKnc=b&WW#G1uuu `Ļwo.]-ѝ4i҆ ~8@K<mC&O{z;qJw,ډR;kQ6$$$7ӑ#GZ[[={w$ @~n_VVFDNNND(39s2ڷo߾}{??nLݻwoK.5k JsrrJJJD"QEE/$JТE܆inݺO?eAAA7of#Xx3>C5_Q|ƍKQBBBBBsDdjjھ}{bF "klww75>}WQQ{-[0.\? ruIMM5k34HQS硔RڰM{l(F[[{РALYV{.PUJJ۷W_}DDGEdSZZ<^ʥ8ot/^LDb۶mq .,4eL"gM,r|kE4ޣOVZy=m/MD uBN,IAMS/0'"=Kw|Z/^0wn焏?.UPPЮ];ݛ\.~UVV޼ysӦM gΜikk<ǏB\\\_yONDTTT֯/99988844466>HMD H;&V6QV[[k.,$/_}#GhnnnxFm6|3]23F$^zѢEUW8pYgccdhhhii) \۷gΜT˫˝2eJii)Sm޽qqq+Vٳ'ݻLSH꒜p_OX7ެ?$ 7n͛7dk?S UUUD*///..J̨ǏgRb.e5ϟ? L7-͛fPcǎibcc߼SdiiLvpppq?ONN^~=EDDivvvU+O:G[H^)+qyisPTsĩ*z8O-:mڴ/^Q~͛7o<ծ]~嗲=z@Z5kטvvvݺucʦ˖-CZo)O8q̼[YYY999111W^=w\aa!SjlٲN:ն>rJMM3kݻWӫWÇkjjX,$Q$&Gpgj%~$Q-Lj#Ahh-[M&{)22r„ E }' Qtt%K}v|ˡz9pΝVΝ;Laȑ+slsi̙EEEIII?޹s'jVnBAA!((s'N|l>̮ HjF1 0O>BGfnY1 rssǏ_jժU~޸qk=MLLd+CVN0gFP\z .WAA<\IePobX'88*f{zzFGG;w.,,3bQ#$*DRfMtof erW\s]v޽ۛ2JD"qjk.]*ѥK>}Tk1y]LNNz`559?"Ǜ:u;ݻxq!HKK?())ر#eddTTT03ȓ$ġ-C6}#ˑpZ3g;믿=k31C@Ko߾mn۷ 2""I222bŊxV\\;fԨQsԩSكzzoڵGQ,ǍHffff蝀$O=Avt0:I@ZyjPD7کStpqq5""ٳٳ͙!됛LlL6maa(Ir ̩ȠAʖ@Arec9@WWLGGGCCC(*+++** B55ק0[S$JWW) Bf%N BRDyn.[O5;5>g @N;}t5iv1v:4:b'"*((I$Qf%N(6[CEF(9]vm̘1o9s$`%%%Lޞ$٤_gIAS&26UoCVUjW$Q*+\HG[q%(.O_ ˦e9sg}fnn奥陙gϞeܹl۷orllt3Q,޽{oVJHTJ H,zֿɛJt;amUHݒr[Uϙm=_B|A}AύsR$Q:tk2s /lX|,̬$ J%m"l&/ֻSs*?{^Bb>(b U3qѣG2ׯ_wwwg2' |>$JGGg> oD]n_Xr?:I:[<#@22^ZҠ \7SޱcG=aU4ѓyIljR)$҅=\-kY @3?8[ر#SxIC٤]v7dSQ^%ʒpJ)X4B4N"H6%@CwڱcG&.**z?''6d7e+kwy%+ji6`TI*cU\uǂSr?LeJ|r¾/@[sΝ[ F***>sUUU ޽{Νܹs޽%K̛7O[[b6lpoӦMkPG:(1]y%彺AHlR̈*)մr 6NT"$"iQLQz>}ӧm-s8.]\zuРA??s^hƍYaaannnnnnEEH$D)((qo=zP IDATQDr֭SNEFFfff2dudMԖq`REl4LSġeq/lbh-VRb-֐D]:R!=d,C+][G[ɽYc:SNݼysJF:İ:`={/QJJʖ-[+z딕Xb5$+NT3(d5dL03mhޫE۴%-^((Kg?lzByUTIDn)Ǐh̙3\kiiiIV!66ɠj4aSSSEEE@ZQQlٲ7k:;;3Ď;j̠%Q=G9U,9+#+C8E8?m8mm͛7y<^[{W^x{<ƍk,1HRfr'ȑ#'Mdaa! l}g_~Cׯ_>zhƌoFIIѣL9s攖ZXXv8kVQY/ f^}YlAiHI/\l@mD"~\jjjN0A3gάqjau @PVV$*555**j}UxⅬҥK̙PSVDk׮b5kd'N2d?ޗ_~IDfILG*-)ʗ(_A븄rn絩ڸ>jhl3K yx<9ugGYYq =yd3~~~'N8qbXX/҈"++KV 'b;99^O?aaawf'N4hS߿N:z*#PIyNG|IT!JI_ܺ\;m9ܹs}||"裏9ҿjZǎ[reddT*URR:{:vb TbkZ6E$zȓVVVak׮|gϞp]tttZZZYYD"rRť'nUR-cYr֗H*+Uih[q5GPM~LNUmիϟ 7ڵkw T<|zyzz=@k!TXXXZZ.W\e[nr^^_-K~j,,, $RD/N5h;Y-zsI;7&牷 ̻|?~RhilmmΝ IΝ;]&ϟߠ~BFFƥK_'[mjiirJ|U022oݺ%Wʕ+GFQG}Hp¿[ħ~Zw,ӳ$ M$Qe vb5mhwxp(7y#PU((MEz<۔SN8q͚5U/ޝ?ӧӧO8p`AA-[pzzz Cfv̙3j{5!!aӦM5>zPءC|t 7~7D4v;wTTYYZO:WVV믿򋬹M6o$&&&33xsW,qk oS߼R>tW_}<-|[[ۋ/߿b8֭[x5##cϞ=5$HzSS~xGƍX_QaaaddkvLU;uT^]wrzիN$lض xPYJG^C먠SV^ T0Ƨ/.bp>}ĉk z֬YEuuuy ߸quj3hРTߛV}-~g ж(i?"y"p@hTjm%u)tQp>07n(**zpɒ%m$IIIuکS۷O<7[AUWRR2fL~g~lQII?ZE6Tchhf͚3f<|| ---}}}DR/kIQ~~iӪL׀$J.׮^qb,4gx\c1QC3nhȳOa=B\rE]]ZO'Ɯ9 %ӧO[YYFʃښjYfҤIʼn'VɽCfff-X,33:> a?:fݲeK'oQmc|[Z}Ȱߺ-ƶip[-)ȡ$lh(|@{/zoBզ=z;wܼyS+[ݻweSLڵ+5\EGqmw~E\]]RJg_L֫re˻SU6JdUƵEru:&Qٙiy䬟_Pm.O͞^?e Ug;~7ג%Kty9D&NX[ -dCJ2$Q + Ji+E\ Z$&UUUUU .TN^/ѣG9MVVo ҘϨQ/p=zt@k/+VꐡAAA [ECQR԰y@OЦ!ЫW/Q$u}t"zƬ?z(%AUZ1,&" C>:ȣEy+y|e%]a7pfDBӧ=X̍fhhxWBMݝ8{*?u֩'44ʕ+W\:|bXVfr7DJ s9 ֗MK :#+sl;t[\QSmݺcǎC{W䱈5->n+42%Qh*f T_\*RQ3mv JBISZUTTTbbbϞ=amml\@sԩl?___ŋ'fY,͖u WtqjJJJN<ɔ 'Z2LfƫĆ&:/=5$Q,rЉV-٪;-UOWI9щz޻FKDbSko:u)f;6Vrw:}$=9s̟?р'^6fʕ+ҤRc9p@Ю];:3g̙III LwZ W^IYzn"#mh[o)kl[6liMtdƾ/3VM*:thԩSRRwE-ܹsS8p33B;ba槨(+_pW} P[~X[JW#hZt?RS*:, N$@kPulexK={ܳg?P@K;wJ$D2n8BCC9qqq {"lX,e˗/ͭZ!..n…hllPj'&G|nܸ\B!M{|r -ٳgϞMD!QNuFD'OvvvF޵]!!!qqq_}#͎7o^anIT l}w/r EFV}L:YwȓD'x[D.… ,4Є̙ h>cPVV?сCDΝ+//'_CX֭nfn޼9~7yxxxzz"\r$Q\?U\RFDT\RTQo%8\FUW((ӤN,vSIhbqQQ}ee%ѴڵkWVVVTTh@+t5k֬Yl޽{D4eʔ,"b:Y&$ mæMTTT.Z(X$Jxފ:JDD|XԓTTHn>,9zM1i Uy\N5{اg]`C9'ה<2.@P>hԨQ%%% v""ٳgsܪXA#xyyڵkĉ5joow^GGG $Jy1$ax 319$DWQ]]-9*9v&Uq9&FZE#"2ѕ?'u>vᘧq._rJ[[ 04͞0aCV^-{i̙C'Q1wF_chbX*F}ASC zNN{td]öURw,W/{z|HLLLKDϞ=x1 u.]h @vܹ}FFX, @=ITC7~Ƞ1͌UMAh99PSC5pl˺ ƒR333333D55O>0'RR" yS-UY"%M%UڒR VmX(G[%͘JR|-pB\\ܑ#GN:eoo߫W/"3f 34@K," q}'lo>=)q}۷ѣ 8 . [X;QoݵkWVVۉCľD5Ds666+W,))4i]|yݺu[l޵k B mb#5RVVѣG=rrr.\`iip455555#Pm Df޽%%%G%qIR !DH:ee1c۷oӧ9FEdZ"1%,sXd"K$[Z[J.EЂ ":x ۷oŽ{vuuuqq1b͉͢/߂:h]E%M7Er__5-ז"у"ҜkKȣ5HZc2ٳg-ڵŋyUUU6eV+:::~D"p8G[[lڴ@;QAIIرcDs+Vxzz=!@54i >bҥׯ_?w\YYȑ#'Maff( ֭[(,,,"""22cǎNNNG622O%$QP+W]V*nݺUKKkD( M>ĉBvf @ lBDN駟&L@Dު ,h߾=BasjcƌrJ~~5k"""՗.]z](MYY̙3gΜ7n\tݻ-eĈ@3hf(@jt֭[nAAA?={D"ٶmۢEtdghh@ ?n$ QWWWWW裏F7o<"ڼyݻ,XN@AB99#5Zz6aFҖ-N nɵ {?C%"bIR|Z'OJ)Ss8џ)̲8Z[s"I*(e"'5y-S\qʯWyQ*Sl lKV;617T s4U岈LaȐ!Ds";wH[[[$mܸʪk׮KDJ߹N~6KIے4-o$,t4Vw IfʕLaΝ+WLNN77:88Q#|N:5))iժUQΡj7\X:H:UUUp[ IDAT"JKK۳gݼywDԿ]kS7eۗHDs_}<;QVV駟1k<ڛodXO5 ,IMM%~رcJuuu0zh*JIdYbccH,3+-[֩S'"j߾=|7'0DC3hJ$Qx"h̙LƍnbvvvL?"rӦMk%%%%,,)⯿Zȑ#!mmm݄$u%QC l$ѝL9666..)GEE͘1)s8YrBDB ˓-fggGFF2ewqKnnn Z?q3BMƆ):tLY6@#==bce#ӿ8m͈.6?{u9($Q|)))a͛0aNP[GOePH)++3)U%J}}}]} hrl˫պ*n$ ?ejj8@`?N&$ 6bP'DmWGt2Ql"} v| p' N6z;$$Qho>OW R|xHC&TQq@c ^i"vWw6MED,Tl6hlNrKIENDB`libeufin-1.6.8/testbench/0000775000175000017500000000000015236145704015531 5ustar grothoffgrothofflibeufin-1.6.8/testbench/src/0000775000175000017500000000000015236145704016320 5ustar grothoffgrothofflibeufin-1.6.8/testbench/src/main/0000775000175000017500000000000015236145704017244 5ustar grothoffgrothofflibeufin-1.6.8/testbench/src/main/kotlin/0000775000175000017500000000000015236145704020544 5ustar grothoffgrothofflibeufin-1.6.8/testbench/src/main/kotlin/Main.kt0000664000175000017500000004133615157551657022011 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.testbench import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.core.main import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.types.enum import com.github.ajalt.clikt.testing.* import io.ktor.client.* import io.ktor.client.engine.cio.* import io.ktor.http.* import kotlinx.coroutines.* import kotlinx.serialization.Serializable import tech.libeufin.common.* import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.LibeufinNexus import tech.libeufin.ebisync.cli.LibeufinEbisync import tech.libeufin.ebics.* import java.time.Instant import kotlin.io.path.* import org.jline.terminal.* import org.jline.reader.* import org.jline.reader.impl.history.* enum class Component { Nexus, Ebisync } val nexusCmd = LibeufinNexus() val ebisyncCmd = LibeufinEbisync() val client = HttpClient(CIO) var thread: Thread? = null var deferred: CompletableDeferred = CompletableDeferred() class Interrupt: Exception("Interrupt") fun step(name: String) { println(ANSI.magenta(name)) } fun msg(msg: String) { println(ANSI.yellow(msg)) } fun err(msg: String) { println(ANSI.red(msg)) } suspend fun CliktCommand.run(arg: String): Boolean { deferred = CompletableDeferred() val task = kotlin.concurrent.thread { deferred.complete(this@run.test(arg)) } thread = task task.join() thread = null val res = deferred.await() print(res.output) val success = res.statusCode == 0 if (success) { println(ANSI.green("OK")) } else { err("ERROR ${res.statusCode}") } return success } data class Kind(val name: String, val settings: String?) { val test get() = settings != null } @Serializable data class Config( val payto: Map ) private val WORDS_REGEX = Regex("\\s+") class Cli : CliktCommand() { override fun help(context: Context) = "Run integration tests on banks provider" val component by argument().enum() val platform by argument() override fun run() { // List available platform val platforms = Path("test/platform").listDirectoryEntries().mapNotNull { val fileName = it.fileName.toString() if (fileName == "config.json") { null } else { fileName.removeSuffix(".conf") } } if (!platforms.contains(platform)) { println("Unknown platform '$platform', expected one of $platforms") throw ProgramResult(1) } // Augment config val simpleCfg = Path("test/platform/$platform.conf").readText() val conf = Path("test/$platform/ebics.conf") conf.writeText( """$simpleCfg ${simpleCfg.replace("[nexus-ebics]", "[ebisync]").replace("[nexus-setup]", "[ebisync-setup]")} [paths] LIBEUFIN_NEXUS_HOME = test/$platform EBISYNC_HOME = test/$platform [nexus-fetch] FREQUENCY = 1h CHECKPOINT_TIME_OF_DAY = 16:52 [ebisync-fetch] FREQUENCY = 1h CHECKPOINT_TIME_OF_DAY = 16:52 DESTINATION = azure-blob-storage AZURE_API_URL = http://localhost:10000/devstoreaccount1/ AZURE_ACCOUNT_NAME = devstoreaccount1 AZURE_ACCOUNT_KEY = Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw== AZURE_CONTAINER = test [ebisync-submit] SOURCE = ebisync-api AUTH_METHOD = none [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufintestbench [ebisyncdb-postgres] CONFIG = postgres:///libeufintestbench """) // Prepare shell val terminal = TerminalBuilder.builder().system(true).build()//.signalHandler(Terminal.SignalHandler.SIG_IGN).build() val history = DefaultHistory() val reader = LineReaderBuilder.builder().terminal(terminal).history(history).build(); terminal.handle(Terminal.Signal.INT) { thread?.let { thread = null it.interrupt() } ?: run { kotlin.system.exitProcess(0) } } val cfg = nexusConfig(conf) // Check if platform is known val host = cfg.cfg.section("nexus-ebics").string("host_base_url").orNull() val kind = when (host) { "https://isotest.postfinance.ch/ebicsweb/ebicsweb" -> Kind("PostFinance IsoTest", "https://isotest.postfinance.ch/corporates/user/settings/ebics") "https://iso20022test.credit-suisse.com/ebicsweb/ebicsweb" -> Kind("Credit Suisse isoTest", "https://iso20022test.credit-suisse.com/user/settings/ebics") "https://ebics.postfinance.ch/ebics/ebics.aspx" -> Kind("PostFinance", null) else -> Kind("Unknown", null) } // Read testbench config val benchCfg: Config = loadJsonFile(Path("test/platform/config.json"), "testbench config") ?: Config(emptyMap()) // Prepare cmds val log = "DEBUG" val flags = " -c $conf -L $log" val debugFlags = "$flags --debug-ebics test/$platform" val ebicsFlags = "$debugFlags --transient" val clientKeysPath = cfg.ebics.clientPrivateKeysPath val bankKeysPath = cfg.ebics.bankPublicKeysPath val currency = cfg.currency val dummyPaytos = mapOf( "CHF" to "payto://iban/GENODED1SPW/DE48330605920000686018?receiver-name=Christian%20Grothoff", "EUR" to "payto://iban/GENODED1SPW/DE48330605920000686018?receiver-name=Christian%20Grothoff" ) val dummyPayto = requireNotNull(dummyPaytos[currency]) { "Missing dummy payto for $currency" } val payto = benchCfg.payto[currency] ?: dummyPayto val recoverDoc = "report statement notification" runBlocking { step("Init ${kind.name}") val (setup, cmds) = when (component) { Component.Ebisync -> { assert(ebisyncCmd.run("dbinit $flags")) val cmds = buildCmds(ebisyncCmd) { put("reset-db", "Reset DB", "dbinit -r $flags") put("recover", "Recover old transactions", "fetch $ebicsFlags --pinned-start 2024-01-01") put("fetch", "Fetch all documents", "fetch $ebicsFlags") put("fetch-wait", "Fetch all documents", "fetch $debugFlags") put("checkpoint", "Run a transient checkpoint", "fetch $ebicsFlags --checkpoint") put("peek", "Run a transient peek", "fetch $ebicsFlags --peek") put("reset-keys", "Reset EBICS keys") { if (kind.test) { clientKeysPath.deleteIfExists() } bankKeysPath.deleteIfExists() } } Pair(suspend { ebisyncCmd.run("setup $debugFlags") }, cmds) } Component.Nexus -> { assert(nexusCmd.run("dbinit $flags")) val cmds = buildCmds(nexusCmd) { put("reset-db", "Reset DB", "dbinit -r $flags") put("recover", "Recover old transactions", "ebics-fetch $ebicsFlags --pinned-start 2024-01-01 $recoverDoc") put("fetch", "Fetch all documents", "ebics-fetch $ebicsFlags") put("fetch-wait", "Fetch all documents", "ebics-fetch $debugFlags") put("checkpoint", "Run a transient checkpoint", "ebics-fetch $ebicsFlags --checkpoint") put("peek", "Run a transient peek", "ebics-fetch $ebicsFlags --peek") put("ack", "Fetch CustomerAcknowledgement", "ebics-fetch $ebicsFlags acknowledgement") put("status", "Fetch CustomerPaymentStatusReport", "ebics-fetch $ebicsFlags status") put("report", "Fetch BankToCustomerAccountReport", "ebics-fetch $ebicsFlags report") put("notification", "Fetch BankToCustomerDebitCreditNotification", "ebics-fetch $ebicsFlags notification") put("statement", "Fetch BankToCustomerStatement", "ebics-fetch $ebicsFlags statement") put("list-incoming", "List incoming transaction", "list incoming $flags") put("list-outgoing", "List outgoing transaction", "list outgoing $flags") put("list-initiated", "List initiated payments", "list initiated $flags") put("list-ack", "List initiated payments pending manual submission acknowledgement", "list initiated $flags --awaiting-ack") put("wss", "Listen to notification over websocket", "testing wss $debugFlags") put("submit", "Submit pending transactions", "ebics-submit $ebicsFlags") put("submit-wait", "Submit pending transaction", "ebics-submit $debugFlags") put("export", "Export pending batches as pain001 messages", "manual export $flags payments.zip") putArgs("import", "Import xml files in root directory") { buildString { append("manual import $flags ") for (file in Path("..").listDirectoryEntries()) { if (file.extension == "xml") { append(file) append(" ") } } } } putArgs("status", "Set batch or transaction status") { "manual status $flags " + it.joinToString(" ") } put("reset-keys", "Reset EBICS keys") { if (kind.test) { clientKeysPath.deleteIfExists() } bankKeysPath.deleteIfExists() } put("tx", "Initiate a new transaction") { val now = Instant.now() nexusCmd.run("initiate-payment $flags --amount=$currency:0.1 --subject \"single $now\" \"$payto\"") } put("txs", "Initiate four new transactions") { val now = Instant.now() repeat(4) { nexusCmd.run("initiate-payment $flags --amount=$currency:${(10.0+it)/100} --subject \"multi $it $now\" \"$payto\"") } } put("tx-bad-name", "Initiate a new transaction with a bad name") { val badPayto = URLBuilder().takeFrom(payto) badPayto.parameters["receiver-name"] = "John Smith" val now = Instant.now() nexusCmd.run("initiate-payment $flags --amount=$currency:0.21 --subject \"bad name $now\" \"$badPayto\"") } put("tx-bad-iban", "Initiate a new transaction to a bad IBAN") { val badPayto = URLBuilder().takeFrom("payto://iban/XX18500105173385245165") badPayto.parameters["receiver-name"] = "John Smith" val now = Instant.now() nexusCmd.run("initiate-payment $flags --amount=$currency:0.22 --subject \"bad iban $now\" \"$badPayto\"") } put("tx-dummy-iban", "Initiate a new transaction to a dummy IBAN") { val now = Instant.now() nexusCmd.run("initiate-payment $flags --amount=$currency:0.23 --subject \"dummy iban $now\" \"$dummyPayto\"") } put("tx-check", "Check transaction semantic", "testing tx-check $flags") } Pair(suspend { nexusCmd.run("ebics-setup $debugFlags") }, cmds) } } while (true) { // Automatic setup if (host != null) { var clientKeys = loadClientKeys(clientKeysPath) val bankKeys = loadBankKeys(bankKeysPath) if (!kind.test && clientKeys == null) { msg("Manual setup is required for non test environment") } else if (clientKeys == null || !clientKeys.submitted_ini || !clientKeys.submitted_hia || bankKeys == null || !bankKeys.accepted) { step("Run EBICS setup") if (!setup()) { clientKeys = loadClientKeys(clientKeysPath) if (kind.test) { if (clientKeys == null || !clientKeys.submitted_ini || !clientKeys.submitted_hia) { msg("Got to ${kind.settings} and click on 'Reset EBICS user'") } else { msg("Got to ${kind.settings} and click on 'Activate EBICS user'") } } else { msg("Activate your keys at your bank") } } } } // REPL val line = try { reader.readLine("testbench> ")!! } catch (e: UserInterruptException) { print(ANSI.red("^C")) System.out.flush() throw ProgramResult(1) } val args = line.split(WORDS_REGEX).toMutableList() val cmdArg = args.removeFirstOrNull() val cmd = cmds[cmdArg] if (cmd != null) { step(cmd.first) cmd.second(args) } else { when (cmdArg) { "" -> continue "exit" -> break "?", "help" -> { println("Commands:") println(" setup - Setup") for ((name, cmd) in cmds) { println(" $name - ${cmd.first}") } } "setup" -> { step("Setup") setup() } else -> err("Unknown command '$cmdArg'") } } } } } } fun main(args: Array) { setupSecurityProperties() Cli().main(args) } typealias Cmds = Map) -> Unit>> data class CmdsBuilder( private val cmd: CliktCommand, val map: MutableMap ) -> Unit>>) { fun putCmd(name: String, step: String, lambda: suspend (List) -> Unit) { map[name] = Pair(step, lambda) } fun put(name: String, step: String, lambda: suspend () -> Unit) { putCmd(name = name, step = step, lambda = { lambda() }) } fun put(name: String, step: String, args: String) { put(name, step) { cmd.run(args) } } fun putArgs(name: String, step: String, parser: (List) -> String) { putCmd(name, step) { args: List -> cmd.run(parser(args)) } } } fun buildCmds(cmd: CliktCommand, actions: CmdsBuilder.() -> Unit): Cmds { val builder = CmdsBuilder(cmd, mutableMapOf()) builder.actions() return builder.map }libeufin-1.6.8/testbench/src/test/0000775000175000017500000000000015236145704017277 5ustar grothoffgrothofflibeufin-1.6.8/testbench/src/test/kotlin/0000775000175000017500000000000015236145704020577 5ustar grothoffgrothofflibeufin-1.6.8/testbench/src/test/kotlin/Iso20022Test.kt0000664000175000017500000001207315161724132023115 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.nexus.* import tech.libeufin.nexus.iso20022.* import tech.libeufin.ebics.* import java.nio.file.Files import java.nio.file.Path import kotlin.io.path.Path import kotlin.io.path.exists import kotlin.io.path.isDirectory import kotlin.io.path.listDirectoryEntries class Iso20022Test { @Test fun sample() { for (sample in Path("sample").listDirectoryEntries()) { if (sample.isDirectory()) { for (case in sample.listDirectoryEntries()) { val content = Files.newInputStream(case) val name = case.toString() println(name) if (name.contains("HAC")) { parseCustomerAck(content) } else if (name.contains("pain.002") || name.contains("pain002") ) { parseCustomerPaymentStatusReport(content) } else { parseTx(content) } } } else { val content = Files.newInputStream(sample) val name = sample.toString() println(name) if (name.contains("HAC")) { parseCustomerAck(content) } else if (name.contains("pain.002") || name.contains("pain002") ) { parseCustomerPaymentStatusReport(content) } else { parseTx(content) } } } } @Test fun logs() { val root = Path("test") if (!root.exists()) return for (platform in root.listDirectoryEntries()) { if (!platform.isDirectory() || platform.fileName.toString() == "platform") continue // List logs var logs = mutableListOf() for (file in platform.listDirectoryEntries()) { if (!file.isDirectory()) continue when (file.fileName.toString()) { "fetch" -> for (transaction in file.listDirectoryEntries()) { if (transaction.isDirectory()) { logs.addAll(transaction.listDirectoryEntries()) } } "submit" -> {} else -> for (transaction in file.listDirectoryEntries()) { when (transaction.fileName.toString()) { "fetch" -> logs.addAll(transaction.listDirectoryEntries()) "submit" -> {} else -> { var payload = transaction.resolve("payload") if (payload.exists()) { logs.addAll(payload.listDirectoryEntries()) continue } payload = transaction.resolve("payload.xml") if (payload.exists()) { logs.add(payload) } } } } } } // Load config val path = root.resolve("platform").resolve("${platform.fileName}.conf") if (!path.exists()) continue val cfg = nexusConfig(root.resolve("platform").resolve("${platform.fileName}.conf")) val currency = cfg.currency val dialect = cfg.ebics.dialect // Parse logs for (log in logs) { val content = Files.newInputStream(log) val name = log.toString() println(name) if (name.contains("wssparam") || name.endsWith(".txt")) { // Skip } else if (name.contains("HAC")) { parseCustomerAck(content) } else if (name.contains("HAA")) { EbicsAdministrative.parseHAA(content) } else if (name.contains("HKD")) { EbicsAdministrative.parseHKD(content) } else if (name.contains("pain.002")) { parseCustomerPaymentStatusReport(content) } else { parseTx(content) } } } } }libeufin-1.6.8/testbench/src/test/kotlin/CliTest.kt0000664000175000017500000001415615122266731022513 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.asUtf8 import tech.libeufin.nexus.* import tech.libeufin.ebics.* import tech.libeufin.nexus.cli.LibeufinNexus import tech.libeufin.ebisync.cli.LibeufinEbisync import java.io.ByteArrayOutputStream import java.io.PrintStream import kotlin.io.path.* import kotlin.test.Test import kotlin.test.assertEquals val nexusCmd = LibeufinNexus() val ebisyncCmd = LibeufinEbisync() fun CliktCommand.testErr(cmd: String, msg: String) { val prevOut = System.err val tmpOut = ByteArrayOutputStream() System.setErr(PrintStream(tmpOut)) val result = test(cmd) System.setErr(prevOut) val tmpStr = tmpOut.asUtf8() println(tmpStr) assertEquals(1, result.statusCode, "'$cmd' should have failed") val line = tmpStr.substringAfterLast(" - ").trimEnd('\n') println(line) assertEquals(msg, line) } class CliTest { /** Test error format related to the keying process */ @Test fun keys() { val nexusCmds = listOf("ebics-submit", "ebics-fetch") val nexusAllCmds = listOf("ebics-submit", "ebics-fetch", "ebics-setup") val ebiSyncCmds = listOf("fetch") val ebiSyncAllCmds = listOf("fetch", "setup") val conf = "conf/cli.conf" val nexusCfg = nexusConfig(Path(conf)) val cfg = nexusCfg.ebics val clientKeysPath = cfg.clientPrivateKeysPath val bankKeysPath = cfg.bankPublicKeysPath clientKeysPath.parent!!.createParentDirectories() clientKeysPath.parent!!.toFile().setWritable(true) bankKeysPath.parent!!.createDirectories() fun checkCmds(msg: String) { for (cmd in listOf("ebics-submit", "ebics-fetch")) { nexusCmd.testErr("$cmd -c $conf", msg.replace("SETUPCMD", "libeufin-nexus ebics-setup")) } for (cmd in listOf("fetch")) { ebisyncCmd.testErr("$cmd -c $conf", msg.replace("SETUPCMD", "libeufin-ebisync setup")) } } fun checkAllCmds(msg: String) { for (cmd in listOf("ebics-submit", "ebics-fetch", "ebics-setup")) { nexusCmd.testErr("$cmd -c $conf", msg) } for (cmd in listOf("fetch", "setup")) { ebisyncCmd.testErr("$cmd -c $conf", msg) } } // Missing client keys clientKeysPath.deleteIfExists() checkCmds("Missing client private keys file at '$clientKeysPath', run 'SETUPCMD' first") // Empty client file clientKeysPath.createFile() checkAllCmds("Could not decode client private keys at '$clientKeysPath': Expected start of the object '{', but had 'EOF' instead at path: $\nJSON input: ") // Bad client json clientKeysPath.writeText("CORRUPTION", Charsets.UTF_8) checkAllCmds("Could not decode client private keys at '$clientKeysPath': Unexpected JSON token at offset 0: Expected start of the object '{', but had 'C' instead at path: $\nJSON input: CORRUPTION") // Missing permission clientKeysPath.toFile().setReadable(false) if (!clientKeysPath.isReadable()) { // Skip if root checkAllCmds("Could not read client private keys at '$clientKeysPath': permission denied") } // Unfinished client persistClientKeys(generateNewKeys(), clientKeysPath) checkCmds("Unsubmitted client private keys, run 'SETUPCMD' first") // Missing bank keys persistClientKeys(generateNewKeys().apply { submitted_hia = true submitted_ini = true }, clientKeysPath) bankKeysPath.deleteIfExists() checkCmds("Missing bank public keys at '$bankKeysPath', run 'SETUPCMD' first") // Empty bank file bankKeysPath.createFile() checkAllCmds("Could not decode bank public keys at '$bankKeysPath': Expected start of the object '{', but had 'EOF' instead at path: $\nJSON input: ") // Bad bank json bankKeysPath.writeText("CORRUPTION", Charsets.UTF_8) checkAllCmds("Could not decode bank public keys at '$bankKeysPath': Unexpected JSON token at offset 0: Expected start of the object '{', but had 'C' instead at path: $\nJSON input: CORRUPTION") // Missing permission bankKeysPath.toFile().setReadable(false) if (!bankKeysPath.isReadable()) { // Skip if root checkAllCmds("Could not read bank public keys at '$bankKeysPath': permission denied") } // Unfinished bank persistBankKeys(BankPublicKeysFile( bank_authentication_public_key = CryptoUtil.genRSAPublic(2048), bank_encryption_public_key = CryptoUtil.genRSAPublic(2048), accepted = false ), bankKeysPath) checkCmds("Unaccepted bank public keys, run 'SETUPCMD' until accepting the bank keys") // Missing permission clientKeysPath.deleteIfExists() clientKeysPath.parent!!.toFile().setWritable(false) if (!clientKeysPath.parent!!.isWritable()) { // Skip if root nexusCmd.testErr("ebics-setup -c $conf", "Could not write client private keys at '$clientKeysPath': permission denied on '${clientKeysPath.parent}'") ebisyncCmd.testErr("setup -c $conf", "Could not write client private keys at '$clientKeysPath': permission denied on '${clientKeysPath.parent}'") } } }libeufin-1.6.8/testbench/src/test/kotlin/MigrationTest.kt0000644000175000017500000002551015037252417023730 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import kotlinx.coroutines.runBlocking import org.junit.Test import tech.libeufin.common.db.* import kotlin.io.path.Path import kotlin.io.path.readText import java.util.UUID import kotlin.test.assertTrue class MigrationTest { @Test fun test() = runBlocking { val conn = pgDataSource("postgres:///libeufincheck").pgConnection() // Drop current schemas conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-drop.sql").readText()) conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-drop.sql").readText()) // libeufin-bank-0001 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0001.sql").readText()) conn.execSQLUpdate(""" INSERT INTO customers (login, password_hash) VALUES ('account_1', 'fack_hash'), ('account_2', 'fack_hash'), ('account_3', 'fack_hash'), ('account_4', 'fack_hash'); INSERT INTO bank_accounts (internal_payto_uri, owning_customer_id) VALUES ('payto_1', 1), ('payto_2', 2), ('payto_3', 3), ('payto_4', 4); INSERT INTO bank_account_transactions(creditor_payto_uri, creditor_name, debtor_payto_uri, debtor_name, subject, amount, transaction_date, direction, bank_account_id) VALUES ('payto_1', 'account_1', 'payto_2', 'account_2', 'subject', (0, 0)::taler_amount, 42, 'credit'::direction_enum, 1), ('payto_1', 'account_1', 'payto_2', 'account_2', 'subject', (0, 0)::taler_amount, 42, 'credit'::direction_enum, 1), ('payto_1', 'account_1', 'payto_2', 'account_2', 'subject', (0, 0)::taler_amount, 42, 'credit'::direction_enum, 1); INSERT INTO taler_exchange_incoming(reserve_pub, bank_transaction) VALUES ('\x6ca1ab1a76a484d7424064c51c49c1947405f42f7d185d052dbf6718d845ec6b'::bytea, 1), ('\xa605637a4852684e4957e6177f41311eacf8661a6a74b90178c487fe347b9918'::bytea, 2); INSERT INTO challenges(code, creation_date, expiration_date, retry_counter) VALUES ('secret_code', 42, 42, 42), ('secret_code', 42, 42, 42); INSERT INTO cashout_operations(request_uid, amount_debit, amount_credit, subject, creation_time, bank_account, challenge, local_transaction) VALUES ('\x6ca1ab1a76a484d7424064c51c49c1947405f42f7d185d052dbf6718d845ec6b'::bytea, (0, 0)::taler_amount, (0, 0)::taler_amount, 'subject', 42, 1, 1, 1), ('\xa605637a4852684e4957e6177f41311eacf8661a6a74b90178c487fe347b9918'::bytea, (0, 0)::taler_amount, (0, 0)::taler_amount, 'subject', 42, 1, 2, NULL); INSERT INTO taler_withdrawal_operations(withdrawal_uuid, amount, reserve_pub, wallet_bank_account) VALUES (gen_random_uuid(), (0, 0)::taler_amount, '\x6ca1ab1a76a484d7424064c51c49c1947405f42f7d185d052dbf6718d845ec6b'::bytea, 1), (gen_random_uuid(), (0, 0)::taler_amount, '\xa605637a4852684e4957e6177f41311eacf8661a6a74b90178c487fe347b9918'::bytea, 2); """) // libeufin-bank-0002 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0002.sql").readText()) // libeufin-bank-0003 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0003.sql").readText()) // libeufin-bank-0004 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0004.sql").readText()) conn.execSQLUpdate(""" UPDATE bank_accounts SET min_cashout=(0, 1) WHERE bank_account_id=2; UPDATE bank_accounts SET min_cashout=(2, 300) WHERE bank_account_id IN (3, 4); """) // libeufin-bank-0005 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0005.sql").readText()) // libeufin-bank-0006 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0006.sql").readText()) // libeufin-bank-0007 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0007.sql").readText()) // libeufin-bank-0008 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0008.sql").readText()) // libeufin-bank-0009 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0009.sql").readText()) // libeufin-bank-0010 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0010.sql").readText()) // libeufin-bank-0011 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0011.sql").readText()) // libeufin-bank-0012 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0012.sql").readText()) conn.execSQLUpdate(""" INSERT INTO config(key, value) VALUES ('cashin_ratio', '{"val": 1, "frac": 2}'::jsonb), ('cashin_fee', '{"val": 3, "frac": 4}'::jsonb), ('cashin_tiny_amount', '{"val": 5, "frac": 6}'::jsonb), ('cashin_min_amount', '{"val": 7, "frac": 8}'::jsonb), ('cashin_rounding_mode', '{"mode": "zero"}'::jsonb), ('cashout_ratio', '{"val": 9, "frac": 10}'::jsonb), ('cashout_fee', '{"val": 11, "frac": 12}'::jsonb), ('cashout_tiny_amount', '{"val": 13, "frac": 14}'::jsonb), ('cashout_min_amount', '{"val": 15, "frac": 16}'::jsonb), ('cashout_rounding_mode', '{"mode": "nearest"}'::jsonb); """) // libeufin-bank-0013 conn.execSQLUpdate(Path("../database-versioning/libeufin-bank-0013.sql").readText()) conn.withStatement( """ SELECT value='{ "cashin": { "fee": { "val": 3, "frac": 4 }, "ratio": { "val": 1, "frac": 2 }, "min_amount": { "val": 7, "frac": 8 }, "tiny_amount": { "val": 5, "frac": 6 }, "rounding_mode": "zero" }, "cashout": { "fee": { "val": 11, "frac": 12 }, "ratio": { "val": 9, "frac": 10 }, "min_amount": { "val": 15, "frac": 16 }, "tiny_amount": { "val": 13, "frac": 14 }, "rounding_mode": "nearest" } }'::jsonb FROM libeufin_bank.config WHERE key='conversion_rate' """ ) { one { assertTrue(it.getBoolean(1)) } } // libeufin-nexus-0001 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0001.sql").readText()) conn.execSQLUpdate(""" INSERT INTO outgoing_transactions(amount, execution_time, message_id) VALUES ((0, 0)::taler_amount, 42, 'id'); INSERT INTO initiated_outgoing_transactions(amount, wire_transfer_subject, initiation_time, credit_payto_uri, outgoing_transaction_id, request_uid) VALUES ((0, 0)::taler_amount, 'subject', 42, 'payto_0', 1, 'request_uid'); """) // libeufin-nexus-0002 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0002.sql").readText()) // libeufin-nexus-0003 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0003.sql").readText()) // libeufin-nexus-0004 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0004.sql").readText()) // libeufin-nexus-0005 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0005.sql").readText()) // libeufin-nexus-0006 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0006.sql").readText()) conn.execSQLUpdate(""" INSERT INTO initiated_outgoing_transactions(amount, wire_transfer_subject, initiation_time, credit_payto_uri, outgoing_transaction_id, request_uid, order_id) VALUES ((42, 0)::taler_amount, 'subject', 0, 'credit_payto', NULL, 'TX0', 'ORDER0'), ((41, 0)::taler_amount, 'subject', 0, 'credit_payto', NULL, 'TX1', NULL); """) // libeufin-nexus-0007 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0007.sql").readText()) // libeufin-nexus-0008 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0008.sql").readText()) // libeufin-nexus-0009 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0009.sql").readText()) conn.execSQLUpdate(""" INSERT INTO incoming_transactions(amount, subject, execution_time, debit_payto, bank_id) VALUES ((1, 0)::taler_amount, 'simple', 42, 'debit_payto', 'first'), ((2, 0)::taler_amount, 'reserve', 42, 'debit_payto', 'second'), ((3, 0)::taler_amount, 'kyc', 42, 'debit_payto', 'third'), ((4, 0)::taler_amount, 'simple', 42, 'debit_payto', '${UUID.randomUUID()}'), ((5, 0)::taler_amount, 'reserve', 42, 'debit_payto', '${UUID.randomUUID()}'), ((6, 0)::taler_amount, 'kyc', 42, 'debit_payto', '${UUID.randomUUID()}');; INSERT INTO talerable_incoming_transactions(incoming_transaction_id, type, reserve_public_key, account_pub) VALUES (2, 'reserve', '\x6ca1ab1a76a484d7424064c51c49c1947405f42f7d185d052dbf6718d845ec6b'::bytea, null), (3, 'kyc', null, '\x6ca1ab1a76a484d7424064c51c49c1947405f42f7d185d052dbf6718d845ec6b'::bytea); """) // libeufin-nexus-0010 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0010.sql").readText()) // libeufin-nexus-0011 conn.execSQLUpdate(Path("../database-versioning/libeufin-nexus-0011.sql").readText()) } }libeufin-1.6.8/testbench/src/test/kotlin/IntegrationTest.kt0000664000175000017500000004221215156463305024264 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test import io.ktor.client.* import io.ktor.client.engine.cio.* import io.ktor.client.plugins.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import kotlinx.coroutines.runBlocking import org.junit.Test import tech.libeufin.bank.BankAccountTransactionsResponse import tech.libeufin.bank.CashoutResponse import tech.libeufin.bank.ConversionResponse import tech.libeufin.bank.RegisterAccountResponse import tech.libeufin.bank.cli.LibeufinBank import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.common.test.* import tech.libeufin.common.api.engine import tech.libeufin.nexus.* import tech.libeufin.nexus.cli.LibeufinNexus import tech.libeufin.nexus.cli.registerIncomingPayment import tech.libeufin.nexus.iso20022.* import java.time.Instant import kotlin.io.path.Path import kotlin.io.path.readText import kotlin.test.* import tech.libeufin.nexus.db.Database as NexusDb const val UNIX_SOCKET_PATH: String = "/tmp/libeufin.sock"; fun CliktCommand.run(cmd: String) { val result = test(cmd) if (result.statusCode != 0) throw Exception(result.output) println(result.output) } fun HttpResponse.assertNoContent() { assertEquals(HttpStatusCode.NoContent, this.status) } fun server(client: HttpClient, lambda: () -> Unit) { globalTestTokens.clear() // Start the HTTP server in another thread kotlin.concurrent.thread(isDaemon = true) { lambda() } // Wait for the HTTP server to be up runBlocking { client.get("/config") } } fun setup(conf: String, lambda: suspend (NexusDb) -> Unit) { try { runBlocking { nexusConfig(Path(conf)).withDb { db, _ -> lambda(db) } } } finally { engine?.stop(0, 0) // Stop http server if started } } inline fun assertException(msg: String, lambda: () -> Unit) { try { lambda() throw Exception("Expected failure: $msg") } catch (e: Exception) { assert(e.message!!.startsWith(msg)) { "${e.message}" } } } class IntegrationTest { val nexusCmd = LibeufinNexus() val bankCmd = LibeufinBank() val client = HttpClient(CIO) { install(HttpRequestRetry) { maxRetries = 10 constantDelay(200, 100) } defaultRequest { url("http://socket/") unixSocket(UNIX_SOCKET_PATH) } } @Test fun mini() { val client = HttpClient(CIO) { install(HttpRequestRetry) { maxRetries = 10 constantDelay(200, 100) } defaultRequest { url("http://0.0.0.0:8080/") } } val flags = "-c conf/mini.conf -L DEBUG" bankCmd.run("dbinit $flags -r") bankCmd.run("passwd admin admin-password $flags") bankCmd.run("dbinit $flags") // Idempotent server(client) { bankCmd.run("serve $flags") } setup("conf/mini.conf") { // Check bank is running client.get("/public-accounts").assertNoContent() } bankCmd.run("gc $flags") server(client) { nexusCmd.run("serve $flags") } engine?.stop(0, 0) } @Test fun errors() { val flags = "-c conf/integration.conf -L DEBUG" nexusCmd.run("dbinit $flags -r") bankCmd.run("dbinit $flags -r") bankCmd.run("passwd admin admin-password $flags") suspend fun NexusDb.checkCount(nbIncoming: Int, nbBounce: Int, nbTalerable: Int) { serializable( """ SELECT (SELECT count(*) FROM incoming_transactions) AS incoming, (SELECT count(*) FROM bounced_transactions) AS bounce, (SELECT count(*) FROM talerable_incoming_transactions) AS talerable; """ ) { one { assertEquals( Triple(nbIncoming, nbBounce, nbTalerable), Triple(it.getInt("incoming"), it.getInt("bounce"), it.getInt("talerable")) ) } } } setup("conf/integration.conf") { db -> val cfg = NexusIngestConfig.default(AccountType.exchange) val userPayTo = IbanPayto.rand("Sir Florian") // Load conversion setup manually as the server would refuse to start without an exchange account val sqlProcedures = Path("../database-versioning/libeufin-conversion-setup.sql") db.conn { it.execSQLUpdate(sqlProcedures.readText()) it.execSQLUpdate("SET search_path TO libeufin_nexus;") } val reservePub = EddsaPublicKey.randEdsaKey() val reservePayment = IncomingPayment( amount = TalerAmount("EUR:10"), debtor = userPayTo, subject = "Error test $reservePub", executionTime = Instant.now(), id = IncomingId(null, "reserve_error", null) ) assertException("ERROR: cashin failed: missing exchange account") { registerIncomingPayment(db, cfg, reservePayment) } db.checkCount(0, 0, 0) // But KYC works registerIncomingPayment( db, cfg, reservePayment.copy( id = IncomingId(null, "kyc", null), subject = "Error test KYC:${EddsaPublicKey.randEdsaKey()}" ) ) db.checkCount(1, 0, 1) // Create exchange account bankCmd.run("create-account $flags -u exchange -p exchange-password --name 'Mr Money' --exchange") // Missing rates registerIncomingPayment(db, cfg, reservePayment.copy(id = IncomingId(null, "rate_error", null))) db.checkCount(2, 1, 1) // Start server server(client) { bankCmd.run("serve $flags") } // Set conversion rates client.postAdmin("/conversion-info/conversion-rate") { json { "cashin_ratio" to "0.8" "cashin_fee" to "KUDOS:0.02" "cashin_tiny_amount" to "KUDOS:0.01" "cashin_rounding_mode" to "nearest" "cashin_min_amount" to "EUR:0" "cashout_ratio" to "1.25" "cashout_fee" to "EUR:0.003" "cashout_tiny_amount" to "EUR:0.01" "cashout_rounding_mode" to "zero" "cashout_min_amount" to "KUDOS:0.1" } }.assertNoContent() assertException("ERROR: cashin failed: admin balance insufficient") { db.payment.registerTalerableIncoming(reservePayment, IncomingSubject.Reserve(reservePub)) } // Allow admin debt bankCmd.run("edit-account admin --debit_threshold KUDOS:100 $flags") // Too small amount db.checkCount(2, 1, 1) registerIncomingPayment(db, cfg, reservePayment.copy( amount = TalerAmount("EUR:0.01"), )) db.checkCount(3, 2, 1) client.getA("/accounts/exchange/transactions").assertNoContent() // Check success val validPayment = reservePayment.copy( subject = "Success $reservePub", id = IncomingId(null, "success", null), ) registerIncomingPayment(db, cfg, validPayment) db.checkCount(4, 2, 2) client.getA("/accounts/exchange/transactions") .assertOkJson() // Check idempotency registerIncomingPayment(db, cfg, validPayment) registerIncomingPayment(db, cfg, validPayment.copy( subject="Success 2 $reservePub" )) db.checkCount(4, 2, 2) } } @Test fun conversion() { suspend fun NexusDb.checkInitiated(amount: TalerAmount, name: String?) { serializable( """ SELECT (amount).val AS amount_val, (amount).frac AS amount_frac, credit_payto, subject FROM initiated_outgoing_transactions ORDER BY initiation_time DESC """ ) { one { val am = it.getAmount("amount", amount.currency) println(it.getString("credit_payto")) val payto = it.getIbanPayto("credit_payto") val subject = it.getString("subject") assertEquals(amount, am) assertEquals(payto.receiverName, name) } } } val flags = "-c conf/integration.conf -L DEBUG" nexusCmd.run("dbinit $flags -r") bankCmd.run("dbinit $flags -r") bankCmd.run("passwd admin admin-password $flags") bankCmd.run("edit-account admin --debit_threshold KUDOS:1000 $flags") bankCmd.run("create-account $flags -u exchange -p exchange-password --name 'Mr Money' --exchange") nexusCmd.run("dbinit $flags") // Idempotent bankCmd.run("dbinit $flags") // Idempotent server(client) { bankCmd.run("serve $flags") } setup("conf/integration.conf") { db -> val userPayTo = IbanPayto.rand("Sir Christian") val fiatPayTo = IbanPayto.rand() // Create user client.postAdmin("/accounts") { json { "username" to "customer" "password" to "customer-password" "name" to "John Smith" "internal_payto_uri" to userPayTo "cashout_payto_uri" to fiatPayTo "debit_threshold" to "KUDOS:100" "contact_data" to obj { "phone" to "+99" } } }.assertOkJson() // Set conversion rates client.postAdmin("/conversion-info/conversion-rate") { json { "cashin_ratio" to "0.8" "cashin_fee" to "KUDOS:0.02" "cashin_tiny_amount" to "KUDOS:0.01" "cashin_rounding_mode" to "nearest" "cashin_min_amount" to "EUR:0" "cashout_ratio" to "1.25" "cashout_fee" to "EUR:0.003" "cashout_tiny_amount" to "EUR:0.01" "cashout_rounding_mode" to "zero" "cashout_min_amount" to "KUDOS:0.1" } }.assertNoContent() // Cashin repeat(3) { i -> val reservePub = EddsaPublicKey.randEdsaKey() val amount = TalerAmount("EUR:${20+i}") val subject = "cashin test $i: $reservePub" nexusCmd.run("testing fake-incoming $flags --subject \"$subject\" --amount $amount $userPayTo") val converted = client.get("/conversion-info/cashin-rate?amount_debit=EUR:${20 + i}") .assertOkJson().amount_credit client.getA("/accounts/exchange/transactions").assertOkJson { val tx = it.transactions.first() assertEquals(subject, tx.subject) assertEquals(converted, tx.amount) } client.getA("/accounts/exchange/taler-wire-gateway/history/incoming").assertOkJson { val tx = it.incoming_transactions.first() assertEquals(converted, tx.amount) assertIs(tx) assertEquals(reservePub, tx.reserve_pub) } } // Cashout repeat(3) { i -> val requestUid = ShortHashCode.rand() val amount = TalerAmount("KUDOS:${10+i}") val converted = client.get("/conversion-info/cashout-rate?amount_debit=$amount") .assertOkJson().amount_credit client.postA("/accounts/customer/cashouts") { json { "request_uid" to requestUid "amount_debit" to amount "amount_credit" to converted } }.assertOkJson() db.checkInitiated(converted, "John Smith") } // Exchange bounce no name repeat(3) { i -> val reservePub = EddsaPublicKey.randEdsaKey() val amount = TalerAmount("EUR:${30+i}") val subject = "exchange bounce test $i: $reservePub" // Cashin nexusCmd.run("testing fake-incoming $flags --subject \"$subject\" --amount $amount $userPayTo") val converted = client.get("/conversion-info/cashin-rate?amount_debit=EUR:${30 + i}") .assertOkJson().amount_credit client.getA("/accounts/exchange/transactions").assertOkJson { val tx = it.transactions.first() assertEquals(subject, tx.subject) assertEquals(converted, tx.amount) } client.getA("/accounts/exchange/taler-wire-gateway/history/incoming").assertOkJson { val tx = it.incoming_transactions.first() assertEquals(converted, tx.amount) assertIs(tx) assertEquals(reservePub, tx.reserve_pub) } // Bounce client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to converted "exchange_base_url" to "http://exchange.example.com/" "wtid" to reservePub "credit_account" to "payto://x-taler-bank/localhost/admin" } }.assertOkJson() db.checkInitiated(amount, "Sir Christian") } // Exchange bounce with name repeat(3) { i -> val reservePub = EddsaPublicKey.randEdsaKey() val amount = TalerAmount("EUR:${40+i}") val subject = "exchange bounce test $i: $reservePub" // Cashin nexusCmd.run("testing fake-incoming $flags --subject \"$subject\" --amount $amount $userPayTo") val converted = client.get("/conversion-info/cashin-rate?amount_debit=EUR:${40 + i}") .assertOkJson().amount_credit client.getA("/accounts/exchange/transactions").assertOkJson { val tx = it.transactions.first() assertEquals(subject, tx.subject) assertEquals(converted, tx.amount) } client.getA("/accounts/exchange/taler-wire-gateway/history/incoming").assertOkJson { val tx = it.incoming_transactions.first() assertEquals(converted, tx.amount) assertIs(tx) assertEquals(reservePub, tx.reserve_pub) } // Bounce client.postA("/accounts/exchange/taler-wire-gateway/transfer") { json { "request_uid" to HashCode.rand() "amount" to converted "exchange_base_url" to "http://exchange.example.com/" "wtid" to reservePub "credit_account" to "payto://x-taler-bank/localhost/admin" } }.assertOkJson() db.checkInitiated(amount, "Sir Christian") } } } } libeufin-1.6.8/testbench/README.md0000664000175000017500000000253515074137503017013 0ustar grothoffgrothoff# LibEuFin Test Bench ## Interactive EBICS test To add a platform write a minimal configuration file at `testbench/test/conf/PLATFORM.conf` such as : ``` ini # testbench/test/conf/PLATFORM.conf [nexus-ebics] currency = CHF # Bank HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_DIALECT = postfinance # EBICS IDs HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 IBAN = CH7789144474425692816 BIC = POFICHBEXXX NAME = LibEuFin Tests ``` To start the interactive EBICS test run : ``` sh make testbench platform=PLATFORM ``` If HOST_BASE_URL is one a known test platform we will generate and then offer to reset client private keys to test keys registration, otherwise, we will expect existing keys to be found at `testbench/test/PLATFORM/client-ebics-keys.json`. This minimal configuration will be augmented on start, you can find the full documentation at `testbench/test/PLATFORM/ebics.conf`. By default, the testbench will use a random dummy IBAN when issuing transactions, but you can specify a real IBAN for real-life testing in the testbench configuration at `testbench/test/config.json` : ``` json // testbench/test/PLATFORM/ebics.conf { "payto": { "CHF": "payto://iban/CH4189144589712575493?receiver-name=John%20Smith", "EUR": "payto://iban/DE54500105177452372744?receiver-name=John%20Smith" } } ``` libeufin-1.6.8/testbench/build.gradle0000664000175000017500000000246415156463305020017 0ustar grothoffgrothoffplugins { id("kotlin") id("application") id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version" } java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } compileKotlin.kotlinOptions.jvmTarget = "17" compileTestKotlin.kotlinOptions.jvmTarget = "17" sourceSets.main.java.srcDirs = ["src/main/kotlin"] dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") implementation(project(":libeufin-common")) implementation(project(":libeufin-bank")) implementation(project(":libeufin-nexus")) implementation(project(":libeufin-ebics")) implementation(project(":libeufin-ebisync")) implementation("com.github.ajalt.clikt:clikt:$clikt_version") implementation("org.postgresql:postgresql:$postgres_version") implementation("org.jline:jline:4.0.0") implementation("io.ktor:ktor-client-mock:$ktor_version") implementation("io.ktor:ktor-server-test-host:$ktor_version") implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") implementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version") } application { mainClass = "tech.libeufin.testbench.MainKt" applicationName = "libeufin-testbench-test" } run { standardInput = System.in }libeufin-1.6.8/testbench/sample/0000775000175000017500000000000015236145704017012 5ustar grothoffgrothoff././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootlibeufin-1.6.8/testbench/sample/10_camt054_Return_Detailavisierung mit Einzelbuchung_ISO2019_v2019.xmllibeufin-1.6.8/testbench/sample/10_camt054_Return_Detailavisierung mit Einzelbuchung_ISO2019_v2019.x0000644000175000017500000000601714674637415033036 0ustar grothoffgrothoff 20201124375204228763929 2022-05-25T00:29:29 1 true SPS/1.7/PROD 20201124375204228763930 2022-05-25T00:29:29 2022-05-24T00:00:00 2022-05-24T23:59:59 OTHR CH5109000000250092291 Bernasconi Maria Biel/Bienne 500.00 CRDT true BOOK
    2020-11-24
    2020-11-24
    075820002ZZTJR1K PMNT ICDT RRTN 1 190520CH02ZZTJR1 PmtInfId-001-03 InstrId-001-03-04 EndToEndId-001-03-04 500.00 CRDT PMNT ICDT RRTN Robert Schneider SA Rue du Lac 177 2503 Biel/Bienne CH8709000000929471495 9000 PostFinance AG Mingerstrasse 20 3030 Bern Kontouebertrag 2022-05-24T20:00:00 AC01 Kontonummer falsch EndToEndId-001-03-04 RETOUR TRANSAKTION NICHT AUSFÜHRBAR Kontouebertrag
    libeufin-1.6.8/testbench/sample/5_pain002 A-Level ACTC (Empfangsbestaetigung FDS)_v2019.xml0000644000175000017500000000124014674637415030541 0ustar grothoffgrothoff 20180315375204222821684 2022-05-02T10:49:10 POFICHBE MsgId-001 pain.001.001.09.ch.03 ACTC ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootlibeufin-1.6.8/testbench/sample/9_camt054 Return_Detailavisierung mit Sammelbuchung_ISO2019_v2019.xmllibeufin-1.6.8/testbench/sample/9_camt054 Return_Detailavisierung mit Sammelbuchung_ISO2019_v2019.xm0000644000175000017500000000604214674637415033032 0ustar grothoffgrothoff 20190520375204012050698 2022-05-20T23:40:06 1 true SPS 20190520375204012050705 2022-05-20T23:40:06 2022-05-20T00:00:00 2022-05-20T23:59:59 OTHR CH2909000000250094239 Robert Schneider SA Grands magasins Biel/Bienne 400.00 CRDT false BOOK
    2022-05-20
    2022-05-20
    086820002PBWFX2U PMNT ICDT RRTN 1 180327CH02P92DYD PmtInfId-004-01 InstrId-004-01-01 EndToEndId-004-01-01 400.00 CRDT PMNT ICDT RRTN Robert Schneider SA Rue du Lac 177 2503 Biel/Bienne CH8709000000929471495 9000 PostFinance AG Mingerstrasse 20 3030 Bern Kontouebertrag 2022-05-20T20:00:00 AC01 Kontonummer falsch SAMMELGUTSCHRIFT RETOUREN VERARBEITUNG VOM 20.05.2022 PAKET ID: 190520CH000006O1
    libeufin-1.6.8/testbench/sample/3_pain002 B-Level und C-Level RJCT_ISO2019_v2019.xml0000644000175000017500000000162614674637415026744 0ustar grothoffgrothoff 204691ACFC/071125/023362 2022-05-02T05:11:25Z POFICHBE MSG-02-QRR-SCOR pain.001.001.09.ch.03 PMTINF-02 RJCT AC01 0999;CH7280005000088877766 Lastkonto unbekannt libeufin-1.6.8/testbench/sample/10_camt054_Return_Detailavisierung mit Einzelbuchung_v2009.xml0000644000175000017500000000567214674637415032346 0ustar grothoffgrothoff 20201124375204228763929 2020-11-25T00:29:29 1 true SPS/1.7/PROD 20201124375204228763930 2020-11-25T00:29:29 2020-11-24T00:00:00 2020-11-24T23:59:59 OTHR CH5109000000250092291 Bernasconi Maria Biel/Bienne 500.00 CRDT true BOOK
    2020-11-24
    2020-11-24
    075820002ZZTJR1K PMNT ICDT RRTN 1 190520CH02ZZTJR1 PmtInfId-001-03 InstrId-001-03-04 EndToEndId-001-03-04 500.00 CRDT PMNT ICDT RRTN Robert Schneider SA Rue du Lac 177 2503 Biel/Bienne CH8709000000929471495 9000 PostFinance AG Mingerstrasse 20 3030 Bern Kontouebertrag 2020-11-24T20:00:00 AC01 Kontonummer falsch EndToEndId-001-03-04 RETOUR TRANSAKTION NICHT AUSFÜHRBAR Kontouebertrag
    libeufin-1.6.8/testbench/sample/3_pain002 B-Level und C-Level RJCT_v2009.xml0000644000175000017500000000233614674637415025714 0ustar grothoffgrothoff 20180315375204222822452 2018-03-15T11:25:12 POFICHBE MsgId-001 pain.001.001.03.ch.02 PmtInfId-001-03 PART InstrId-001-03-04 EndToEndId-001-03-04 RJCT AC01 1301813;Konto ungültig 2018-03-16 2018-03-16 libeufin-1.6.8/testbench/sample/2_pain002 B-Level ACCP_v2019.xml0000644000175000017500000000140714674637415023677 0ustar grothoffgrothoff 204691ACFC/071125/023228 2022-05-02T05:11:25Z POFICHBE MSG-02-QRR-SCOR pain.001.001.09.ch.03 PMTINF-01 ACCP libeufin-1.6.8/testbench/sample/6_pain002 A-Level RJCT (Empfangsbestaetigung FDS)_v2009.xml0000644000175000017500000000151714674637415030600 0ustar grothoffgrothoff 20180326375204011685776 2018-03-26T14:40:00 POFICHBE MsgId-005 pain.001.001.03.ch.02 RJCT AM10 904114;ControlSum fehlerhaft libeufin-1.6.8/testbench/sample/6_pain002 A-Level RJCT (Empfangsbestaetigung FDS)_v2019.xml0000644000175000017500000000143514674637415030600 0ustar grothoffgrothoff 20180326375204011685776 2022-05-02T14:40:00 POFICHBE MsgId-005 pain.001.001.09.ch.03 RJCT AM10 904114;ControlSum fehlerhaft libeufin-1.6.8/testbench/sample/9_camt054 Return_Detailavisierung mit Sammelbuchung_v2009.xml0000644000175000017500000000602714674637415032162 0ustar grothoffgrothoff 20190520375204012050698 2019-05-20T23:40:06 1 true SPS/1.6/PROD 20190520375204012050705 2019-05-20T23:40:06 2019-05-20T00:00:00 2019-05-20T23:59:59 OTHR CH2909000000250094239 Robert Schneider SA Grands magasins Biel/Bienne 400.00 CRDT false BOOK
    2019-05-20
    2019-05-20
    086820002PBWFX2U PMNT ICDT RRTN 1 180327CH02P92DYD PmtInfId-004-01 InstrId-004-01-01 EndToEndId-004-01-01 400.00 CRDT PMNT ICDT RRTN Robert Schneider SA Rue du Lac 177 2503 Biel/Bienne CH8709000000929471495 9000 PostFinance AG Mingerstrasse 20 3030 Bern Kontouebertrag 2019-05-20T20:00:00 AC01 Kontonummer falsch SAMMELGUTSCHRIFT RETOUREN VERARBEITUNG VOM 20.05.2019 PAKET ID: 190520CH000006O1
    libeufin-1.6.8/testbench/sample/postfinance/0000775000175000017500000000000015236145704021323 5ustar grothoffgrothoff././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/camt053_P_CH2909000000250094239_1110092698_0_2020112503071366_v2019.xmllibeufin-1.6.8/testbench/sample/postfinance/camt053_P_CH2909000000250094239_1110092698_0_202011250300000644000175000017500000001352414676232027027750 0ustar grothoffgrothoff 20201124375204229003967 2020-11-25T02:02:16 1 true SPS/2.0/PROD 20201124375204229003973 118 2020-11-25T02:02:16 2020-06-24T00:00:00 2020-06-24T23:59:59 CH2909000000250094239 CHF Robert Schneider SA Grands magasins Biel/Bienne OPBD 211993.19 CRDT
    2020-11-24
    CLBD 215112.21 CRDT
    2020-11-24
    CLAV 215112.21 CRDT
    2020-11-24
    FWAV 216649.21 CRDT
    2020-11-25
    41100000000872849 4.50 CRDT false BOOK
    2020-11-24
    2020-11-24
    0758103031480900 PMNT IDDT PMDD 0758103031480900 4.50 CRDT GUTSCHRIFT CH-DD-BASISLASTSCHRIFT ID-NR. DES ZAHLUNGSEMPFÄNGERS: 41100000000872849 REFERENZ-NR: PmtInfId-CHDD-1
    77.70 DBIT false BOOK
    2020-11-24
    2020-11-24
    0758103031480977 PMNT ICDT AUTT 0758103031480977 77.70 CRDT GUTSCHRIFT CH-DD-BASISLASTSCHRIFT ID-NR. DES ZAHLUNGSEMPFÄNGERS: 41100000000872849 REFERENZ-NR: PmtInfId-CHDD-1
    1500.00 CRDT false BOOK
    2020-11-24
    2020-11-24
    07582000303F0C7U PMNT RCDT AUTT 07582000303F0C7U 1500.00 CRDT SAMMELGUTSCHRIFT FÜR KONTO: CH2909000000250094239 VERARBEITUNG VOM 23.11.2020 PAKET ID: 9999999999999999
    CH2909000000250094239 1537.00 CRDT false BOOK
    2020-11-24
    2020-11-25
    07582000303KBMSU PMNT RCDT VCOM 07582000303KBMSU 1537.00 CRDT SAMMELGUTSCHRIFT FÜR KONTO: CH2909000000250094239 VERARBEITUNG VOM 24.11.2020 PAKET ID: 9999999999999998
    CH7730000001250094239 1692.22 CRDT false BOOK
    2020-11-24
    2020-11-24
    07582000303KBMSU PMNT RCDT VCOM 07582000303KBMSU 1692.22 CRDT SAMMELGUTSCHRIFT FÜR KONTO: CH7730000001250094239 VERARBEITUNG VOM 24.11.2020 PAKET ID: 201124CH000009TB
    ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111119_0_2022030911011199_v2009.xmllibeufin-1.6.8/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111119_0_202203091100000644000175000017500000000646014676232027027733 0ustar grothoffgrothoff 20200618375204295372463 2022-03-08T23:31:31 1 true SPS/1.7/PROD 20200618375204295372465 2022-03-08T23:31:31 2022-03-08T00:00:00 2022-03-08T23:59:59 OTHR CH2909000000250094239 Robert Schneider SA Grands magasins Biel/Bienne CH2909000000250094239 501.05 CRDT false BOOK
    2022-03-08
    2022-03-08
    1000000000000000 PMNT RCDT AUTT 1 2000000000000000 1006265-25bbb3b1a NOTPROVIDED 00 00000000000000000000020 501.05 CRDT PMNT RCDT AUTT Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne CH5109000000250092291 CH2909000000250094239 POFICHBEXXX POSTFINANCE AG MINGERSTRASSE , 20 3030 BERN Muster Musterfile ?REJECT?0 ?ERROR?000 2022-03-08T20:00:00 SAMMELGUTSCHRIFT FÜR KONTO: CH2909000000250094239 VERARBEITUNG VOM 08.03.2022 PAKET ID: 200000000000XXX
    ././@LongLink0000644000000000000000000000017200000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/camt054-CHDD_P_CH2909000000250094239_1110097484_0_20220615375204228751067.xmllibeufin-1.6.8/testbench/sample/postfinance/camt054-CHDD_P_CH2909000000250094239_1110097484_0_2022060000644000175000017500000000720714676232027030064 0ustar grothoffgrothoff 20220615375204228751067 2022-06-15T23:20:22 1 true SPS/1.7/PROD 20220615375204228751070 2022-06-15T23:20:22 2022-06-14T00:00:00 2022-06-15T23:59:59 OTHR CH2909000000250094239 41100000000872849 4.50 CRDT false BOOK
    2022-06-15
    2022-06-15
    0758103031480900 PMNT IDDT PMDD 2 MsgId-CHDD-Musterfile 201-31295208-1 PmtInfId-CHDD-1 InstrId-CHDD-1 E2EId-CHDD-1 1.50 CRDT PMNT IDDT PMDD Maria Bernasconi Place de la Gare 12 2502 Biel CH CH5109000000250092291 Rechnung 1001 2022-06-15T20:00:00 MsgId-CHDD-Musterfile 201-31295208-2 PmtInfId-CHDD-1 InstrId-CHDD-2 E2EId-CHDD-2 3.00 CRDT PMNT IDDT PMDD Maria Bernasconi Place de la Gare 12 2502 Biel CH CH5109000000250092291 Rechnung 1002 2022-06-15T20:00:00 GUTSCHRIFT CH-DD-BASISLASTSCHRIFT ID-NR. DES ZAHLUNGSEMPFÄNGERS: 41100000000872849 REFERENZ-NR: PmtInfId-CHDD-1
    ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111112_0_2022031011011199_v2019.xmllibeufin-1.6.8/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111112_0_202203101100000644000175000017500000000664614676232027027722 0ustar grothoffgrothoff 20200618375204295372463 2022-03-10T23:40:14 1 true SPS/2.0/PROD 20200618375204295372465 2022-03-10T23:40:14 2022-03-10T00:00:00 2022-03-10T23:59:59 CH2909000000250094239 CHF Robert Schneider SA Grands magasins Biel/Bienne CH2909000000250094239 522.10 CRDT false BOOK
    2022-03-10
    2022-03-10
    1000000000000000 PMNT RCDT ATXN 1 2000000000000000 1006265-25bbb3b1a NOTPROVIDED b009c997-97b3-4a9c-803c-d645a7276bf0 00 00000000000000000000020 522.10 CRDT PMNT RCDT ATXN Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne CH5109000000250092291 CH2909000000250094239 POFICHBEXXX POSTFINANCE AG MINGERSTRASSE 20 3030 BERNE ?REJECT?0 ?ERROR?000 2022-03-10T20:00:00 GUTSCHRIFT AUFTRAGGEBER: Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne REFERENZEN: NOTPROVIDED 1006265-25bbb3b1a 2000000000000000
    ././@LongLink0000644000000000000000000000020300000000000011576 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092704_0_2019042500372179_v2009.xmllibeufin-1.6.8/testbench/sample/postfinance/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092700000644000175000017500000000617614676232027030132 0ustar grothoffgrothoff 20190424375204228750928 2019-04-25T00:20:05 1 true SPS/1.6/PROD 20190424375204228750931 2019-04-25T00:20:05 2019-04-24T00:00:00 2019-04-24T23:59:59 OTHR CH2909000000250094239 Robert Schneider SA 020010001 147.00 DBIT false BOOK
    2019-04-24
    2019-04-25
    100820002V496ZRA PMNT CNTR CWDL 4.40 4.40 DBIT false 6 1 180410CH02UZ2PC1 06 20190423848301000100105 147.00 DBIT PMNT CNTR CWDL 4.40 4.40 DBIT false 6 Maria Bernasconi CH5109000000250092291 100041698214115449371805278 ?REJECT?0 2019-04-23T20:00:00 SAMMELLASTSCHRIFT ASR VERARBEITUNG VOM 24.04.2019 KUNDENNUMMER 02-1000-1 PAKET ID: 180410CH00000AL0
    ././@LongLink0000644000000000000000000000017200000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/pain002_CHDD_P_CH2909000000250094239_1110097483_0_20220614375204216308259.xmllibeufin-1.6.8/testbench/sample/postfinance/pain002_CHDD_P_CH2909000000250094239_1110097483_0_2022060000644000175000017500000000153314676232027030135 0ustar grothoffgrothoff 20220614375204216308259 2022-06-14T17:22:51 POFICHBE MsgId-CHDD-Musterfile pain.008.001.02.ch.03 PmtInfId-CHDD-1 ACCP ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111112_0_2022031011011199_v2009.xmllibeufin-1.6.8/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111112_0_202203101100000644000175000017500000000642014676232027027710 0ustar grothoffgrothoff 20200618375204295372463 2022-03-10T23:40:14 1 true SPS/1.7/PROD 20200618375204295372465 2022-03-10T23:40:14 2022-03-10T00:00:00 2022-03-10T23:59:59 OTHR CH2909000000250094239 Robert Schneider SA Grands magasins Biel/Bienne CH2909000000250094239 522.10 CRDT false BOOK
    2022-03-10
    2022-03-10
    1000000000000000 PMNT RCDT ATXN 1 2000000000000000 1006265-25bbb3b1a NOTPROVIDED 00 00000000000000000000020 522.10 CRDT PMNT RCDT ATXN Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne CH5109000000250092291 CH2909000000250094239 POFICHBEXXX POSTFINANCE AG MINGERSTRASSE 20 3030 BERNE ?REJECT?0 ?ERROR?000 2022-03-10T20:00:00 GUTSCHRIFT AUFTRAGGEBER: Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne REFERENZEN: NOTPROVIDED 1006265-25bbb3b1a 2000000000000000
    ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111119_0_2022030911011199_v2019.xmllibeufin-1.6.8/testbench/sample/postfinance/camt054_P_CH2909000000250094239_1111111119_0_202203091100000644000175000017500000000670514676232027027735 0ustar grothoffgrothoff 20200618375204295372463 2022-03-08T23:31:31 1 true SPS/2.0/PROD 20200618375204295372465 2022-03-08T23:31:31 2022-03-08T00:00:00 2022-03-08T23:59:59 CH2909000000250094239 CHF Robert Schneider SA Grands magasins Biel/Bienne CH2909000000250094239 501.05 CRDT false BOOK
    2022-03-08
    2022-03-08
    1000000000000000 PMNT RCDT AUTT 1 2000000000000000 1006265-25bbb3b1a NOTPROVIDED b009c997-97b3-4a9c-803c-d645a7276b0 00 00000000000000000000020 501.05 CRDT PMNT RCDT AUTT Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne CH5109000000250092291 CH2909000000250094239 POFICHBEXXX POSTFINANCE AG MINGERSTRASSE , 20 3030 BERN Muster Musterfile ?REJECT?0 ?ERROR?000 2022-03-08T20:00:00 SAMMELGUTSCHRIFT FÜR KONTO: CH2909000000250094239 VERARBEITUNG VOM 08.03.2022 PAKET ID: 200000000000XXX
    ././@LongLink0000644000000000000000000000017300000000000011604 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/200519_camt052_P_CH2909000000250094239_1110092686_0_2019042416072347_v2019.xmllibeufin-1.6.8/testbench/sample/postfinance/200519_camt052_P_CH2909000000250094239_1110092686_0_20190000644000175000017500000000705514676232027030042 0ustar grothoffgrothoff 20190424375204223062173 2019-04-24T16:07:09 1 true SPS/2.0/PROD 20190424375204223062174 78 2019-04-24T16:07:09 2019-04-24T00:00:00 2019-04-24T16:00:00 CH2909000000250094239 CHF Robert Schneider SA Grands magasins Biel/Bienne OPBD 208509.19 CRDT
    2019-04-24
    ITBD 207596.19 CRDT
    2019-04-24
    XPCD 207596.19 CRDT
    2019-04-24
    103.00 DBIT false BOOK
    2019-04-24
    2019-04-24
    074820002ZU1EPZK PMNT ICDT AUTT 20190423-000369773 25-1120172999-1 30003101 20190423001255000100005 b009c997-97b3-4a9c-803c-d645a7276bf2 103.00 DBIT GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101
    913.00 DBIT false BOOK
    2019-04-24
    2019-04-24
    074820002ZU1EQ0K PMNT ICDT AUTT 20190423-000369773 25-1120172999-2 30003101 20190423001255000100006 b009c997-97b3-4a9c-803c-d645a7276bf1 913.00 DBIT GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101
    ././@LongLink0000644000000000000000000000017400000000000011605 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/200519_camt054-Credit_P_CH2909000000250094239_1110092691_0_2019042421291293.xmllibeufin-1.6.8/testbench/sample/postfinance/200519_camt054-Credit_P_CH2909000000250094239_11100926910000644000175000017500000000337314676232027030355 0ustar grothoffgrothoff 201904245375204223076552 2019-04-24T21:28:58 1 true SPS/1.6/PROD 20190424375204223076553 2019-04-24T21:28:58 2019-04-24T21:28:58 2019-04-24T21:28:58 CDTN CH2909000000250094239 Robert Schneider SA Grands magasins Biel/Bienne 1500.00 CRDT false BOOK
    2019-04-24
    2019-04-25
    074820002ZZ9J42U PMNT RCDT VCOM 074820002ZZ9J42U 1500.00 CRDT SAMMELGUTSCHRIFT ESR VERARBEITUNG VOM 24.04.2019 KUNDENNUMMER 01-429580-3 PAKET ID: 180315CH00000HPA
    ././@LongLink0000644000000000000000000000016500000000000011605 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/200519_camt052_P_CH2909000000250094239_1110092686_0_2019042416072347.xmllibeufin-1.6.8/testbench/sample/postfinance/200519_camt052_P_CH2909000000250094239_1110092686_0_20190000644000175000017500000000655114676232027030042 0ustar grothoffgrothoff 20190424375204223062173 2019-04-24T16:07:09 1 true SPS/1.6/PROD 20190424375204223062174 78 2019-04-24T16:07:09 2019-04-24T00:00:00 2019-04-24T16:00:00 CH2909000000250094239 Robert Schneider SA Grands magasins Biel/Bienne OPBD 208509.19 CRDT
    2019-04-24
    ITBD 207596.19 CRDT
    2019-04-24
    XPCD 207596.19 CRDT
    2019-04-24
    103.00 DBIT false BOOK
    2019-04-24
    2019-04-24
    074820002ZU1EPZK PMNT ICDT AUTT 20190423-000369773 25-1120172999-1 30003101 20190423001255000100005 103.00 DBIT GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101
    913.00 DBIT false BOOK
    2019-04-24
    2019-04-24
    074820002ZU1EQ0K PMNT ICDT AUTT 20190423-000369773 25-1120172999-2 30003101 20190423001255000100006 913.00 DBIT GIRO POST CH5109000000250092291 Bernasconi Maria Place de la Gare 12 2502 Biel/Bienne SENDER REFERENZ: 30003101
    ././@LongLink0000644000000000000000000000020100000000000011574 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/200519_camt054-chdd_p_ch2909000000250094239_1110097484_0_20190520700381159_v2019.xmllibeufin-1.6.8/testbench/sample/postfinance/200519_camt054-chdd_p_ch2909000000250094239_1110097484_00000644000175000017500000001046114676232027030425 0ustar grothoffgrothoff 20190520375204228751067 2019-05-19T00:20:22 1 true SPS/2.0/PROD 20190516375204228751070 2019-05-20T00:20:22 2019-05-19T00:00:00 2019-05-19T23:59:59 CH2909000000250094239 CHF Robert Schneider SA Grands magasins Biel/Bienne 41100000000872849 4.50 CRDT false BOOK
    2019-05-19
    2019-05-19
    0758103031480900 PMNT IDDT PMDD 2 MsgId-CHDD-Musterfile 201-31295208-1 PmtInfId-CHDD-1 InstrId-CHDD-1 E2EId-CHDD-1 b009c997-97b3-4a9c-803c-d645a7276bf5 1.50 CRDT PMNT IDDT PMDD Maria Bernasconi Place de la Gare 12 2502 Biel CH CH5109000000250092291 41100000000872849 Rechnung 1001 2019-05-19T20:00:00 MsgId-CHDD-Musterfile 201-31295208-2 PmtInfId-CHDD-1 InstrId-CHDD-2 E2EId-CHDD-2 b009c997-97b3-4a9c-803c-d645a7276bf5 3.00 CRDT PMNT IDDT PMDD Maria Bernasconi Place de la Gare 12 2502 Biel CH CH5109000000250092291 41100000000872849 Rechnung 1002 2019-05-19T20:00:00 GUTSCHRIFT CH-DD-BASISLASTSCHRIFT ID-NR. DES ZAHLUNGSEMPFÄNGERS: 41100000000872849 REFERENZ-NR: PmtInfId-CHDD-1
    ././@LongLink0000644000000000000000000000016400000000000011604 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/camt053_P_CH2909000000250094239_1110092698_0_2020062503071366_v2009.xmllibeufin-1.6.8/testbench/sample/postfinance/camt053_P_CH2909000000250094239_1110092698_0_202006250300000644000175000017500000001331714676232027027754 0ustar grothoffgrothoff 20201124375204229003967 2020-11-25T02:02:16 1 true SPS/1.7/PROD 20201124375204229003973 118 2020-11-25T02:02:16 2020-06-24T00:00:00 2020-06-24T23:59:59 CH2909000000250094239 Robert Schneider SA Grands magasins Biel/Bienne OPBD 211993.19 CRDT
    2020-11-24
    CLBD 215112.21 CRDT
    2020-11-24
    CLAV 215112.21 CRDT
    2020-11-24
    FWAV 216649.21 CRDT
    2020-11-25
    41100000000872849 4.50 CRDT false BOOK
    2020-11-24
    2020-11-24
    0758103031480900 PMNT IDDT PMDD 0758103031480900 4.50 CRDT GUTSCHRIFT CH-DD-BASISLASTSCHRIFT ID-NR. DES ZAHLUNGSEMPFÄNGERS: 41100000000872849 REFERENZ-NR: PmtInfId-CHDD-1
    77.70 DBIT false BOOK
    2020-11-24
    2020-11-24
    0758103031480977 PMNT ICDT AUTT 0758103031480977 77.70 CRDT GUTSCHRIFT CH-DD-BASISLASTSCHRIFT ID-NR. DES ZAHLUNGSEMPFÄNGERS: 41100000000872849 REFERENZ-NR: PmtInfId-CHDD-1
    CH2909000000250094239 1500.00 CRDT false BOOK
    2020-11-24
    2020-11-24
    07582000303F0C7U PMNT RCDT AUTT 07582000303F0C7U 1500.00 CRDT SAMMELGUTSCHRIFT FÜR KONTO: CH2909000000250094239 VERARBEITUNG VOM 23.11.2020 PAKET ID: 9999999999999999
    CH7730000001250094239 1537.00 CRDT false BOOK
    2020-11-24
    2020-11-25
    07582000303KBMSU PMNT RCDT VCOM 07582000303KBMSU 1537.00 CRDT SAMMELGUTSCHRIFT FÜR KONTO: CH7730000001250094239 VERARBEITUNG VOM 24.11.2020 PAKET ID: 201124CH000009TC
    CH7730000001250094239 1692.22 CRDT false BOOK
    2020-11-24
    2020-11-24
    07582000303KBMSU PMNT RCDT VCOM 07582000303KBMSU 1692.22 CRDT SAMMELGUTSCHRIFT FÜR KONTO: CH7730000001250094239 VERARBEITUNG VOM 24.11.2020 PAKET ID: 201124CH000009TB
    ././@LongLink0000644000000000000000000000020300000000000011576 Lustar rootrootlibeufin-1.6.8/testbench/sample/postfinance/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092704_0_2019042500372179_v2019.xmllibeufin-1.6.8/testbench/sample/postfinance/200519_camt054-ESR-ASR_P_CH2909000000250094239_1110092700000644000175000017500000000620614676232027030124 0ustar grothoffgrothoff 20190424375204228750928 2019-04-25T00:20:05 1 true SPS/2.0/PROD 20190424375204228750931 2019-04-25T00:20:05 2019-04-24T00:00:00 2019-04-24T23:59:59 CH2909000000250094239 CHF Robert Schneider SA 020010001 147.00 DBIT false BOOK
    2019-04-24
    2019-04-25
    100820002V496ZRA PMNT CNTR CWDL 4.40 4.40 DBIT false 6 1 180410CH02UZ2PC1 06 20190423848301000100105 147.00 DBIT PMNT CNTR CWDL 4.40 4.40 DBIT false 6 Maria Bernasconi CH5109000000250092291 100041698214115449371805278 ?REJECT?0 2019-04-23T20:00:00 SAMMELLASTSCHRIFT ASR VERARBEITUNG VOM 24.04.2019 KUNDENNUMMER 02-1000-1 PAKET ID: 180410CH00000AL0
    libeufin-1.6.8/testbench/sample/2_pain002 B-Level ACCP_v2009.xml0000644000175000017500000000237014674637415023676 0ustar grothoffgrothoff 201803263752040116782752018-03-26T12:09:48POFICHBEMsgId-006pain.001.001.03.ch.02PmtInfId-006-01RJCTPOFICHBENARR1297193;Sammelauftrag ohne ausführbaren EinzelauftragInstrId-006-01-01EndToEndId-006-01-01RJCTAC011301813;Konto ungültig2018-03-272018-03-27 libeufin-1.6.8/testbench/sample/5_pain002 A-Level ACTC (Empfangsbestaetigung FDS)_v2009.xml0000644000175000017500000000157614674637415030554 0ustar grothoffgrothoff 20180315375204222821684 2018-03-15T10:49:10 POFICHBE MsgId-001 pain.001.001.03.ch.02 ACTC libeufin-1.6.8/testbench/sample/cs/0000775000175000017500000000000015236145704017417 5ustar grothoffgrothoff././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.054_SIC_04_088583185407_NN_0885831854071000_20221022_170251_005.xmllibeufin-1.6.8/testbench/sample/cs/camt.054_SIC_04_088583185407_NN_0885831854071000_20221022_170251_0000644000175000017500000002657614676232027027322 0ustar grothoffgrothoff CAMT054_20221022_180251119_4Z2WCTQ4 2022-10-22T17:02:51.119Z 1 true 4BA01709118000075 2022-10-22T17:02:51.119Z 2022-10-22T00:00:00.000+01:00 2022-10-22T23:59:59.999+01:00 C53F CH7705881831854071000 010026540 7761.35 CRDT BOOK
    2022-10-22
    2022-10-22
    4BA01709118000075/1 PMNT IDDT PMDD 5 7761.35 2561.35 CRDT 2561.35 PMNT IDDT PMDD Example SA Place du Marché 1 2222 Village ISR Reference 999999123456789012345678028 1400.00 CRDT 1400.00 PMNT IDDT PMDD Bäckerei-Konditorei Meier Landstrasse 1 5555 Unterdorf CH ISR Reference 999999123456789012345678033 1200.00 CRDT 1200.00 PMNT IDDT PMDD NOTPROVIDED ISR Reference 999999123456789012345678049 1100.00 CRDT 1100.00 PMNT IDDT PMDD NOTPROVIDED ISR Reference 999999123456789012345678057 1500.00 CRDT 1500.00 PMNT IDDT PMDD NOTPROVIDED ISR Reference 999999123456789012345678065
    010026540 119.45 CRDT BOOK
    2022-10-22
    2022-10-21
    4BA02002068000015/1 PMNT IDDT PMDD 1 119.45 119.45 CRDT 119.45 PMNT IDDT PMDD Peter Muster Musterstrasse 5 8001 Zuerich CH ISR Reference 901709123456789012345000003
    ././@LongLink0000644000000000000000000000015700000000000011606 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.053_SPS_08_088583185407_DC_0885831854071000_20221223_010729778_000.xmllibeufin-1.6.8/testbench/sample/cs/camt.053_SPS_08_088583185407_DC_0885831854071000_20221223_01072970000644000175000017500000004417714676232027027262 0ustar grothoffgrothoff CAMT053_20221223_010729756_VJC7LIIF 2022-12-23T01:07:29.756Z 1 true SPS/2.0/PROD cbe792bcaaf74a87b6c5c0c77df10872 58 2022-12-23T01:07:29.778Z 2022-12-22T00:00:00+01:00 2022-12-22T23:59:00+01:00 0885831854071000 CHF Barbara Muster Zürich CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 7751.38 CRDT
    2022-12-22
    FWAV 25273.34 CRDT
    2022-12-23
    CLAV 19273.34 CRDT
    2022-12-22
    CLBD 25273.34 CRDT
    2022-12-22
    17 18258.18 17521.96 CRDT 9 17890.07 8 368.11 2.36 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-43783/1 PMNT ICDT AUTT 2 2 2.36 EUR CHF 1.18 2022-12-22T00:00:00.000+01:00 MSG0150D4D8E71C447EBF774FB84E1F7946 BLVL-1-18032208215187 1 2
    4.78 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQN-180322-CS-58740/1 PMNT ICDT AUTT 5 5 4.78 USD CHF 0.95611387 2022-12-22T00:00:00.000+01:00 5 5 DBIT false INTERNAL MSG40BF23DB52794241A8DBE60391E04976 BLVL-1-18032208093429 1 5 ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    9.57 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-43962/1 PMNT ICDT AUTT 10 10 9.57 USD CHF 0.95711254 2022-12-22T00:00:00.000+01:00 23 5 DBIT false INTERNAL 18 DBIT false EXTERNAL MSGEADAC6D735B14EEBA29FB52A459DD44F BLVL-1-18032208261993 1 10 ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    10.1 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQN-180322-CS-58062/1 PMNT ICDT AUTT 10.1 10.1 MSG0D6E675AB5794B5BA889A0CCEAAD1D16 BLVL-1-18032207545645 1 10.1
    10.2 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-40797/1 PMNT ICDT AUTT 10.2 10.2 MSG71784A43AF5747B6A60C17CFD29B1712 BLVL-1-18032207590104 1 10.2
    100 DBIT BOOK
    2022-12-22
    2022-12-22
    DNWL-180322-CS-87851/1 PMNT ICDT BOOK 100 100 57af4bcfda8d4f8fb958c5424d73c12e DNWL-221222-CS-87851 DNCS-20221222-IXN0 DNCS-20221222-IXN0-TXN0 SP-57273905-0 100 DBIT Barbara Muster, Zürich Barbara Muster, Zürich CH3704835833740031000 CHBCC 04835 Credit Suisse (Schweiz) AG Paradeplatz 8 8070 Zürich CH
    120 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-40193/1 PMNT ICDT AUTT 120 120 MSG270C529F8169437186D63B1339FC09F9 BLVL-1-18032207463420 1 120
    111.1 DBIT BOOK
    2022-12-22
    2022-12-22
    DNRD-180323-CS-75599/1 PMNT ICDT AUTT 111.1 111.1 MSG4583D8DC482546E1B19F092AC83A2665 BLVL-1-19030708451663 2 111.1
    2.8 CRDT false BOOK
    2022-12-22
    2022-12-22
    08351803222247667/1 XTND NTAV NTAV 8037 8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.12.22
    3 CRDT BOOK
    2022-12-22
    2022-12-22
    80WL-180322-CS-55958/1 PMNT RCDT DMCT 3 13TF-180322-MS-85571 80WL-180322-CS-55958 13TF-180322-MS-85571 NOTPROVIDED 3 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 23456
    3.47 CRDT BOOK
    2022-12-22
    2022-12-22
    80WR-180322-CS-15197/1 PMNT RCDT ESCT 3 3.47 EUR CHF 1.15632286 2022-12-22T00:00:00.000+01:00 13TL-180322-MS-32279 80WR-180322-CS-15197 13TL-180322-MS-32279 NOTPROVIDED 3 CRDT KOWALSKI JAN PL SZCZYTNICKA 9 PL WROCLAW Invoice 45678
    6000 CRDT BOOK
    2022-12-22
    2022-12-23
    08922018031005244600/1 PMNT RCDT DMCT 6000 31XY-180322-MS-85571 91AB-180322-CS-55958 31XY-180322-MS-85571 NOTPROVIDED 6000 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 67890
    3000 CRDT true BOOK
    2022-12-22
    2022-12-22
    80WE-180321-CS-53986/1 PMNT RCDT RRTN 3000 13TJ-180321-MS-42880 80WE-180321-CS-53986 13TJ-180321-MS-42880 ETE68E82E7E701E4DB2B838318A8BA551CF 3000 CRDT Barbara Muster 8001 Zuerich PMNT ICDT DMCT UBSWCHZH80A NARR RETOUR SIC VAL 22.12.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH /SETT/2022-12-22T15:52:42
    2.75 CRDT false BOOK
    2022-12-22
    2022-12-22
    08351803222252626/1 XTND NTAV NTAV 8037 8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am 22.12.22
    010026540 7761.35 CRDT false BOOK
    2022-12-22
    2022-12-22
    4BA01709118000075/1 PMNT IDDT PMDD 4BA01709118000075 5 7761.35 CRDT ?21010026540 999999
    010026540 119.45 CRDT false BOOK
    2022-12-22
    2022-12-21
    4BA02002068000015/1 PMNT IDDT PMDD 4BA02002068000015 1 119.45 CRDT ?21010026540 901709
    CH4531000831854071000 997.25 CRDT false BOOK
    2022-12-22
    2022-12-22
    4BA01709118000076/1 PMNT RCDT VCOM 0.20 0.20 false 4BA01709118000076 2 997.25 CRDT 13RG-171123-MS-49260 80UL-171123-CS-35154 13RG-171123-MS-49260 123456789123456789ACE eb6305c9-1f7f-49de-aed0-16487c27b42d 0233458UP0198446 900.00 CRDT 900.00 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL 1.00000
    DEBT
    Max Muster Bundesplatz 1 3003 Bern Pia-Maria Rutschmann-Schnyder CH Grosse Marktgasse 28 9400 Rorschach QRR 000000000000000000000000034 FREE TEXT
    24RG-182123-MS-49280 81UL-172223-CS-35164 24RG-182123-MS-49280 23456789123456789ACE2 84eed956-57c0-4c39-b2d3-66d6dad93a68 1223457TO9086198 97.25 CRDT 97.25 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL 1.00000
    DEBT
    SARAH DUPONT LANDSTRASSE 334 CH 3280 MURTEN Roland Dupont CH Landstrasse 334 3280 Murten QRR 000000000000000000000000026 RANDOM TEXT
    ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.053_SPS_08_088583185407_ND_0885831854071000_20221223_010729778000.xmllibeufin-1.6.8/testbench/sample/cs/camt.053_SPS_08_088583185407_ND_0885831854071000_20221223_01072970000644000175000017500000003676414676232027027300 0ustar grothoffgrothoff CAMT053_20221223_010729756_VJC7LIIF 2022-12-23T01:07:29.756Z 1 true SPS/2.0/PROD cbe792bcaaf74a87b6c5c0c77df10872 58 2022-12-23T01:07:29.778Z 2022-12-22T00:00:00+01:00 2022-12-22T23:59:00+01:00 0885831854071000 CHF Barbara Muster Zürich CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 7751.38 CRDT
    2022-12-22
    FWAV 25273.34 CRDT
    2022-12-23
    CLAV 19273.34 CRDT
    2022-12-22
    CLBD 25273.34 CRDT
    2022-12-22
    17 18258.18 17521.96 CRDT 9 17890.07 8 368.11 2.36 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-43783/1 PMNT ICDT AUTT 2 2 2.36 EUR CHF 1.18 2022-12-22T00:00:00.000+01:00 MSG0150D4D8E71C447EBF774FB84E1F7946 BLVL-1-18032208215187 1 2
    4.78 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQN-180322-CS-58740/1 PMNT ICDT AUTT 5 5 4.78 USD CHF 0.95611387 2022-12-22T00:00:00.000+01:00 5 5 DBIT false INTERNAL MSG40BF23DB52794241A8DBE60391E04976 BLVL-1-18032208093429 1 5 ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    9.57 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-43962/1 PMNT ICDT AUTT 10 10 9.57 USD CHF 0.95711254 2022-12-22T00:00:00.000+01:00 23 5 DBIT false INTERNAL 18 DBIT false EXTERNAL MSGEADAC6D735B14EEBA29FB52A459DD44F BLVL-1-18032208261993 1 10 ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    10.1 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQN-180322-CS-58062/1 PMNT ICDT AUTT 10.1 10.1 MSG0D6E675AB5794B5BA889A0CCEAAD1D16 BLVL-1-18032207545645 1 10.1
    10.2 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-40797/1 PMNT ICDT AUTT 10.2 10.2 MSG71784A43AF5747B6A60C17CFD29B1712 BLVL-1-18032207590104 1 10.2
    100 DBIT BOOK
    2022-12-22
    2022-12-22
    DNWL-180322-CS-87851/1 PMNT ICDT BOOK 100 100 57af4bcfda8d4f8fb958c5424d73c12e DNWL-221222-CS-87851 DNCS-20221222-IXN0 DNCS-20221222-IXN0-TXN0 SP-57273905-0 100 DBIT Barbara Muster, Zürich Barbara Muster, Zürich CH3704835833740031000 CHBCC 04835 Credit Suisse (Schweiz) AG Paradeplatz 8 8070 Zürich CH
    120 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-40193/1 PMNT ICDT AUTT 120 120 MSG270C529F8169437186D63B1339FC09F9 BLVL-1-18032207463420 1 120
    111.1 DBIT BOOK
    2022-12-22
    2022-12-22
    DNRD-180323-CS-75599/1 PMNT ICDT AUTT 111.1 111.1 MSG4583D8DC482546E1B19F092AC83A2665 BLVL-1-19030708451663 2 111.1
    2.8 CRDT false BOOK
    2022-12-22
    2022-12-22
    08351803222247667/1 XTND NTAV NTAV 8037 8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.12.22
    3 CRDT BOOK
    2022-12-22
    2022-12-22
    80WL-180322-CS-55958/1 PMNT RCDT DMCT 3 13TF-180322-MS-85571 80WL-180322-CS-55958 13TF-180322-MS-85571 NOTPROVIDED 3 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 23456
    3.47 CRDT BOOK
    2022-12-22
    2022-12-22
    80WR-180322-CS-15197/1 PMNT RCDT ESCT 3 3.47 EUR CHF 1.15632286 2022-12-22T00:00:00.000+01:00 13TL-180322-MS-32279 80WR-180322-CS-15197 13TL-180322-MS-32279 NOTPROVIDED 3 CRDT KOWALSKI JAN PL SZCZYTNICKA 9 PL WROCLAW Invoice 45678
    6000 CRDT BOOK
    2022-12-22
    2022-12-23
    08922018031005244600/1 PMNT RCDT DMCT 6000 31XY-180322-MS-85571 91AB-180322-CS-55958 31XY-180322-MS-85571 NOTPROVIDED 6000 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 67890
    3000 CRDT true BOOK
    2022-12-22
    2022-12-22
    80WE-180321-CS-53986/1 PMNT RCDT RRTN 3000 13TJ-180321-MS-42880 80WE-180321-CS-53986 13TJ-180321-MS-42880 ETE68E82E7E701E4DB2B838318A8BA551CF 3000 CRDT Barbara Muster 8001 Zuerich PMNT ICDT DMCT UBSWCHZH80A NARR RETOUR SIC VAL 22.12.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH /SETT/2022-12-22T15:52:42
    2.75 CRDT false BOOK
    2022-12-22
    2022-12-22
    08351803222252626/1 XTND NTAV NTAV 8037 8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am 22.12.22
    010026540 7761.35 CRDT false BOOK
    2022-12-22
    2022-12-22
    4BA01709118000075/1 PMNT IDDT PMDD 4BA01709118000075 5 7761.35 CRDT ?21010026540 999999
    010026540 119.45 CRDT false BOOK
    2022-12-22
    2022-12-21
    4BA02002068000015/1 PMNT IDDT PMDD 4BA02002068000015 1 119.45 CRDT ?21010026540 901709
    CH4531000831854071000 997.25 CRDT false BOOK
    2022-12-22
    2022-12-22
    4BA01709118000076/1 PMNT RCDT VCOM 4BA01709118000076 5 997.25 CRDT
    ././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/QRIBAN_camt.054_SPS_08_088583185407_NN_0885831854071000_20221222_180251_006.xmllibeufin-1.6.8/testbench/sample/cs/QRIBAN_camt.054_SPS_08_088583185407_NN_0885831854071000_20221222_0000644000175000017500000003654414676232027027570 0ustar grothoffgrothoff CAMT054_20221222_180251119_4Z2WCTQ4 2022-12-22T17:02:51.119Z 1 true SPS/2.0/PROD 4BA01709118000076 2022-03-22T17:02:51.119Z 2022-12-22T00:00:00.000+01:00 2022-12-22T23:59:59.999+01:00 CH5104835831854071000 CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID CH4531000831854071000 997.25 CRDT BOOK
    2022-12-22
    2010-12-22
    4BA01709118000076/1 PMNT RCDT VCOM 997.25 2.85 2.85 false 4BA01709118000076 5 997.25 13RF-190418-MS-65113 80XI-190418-CS-80256 13RF-190418-MS-65113 EndToEndId-0000000010 eb6305c9-1f7f-49de-aed0-16487c27b42d 477.25 CRDT 477.25 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL Example SA Example SA CH Place du Marché 1 2222 Village Example SA CH Place du Marché 1 2222 Village QRR 999999123456789012345678028 Déduction faite de 3% d'escompte 13RF-190418-MS-65114 80XI-190418-CS-80257 13RF-190418-MS-65114 EndToEndId-0000000011 eb6305c9-1f7f-49de-aed0-16487c27b42b 140 CRDT 140 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL Hans Meier Hans Meier Landstrasse 1 5555 Unterdorf CH Bäckerei-Konditorei Meier Landstrasse 1 5555 Unterdorf CH QRR 999999123456789012345678033 Auftrag vom 15.02.2022 13RF-190418-MS-65115 80XI-190418-CS-80258 13RF-190418-MS-65115 EndToEndId-0000000012 120 CRDT 120 PMNT RCDT VCOM 2.45 2.35 DBIT false 2 0.10 DBIT false INTERNAL SCHALTEREINZAHLUNG CH PETER MEIER SEMPACHERSTRASSE 1 6789 MITTELDORF CH QRR 999999123456789012345678049 000000/00000/000000/17.12.2022 13RF-190418-MS-65116 80XI-190418-CS-80259 13RF-190418-MS-65116 EndToEndId-0000000013 110 CRDT 110 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL RUTH MEIER OBERDORFSTRASSE 1 CH 5678 UNTERDORF QRR 999999123456789012345678057 13RF-190418-MS-65117 80XI-190418-CS-80260 13RF-190418-MS-65117 EndToEndId-0000000014 150 CRDT 150 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL Anna Meier CH Nachbardorfstrasse 1 9999 Obertal Anna Meier Nachbardorfstrasse 1 9999 Obertal CH QRR 999999123456789012345678065 Order 1234567
    ././@LongLink0000644000000000000000000000016300000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/QRIBAN_camt.054_SIC_04_088583185407_NN_0885831854071000_20221222_180251_006.xmllibeufin-1.6.8/testbench/sample/cs/QRIBAN_camt.054_SIC_04_088583185407_NN_0885831854071000_20221222_0000644000175000017500000003533114676232027027526 0ustar grothoffgrothoff CAMT054_20221222_180251119_4Z2WCTQ4 2022-12-22T17:02:51.119Z 1 true SPS/1.7/PROD 4BA01709118000076 2022-12-22T17:02:51.119Z 2022-12-22T00:00:00.000+01:00 2022-12-22T23:59:59.999+01:00 C53F CH5104835831854071000 CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID CH4531000831854071000 997.25 CRDT BOOK
    2022-12-22
    2010-12-22
    4BA01709118000076/1 PMNT RCDT VCOM 997.25 2.85 2.85 false 4BA01709118000076 5 997.25 13RF-190418-MS-65113 80XI-190418-CS-80256 13RF-190418-MS-65113 EndToEndId-0000000010 477.25 CRDT 477.25 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL Example SA CH Place du Marché 1 2222 Village Example SA CH Place du Marché 1 2222 Village QRR 999999123456789012345678028 Déduction faite de 3% d'escompte 13RF-190418-MS-65114 80XI-190418-CS-80257 13RF-190418-MS-65114 EndToEndId-0000000011 140 CRDT 140 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL Hans Meier Landstrasse 1 5555 Unterdorf CH Bäckerei-Konditorei Meier Landstrasse 1 5555 Unterdorf CH QRR 999999123456789012345678033 Auftrag vom 15.02.2022 13RF-190418-MS-65115 80XI-190418-CS-80258 13RF-190418-MS-65115 EndToEndId-0000000012 120 CRDT 120 PMNT RCDT VCOM 2.45 2.35 DBIT false 2 0.10 DBIT false INTERNAL SCHALTEREINZAHLUNG CH PETER MEIER SEMPACHERSTRASSE 1 6789 MITTELDORF CH QRR 999999123456789012345678049 000000/00000/000000/17.02.2022 13RF-190418-MS-65116 80XI-190418-CS-80259 13RF-190418-MS-65116 EndToEndId-0000000013 110 CRDT 110 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL RUTH MEIER OBERDORFSTRASSE 1 CH 5678 UNTERDORF QRR 999999123456789012345678057 13RF-190418-MS-65117 80XI-190418-CS-80260 13RF-190418-MS-65117 EndToEndId-0000000014 150 CRDT 150 PMNT RCDT VCOM 0.10 0.10 DBIT false INTERNAL Anna Meier CH Nachbardorfstrasse 1 9999 Obertal Anna Meier Nachbardorfstrasse 1 9999 Obertal CH QRR 999999123456789012345678065 Order 1234567
    ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.052_SIC_04_050483017844_WD_0504830178442001_20171127_230054_002.xmllibeufin-1.6.8/testbench/sample/cs/camt.052_SIC_04_050483017844_WD_0504830178442001_20171127_230054_0000644000175000017500000110641414676232027027266 0ustar grothoffgrothoff CAMT052_20171127_230054396_2XFDFW86 2017-11-27T23:00:54.396Z 1 true SPS/1.7/PROD 3edc45b55b044b0aa909e458b9c551d2 4 2017-11-27T23:00:54.402Z 0504830178442001 EUR Your Company Name Adress Line CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 582975.5 DBIT
    2017-11-27
    ITBD 808704.88 DBIT
    2017-11-27
    50 333005.56 225729.38 DBIT 22 53638.09 28 279367.47 903.61 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37494/1 PMNT ICDT XBCT 1042 1042 903.61 USD EUR 0.86719 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37494 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-01 EndToEndId-BP04-B-POS2-01-01 1042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    904.47 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37499/2 PMNT ICDT XBCT 1043 1043 904.47 USD EUR 0.86718 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37499 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-01 EndToEndId-BP04-B-POS2-02-01 1043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    1770.79 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37495/1 PMNT ICDT XBCT 2042 2042 1770.79 USD EUR 0.86718 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37495 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-02 EndToEndId-BP04-B-POS2-01-02 2042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    1771.66 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37500/1 PMNT ICDT XBCT 2043 2043 1771.66 USD EUR 0.86719 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37500 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-02 EndToEndId-BP04-B-POS2-02-02 2043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    2637.98 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37496/1 PMNT ICDT XBCT 3042 3042 2637.98 USD EUR 0.86719 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37496 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-03 EndToEndId-BP04-B-POS2-01-03 3042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    2638.85 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37501/1 PMNT ICDT XBCT 3043 3043 2638.85 USD EUR 0.86719 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37501 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-03 EndToEndId-BP04-B-POS2-02-03 3043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    3505.17 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37497/1 PMNT ICDT XBCT 4042 4042 3505.17 USD EUR 0.86719 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37497 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-04 EndToEndId-BP04-B-POS2-01-04 4042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    3506.03 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37502/1 PMNT ICDT XBCT 4043 4043 3506.03 USD EUR 0.86719 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37502 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-04 EndToEndId-BP04-B-POS2-02-04 4043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    4372.35 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37498/1 PMNT ICDT XBCT 5042 5042 4372.35 USD EUR 0.86719 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37498 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-05 EndToEndId-BP04-B-POS2-01-05 5042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    4373.22 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNVA-171127-CS-37503/1 PMNT ICDT XBCT 5043 5043 4373.22 USD EUR 0.86719 2017-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37503 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-05 EndToEndId-BP04-B-POS2-02-05 5043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    13155.32 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88144/1 PMNT ICDT OTHR 15200 15200 13155.32 USD EUR 0.86548158 2017-11-27T00:00:00.000+01:00 MsgId-BP04-A-POS2 PmtInfId-BP04-A-POS2-01 5 15200 MsgId-BP04-A-POS2 DNUC-191001-CS-03640 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-01 EndToEndId-BP04-A-POS2-01-01 1040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03651 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-02 EndToEndId-BP04-A-POS2-01-02 2040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03662 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-05 EndToEndId-BP04-A-POS2-01-05 5040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03673 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-04 EndToEndId-BP04-A-POS2-01-04 4040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03684 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-03 EndToEndId-BP04-A-POS2-01-03 3040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    13159.64 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88145/1 PMNT ICDT OTHR 15205 15205 13159.64 USD EUR 0.86548109 2017-11-27T00:00:00.000+01:00 MsgId-BP04-A-POS2 PmtInfId-BP04-A-POS2-02 5 15205 MsgId-BP04-A-POS2 DNUC-191001-CS-03695 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-03 EndToEndId-BP04-A-POS2-02-03 3041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03606 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-01 EndToEndId-BP04-A-POS2-02-01 1041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03717 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-02 EndToEndId-BP04-A-POS2-02-02 2041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03728 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-04 EndToEndId-BP04-A-POS2-02-04 4041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03739 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-05 EndToEndId-BP04-A-POS2-02-05 5041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    13241.86 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88152/1 PMNT ICDT OTHR 15300 15300 13241.86 USD EUR 0.86548105 2017-11-27T00:00:00.000+01:00 MsgId-BP06-POS2 PmtInfId-BP06-POS2-01 5 15300 MsgId-BP06-POS2 DNUC-191001-CS-03740 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-03 EndToEndId-BP06-POS2-01-03 3060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03751 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-02 EndToEndId-BP06-POS2-01-02 2060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03762 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-05 EndToEndId-BP06-POS2-01-05 5060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03773 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-01 EndToEndId-BP06-POS2-01-01 1060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03784 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-04 EndToEndId-BP06-POS2-01-04 4060 DBIT Max Muster BP06-POS2 CH Adress Line 4 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2
    13246.19 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88153/1 PMNT ICDT OTHR 15305 15305 13246.19 USD EUR 0.86548122 2017-11-27T00:00:00.000+01:00 MsgId-BP06-POS2 PmtInfId-BP06-POS2-02 5 15305 MsgId-BP06-POS2 DNUC-191001-CS-03795 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-01 EndToEndId-BP06-POS2-02-01 1061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03806 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-03 EndToEndId-BP06-POS2-02-03 3061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03817 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-04 EndToEndId-BP06-POS2-02-04 4061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03828 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-05 EndToEndId-BP06-POS2-02-05 5061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03839 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-02 EndToEndId-BP06-POS2-02-02 2061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2
    13273.3 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88136/1 PMNT ICDT OTHR 15000 15000 13273.3 CHF EUR 0.88488667 2017-11-27T00:00:00.000+01:00 MsgId-BP01-POS3 PmtInfId-BP01-POS3-01 5 15000 MsgId-BP01-POS3 DNUC-191001-CS-03840 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-01 EndToEndId-BP01-POS3-01-01 1000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 111111111111111111111111110 MsgId-BP01-POS3 DNUC-191001-CS-03851 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-02 EndToEndId-BP01-POS3-01-02 2000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 222222222222222222222222222 MsgId-BP01-POS3 DNUC-191001-CS-03862 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-03 EndToEndId-BP01-POS3-01-03 3000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 333333333333333333333333334 MsgId-BP01-POS3 DNUC-191001-CS-03873 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-04 EndToEndId-BP01-POS3-01-04 4000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 444444444444444444444444444 MsgId-BP01-POS3 DNUC-191001-CS-03884 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-05 EndToEndId-BP01-POS3-01-05 5000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 555555555555555555555555559
    13332.74 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88155/1 PMNT ICDT OTHR 15405 15405 13332.74 USD EUR 0.86548134 2017-11-27T00:00:00.000+01:00 MsgId-BP08-POS2 PmtInfId-BP08-POS2-02 5 15405 MsgId-BP08-POS2 DNUC-191001-CS-03895 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-01 EndToEndId-BP08-POS2-02-01 36501096 1081 DBIT Max Muster Creditor Name Street Name 1 12345 Town Name CH ChequeDeliverTo MsgId-BP08-POS2 DNUC-191001-CS-03906 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-02 EndToEndId-BP08-POS2-02-02 36501097 2081 DBIT Max Muster Creditor Name Street Name 2 12345 Town Name CH ChequeDeliverTo MsgId-BP08-POS2 DNUC-191001-CS-03917 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-03 EndToEndId-BP08-POS2-02-03 36501098 3081 DBIT Max Muster Creditor Name Street Name 3 12345 Town Name CH ChequeDeliverTo MsgId-BP08-POS2 DNUC-191001-CS-03928 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-04 EndToEndId-BP08-POS2-02-04 36501099 4081 DBIT Max Muster Creditor Name Street Name 4 12345 Town Name CH ChequeDeliverTo MsgId-BP08-POS2 DNUC-191001-CS-03939 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-05 EndToEndId-BP08-POS2-02-05 36501100 5081 DBIT Max Muster Creditor Name Street Name 5 12345 Town Name CH ChequeDeliverTo
    13361.79 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88138/1 PMNT ICDT OTHR 15100 15100 13361.79 CHF EUR 0.88488675 2017-11-27T00:00:00.000+01:00 MsgId-BP02-POS2 PmtInfId-BP02-POS2-01 5 15100 MsgId-BP02-POS2 DNUC-191001-CS-03940 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-03 EndToEndId-BP02-POS2-01-03 3020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-03951 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-04 EndToEndId-BP02-POS2-01-04 4020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-03962 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-05 EndToEndId-BP02-POS2-01-05 5020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-03973 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-01 EndToEndId-BP02-POS2-01-01 1020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-03984 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-02 EndToEndId-BP02-POS2-01-02 2020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2
    13406.04 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88140/1 PMNT ICDT OTHR 15150 15150 13406.04 CHF EUR 0.88488713 2017-11-27T00:00:00.000+01:00 MsgId-BP03-A-POS3 PmtInfId-BP03-A-POS3-01 5 15150 MsgId-BP03-A-POS3 DNUC-191001-CS-03995 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-01 EndToEndId-BP03-A-POS3-01-01 1030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04006 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-02 EndToEndId-BP03-A-POS3-01-02 2030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04017 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-03 EndToEndId-BP03-A-POS3-01-03 3030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04028 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-04 EndToEndId-BP03-A-POS3-01-04 4030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04039 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-05 EndToEndId-BP03-A-POS3-01-05 5030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    13414.89 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88142/1 PMNT ICDT OTHR 15160 15160 13414.89 CHF EUR 0.8848872 2017-11-27T00:00:00.000+01:00 MsgId-BP03-B-POS2 PmtInfId-BP03-B-POS2-01 5 15160
    13419.31 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88143/1 PMNT ICDT OTHR 15165 15165 13419.31 CHF EUR 0.88488691 2017-11-27T00:00:00.000+01:00 MsgId-BP03-B-POS2 PmtInfId-BP03-B-POS2-02 5 15165
    13627.26 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88154/1 PMNT ICDT OTHR 15400 15400 13627.26 CHF EUR 0.88488701 2017-11-27T00:00:00.000+01:00 MsgId-BP08-POS2 PmtInfId-BP08-POS2-01 5 15400 MsgId-BP08-POS2 DNUC-191001-CS-04040 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-04 EndToEndId-BP08-POS2-01-04 36501094 4080 DBIT Max Muster Creditor Name Street Name 4 12345 Town Name CH ChequeDeliverTo MsgId-BP08-POS2 DNUC-191001-CS-04051 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-03 EndToEndId-BP08-POS2-01-03 36501093 3080 DBIT Max Muster Creditor Name Street Name 3 12345 Town Name CH ChequeDeliverTo MsgId-BP08-POS2 DNUC-191001-CS-04062 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-05 EndToEndId-BP08-POS2-01-05 36501095 5080 DBIT Max Muster Creditor Name Street Name 5 12345 Town Name CH ChequeDeliverTo MsgId-BP08-POS2 DNUC-191001-CS-04073 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-01 EndToEndId-BP08-POS2-01-01 36501091 1080 DBIT Max Muster Creditor Name Street Name 1 12345 Town Name CH ChequeDeliverTo MsgId-BP08-POS2 DNUC-191001-CS-04084 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-02 EndToEndId-BP08-POS2-01-02 36501092 2080 DBIT Max Muster Creditor Name Street Name 2 12345 Town Name CH ChequeDeliverTo
    15055 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88137/1 PMNT ICDT OTHR 15055 15055 MsgId-BP01-POS3 PmtInfId-BP01-POS3-02 5 15055 MsgId-BP01-POS3 DNUC-191001-CS-04084 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-04 EndToEndId-BP01-POS3-02-04 4011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 444444444444444444444444444 MsgId-BP01-POS3 DNUC-191001-CS-04095 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-05 EndToEndId-BP01-POS3-02-05 5011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 555555555555555555555555559 MsgId-BP01-POS3 DNUC-191001-CS-04106 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-01 EndToEndId-BP01-POS3-02-01 1011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 111111111111111111111111110 MsgId-BP01-POS3 DNUC-191001-CS-04117 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-02 EndToEndId-BP01-POS3-02-02 2011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 222222222222222222222222222 MsgId-BP01-POS3 DNUC-191001-CS-04128 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-03 EndToEndId-BP01-POS3-02-03 3011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 333333333333333333333333334
    15105 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88139/1 PMNT ICDT OTHR 15105 15105 MsgId-BP02-POS2 PmtInfId-BP02-POS2-02 5 15105 MsgId-BP02-POS2 DNUC-191001-CS-04139 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-03 EndToEndId-BP02-POS2-02-03 3021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-04140 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-04 EndToEndId-BP02-POS2-02-04 4021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-04151 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-05 EndToEndId-BP02-POS2-02-05 5021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-04162 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-01 EndToEndId-BP02-POS2-02-01 1021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-04173 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-02 EndToEndId-BP02-POS2-02-02 2021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2
    15155 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88141/1 PMNT ICDT OTHR 15155 15155 MsgId-BP03-A-POS3 PmtInfId-BP03-A-POS3-02 5 15155 MsgId-BP03-A-POS3 DNUC-191001-CS-04184 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-04 EndToEndId-BP03-A-POS3-02-04 4031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04195 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-05 EndToEndId-BP03-A-POS3-02-05 5031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04206 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-02 EndToEndId-BP03-A-POS3-02-02 2031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04217 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-03 EndToEndId-BP03-A-POS3-02-03 3031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04228 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-01 EndToEndId-BP03-A-POS3-02-01 1031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    15250 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88148/1 PMNT ICDT OTHR 15250 15250 MsgId-BP05-A-POS2 PmtInfId-BP05-A-POS2-01 5 15250 MsgId-BP05-A-POS2 DNUC-191001-CS-04239 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-02 EndToEndId-BP05-A-POS2-01-02 2050 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04240 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-04 EndToEndId-BP05-A-POS2-01-04 4050 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04251 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-05 EndToEndId-BP05-A-POS2-01-05 5050 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04262 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-01 EndToEndId-BP05-A-POS2-01-01 1050 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04273 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-03 EndToEndId-BP05-A-POS2-01-03 3050 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2
    15255 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88149/1 PMNT ICDT OTHR 15255 15255 MsgId-BP05-A-POS2 PmtInfId-BP05-A-POS2-02 5 15255 MsgId-BP05-A-POS2 DNUC-191001-CS-04284 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-01 EndToEndId-BP05-A-POS2-02-01 1051 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04295 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-05 EndToEndId-BP05-A-POS2-02-05 5051 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04306 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-03 EndToEndId-BP05-A-POS2-02-03 3051 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04317 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-04 EndToEndId-BP05-A-POS2-02-04 4051 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04328 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-02 EndToEndId-BP05-A-POS2-02-02 2051 DBIT Max Muster BP05-A-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2
    15260 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88150/1 PMNT ICDT OTHR 15260 15260 MsgId-BP05-B-POS2 PmtInfId-BP05-B-POS2-01 5 15260 MsgId-BP05-B-POS2 DNUC-191001-CS-04339 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-03 EndToEndId-BP05-B-POS2-01-03 3052 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-04340 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-04 EndToEndId-BP05-B-POS2-01-04 4052 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-04351 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-05 EndToEndId-BP05-B-POS2-01-05 5052 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-04362 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-01 EndToEndId-BP05-B-POS2-01-01 1052 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-04373 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-02 EndToEndId-BP05-B-POS2-01-02 2052 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2
    15265 DBIT false BOOK
    2017-11-27
    2017-11-27
    DNTS-171127-CS-88151/1 PMNT ICDT OTHR 15265 15265 MsgId-BP05-B-POS2 PmtInfId-BP05-B-POS2-02 5 15265 MsgId-BP05-B-POS2 DNUC-191001-CS-04384 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-04 EndToEndId-BP05-B-POS2-02-04 4053 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-0495 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-01 EndToEndId-BP05-B-POS2-02-01 1053 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-0506 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-03 EndToEndId-BP05-B-POS2-02-03 3053 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-0517 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-02 EndToEndId-BP05-B-POS2-02-02 2053 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-0528 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-05 EndToEndId-BP05-B-POS2-02-05 5053 DBIT Max Muster BP05-B-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2
    881.87 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36700/1 PMNT RCDT RRTN 1030 913.28889 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49186 80VA-171127-CS-36700 13S0-171127-MS-49186 1030 CRDT BP03-A-POS3 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    883.59 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36739/1 PMNT RCDT RRTN 1032 915.06227 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36739 13S0-171127-MS-49188 1032 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    884.44 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36746/1 PMNT RCDT RRTN 1033 915.94896 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36746 13S0-171127-MS-49188 1033 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    900 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36835/1 PMNT RCDT DMCT 1000 900 CHF EUR 0.9 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49199 80VA-171127-CS-36835 13S0-171127-MS-49199 E2EPBP13-INEUR11171127H00 900 CRDT Debtor Name Adress Line 1 Adress Line 2
    1738.06 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36701/1 PMNT RCDT RRTN 2030 1799.97714 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49186 80VA-171127-CS-36701 13S0-171127-MS-49186 2030 CRDT BP03-A-POS3 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    1739.77 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36747/1 PMNT RCDT RRTN 2032 1801.75052 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36747 13S0-171127-MS-49188 2032 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    1740.63 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36748/1 PMNT RCDT RRTN 2033 1802.63721 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36748 13S0-171127-MS-49188 2033 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    1800 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36836/1 PMNT RCDT DMCT 2000 1800 CHF EUR 0.9 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49199 80VA-171127-CS-36836 13S0-171127-MS-49199 E2EPBP13-INEUR12171127H00 1800 CRDT Debtor Name Adress Line 1 Adress Line 2
    2594.25 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36702/1 PMNT RCDT RRTN 3030 2686.66539 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49186 80VA-171127-CS-36702 13S0-171127-MS-49186 3030 CRDT BP03-A-POS3 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    2595.96 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36749/1 PMNT RCDT RRTN 3032 2688.43876 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36749 13S0-171127-MS-49188 3032 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    2596.82 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36750/1 PMNT RCDT RRTN 3033 2689.32545 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36750 13S0-171127-MS-49188 3033 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    2654.18 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36830/1 PMNT RCDT DMCT 3100 2654.18 CHF EUR 1.1679679 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36830 13S0-171127-MS-49197 E2EBP12-INCHF117171127JB00 3100 CRDT Debtor Name Adress Line 1 Adress Line 2
    2700 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36839/1 PMNT RCDT DMCT 3000 2700 CHF EUR 0.9 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49200 80VA-171127-CS-36839 13S0-171127-MS-49200 E2EPBP13-INEUR13171127H00 2700 CRDT Debtor Name Adress Line 1 Adress Line 2
    2739.8 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36831/1 PMNT RCDT DMCT 3200 2739.8 CHF EUR 1.1679679 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36831 13S0-171127-MS-49197 E2EBP12-INCHF127171127JB00 3200 CRDT Debtor Name Adress Line 1 Adress Line 2
    2825.42 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36832/1 PMNT RCDT DMCT 3300 2825.42 CHF EUR 1.1679679 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36832 13S0-171127-MS-49197 E2EBP12-INCHF137171127JB00 3300 CRDT Debtor Name Adress Line 1 Adress Line 2
    2911.04 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36833/1 PMNT RCDT DMCT 3400 2911.04 CHF EUR 1.1679679 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36833 13S0-171127-MS-49197 E2EBP12-INCHF147171127JB00 3400 CRDT Debtor Name Adress Line 1 Adress Line 2
    2996.66 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36834/1 PMNT RCDT DMCT 3500 2996.66 CHF EUR 1.1679679 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36834 13S0-171127-MS-49197 E2EBP12-INCHF157171127JB00 3500 CRDT Debtor Name Adress Line 1 Adress Line 2
    3450.44 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36703/1 PMNT RCDT RRTN 4030 3573.35363 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49186 80VA-171127-CS-36703 13S0-171127-MS-49186 4030 CRDT BP03-A-POS3 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    3452.15 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36751/1 PMNT RCDT RRTN 4032 3575.12701 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36751 13S0-171127-MS-49188 4032 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    3453.01 CRDT true BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36752/1 PMNT RCDT RRTN 4033 3576.0137 CHF EUR 1.1277921 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36752 13S0-171127-MS-49188 4033 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    3600 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36837/1 PMNT RCDT DMCT 4000 3600 CHF EUR 0.9 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49199 80VA-171127-CS-36837 13S0-171127-MS-49199 E2EPBP13-INEUR14171127H00 3600 CRDT Debtor Name Adress Line 1 Adress Line 2
    4500 CRDT false BOOK
    2017-11-27
    2017-11-27
    80VA-171127-CS-36838/1 PMNT RCDT DMCT 5000 4500 CHF EUR 0.9 2017-11-27T00:00:00.000+01:00 13S0-171127-MS-49199 80VA-171127-CS-36838 13S0-171127-MS-49199 E2EPBP13-INEUR15171127H00 4500 CRDT Debtor Name Adress Line 1 Adress Line 2
    13273.3 DBIT false PDNG
    2017-11-15
    DNSJ-171115-CS-80769 XTND NTAV NTAV 1520 1520
    220000000 CRDT false PDNG
    2017-11-22
    DNSJ-171115-CS-90770 XTND NTAV NTAV 8017 8017
    10000000 CRDT false PDNG
    2017-11-22
    DNSJ-171115-CS-90781 XTND NTAV NTAV 8017 8017
    ././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.053_SIC_04_088583185407_ND_0885831854071000_20220323_010729778000_000.xmllibeufin-1.6.8/testbench/sample/cs/camt.053_SIC_04_088583185407_ND_0885831854071000_20220323_01072970000644000175000017500000003637014676232027027236 0ustar grothoffgrothoff CAMT053_20220323_010729756_VJC7LIIF 2022-03-23T01:07:29.756Z 1 true SPS/1.7/PROD cbe792bcaaf74a87b6c5c0c77df10872 58 2022-03-23T01:07:29.778Z 2022-03-22T00:00:00+01:00 2022-03-22T23:59:00+01:00 0885831854071000 CHF Barbara Muster Zürich CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 7751.38 CRDT
    2022-03-22
    FWAV 25273.34 CRDT
    2022-03-23
    CLAV 19273.34 CRDT
    2022-03-22
    CLBD 25273.34 CRDT
    2022-03-22
    17 18258.18 17521.96 CRDT 9 17890.07 8 368.11 2.36 DBIT BOOK
    2022-03-22
    2022-03-22
    DNQR-180322-CS-43783/1 PMNT ICDT AUTT 2 2 2.36 EUR CHF 1.18 2022-03-22T00:00:00.000+01:00 MSG0150D4D8E71C447EBF774FB84E1F7946 BLVL-1-18032208215187 1 2
    4.78 DBIT BOOK
    2022-03-22
    2022-03-22
    DNQN-180322-CS-58740/1 PMNT ICDT AUTT 5 5 4.78 USD CHF 0.95611387 2022-03-22T00:00:00.000+01:00 5 5 DBIT false INTERNAL MSG40BF23DB52794241A8DBE60391E04976 BLVL-1-18032208093429 1 5 ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    9.57 DBIT BOOK
    2022-03-22
    2022-03-22
    DNQR-180322-CS-43962/1 PMNT ICDT AUTT 10 10 9.57 USD CHF 0.95711254 2022-03-22T00:00:00.000+01:00 23 5 DBIT false INTERNAL 18 DBIT false EXTERNAL MSGEADAC6D735B14EEBA29FB52A459DD44F BLVL-1-18032208261993 1 10 ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    10.1 DBIT BOOK
    2022-03-22
    2022-03-22
    DNQN-180322-CS-58062/1 PMNT ICDT AUTT 10.1 10.1 MSG0D6E675AB5794B5BA889A0CCEAAD1D16 BLVL-1-18032207545645 1 10.1
    10.2 DBIT BOOK
    2022-03-22
    2022-03-22
    DNQR-180322-CS-40797/1 PMNT ICDT AUTT 10.2 10.2 MSG71784A43AF5747B6A60C17CFD29B1712 BLVL-1-18032207590104 1 10.2
    100 DBIT BOOK
    2022-03-22
    2022-03-22
    DNWL-180322-CS-87851/1 PMNT ICDT BOOK 100 100 57af4bcfda8d4f8fb958c5424d73c12e DNWL-180322-CS-87851 DNCS-20220322-IXN0 DNCS-20220322-IXN0-TXN0 SP-57273905-0 100 DBIT Barbara Muster, Zürich Barbara Muster, Zürich CH3704835833740031000 CHBCC 04835 Credit Suisse (Schweiz) AG Paradeplatz 8 8070 Zürich CH
    120 DBIT BOOK
    2022-03-22
    2022-03-22
    DNQR-180322-CS-40193/1 PMNT ICDT AUTT 120 120 MSG270C529F8169437186D63B1339FC09F9 BLVL-1-18032207463420 1 120
    111.1 DBIT BOOK
    2022-03-22
    2022-03-22
    DNRD-180323-CS-75599/1 PMNT ICDT AUTT 111.1 111.1 MSG4583D8DC482546E1B19F092AC83A2665 BLVL-1-19030708451663 2 111.1
    2.8 CRDT false BOOK
    2022-03-22
    2022-03-22
    08351803222247667/1 XTND NTAV NTAV 8037 8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.03.18
    3 CRDT BOOK
    2022-03-22
    2022-03-22
    80WL-180322-CS-55958/1 PMNT RCDT DMCT 3 13TF-180322-MS-85571 80WL-180322-CS-55958 13TF-180322-MS-85571 NOTPROVIDED 3 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 23456
    3.47 CRDT BOOK
    2022-03-22
    2022-03-22
    80WR-180322-CS-15197/1 PMNT RCDT ESCT 3 3.47 EUR CHF 1.15632286 2022-03-22T00:00:00.000+01:00 13TL-180322-MS-32279 80WR-180322-CS-15197 13TL-180322-MS-32279 NOTPROVIDED 3 CRDT KOWALSKI JAN PL SZCZYTNICKA 9 PL WROCLAW Invoice 45678
    6000 CRDT BOOK
    2022-03-22
    2022-03-23
    08922018031005244600/1 PMNT RCDT DMCT 6000 31XY-180322-MS-85571 91AB-180322-CS-55958 31XY-180322-MS-85571 NOTPROVIDED 6000 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 67890
    3000 CRDT true BOOK
    2022-03-22
    2022-03-22
    80WE-180321-CS-53986/1 PMNT RCDT RRTN 3000 13TJ-180321-MS-42880 80WE-180321-CS-53986 13TJ-180321-MS-42880 ETE68E82E7E701E4DB2B838318A8BA551CF 3000 CRDT Barbara Muster 8001 Zuerich PMNT ICDT DMCT UBSWCHZH80A NARR RETOUR SIC VAL 22.03.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH /SETT/2022-03-22T15:52:42
    2.75 CRDT false BOOK
    2022-03-22
    2022-03-22
    08351803222252626/1 XTND NTAV NTAV 8037 8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am 22.03.18
    010026540 7761.35 CRDT false BOOK
    2022-03-22
    2022-03-22
    4BA01709118000075/1 PMNT IDDT PMDD 4BA01709118000075 5 7761.35 CRDT ?21010026540 999999
    010026540 119.45 CRDT false BOOK
    2022-03-22
    2022-03-21
    4BA02002068000015/1 PMNT IDDT PMDD 4BA02002068000015 1 119.45 CRDT ?21010026540 901709
    CH4531000831854071000 997.25 CRDT false BOOK
    2022-03-22
    2022-03-22
    4BA01709118000076/1 PMNT RCDT VCOM 4BA01709118000076 5 997.25 CRDT
    libeufin-1.6.8/testbench/sample/cs/camt.054_SPS_08_088583185407_NN_0885831854071000_170251_005.xml0000644000175000017500000002135314676232027027413 0ustar grothoffgrothoff CAMT054_20221222_180251119_4Z2WCTQ4 2022-12-22T17:02:51.119Z 1 true 4BA01709118000075 2022-12-22T17:02:51.119Z 2022-12-22T00:00:00.000+01:00 2022-12-22T23:59:59.999+01:00 CH7705881831854071000 010026540 7761.35 CRDT BOOK
    2022-12-22
    2022-12-22
    4BA01709118000075/1 PMNT IDDT PMDD 5 7761.35 2561.35 CRDT 2561.35 PMNT IDDT PMDD Example SA Place du Marché 1 2222 Village ISR Reference 999999123456789012345678028 1400.00 CRDT 1400.00 PMNT IDDT PMDD Bäckerei-Konditorei Meier Landstrasse 1 5555 Unterdorf CH ISR Reference 999999123456789012345678033 1200.00 CRDT 1200.00 PMNT IDDT PMDD NOTPROVIDED ISR Reference 999999123456789012345678049 1100.00 CRDT 1100.00 PMNT IDDT PMDD NOTPROVIDED ISR Reference 999999123456789012345678057 1500.00 CRDT 1500.00 PMNT IDDT PMDD NOTPROVIDED ISR Reference 999999123456789012345678065
    ././@LongLink0000644000000000000000000000016200000000000011602 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.053_SIC_04_088583185407_WD_0885831854071000_20220323_010729778000_000.xmllibeufin-1.6.8/testbench/sample/cs/camt.053_SIC_04_088583185407_WD_0885831854071000_20220323_01072970000644000175000017500000016070014676232027027242 0ustar grothoffgrothoff CAMT053_20221223_010729756_VJC7LIIF 2022-12-23T01:07:29.756Z 1 true SPS/1.7/PROD cbe792bcaaf74a87b6c5c0c77df10872 58 2022-12-23T01:07:29.778Z 2022-12-22T00:00:00+01:00 2022-12-22T23:59:00+01:00 0885831854071000 CHF Barbara Muster Zürich CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 7751.38 CRDT
    2022-12-22
    FWAV 25153.89 CRDT
    2022-12-23
    CLAV 19153.89 CRDT
    2022-12-22
    CLBD 25153.89 CRDT
    2022-12-22
    16 18138.73 17402.51 CRDT 8 17770.62 8 368.11 2.36 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-43783/1 PMNT ICDT ESCT 2 2 2.36 EUR CHF 1.18 2022-12-22T00:00:00.000+01:00 MSG0150D4D8E71C447EBF774FB84E1F7946 DNQR-180322-CS-43783 BLVL-1-18032208215187 CLVL-1-18032711450502-1 ETEF9123BE97B2243629A9CF12FC6B6B80D 2 DBIT Barbara Muster Jan Kowalski PL Szczytnicka 9 50-382 Wroclaw PL79105015751000002345678901 INGBPLPW ING BANK SLASKI SA PL UL. SOKOLSKA 34 40-086 KATOWICE PL
    4.78 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQN-180322-CS-58740/1 PMNT ICDT AUTT 5 5 4.78 USD CHF 0.95611387 2022-12-22T00:00:00.000+01:00 5 5 DBIT false INTERNAL MSG40BF23DB52794241A8DBE60391E04976 BLVL-1-18032208093429 1 5 MSG40BF23DB52794241A8DBE60391E04976 DNQR-180322-CS-43794 BLVL-1-18032208093429 CLVL-1-18032711020928-1 ETE6A71EE9E18FF485EAC881A3B2E93475A 5 DBIT PMNT ICDT XBCT Barbara Muster Max Muster 8008 Zuerich CH85002582584X1234560 CHBCC 00258 UBS Switzerland AG Zentralstrasse 55 5610 Wohlen AG 1 CH ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    9.57 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-43962/1 PMNT ICDT AUTT 10 10 9.57 USD CHF 0.95711254 2022-12-22T00:00:00.000+01:00 23 5 DBIT false INTERNAL 18 DBIT false EXTERNAL MSGEADAC6D735B14EEBA29FB52A459DD44F BLVL-1-18032208261993 1 10 MSGEADAC6D735B14EEBA29FB52A459DD44F DNQR-180322-CS-43705 BLVL-1-18032208261993 CLVL-1-18032711084266-1 ETE1B58D1C4D44F4D75A481832C36D54D3E 10 DBIT PMNT ICDT XBCT Barbara Muster Jan Kowalski Szczytnicka 9 50-382 Wroclaw PL PL79105015751000002345678901 INGBPLPW ING BANK SLASKI SA PL UL. SOKOLSKA 34 40-086 KATOWICE PL Invoice AB-123-C ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    10.1 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQN-180322-CS-58062/1 PMNT ICDT DMCT 10.1 10.1 MSG0D6E675AB5794B5BA889A0CCEAAD1D16 DNQN-180322-CS-58062 BLVL-1-18032207545645 5139/180314/1ABC 5139/180314/1ABC 10.1 DBIT Max Muster CH Seefeldstrasse 1 8008 Zurich CH85002582584X1234560 CHBCC 00258 UBS Switzerland AG Zentralstrasse 55 5610 Wohlen AG 1 CH Rechnungsnummer 18C527-005
    10.2 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-40797/1 PMNT ICDT AUTT 10.2 10.2 MSG71784A43AF5747B6A60C17CFD29B1712 BLVL-1-18032207590104 1 10.2 MSG71784A43AF5747B6A60C17CFD29B1712 DNQR-180322-CS-43716 BLVL-1-18032207590104 CLVL-1-18032710592518-1 ETE53005D7923CD49509A3E7DB9BEC094A9 10.2 DBIT PMNT ICDT DMCT Barbara Muster Max Muster 8008 Zuerich CH85002582584X1234560 CHBCC 00258 UBS Switzerland AG Zentralstrasse 55 5610 Wohlen AG 1 CH
    100 DBIT BOOK
    2022-12-22
    2022-12-22
    DNWL-180322-CS-87851/1 PMNT ICDT BOOK 100 100 57af4bcfda8d4f8fb958c5424d73c12e DNWL-180322-CS-87851 DNCS-20220322-IXN0 DNCS-20220322-IXN0-TXN0 SP-57273905-0 100 DBIT Barbara Muster, Zürich Barbara Muster, Zürich CH3704835833740031000 CHBCC 04835 Credit Suisse (Schweiz) AG Paradeplatz 8 8070 Zürich CH
    120 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-40193/1 PMNT ICDT AUTT 120 120 MSG270C529F8169437186D63B1339FC09F9 BLVL-1-18032207463420 1 120 MSG270C529F8169437186D63B1339FC09F9 DNQR-180322-CS-43727 BLVL-1-18032207463420 CLVL-1-18032710510965-1 ETEE529F052BD2B4C8B85F345FC543B4930 120 DBIT Barbara Muster Hauptstrasse 1 8001 Zürich CH Aero Club der Schweiz Lidostrasse 5 6006 Luzern CH0930778123456789000 CHBCC 00778 Luzerner Kantonalbank AG Pilatusstrasse 12 6002 Luzern CH QRR 047280000701047470007679672 Aero Club der Schweiz
    111.1 DBIT BOOK
    2022-12-22
    2022-12-22
    DNRD-180323-CS-75599/1 PMNT ICDT AUTT 111.1 111.1 MSG4583D8DC482546E1B19F092AC83A2665 BLVL-1-19030708451663 2 111.1 MSG4583D8DC482546E1B19F092AC83A2665 DNQR-180322-CS-43738 BLVL-1-19030708451663 CLVL-1-19030708451663-1 ETE29CDDA854EE2484ABEF9DE87A81E0C8F 11.10 DBIT PMNT ICDT DMCT Barbara Muster Max Muster 8008 Zuerich CH85002582584X1234560 CHBCC 00258 UBS Switzerland AG Zentralstrasse 55 5610 Wohlen AG 1 CH MSG4583D8DC482546E1B19F092AC83A2665 DNQR-180322-CS-43749 BLVL-1-19030708451663 CLVL-1-19030708451663-2 ETE241D2750BC49461AAE9A98093F458940 100 DBIT PMNT ICDT VCOM Barbara Muster Hauptstrasse 1 8001 Zürich CH Aero Club der Schweiz Lidostrasse 5 6006 Luzern CH0930778123456789000 CHBCC 00778 Luzerner Kantonalbank AG Pilatusstrasse 12 6002 Luzern CH QRR 047280000701047470007679688
    2.8 CRDT false BOOK
    2022-12-22
    2022-12-22
    08351803222247667/1 XTND NTAV NTAV 8037 8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.12.22
    3 CRDT BOOK
    2022-12-22
    2022-12-22
    80WL-180322-CS-55958/1 PMNT RCDT DMCT 3 13TF-180322-MS-85571 80WL-180322-CS-55958 13TF-180322-MS-85571 NOTPROVIDED 3 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 23456
    3.47 CRDT BOOK
    2022-12-22
    2022-12-22
    80WR-180322-CS-15197/1 PMNT RCDT ESCT 3 3.47 EUR CHF 1.15632286 2022-12-22T00:00:00.000+01:00 13TL-180322-MS-32279 80WR-180322-CS-15197 13TL-180322-MS-32279 NOTPROVIDED 3 CRDT KOWALSKI JAN PL SZCZYTNICKA 9 PL WROCLAW Invoice 45678
    6000 CRDT BOOK
    2022-12-22
    2022-12-23
    08922018031005244600/1 PMNT RCDT DMCT 6000 31XY-180322-MS-85571 91AB-180322-CS-55958 31XY-180322-MS-85571 NOTPROVIDED 6000 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 67890
    3000 CRDT true BOOK
    2022-12-22
    2022-12-22
    80WE-180321-CS-53986/1 PMNT RCDT RRTN 3000 13TJ-180321-MS-42880 80WE-180321-CS-53986 13TJ-180321-MS-42880 ETE68E82E7E701E4DB2B838318A8BA551CF 3000 CRDT Barbara Muster 8001 Zuerich PMNT ICDT DMCT UBSWCHZH80A NARR RETOUR SIC VAL 22.12.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH /SETT/2022-12-22T15:52:42
    2.75 CRDT false BOOK
    2022-12-22
    2022-12-22
    08351803222252626/1 XTND NTAV NTAV 8037 8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am 22.12.22
    010026540 7761.35 CRDT BOOK
    2022-12-22
    2022-12-22
    80UL-171123-CS-35153/1 PMNT IDDT PMDD 7761.35 13RG-171123-MS-49259 80UL-171123-CS-35153 13RG-171123-MS-49259 E2EBP11-ESR12171123 7761.35 CRDT Max Muster CH Bundesplatz 1 3003 Bern ISR Reference 999999111122233344455678805 ?21010026540 999999
    CH4531000831854071000 997.25 CRDT false BOOK
    2022-12-22
    2022-12-22
    80UL171123CS35154/1001 PMNT RCDT VCOM 997.25 0.10 0.10 DBIT false INTERNAL 13RG-171123-MS-49260 80UL-171123-CS-35154 13RG-171123-MS-49260 E2EBP11-ESR12171124 997.25 CRDT 0.10 0.10 DBIT false INTERNAL Max Muster CH Bundesplatz 1 3003 Bern Pia-Maria Rutschmann-Schnyder CH Grosse Marktgasse 28 9400 Rorschach QRR 999999111122233344455678805 Manuelle Bemerkung
    ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.053_SPS_08_088583185407_WD_0885831854071000_20221223_010729778000.xmllibeufin-1.6.8/testbench/sample/cs/camt.053_SPS_08_088583185407_WD_0885831854071000_20221223_01072970000644000175000017500000016074214676232027027303 0ustar grothoffgrothoff CAMT053_20221223_010729756_VJC7LIIF 2022-12-23T01:07:29.756Z 1 true SPS/2.0/PROD cbe792bcaaf74a87b6c5c0c77df10872 58 2022-12-23T01:07:29.778Z 2022-12-22T00:00:00+01:00 2022-12-22T23:59:00+01:00 0885831854071000 CHF Barbara Muster Zürich CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 7751.38 CRDT
    2022-12-22
    FWAV 25153.89 CRDT
    2022-12-23
    CLAV 19153.89 CRDT
    2022-12-22
    CLBD 25153.89 CRDT
    2022-12-22
    16 18138.73 17402.51 CRDT 8 17770.62 8 368.11 2.36 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-43783/1 PMNT ICDT ESCT 2 2 2.36 EUR CHF 1.18 2022-12-22T00:00:00.000+01:00 MSG0150D4D8E71C447EBF774FB84E1F7946 DNQR-180322-CS-43783 BLVL-1-18032208215187 CLVL-1-18032711450502-1 ETEF9123BE97B2243629A9CF12FC6B6B80D 2 DBIT Barbara Muster Jan Kowalski PL Szczytnicka 9 50-382 Wroclaw PL79105015751000002345678901 INGBPLPW ING BANK SLASKI SA PL UL. SOKOLSKA 34 40-086 KATOWICE PL
    4.78 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQN-180322-CS-58740/1 PMNT ICDT AUTT 5 5 4.78 USD CHF 0.95611387 2022-12-22T00:00:00.000+01:00 5 5 DBIT false INTERNAL MSG40BF23DB52794241A8DBE60391E04976 BLVL-1-18032208093429 1 5 MSG40BF23DB52794241A8DBE60391E04976 DNQR-180322-CS-43794 BLVL-1-18032208093429 CLVL-1-18032711020928-1 ETE6A71EE9E18FF485EAC881A3B2E93475A 5 DBIT PMNT ICDT XBCT Barbara Muster Max Muster 8008 Zuerich CH85002582584X1234560 CHBCC 00258 UBS Switzerland AG Zentralstrasse 55 5610 Wohlen AG 1 CH ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    9.57 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-43962/1 PMNT ICDT AUTT 10 10 9.57 USD CHF 0.95711254 2022-12-22T00:00:00.000+01:00 23 5 DBIT false INTERNAL 18 DBIT false EXTERNAL MSGEADAC6D735B14EEBA29FB52A459DD44F BLVL-1-18032208261993 1 10 MSGEADAC6D735B14EEBA29FB52A459DD44F DNQR-180322-CS-43705 BLVL-1-18032208261993 CLVL-1-18032711084266-1 ETE1B58D1C4D44F4D75A481832C36D54D3E 10 DBIT PMNT ICDT XBCT Barbara Muster Jan Kowalski Szczytnicka 9 50-382 Wroclaw PL PL79105015751000002345678901 INGBPLPW ING BANK SLASKI SA PL UL. SOKOLSKA 34 40-086 KATOWICE PL Invoice AB-123-C ?62Relevant charges will be billed at the end of the accounting period taking into account the product-specific terms and conditions.
    10.1 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQN-180322-CS-58062/1 PMNT ICDT DMCT 10.1 10.1 MSG0D6E675AB5794B5BA889A0CCEAAD1D16 DNQN-180322-CS-58062 BLVL-1-18032207545645 5139/180314/1ABC 5139/180314/1ABC 10.1 DBIT Max Muster CH Seefeldstrasse 1 8008 Zurich CH85002582584X1234560 CHBCC 00258 UBS Switzerland AG Zentralstrasse 55 5610 Wohlen AG 1 CH Rechnungsnummer 18C527-005
    10.2 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-40797/1 PMNT ICDT AUTT 10.2 10.2 MSG71784A43AF5747B6A60C17CFD29B1712 BLVL-1-18032207590104 1 10.2 MSG71784A43AF5747B6A60C17CFD29B1712 DNQR-180322-CS-43716 BLVL-1-18032207590104 CLVL-1-18032710592518-1 ETE53005D7923CD49509A3E7DB9BEC094A9 10.2 DBIT PMNT ICDT DMCT Barbara Muster Max Muster 8008 Zuerich CH85002582584X1234560 CHBCC 00258 UBS Switzerland AG Zentralstrasse 55 5610 Wohlen AG 1 CH
    100 DBIT BOOK
    2022-12-22
    2022-12-22
    DNWL-180322-CS-87851/1 PMNT ICDT BOOK 100 100 57af4bcfda8d4f8fb958c5424d73c12e DNWL-180322-CS-87851 DNCS-20220322-IXN0 DNCS-20220322-IXN0-TXN0 SP-57273905-0 100 DBIT Barbara Muster, Zürich Barbara Muster, Zürich CH3704835833740031000 CHBCC 04835 Credit Suisse (Schweiz) AG Paradeplatz 8 8070 Zürich CH
    120 DBIT BOOK
    2022-12-22
    2022-12-22
    DNQR-180322-CS-40193/1 PMNT ICDT AUTT 120 120 MSG270C529F8169437186D63B1339FC09F9 BLVL-1-18032207463420 1 120 MSG270C529F8169437186D63B1339FC09F9 DNQR-180322-CS-43727 BLVL-1-18032207463420 CLVL-1-18032710510965-1 ETEE529F052BD2B4C8B85F345FC543B4930 120 DBIT PMNT ICDT VCOM Barbara Muster Hauptstrasse 1 8001 Zürich CH Aero Club der Schweiz Lidostrasse 5 6006 Luzern CH0930778123456789000 CHBCC 00778 Luzerner Kantonalbank AG Pilatusstrasse 12 6002 Luzern CH QRR 047280000701047470007679672 Aero Club der Schweiz
    111.1 DBIT BOOK
    2022-12-22
    2022-12-22
    DNRD-180323-CS-75599/1 PMNT ICDT AUTT 111.1 111.1 MSG4583D8DC482546E1B19F092AC83A2665 BLVL-1-19030708451663 2 111.1 MSG4583D8DC482546E1B19F092AC83A2665 DNQR-180322-CS-43738 BLVL-1-19030708451663 CLVL-1-19030708451663-1 ETE29CDDA854EE2484ABEF9DE87A81E0C8F 11.10 DBIT PMNT ICDT DMCT Barbara Muster Max Muster 8008 Zuerich CH85002582584X1234560 CHBCC 00258 UBS Switzerland AG Zentralstrasse 55 5610 Wohlen AG 1 CH MSG4583D8DC482546E1B19F092AC83A2665 DNQR-180322-CS-43749 BLVL-1-19030708451663 CLVL-1-19030708451663-2 ETE241D2750BC49461AAE9A98093F458940 100 DBIT PMNT ICDT VCOM Barbara Muster Hauptstrasse 1 8001 Zürich CH Aero Club der Schweiz Lidostrasse 5 6006 Luzern CH0930778123456789000 CHBCC 00778 Luzerner Kantonalbank AG Pilatusstrasse 12 6002 Luzern CH QRR 047280000701047470007679688
    2.8 CRDT false BOOK
    2022-12-22
    2022-12-22
    08351803222247667/1 XTND NTAV NTAV 8037 8037?0508351803222247667?32BARBARA MUSTER 8001 ZURICH?60RECHNUNG 34567?24USD 3.00 Kurs 0.939874 fixiert am 22.03.18
    3 CRDT BOOK
    2022-12-22
    2022-12-22
    80WL-180322-CS-55958/1 PMNT RCDT DMCT 3 13TF-180322-MS-85571 80WL-180322-CS-55958 13TF-180322-MS-85571 NOTPROVIDED eb6305c9-1f7f-49de-aed0-16487c27b42f 3 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 23456
    3.47 CRDT BOOK
    2022-12-22
    2022-12-22
    80WR-180322-CS-15197/1 PMNT RCDT ESCT 3 3.47 EUR CHF 1.15632286 2022-12-22T00:00:00.000+01:00 13TL-180322-MS-32279 80WR-180322-CS-15197 13TL-180322-MS-32279 NOTPROVIDED 3 CRDT KOWALSKI JAN PL SZCZYTNICKA 9 PL WROCLAW Invoice 45678
    6000 CRDT BOOK
    2022-12-22
    2022-12-23
    08922018031005244600/1 PMNT RCDT DMCT 6000 31XY-180322-MS-85571 91AB-180322-CS-55958 31XY-180322-MS-85571 NOTPROVIDED 6000 CRDT BARBARA MUSTER 8001 ZURICH RECHNUNG 67890
    3000 CRDT true BOOK
    2022-12-22
    2022-12-22
    80WE-180321-CS-53986/1 PMNT RCDT RRTN 3000 13TJ-180321-MS-42880 80WE-180321-CS-53986 13TJ-180321-MS-42880 ETE68E82E7E701E4DB2B838318A8BA551CF 3000 CRDT Barbara Muster 8001 Zuerich PMNT ICDT DMCT UBSWCHZH80A NARR RETOUR SIC VAL 22.03.2022 BEGUENSTIGTENANGABEN UNGENUEGEND BARBARA MUSTER 8001 ZUERICH /SETT/2022-12-22T15:52:42
    2.75 CRDT false BOOK
    2022-12-22
    2022-12-22
    08351803222252626/1 XTND NTAV NTAV 8037 8037?0508351803222252626?32KOWALSKI JAN SZCZYTNICKA 9 PL WROCLAW?60CREDIT TRANSFER IN PLN?24PLN 10.00 Kurs 27.34535 fixiert am 22.03.18
    010026540 7761.35 CRDT BOOK
    2022-12-22
    2022-12-22
    80UL-171123-CS-35153/1 PMNT IDDT PMDD 7761.35 13RG-171123-MS-49259 80UL-171123-CS-35153 13RG-171123-MS-49259 E2EBP11-ESR12171123 7761.35 CRDT Max Muster CH Bundesplatz 1 3003 Bern ISR Reference 999999111122233344455678805 ?21010026540 999999
    CH4531000831854071000 997.25 CRDT false BOOK
    2022-12-22
    2022-12-22
    80UL171123CS35154/1001 PMNT RCDT VCOM 997.25 0.10 0.10 DBIT false INTERNAL 13RG-171123-MS-49260 80UL-171123-CS-35154 13RG-171123-MS-49260 E2EBP11-ESR12171124 eb6305c9-1f7f-49de-aed0-16487c27b42d 997.25 CRDT 0.10 0.10 DBIT false INTERNAL Max Muster CH Bundesplatz 1 3003 Bern Pia-Maria Rutschmann-Schnyder CH Grosse Marktgasse 28 9400 Rorschach QRR 999999111122233344455678805 Manuelle Bemerkung
    ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.052_SPS_08_050483017844_WD_0504830178442001_20221127_230054_002.xmllibeufin-1.6.8/testbench/sample/cs/camt.052_SPS_08_050483017844_WD_0504830178442001_20221127_230054_0000644000175000017500000107630114676232027027316 0ustar grothoffgrothoff CAMT052_20221127_230054396_2XFDFW86 2022-11-27T23:00:54.396+01:00 1 true SPS/2.0/PROD 3edc45b55b044b0aa909e458b9c551d2 4 2022-11-27T23:00:54.402+01:00 0504-8301784-42-001 EUR Your Company Name Adress Line CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 582975.5 DBIT
    2022-11-27
    ITBD 808704.88 DBIT
    2022-11-27
    50 333005.56 225729.38 DBIT 22 53638.09 28 279367.47 903.61 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37494/1 PMNT ICDT XBCT 1042 1042 903.61 USD EUR 0.86719 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37494 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-01 EndToEndId-BP04-B-POS2-01-01 1042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    904.47 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37499/2 PMNT ICDT XBCT 1043 1043 904.47 USD EUR 0.86718 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37499 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-01 EndToEndId-BP04-B-POS2-02-01 1043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    1770.79 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37495/1 PMNT ICDT XBCT 2042 2042 1770.79 USD EUR 0.86718 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37495 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-02 EndToEndId-BP04-B-POS2-01-02 2042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    1771.66 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37500/1 PMNT ICDT XBCT 2043 2043 1771.66 USD EUR 0.86719 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37500 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-02 EndToEndId-BP04-B-POS2-02-02 2043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    2637.98 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37496/1 PMNT ICDT XBCT 3042 3042 2637.98 USD EUR 0.86719 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37496 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-03 EndToEndId-BP04-B-POS2-01-03 3042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    2638.85 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37501/1 PMNT ICDT XBCT 3043 3043 2638.85 USD EUR 0.86719 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37501 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-03 EndToEndId-BP04-B-POS2-02-03 3043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    3505.17 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37497/1 PMNT ICDT XBCT 4042 4042 3505.17 USD EUR 0.86719 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37497 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-04 EndToEndId-BP04-B-POS2-01-04 4042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    3506.03 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37502/1 PMNT ICDT XBCT 4043 4043 3506.03 USD EUR 0.86719 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37502 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-04 EndToEndId-BP04-B-POS2-02-04 4043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    4372.35 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37498/1 PMNT ICDT XBCT 5042 5042 4372.35 USD EUR 0.86719 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37498 PmtInfId-BP04-B-POS2-01 InstrId-BP04-B-POS2-01-05 EndToEndId-BP04-B-POS2-01-05 5042 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    4373.22 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNVA-171127-CS-37503/1 PMNT ICDT XBCT 5043 5043 4373.22 USD EUR 0.86719 2022-11-27T00:00:00.000+01:00 MsgId-BP04-B-POS2 DNVA-171127-CS-37503 PmtInfId-BP04-B-POS2-02 InstrId-BP04-B-POS2-02-05 EndToEndId-BP04-B-POS2-02-05 5043 DBIT Max Muster BP04-B-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    13155.32 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88144/1 PMNT ICDT OTHR 15200 15200 13155.32 USD EUR 0.86548158 2022-11-27T00:00:00.000+01:00 MsgId-BP04-A-POS2 PmtInfId-BP04-A-POS2-01 5 15200 MsgId-BP04-A-POS2 DNUC-191001-CS-03640 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-01 EndToEndId-BP04-A-POS2-01-01 1040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03651 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-02 EndToEndId-BP04-A-POS2-01-02 2040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03662 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-05 EndToEndId-BP04-A-POS2-01-05 5040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03673 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-04 EndToEndId-BP04-A-POS2-01-04 4040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03684 PmtInfId-BP04-A-POS2-01 InstrId-BP04-A-POS2-01-03 EndToEndId-BP04-A-POS2-01-03 3040 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    13159.64 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88145/1 PMNT ICDT OTHR 15205 15205 13159.64 USD EUR 0.86548109 2022-11-27T00:00:00.000+01:00 MsgId-BP04-A-POS2 PmtInfId-BP04-A-POS2-02 5 15205 MsgId-BP04-A-POS2 DNUC-191001-CS-03695 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-03 EndToEndId-BP04-A-POS2-02-03 3041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03606 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-01 EndToEndId-BP04-A-POS2-02-01 1041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03717 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-02 EndToEndId-BP04-A-POS2-02-02 2041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03728 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-04 EndToEndId-BP04-A-POS2-02-04 4041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP04-A-POS2 DNUC-191001-CS-03739 PmtInfId-BP04-A-POS2-02 InstrId-BP04-A-POS2-02-05 EndToEndId-BP04-A-POS2-02-05 5041 DBIT Max Muster BP04-A-POS2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    13241.86 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88152/1 PMNT ICDT OTHR 15300 15300 13241.86 USD EUR 0.86548105 2022-11-27T00:00:00.000+01:00 MsgId-BP06-POS2 PmtInfId-BP06-POS2-01 5 15300 MsgId-BP06-POS2 DNUC-191001-CS-03740 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-03 EndToEndId-BP06-POS2-01-03 3060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03751 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-02 EndToEndId-BP06-POS2-01-02 2060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03762 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-05 EndToEndId-BP06-POS2-01-05 5060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03773 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-01 EndToEndId-BP06-POS2-01-01 1060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03784 PmtInfId-BP06-POS2-01 InstrId-BP06-POS2-01-04 EndToEndId-BP06-POS2-01-04 4060 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2
    13246.19 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88153/1 PMNT ICDT OTHR 15305 15305 13246.19 USD EUR 0.86548122 2022-11-27T00:00:00.000+01:00 MsgId-BP06-POS2 PmtInfId-BP06-POS2-02 5 15305 MsgId-BP06-POS2 DNUC-191001-CS-03795 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-01 EndToEndId-BP06-POS2-02-01 1061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03806 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-03 EndToEndId-BP06-POS2-02-03 3061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03817 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-04 EndToEndId-BP06-POS2-02-04 4061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03828 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-05 EndToEndId-BP06-POS2-02-05 5061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP06-POS2 DNUC-191001-CS-03839 PmtInfId-BP06-POS2-02 InstrId-BP06-POS2-02-02 EndToEndId-BP06-POS2-02-02 2061 DBIT Max Muster BP06-POS2 CH Adress Line 1 Adress Line 2 CH3704835833740031000 ESSEGB2L Creditor Agent Name CH Adress Line 1 Adress Line 2
    13273.3 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88136/1 PMNT ICDT OTHR 15000 15000 13273.3 CHF EUR 0.88488667 2022-11-27T00:00:00.000+01:00 MsgId-BP01-POS3 PmtInfId-BP01-POS3-01 5 15000 MsgId-BP01-POS3 DNUC-191001-CS-03840 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-01 EndToEndId-BP01-POS3-01-01 1000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 111111111111111111111111110 MsgId-BP01-POS3 DNUC-191001-CS-03851 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-02 EndToEndId-BP01-POS3-01-02 2000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 222222222222222222222222222 MsgId-BP01-POS3 DNUC-191001-CS-03862 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-03 EndToEndId-BP01-POS3-01-03 3000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 333333333333333333333333334 MsgId-BP01-POS3 DNUC-191001-CS-03873 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-04 EndToEndId-BP01-POS3-01-04 4000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 444444444444444444444444444 MsgId-BP01-POS3 DNUC-191001-CS-03884 PmtInfId-BP01-POS3-01 InstrId-BP01-POS3-01-05 EndToEndId-BP01-POS3-01-05 5000 DBIT Max Muster BP01-POS3 010643794 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 555555555555555555555555559
    13332.74 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88155/1 PMNT ICDT OTHR 15405 15405 13332.74 USD EUR 0.86548134 2022-11-27T00:00:00.000+01:00 MsgId-BP08-POS2 PmtInfId-BP08-POS2-02 5 15405 MsgId-BP08-POS2 DNUC-191001-CS-03895 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-01 EndToEndId-BP08-POS2-02-01 36501096 1081 DBIT Max Muster Creditor Name Street Name 1 12345 Town Name CH ChequeDeliverTo Hans Meier MsgId-BP08-POS2 DNUC-191001-CS-03906 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-02 EndToEndId-BP08-POS2-02-02 36501097 2081 DBIT Max Muster Creditor Name Street Name 1 12345 Town Name CH ChequeDeliverTo Hans Meier MsgId-BP08-POS2 DNUC-191001-CS-03917 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-03 EndToEndId-BP08-POS2-02-03 36501098 3081 DBIT Max Muster Creditor Name Street Name 1 12345 Town Name CH ChequeDeliverTo Hans Meier MsgId-BP08-POS2 DNUC-191001-CS-03928 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-04 EndToEndId-BP08-POS2-02-04 36501099 4081 DBIT Max Muster Creditor Name Street Name 1 12345 Town Name CH ChequeDeliverTo Hans Meier MsgId-BP08-POS2 DNUC-191001-CS-03939 PmtInfId-BP08-POS2-02 InstrId-BP08-POS2-02-05 EndToEndId-BP08-POS2-02-05 36501100 5081 DBIT Max Muster Creditor Name Street Name 1 12345 Town Name CH ChequeDeliverTo Hans Meier
    13361.79 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88138/1 PMNT ICDT OTHR 15100 15100 13361.79 CHF EUR 0.88488675 2022-11-27T00:00:00.000+01:00 MsgId-BP02-POS2 PmtInfId-BP02-POS2-01 5 15100 MsgId-BP02-POS2 DNUC-191001-CS-03940 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-03 EndToEndId-BP02-POS2-01-03 3020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-03951 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-04 EndToEndId-BP02-POS2-01-04 4020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-03962 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-05 EndToEndId-BP02-POS2-01-05 5020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-03973 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-01 EndToEndId-BP02-POS2-01-01 1020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-03984 PmtInfId-BP02-POS2-01 InstrId-BP02-POS2-01-02 EndToEndId-BP02-POS2-01-02 2020 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2
    13406.04 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88140/1 PMNT ICDT OTHR 15150 15150 13406.04 CHF EUR 0.88488713 2022-11-27T00:00:00.000+01:00 MsgId-BP03-A-POS3 PmtInfId-BP03-A-POS3-01 5 15150 MsgId-BP03-A-POS3 DNUC-191001-CS-03995 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-01 EndToEndId-BP03-A-POS3-01-01 1030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04006 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-02 EndToEndId-BP03-A-POS3-01-02 2030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04017 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-03 EndToEndId-BP03-A-POS3-01-03 3030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04028 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-04 EndToEndId-BP03-A-POS3-01-04 4030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04039 PmtInfId-BP03-A-POS3-01 InstrId-BP03-A-POS3-01-05 EndToEndId-BP03-A-POS3-01-05 5030 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH5604835012345678009 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    13414.89 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88142/1 PMNT ICDT OTHR 15160 15160 13414.89 CHF EUR 0.8848872 2022-11-27T00:00:00.000+01:00 MsgId-BP03-B-POS2 PmtInfId-BP03-B-POS2-01 5 15160
    13419.31 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88143/1 PMNT ICDT OTHR 15165 15165 13419.31 CHF EUR 0.88488691 2022-11-27T00:00:00.000+01:00 MsgId-BP03-B-POS2 PmtInfId-BP03-B-POS2-02 5 15165
    13627.26 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88154/1 PMNT ICDT OTHR 15400 15400 13627.26 CHF EUR 0.88488701 2022-11-27T00:00:00.000+01:00 MsgId-BP08-POS2 PmtInfId-BP08-POS2-01 5 15400 MsgId-BP08-POS2 DNUC-191001-CS-04040 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-04 EndToEndId-BP08-POS2-01-04 36501094 4080 DBIT Max Muster Creditor Name Street Name 4 12345 Town Name CH ChequeDeliverTo Hans Meier MsgId-BP08-POS2 DNUC-191001-CS-04051 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-03 EndToEndId-BP08-POS2-01-03 36501093 3080 DBIT Max Muster Creditor Name Street Name 4 12345 Town Name CH ChequeDeliverTo Hans Meier MsgId-BP08-POS2 DNUC-191001-CS-04062 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-05 EndToEndId-BP08-POS2-01-05 36501095 5080 DBIT Max Muster Creditor Name Street Name 4 12345 Town Name CH ChequeDeliverTo Hans Meier MsgId-BP08-POS2 DNUC-191001-CS-04073 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-01 EndToEndId-BP08-POS2-01-01 36501091 1080 DBIT Max Muster Creditor Name Street Name 4 12345 Town Name CH ChequeDeliverTo Hans Meier MsgId-BP08-POS2 DNUC-191001-CS-04084 PmtInfId-BP08-POS2-01 InstrId-BP08-POS2-01-02 EndToEndId-BP08-POS2-01-02 36501092 2080 DBIT Max Muster Creditor Name Street Name 4 12345 Town Name CH ChequeDeliverTo Hans Meier
    15055 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88137/1 PMNT ICDT OTHR 15055 15055 MsgId-BP01-POS3 PmtInfId-BP01-POS3-02 5 15055 MsgId-BP01-POS3 DNUC-191001-CS-04084 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-04 EndToEndId-BP01-POS3-02-04 4011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 444444444444444444444444444 MsgId-BP01-POS3 DNUC-191001-CS-04095 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-05 EndToEndId-BP01-POS3-02-05 5011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 555555555555555555555555559 MsgId-BP01-POS3 DNUC-191001-CS-04106 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-01 EndToEndId-BP01-POS3-02-01 1011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 111111111111111111111111110 MsgId-BP01-POS3 DNUC-191001-CS-04117 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-02 EndToEndId-BP01-POS3-02-02 2011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 222222222222222222222222222 MsgId-BP01-POS3 DNUC-191001-CS-04128 PmtInfId-BP01-POS3-02 InstrId-BP01-POS3-02-03 EndToEndId-BP01-POS3-02-03 3011 DBIT Max Muster BP01-POS3 034567896 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 ISR Reference 333333333333333333333333334
    15105 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88139/1 PMNT ICDT OTHR 15105 15105 MsgId-BP02-POS2 PmtInfId-BP02-POS2-02 5 15105 MsgId-BP02-POS2 DNUC-191001-CS-04139 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-03 EndToEndId-BP02-POS2-02-03 3021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-04140 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-04 EndToEndId-BP02-POS2-02-04 4021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-04151 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-05 EndToEndId-BP02-POS2-02-05 5021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-04162 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-01 EndToEndId-BP02-POS2-02-01 1021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2 MsgId-BP02-POS2 DNUC-191001-CS-04173 PmtInfId-BP02-POS2-02 InstrId-BP02-POS2-02-02 EndToEndId-BP02-POS2-02-02 2021 DBIT Max Muster BP02-POS2 Adress Line 1 Adress Line 2 700041528 CHBCC 09000 Creditor Agent Name Adress Line 1 Adress Line 2
    15155 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88141/1 PMNT ICDT OTHR 15155 15155 MsgId-BP03-A-POS3 PmtInfId-BP03-A-POS3-02 5 15155 MsgId-BP03-A-POS3 DNUC-191001-CS-04184 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-04 EndToEndId-BP03-A-POS3-02-04 4031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04195 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-05 EndToEndId-BP03-A-POS3-02-05 5031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04206 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-02 EndToEndId-BP03-A-POS3-02-02 2031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04217 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-03 EndToEndId-BP03-A-POS3-02-03 3031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2 MsgId-BP03-A-POS3 DNUC-191001-CS-04228 PmtInfId-BP03-A-POS3-02 InstrId-BP03-A-POS3-02-01 EndToEndId-BP03-A-POS3-02-01 1031 DBIT Max Muster BP03-A-POS3 Adress Line 1 Adress Line 2 CH7304835833740032001 CHBCC 04835 Credit Suisse (Schweiz) AG Adress Line 1 Adress Line 2
    15250 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88148/1 PMNT ICDT OTHR 15250 15250 MsgId-BP05-A-POS2 PmtInfId-BP05-A-POS2-01 5 15250 MsgId-BP05-A-POS2 DNUC-191001-CS-04239 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-02 EndToEndId-BP05-A-POS2-01-02 2050 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04240 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-04 EndToEndId-BP05-A-POS2-01-04 4050 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04251 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-05 EndToEndId-BP05-A-POS2-01-05 5050 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04262 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-01 EndToEndId-BP05-A-POS2-01-01 1050 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04273 PmtInfId-BP05-A-POS2-01 InstrId-BP05-A-POS2-01-03 EndToEndId-BP05-A-POS2-01-03 3050 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2
    15255 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88149/1 PMNT ICDT OTHR 15255 15255 MsgId-BP05-A-POS2 PmtInfId-BP05-A-POS2-02 5 15255 MsgId-BP05-A-POS2 DNUC-191001-CS-04284 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-01 EndToEndId-BP05-A-POS2-02-01 1051 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04295 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-05 EndToEndId-BP05-A-POS2-02-05 5051 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04306 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-03 EndToEndId-BP05-A-POS2-02-03 3051 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04317 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-04 EndToEndId-BP05-A-POS2-02-04 4051 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-A-POS2 DNUC-191001-CS-04328 PmtInfId-BP05-A-POS2-02 InstrId-BP05-A-POS2-02-02 EndToEndId-BP05-A-POS2-02-02 2051 DBIT Max Muster BP05-A-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2
    15260 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88150/1 PMNT ICDT OTHR 15260 15260 MsgId-BP05-B-POS2 PmtInfId-BP05-B-POS2-01 5 15260 MsgId-BP05-B-POS2 DNUC-191001-CS-04339 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-03 EndToEndId-BP05-B-POS2-01-03 3052 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-04340 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-04 EndToEndId-BP05-B-POS2-01-04 4052 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-04351 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-05 EndToEndId-BP05-B-POS2-01-05 5052 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-04362 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-01 EndToEndId-BP05-B-POS2-01-01 1052 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-04373 PmtInfId-BP05-B-POS2-01 InstrId-BP05-B-POS2-01-02 EndToEndId-BP05-B-POS2-01-02 2052 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2
    15265 DBIT false BOOK
    2022-11-27
    2022-11-27
    DNTS-171127-CS-88151/1 PMNT ICDT OTHR 15265 15265 MsgId-BP05-B-POS2 PmtInfId-BP05-B-POS2-02 5 15265 MsgId-BP05-B-POS2 DNUC-191001-CS-04384 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-04 EndToEndId-BP05-B-POS2-02-04 4053 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-0495 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-01 EndToEndId-BP05-B-POS2-02-01 1053 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-0506 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-03 EndToEndId-BP05-B-POS2-02-03 3053 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-0517 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-02 EndToEndId-BP05-B-POS2-02-02 2053 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2 MsgId-BP05-B-POS2 DNUC-191001-CS-0528 PmtInfId-BP05-B-POS2-02 InstrId-BP05-B-POS2-02-05 EndToEndId-BP05-B-POS2-02-05 5053 DBIT Max Muster BP05-B-POS2 Adress Line 1 Adress Line 2 CH3704835833740031000 INGDDEFFXXX Creditor Agent Name CH Adress Line 1 Adress Line 2
    881.87 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36700/1 PMNT RCDT RRTN 1030 913.28889 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49186 80VA-171127-CS-36700 13S0-171127-MS-49186 1030 CRDT BP03-A-POS3 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    883.59 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36739/1 PMNT RCDT RRTN 1032 915.06227 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36739 13S0-171127-MS-49188 1032 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    884.44 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36746/1 PMNT RCDT RRTN 1033 915.94896 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36746 13S0-171127-MS-49188 1033 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    900 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36835/1 PMNT RCDT DMCT 1000 900 CHF EUR 0.9 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49199 80VA-171127-CS-36835 13S0-171127-MS-49199 E2EPBP13-INEUR11171127H00 900 CRDT Debtor Name Adress Line 1 Adress Line 2
    1738.06 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36701/1 PMNT RCDT RRTN 2030 1799.97714 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49186 80VA-171127-CS-36701 13S0-171127-MS-49186 2030 CRDT BP03-A-POS3 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    1739.77 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36747/1 PMNT RCDT RRTN 2032 1801.75052 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36747 13S0-171127-MS-49188 2032 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    1740.63 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36748/1 PMNT RCDT RRTN 2033 1802.63721 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36748 13S0-171127-MS-49188 2033 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    1800 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36836/1 PMNT RCDT DMCT 2000 1800 CHF EUR 0.9 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49199 80VA-171127-CS-36836 13S0-171127-MS-49199 E2EPBP13-INEUR12171127H00 1800 CRDT Debtor Name Adress Line 1 Adress Line 2
    2594.25 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36702/1 PMNT RCDT RRTN 3030 2686.66539 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49186 80VA-171127-CS-36702 13S0-171127-MS-49186 3030 CRDT BP03-A-POS3 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    2595.96 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36749/1 PMNT RCDT RRTN 3032 2688.43876 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36749 13S0-171127-MS-49188 3032 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    2596.82 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36750/1 PMNT RCDT RRTN 3033 2689.32545 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36750 13S0-171127-MS-49188 3033 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    2654.18 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36830/1 PMNT RCDT DMCT 3100 2654.18 CHF EUR 1.1679679 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36830 13S0-171127-MS-49197 E2EBP12-INCHF117171127JB00 3100 CRDT Debtor Name Adress Line 1 Adress Line 2
    2700 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36839/1 PMNT RCDT DMCT 3000 2700 CHF EUR 0.9 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49200 80VA-171127-CS-36839 13S0-171127-MS-49200 E2EPBP13-INEUR13171127H00 2700 CRDT Debtor Name Adress Line 1 Adress Line 2
    2739.8 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36831/1 PMNT RCDT DMCT 3200 2739.8 CHF EUR 1.1679679 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36831 13S0-171127-MS-49197 E2EBP12-INCHF127171127JB00 3200 CRDT Debtor Name Adress Line 1 Adress Line 2
    2825.42 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36832/1 PMNT RCDT DMCT 3300 2825.42 CHF EUR 1.1679679 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36832 13S0-171127-MS-49197 E2EBP12-INCHF137171127JB00 3300 CRDT Debtor Name Adress Line 1 Adress Line 2
    2911.04 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36833/1 PMNT RCDT DMCT 3400 2911.04 CHF EUR 1.1679679 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36833 13S0-171127-MS-49197 E2EBP12-INCHF147171127JB00 3400 CRDT Debtor Name Adress Line 1 Adress Line 2
    2996.66 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36834/1 PMNT RCDT DMCT 3500 2996.66 CHF EUR 1.1679679 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49197 80VA-171127-CS-36834 13S0-171127-MS-49197 E2EBP12-INCHF157171127JB00 3500 CRDT Debtor Name Adress Line 1 Adress Line 2
    3450.44 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36703/1 PMNT RCDT RRTN 4030 3573.35363 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49186 80VA-171127-CS-36703 13S0-171127-MS-49186 4030 CRDT BP03-A-POS3 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    3452.15 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36751/1 PMNT RCDT RRTN 4032 3575.12701 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36751 13S0-171127-MS-49188 4032 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    3453.01 CRDT true BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36752/1 PMNT RCDT RRTN 4033 3576.0137 CHF EUR 1.1277921 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49188 80VA-171127-CS-36752 13S0-171127-MS-49188 4033 CRDT BP03-B-POS2 Adress Line 1 Adress Line 2 PMNT ICDT OTHR CRESCHZZ MS03
    3600 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36837/1 PMNT RCDT DMCT 4000 3600 CHF EUR 0.9 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49199 80VA-171127-CS-36837 13S0-171127-MS-49199 E2EPBP13-INEUR14171127H00 3600 CRDT Debtor Name Adress Line 1 Adress Line 2
    4500 CRDT false BOOK
    2022-11-27
    2022-11-27
    80VA-171127-CS-36838/1 PMNT RCDT DMCT 5000 4500 CHF EUR 0.9 2022-11-27T00:00:00.000+01:00 13S0-171127-MS-49199 80VA-171127-CS-36838 13S0-171127-MS-49199 E2EPBP13-INEUR15171127H00 4500 CRDT Debtor Name Adress Line 1 Adress Line 2
    13273.3 DBIT false PDNG
    2022-11-15
    DNSJ-171115-CS-80769 XTND NTAV NTAV 1520 1520
    220000000 CRDT false PDNG
    2022-11-22
    DNSJ-171115-CS-90770 XTND NTAV NTAV 8017 8017
    10000000 CRDT false PDNG
    2022-11-22
    DNSJ-171115-CS-90781 XTND NTAV NTAV 8017 8017
    ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.052_SIC_04_050483017844_ND_0504830178442001_20171127_230054_001.xmllibeufin-1.6.8/testbench/sample/cs/camt.052_SIC_04_050483017844_ND_0504830178442001_20171127_230054_0000644000175000017500000000544314676232027027254 0ustar grothoffgrothoff CAMT052_20171127_230054037_5R83DWV3 2017-11-27T23:00:54.038Z 1 true SPS/1.7/PROD 4c41ae16ae0a41bda7575de162e53b2a 4 2017-11-27T23:00:54.149Z 0504830178442001 EUR Your Company Name Adress Line CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 582975.5 DBIT
    2017-11-27
    ITBD 808704.88 DBIT
    2017-11-27
    50 333005.56 225729.38 DBIT 22 53638.09 28 279367.47
    ././@LongLink0000644000000000000000000000015400000000000011603 Lustar rootrootlibeufin-1.6.8/testbench/sample/cs/camt.052_SPS_08_050483017844_ND_0504830178442001_20171127_230054_001.xmllibeufin-1.6.8/testbench/sample/cs/camt.052_SPS_08_050483017844_ND_0504830178442001_20171127_230054_0000644000175000017500000000544314676232027027307 0ustar grothoffgrothoff CAMT052_20171127_230054037_5R83DWV3 2017-11-27T23:00:54.038Z 1 true SPS/1.7/PROD 4c41ae16ae0a41bda7575de162e53b2a 4 2017-11-27T23:00:54.149Z 0504830178442001 EUR Your Company Name Adress Line CRESCHZZ80A CREDIT SUISSE (Switzerland) Ltd. CHE-116.285.487 MWST VAT-ID OPBD 582975.5 DBIT
    2017-11-27
    ITBD 808704.88 DBIT
    2017-11-27
    50 333005.56 225729.38 DBIT 22 53638.09 28 279367.47
    libeufin-1.6.8/testbench/clean_test_logs.py0000775000175000017500000000472615100747127021261 0ustar grothoffgrothoff#!/usr/bin/python3 # Clean testbench logs directory to only keep unique and useful files import hashlib from pathlib import Path from string import whitespace DIR = Path("test") def rmtree(p: Path): """Recursively delete file or directory""" if p.exists(): if p.is_dir(): for child in p.iterdir(): rmtree(child) p.rmdir() else: p.unlink() def remove(p: Path, reason: str): """Announce and recursively remove file or directory""" print(f"rm {reason} {p}") rmtree(p) content_hashes = set() def rm_if_similar(p: Path, content: str): """Delete file if another file has the same content""" # Remove whitespace from file normalized = content.translate(str.maketrans("", "", whitespace)) # Hash their content hash = hashlib.blake2b(normalized.encode(), usedforsecurity=False).hexdigest() if hash in content_hashes: remove(p, "similar") else: content_hashes.add(hash) for platform in DIR.iterdir(): if not platform.is_dir(): continue for date in platform.iterdir(): if not date.is_dir(): continue for request in date.iterdir(): payload_file_path = request.joinpath("payload.xml") payload_dir_path = request.joinpath("payload") if payload_file_path.exists(): content = payload_file_path.read_text() if "HAC" in request.name and "ORDER_HAC_FINAL_NEG" not in content: remove(request, "simple hac") elif "HAA" in request.name and "" not in content: remove(request, "empty haa") elif "wssparam" in request.name: remove(request, "wssparam") else: rm_if_similar(payload_file_path, content) elif payload_dir_path.exists(): for file in payload_dir_path.iterdir(): content = file.read_text() rm_if_similar(file, content) if not any(payload_dir_path.iterdir()): remove(request, "empty request") elif ( request.name != "fetch" and request.name != "submit" and not payload_file_path.exists() and not payload_dir_path.exists() ): remove(request, "empty request") if not any(date.iterdir()): remove(date, "empty dir") libeufin-1.6.8/testbench/conf/0000775000175000017500000000000015236145704016456 5ustar grothoffgrothofflibeufin-1.6.8/testbench/conf/cli.conf0000664000175000017500000000133215122266731020071 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = CHF BANK_DIALECT = postfinance HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_PUBLIC_KEYS_FILE = /tmp/libeufin-test/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = /tmp/libeufin-test/client-keys.json IBAN = CH7789144474425692816 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 BIC = BIC NAME = myname [ebisync] BANK_PUBLIC_KEYS_FILE = /tmp/libeufin-test/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = /tmp/libeufin-test/client-keys.json HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck [ebisyncdb-postgres] CONFIG = postgres:///libeufinchecklibeufin-1.6.8/testbench/conf/mini.conf0000664000175000017500000000074715122266731020267 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ [nexus-ebics] CURRENCY = CHF # Bank HOST_BASE_URL = http://bank.example.com/ BANK_DIALECT = postfinance # EBICS IDs HOST_ID = mybank USER_ID = myuser PARTNER_ID = myorg # Account information IBAN = myiban BIC = mybic NAME = myname [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufincheck [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck [ebisyncdb-postgres] CONFIG = postgres:///libeufinchecklibeufin-1.6.8/testbench/conf/integration.conf0000664000175000017500000000141015110141204021622 0ustar grothoffgrothoff[libeufin-bank] CURRENCY = KUDOS BASE_URL = http://localhost:8080/ WIRE_TYPE = x-taler-bank X_TALER_BANK_PAYTO_HOSTNAME = https://bank.example.com SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes allow_conversion = YES FIAT_CURRENCY = EUR tan_sms = libeufin-tan-file.sh tan_email = libeufin-tan-fail.sh SERVE = unix UNIXPATH = /tmp/libeufin.sock [nexus-ebics] CURRENCY = EUR # Bank HOST_BASE_URL = http://bank.example.com/ BANK_DIALECT = postfinance # EBICS IDs HOST_ID = mybank USER_ID = myuser PARTNER_ID = myorg # Account information IBAN = myiban BIC = mybic NAME = myname [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufincheck [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck libeufin-1.6.8/testbench/conf/test.conf0000664000175000017500000000116215122266731020302 0ustar grothoffgrothoff[nexus-ebics] CURRENCY = CHF BANK_DIALECT = postfinance HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_PUBLIC_KEYS_FILE = /tmp/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = /tmp/client-keys.json IBAN = CH7789144474425692816 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 BIC = BIC NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck [nexus-httpd-wire-gateway-api] ENABLED = YES AUTH_METHOD = bearer TOKEN = secret-token [nexus-httpd-revenue-api] ENABLED = YES AUTH_METHOD = bearer TOKEN = secret-token [nexus-httpd-observability-api] ENABLED = YES AUTH_METHOD = nonelibeufin-1.6.8/database-versioning/0000775000175000017500000000000015236145704017477 5ustar grothoffgrothofflibeufin-1.6.8/database-versioning/libeufin-bank-0012.sql0000664000175000017500000000316615156463305023315 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0012', NULL, NULL); SET search_path TO libeufin_bank; -- Add no_amount_to_wallet for withdrawal ALTER TABLE taler_withdrawal_operations ADD COLUMN no_amount_to_wallet BOOLEAN DEFAULT false; -- Better polymorphism schema ALTER TABLE taler_exchange_incoming ADD COLUMN metadata BYTEA; UPDATE taler_exchange_incoming SET metadata=COALESCE(reserve_pub, account_pub, wad_id); ALTER TABLE taler_exchange_incoming DROP CONSTRAINT incoming_polymorphism, DROP COLUMN reserve_pub, DROP COLUMN account_pub, DROP COLUMN wad_id, ALTER COLUMN metadata SET NOT NULL, ADD CONSTRAINT polymorphism CHECK( CASE type WHEN 'wad' THEN LENGTH(metadata)=24 AND origin_exchange_url IS NOT NULL ELSE LENGTH(metadata)=32 AND origin_exchange_url IS NULL END ); CREATE UNIQUE INDEX taler_exchange_incoming_unique_reserve_pub ON taler_exchange_incoming (metadata) WHERE type = 'reserve'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0014.sql0000664000175000017500000000473015221677432023545 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2026 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0014', NULL, NULL); SET search_path TO libeufin_nexus; -- Drop unused index DROP INDEX talerable_incoming_polymorphism; -- Add outgoing transactions metadata field ALTER TABLE transfer_operations ADD COLUMN metadata TEXT; ALTER TABLE talerable_outgoing_transactions ADD COLUMN metadata TEXT; -- Replace unused wad type with new mapping type ALTER TYPE taler_incoming_type RENAME VALUE 'wad' TO 'map'; ALTER TABLE talerable_incoming_transactions ADD COLUMN authorization_pub BYTEA CHECK (LENGTH(authorization_pub)=32), ADD COLUMN authorization_sig BYTEA CHECK (LENGTH(authorization_sig)=64); CREATE TABLE prepared_transfers ( type taler_incoming_type NOT NULL, account_pub BYTEA NOT NULL CHECK (LENGTH(account_pub)=32), authorization_pub BYTEA UNIQUE NOT NULL CHECK (LENGTH(authorization_pub)=32), authorization_sig BYTEA NOT NULL CHECK (LENGTH(authorization_sig)=64), recurrent BOOLEAN NOT NULL, reference_number TEXT UNIQUE CHECK(reference_number ~ '^\d{27}$'), registered_at INT8 NOT NULL, incoming_transaction_id INT8 UNIQUE REFERENCES incoming_transactions(incoming_transaction_id) ON DELETE CASCADE ); CREATE UNIQUE INDEX prepared_transfers_unique_reserve_pub ON prepared_transfers (account_pub) WHERE type = 'reserve'; CREATE INDEX prepared_transfers_timestamp ON prepared_transfers (registered_at); CREATE TABLE pending_recurrent_incoming_transactions( incoming_transaction_id INT8 NOT NULL UNIQUE REFERENCES incoming_transactions(incoming_transaction_id) ON DELETE CASCADE, authorization_pub BYTEA NOT NULL REFERENCES prepared_transfers(authorization_pub) ); CREATE INDEX pending_recurrent_incoming_transactions_auth_pub ON pending_recurrent_incoming_transactions (authorization_pub); COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0012.sql0000664000175000017500000000162715054666752023554 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0012', NULL, NULL); SET search_path TO libeufin_nexus; ALTER TABLE initiated_outgoing_transactions ADD COLUMN awaiting_ack BOOLEAN NOT NULL DEFAULT TRUE; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0006.sql0000644000175000017500000000425614674637415023557 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0006', NULL, NULL); SET search_path TO libeufin_nexus; -- Support all taler incoming transaction types CREATE TYPE taler_incoming_type AS ENUM ('reserve' ,'kyc', 'wad'); ALTER TABLE talerable_incoming_transactions ADD type taler_incoming_type NOT NULL DEFAULT 'reserve', ADD account_pub BYTEA CHECK (LENGTH(account_pub)=32), ADD origin_exchange_url TEXT, ADD wad_id BYTEA CHECK (LENGTH(wad_id)=24), ALTER COLUMN reserve_public_key DROP NOT NULL, ADD CONSTRAINT incoming_polymorphism CHECK( CASE type WHEN 'reserve' THEN reserve_public_key IS NOT NULL AND account_pub IS NULL AND origin_exchange_url IS NULL AND wad_id IS NULL WHEN 'kyc' THEN reserve_public_key IS NULL AND account_pub IS NOT NULL AND origin_exchange_url IS NULL AND wad_id IS NULL WHEN 'wad' THEN reserve_public_key IS NULL AND account_pub IS NULL AND origin_exchange_url IS NOT NULL AND wad_id IS NOT NULL END ); ALTER TABLE talerable_incoming_transactions ALTER COLUMN type DROP DEFAULT; CREATE INDEX talerable_incoming_transactions_kyc_index ON talerable_incoming_transactions (account_pub) WHERE account_pub IS NOT NULL; COMMENT ON INDEX talerable_incoming_transactions_kyc_index IS 'for reconciling KYC transaction without bank_id'; CREATE INDEX initiated_outgoing_transactions_status_index ON initiated_outgoing_transactions (submitted); COMMENT ON INDEX initiated_outgoing_transactions_status_index IS 'for listing taler transfers by status'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0008.sql0000644000175000017500000000174414714760146023551 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0008', NULL, NULL); SET search_path TO libeufin_nexus; CREATE TABLE kv ( key TEXT NOT NULL PRIMARY KEY, value JSONB NOT NULL ); COMMENT ON TYPE kv IS 'Store key/value data that do not fit well in a traditional relational table.'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0015.sql0000664000175000017500000000653215156463305023320 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2026 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0015', NULL, NULL); SET search_path TO libeufin_bank; -- Allow withdrawal not linked to a bank account -- Store the exchange account ID instead of the payto -- Support non reserve withdrawals ALTER TABLE taler_withdrawal_operations ALTER COLUMN wallet_bank_account DROP NOT NULL, ADD COLUMN exchange_bank_account INT8 REFERENCES bank_accounts(bank_account_id) ON DELETE SET NULL, ADD COLUMN type taler_incoming_type NOT NULL DEFAULT 'reserve', DROP CONSTRAINT taler_withdrawal_operations_reserve_pub_key; UPDATE taler_withdrawal_operations SET exchange_bank_account=(SELECT bank_account_id FROM bank_accounts WHERE internal_payto=selected_exchange_payto); ALTER TABLE taler_withdrawal_operations DROP COLUMN selected_exchange_payto; CREATE UNIQUE INDEX taler_withdrawal_operations_unique_reserve_pub ON taler_withdrawal_operations (reserve_pub) WHERE type = 'reserve'; -- Add outgoing transactions metadata field ALTER TABLE transfer_operations ADD COLUMN metadata TEXT; -- Replace unused wad type with new mapping type ALTER TYPE taler_incoming_type RENAME VALUE 'wad' TO 'map'; ALTER TABLE taler_exchange_incoming ADD COLUMN authorization_pub BYTEA CHECK (LENGTH(authorization_pub)=32), ADD COLUMN authorization_sig BYTEA CHECK (LENGTH(authorization_sig)=64); CREATE TABLE prepared_transfers ( type taler_incoming_type NOT NULL, account_pub BYTEA NOT NULL CHECK (LENGTH(account_pub)=32), authorization_pub BYTEA UNIQUE NOT NULL CHECK (LENGTH(authorization_pub)=32), authorization_sig BYTEA NOT NULL CHECK (LENGTH(authorization_sig)=64), recurrent BOOLEAN NOT NULL, withdrawal_id INT8 UNIQUE REFERENCES taler_withdrawal_operations(withdrawal_id), registered_at INT8 NOT NULL, bank_transaction_id INT8 UNIQUE REFERENCES bank_account_transactions(bank_transaction_id) ON DELETE CASCADE ); CREATE UNIQUE INDEX prepared_transfers_unique_reserve_pub ON prepared_transfers (account_pub) WHERE type = 'reserve'; CREATE INDEX prepared_transfers_timestamp ON prepared_transfers (registered_at); CREATE TABLE pending_recurrent_incoming_transactions( bank_transaction_id INT8 NOT NULL UNIQUE REFERENCES bank_account_transactions(bank_transaction_id) ON DELETE CASCADE, debtor_account_id INT8 NOT NULL REFERENCES bank_accounts(bank_account_id) ON DELETE CASCADE, authorization_pub BYTEA NOT NULL REFERENCES prepared_transfers(authorization_pub) ); CREATE INDEX pending_recurrent_incoming_transactions_auth_pub ON pending_recurrent_incoming_transactions (authorization_pub); COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0007.sql0000644000175000017500000001010614707664064023544 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0007', NULL, NULL); SET search_path TO libeufin_nexus; -- Add a new submission state reusing a currently unused slot ALTER TYPE submission_state RENAME VALUE 'never_heard_back' TO 'pending'; ALTER TYPE submission_state ADD VALUE 'late_failure'; -- Batch of initiated_outgoing_transactions CREATE TABLE initiated_outgoing_batches( initiated_outgoing_batch_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE, creation_date INT8 NOT NULL, sum taler_amount NOT NULL DEFAULT (0, 0), message_id TEXT NOT NULL UNIQUE CHECK (char_length(message_id) <= 35), order_id TEXT UNIQUE, submission_date INT8, submission_counter INT4 NOT NULL DEFAULT 0, status submission_state NOT NULL DEFAULT 'unsubmitted', status_msg TEXT ); COMMENT ON COLUMN initiated_outgoing_transactions.order_id IS 'Order ID of the EBICS upload transaction, used to track EBICS order status.'; -- Add batch column to initiated_outgoing_transactions ALTER TABLE initiated_outgoing_transactions ADD COLUMN initiated_outgoing_batch_id INT8 REFERENCES initiated_outgoing_batches (initiated_outgoing_batch_id); -- Create a batch for all existing initiated_outgoing_transactions INSERT INTO initiated_outgoing_batches(creation_date, message_id, order_id, submission_date, submission_counter, status, status_msg) SELECT initiation_time, request_uid, order_id, last_submission_time, submission_counter, (CASE WHEN submitted = 'success' OR submitted = 'permanent_failure' THEN 'success' ELSE 'pending' END)::submission_state, failure_message FROM initiated_outgoing_transactions; -- Link initiated_outgoing_transactions to their initiated_outgoing_batches UPDATE initiated_outgoing_transactions SET initiated_outgoing_batch_id = ( SELECT initiated_outgoing_batch_id FROM initiated_outgoing_batches WHERE request_uid=message_id ); -- Drop now unused columns from initiated_outgoing_transactions and rename some ALTER TABLE initiated_outgoing_transactions DROP COLUMN order_id, DROP COLUMN last_submission_time, DROP COLUMN submission_counter, DROP COLUMN hidden; -- Add necessary indexes CREATE INDEX initiated_outgoing_batches_status_index ON initiated_outgoing_batches (status); COMMENT ON INDEX initiated_outgoing_batches_status_index IS 'for listing taler batch by status for a future admin UI'; CREATE INDEX initiated_outgoing_transactions_batch_index ON initiated_outgoing_transactions (initiated_outgoing_batch_id); COMMENT ON INDEX initiated_outgoing_transactions_batch_index IS 'for listing transactions in batches'; -- Renaming ALTER TABLE incoming_transactions RENAME COLUMN wire_transfer_subject TO subject; ALTER TABLE incoming_transactions RENAME COLUMN debit_payto_uri TO debit_payto; ALTER TABLE outgoing_transactions RENAME COLUMN wire_transfer_subject TO subject; ALTER TABLE outgoing_transactions RENAME COLUMN credit_payto_uri TO credit_payto; ALTER TABLE outgoing_transactions RENAME COLUMN message_id TO end_to_end_id; ALTER TABLE initiated_outgoing_transactions RENAME COLUMN wire_transfer_subject TO subject; ALTER TABLE initiated_outgoing_transactions RENAME COLUMN credit_payto_uri TO credit_payto; ALTER TABLE initiated_outgoing_transactions RENAME COLUMN submitted TO status; ALTER TABLE initiated_outgoing_transactions RENAME COLUMN failure_message TO status_msg; ALTER TABLE initiated_outgoing_transactions RENAME COLUMN request_uid TO end_to_end_id; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0011.sql0000664000175000017500000000165415074137503023311 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0011', NULL, NULL); SET search_path TO libeufin_bank; ALTER TYPE op_enum ADD VALUE 'create_token'; ALTER TABLE customers ADD COLUMN token_creation_counter INT2 NOT NULL DEFAULT 0; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0004.sql0000644000175000017500000000171014674637415023316 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0004', NULL, NULL); SET search_path TO libeufin_bank; ALTER TABLE bank_accounts ADD min_cashout taler_amount; COMMENT ON COLUMN bank_accounts.min_cashout IS 'Custom minimum cashout amount for this account'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-conversion-drop.sql0000644000175000017500000000043414674637415025153 0ustar grothoffgrothoffBEGIN; SET search_path TO libeufin_bank; DROP TRIGGER IF EXISTS cashin_link ON libeufin_nexus.talerable_incoming_transactions; DROP FUNCTION IF EXISTS cashin_link; DROP TRIGGER IF EXISTS cashout_link ON libeufin_bank.cashout_operations; DROP FUNCTION IF EXISTS cashout_link; COMMIT;libeufin-1.6.8/database-versioning/libeufin-nexus-0013.sql0000664000175000017500000000156415110141204023522 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0013', NULL, NULL); SET search_path TO libeufin_nexus; ALTER TABLE outgoing_transactions ADD COLUMN debit_fee taler_amount; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0005.sql0000644000175000017500000000161014674637415023545 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0005', NULL, NULL); SET search_path TO libeufin_nexus; CREATE TABLE pending_ebics_transactions ( tx_id TEXT NOT NULL UNIQUE PRIMARY KEY ); COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0005.sql0000644000175000017500000000254514674637415023326 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0005', NULL, NULL); SET search_path TO libeufin_bank; -- Make withdrawal amount optional and add optional suggested_amount ALTER TABLE taler_withdrawal_operations ADD suggested_amount taler_amount; ALTER TABLE taler_withdrawal_operations ALTER COLUMN amount DROP NOT NULL; -- Add description and last_access to bearer_tokens ALTER TABLE bearer_tokens ADD description TEXT; ALTER TABLE bearer_tokens ADD last_access INT8; UPDATE bearer_tokens SET last_access=creation_time; ALTER TABLE bearer_tokens ALTER COLUMN last_access SET NOT NULL; -- Add new token scope 'revenue' ALTER TYPE token_scope_enum ADD VALUE 'revenue'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0006.sql0000644000175000017500000000336414674637415023327 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0006', NULL, NULL); SET search_path TO libeufin_bank; -- Add missing index for common queries CREATE INDEX bank_accounts_public_index ON bank_accounts (bank_account_id) WHERE is_public = true; COMMENT ON INDEX bank_accounts_public_index IS 'for listing public accounts'; CREATE INDEX bank_account_transactions_index ON bank_account_transactions (bank_account_id, bank_transaction_id); COMMENT ON INDEX bank_accounts_public_index IS 'for listing bank account''s transaction'; CREATE INDEX bearer_tokens_index ON bearer_tokens USING btree (bank_customer, bearer_token_id); COMMENT ON INDEX bearer_tokens_index IS 'for listing bank customer''s bearer token'; CREATE INDEX cashout_operations_index ON cashout_operations USING btree (bank_account, cashout_id); COMMENT ON INDEX cashout_operations_index IS 'for listing bank customer''s cashout operations'; CREATE INDEX customers_deleted_index ON customers (customer_id) WHERE deleted_at IS NOT NULL; COMMENT ON INDEX customers_deleted_index IS 'for garbage collection'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0008.sql0000644000175000017500000000234614676232027023320 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0008', NULL, NULL); SET search_path TO libeufin_bank; ALTER TABLE customers RENAME COLUMN login TO username; ALTER TABLE bank_accounts RENAME internal_payto_uri TO internal_payto; ALTER TABLE bank_account_transactions RENAME debtor_payto_uri TO debtor_payto; ALTER TABLE bank_account_transactions RENAME creditor_payto_uri TO creditor_payto; ALTER TABLE bank_account_transactions DROP COLUMN account_servicer_reference, DROP COLUMN payment_information_id, DROP COLUMN end_to_end_id; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0003.sql0000644000175000017500000000252614674637415023323 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0003', NULL, NULL); SET search_path TO libeufin_bank; CREATE TABLE bank_transaction_operations (request_uid BYTEA UNIQUE CHECK (LENGTH(request_uid)=32) ,bank_transaction INT8 UNIQUE NOT NULL REFERENCES bank_account_transactions(bank_transaction_id) ON DELETE CASCADE ); COMMENT ON TABLE bank_transaction_operations IS 'Operation table for idempotent bank transactions.'; ALTER TABLE customers ADD deleted_at INT8; COMMENT ON COLUMN customers.deleted_at IS 'Indicates a deletion request, we keep the account in the database until all its transactions have been deleted for compliance.'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0004.sql0000644000175000017500000000163614674637415023554 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0004', NULL, NULL); SET search_path TO libeufin_nexus; -- TODO fix this hack in a future update ALTER TABLE incoming_transactions ALTER COLUMN bank_id DROP NOT NULL; COMMIT; libeufin-1.6.8/database-versioning/libeufin-conversion-setup.sql0000664000175000017500000000503015156463305025335 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024, 2025, 2026 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SET search_path TO libeufin_bank; DROP TRIGGER IF EXISTS cashin_link ON libeufin_nexus.talerable_incoming_transactions; DROP FUNCTION IF EXISTS cashin_link; CREATE OR REPLACE FUNCTION cashin_link() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE now_date INT8; local_amount libeufin_bank.taler_amount; local_subject TEXT; too_small BOOLEAN; balance_insufficient BOOLEAN; no_account BOOLEAN; BEGIN -- Only reserve transaction triggers cashin IF NEW.type != 'reserve' THEN RETURN NEW; END IF; SELECT (amount).val, (amount).frac, subject, execution_time INTO local_amount.val, local_amount.frac, local_subject, now_date FROM libeufin_nexus.incoming_transactions WHERE incoming_transaction_id = NEW.incoming_transaction_id; SET search_path TO libeufin_bank; SELECT out_too_small, out_balance_insufficient, out_no_account INTO too_small, balance_insufficient, no_account FROM libeufin_bank.cashin(now_date, NEW.metadata, local_amount, local_subject); SET search_path TO libeufin_nexus; -- Bounce on soft failures IF too_small THEN -- TODO bounce fees ? PERFORM bounce_incoming( NEW.incoming_transaction_id ,((local_amount).val, (local_amount).frac)::taler_amount ,libeufin_nexus.ebics_id_gen() ,now_date ,'amount too small to be converted' ); RETURN NULL; END IF; -- Error on hard failures IF no_account THEN RAISE EXCEPTION 'cashin failed: missing exchange account'; END IF; IF balance_insufficient THEN RAISE EXCEPTION 'cashin failed: admin balance insufficient'; END IF; RETURN NEW; END; $$; CREATE OR REPLACE TRIGGER cashin_link BEFORE INSERT ON libeufin_nexus.talerable_incoming_transactions FOR EACH ROW EXECUTE FUNCTION cashin_link(); COMMIT;libeufin-1.6.8/database-versioning/libeufin-bank-0013.sql0000644000175000017500000001052415037252417023306 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0013', NULL, NULL); SET search_path TO libeufin_bank; -- Remove all existing functions DO $do$ BEGIN IF EXISTS (SELECT FROM config WHERE key LIKE 'cashin_%') THEN INSERT INTO config (key, value) VALUES ('conversion_rate', jsonb_build_object( 'cashin', jsonb_build_object( 'ratio', jsonb_build_object( 'val', (SELECT value->'val' FROM config WHERE key='cashin_ratio'), 'frac', (SELECT value->'frac' FROM config WHERE key='cashin_ratio') ), 'fee', jsonb_build_object( 'val', (SELECT value->'val' FROM config WHERE key='cashin_fee'), 'frac', (SELECT value->'frac' FROM config WHERE key='cashin_fee') ), 'tiny_amount', jsonb_build_object( 'val', (SELECT value->'val' FROM config WHERE key='cashin_tiny_amount'), 'frac', (SELECT value->'frac' FROM config WHERE key='cashin_tiny_amount') ), 'min_amount', jsonb_build_object( 'val', (SELECT value->'val' FROM config WHERE key='cashin_min_amount'), 'frac', (SELECT value->'frac' FROM config WHERE key='cashin_min_amount') ), 'rounding_mode', (SELECT value->'mode' FROM config WHERE key='cashin_rounding_mode') ), 'cashout', jsonb_build_object( 'ratio', jsonb_build_object( 'val', (SELECT value->'val' FROM config WHERE key='cashout_ratio'), 'frac', (SELECT value->'frac' FROM config WHERE key='cashout_ratio') ), 'fee', jsonb_build_object( 'val', (SELECT value->'val' FROM config WHERE key='cashout_fee'), 'frac', (SELECT value->'frac' FROM config WHERE key='cashout_fee') ), 'tiny_amount', jsonb_build_object( 'val', (SELECT value->'val' FROM config WHERE key='cashout_tiny_amount'), 'frac', (SELECT value->'frac' FROM config WHERE key='cashout_tiny_amount') ), 'min_amount', jsonb_build_object( 'val', (SELECT value->'val' FROM config WHERE key='cashout_min_amount'), 'frac', (SELECT value->'frac' FROM config WHERE key='cashout_min_amount') ), 'rounding_mode', (SELECT value->'mode' FROM config WHERE key='cashout_rounding_mode') ) ) ); DELETE FROM config WHERE key LIKE 'cashin_%' OR key LIKE 'cashout_%'; END IF; END $do$; CREATE TABLE conversion_rate_classes ( conversion_rate_class_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,name TEXT NOT NULL UNIQUE ,description TEXT ,cashin_ratio taler_amount ,cashin_fee taler_amount ,cashin_min_amount taler_amount ,cashin_rounding_mode rounding_mode ,cashout_ratio taler_amount ,cashout_fee taler_amount ,cashout_min_amount taler_amount ,cashout_rounding_mode rounding_mode ); COMMENT ON TABLE conversion_rate_classes IS 'TODO'; ALTER TABLE bank_accounts ADD COLUMN conversion_rate_class_id INT4 REFERENCES conversion_rate_classes(conversion_rate_class_id); -- Migrate existing user config INSERT INTO conversion_rate_classes(name, cashout_min_amount) SELECT format('migrated min_cashout=%s.%s', (min_cashout).val, TRIM(TRAILING '0' FROM LPAD((min_cashout).frac::text, 8, '0'))), min_cashout FROM bank_accounts WHERE min_cashout IS NOT NULL GROUP BY min_cashout; UPDATE bank_accounts SET conversion_rate_class_id=( SELECT conversion_rate_class_id FROM conversion_rate_classes WHERE cashout_min_amount=min_cashout ) WHERE min_cashout IS NOT NULL; ALTER TABLE bank_accounts DROP COLUMN min_cashout; CREATE INDEX accounts_conversion_rate_class_id ON bank_accounts (conversion_rate_class_id); COMMENT ON INDEX accounts_conversion_rate_class_id IS 'link accounts to their conversion rate class'; COMMIT; libeufin-1.6.8/database-versioning/versioning.sql0000644000175000017500000002675614674637415022433 0ustar grothoffgrothoff-- LICENSE AND COPYRIGHT -- -- Copyright (C) 2010 Hubert depesz Lubaczewski -- -- This program is distributed under the (Revised) BSD License: -- L -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions -- are met: -- -- * Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- -- * Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in the -- documentation and/or other materials provided with the distribution. -- -- * Neither the name of Hubert depesz Lubaczewski's Organization -- nor the names of its contributors may be used to endorse or -- promote products derived from this software without specific -- prior written permission. -- -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- -- Code origin: https://gitlab.com/depesz/Versioning/blob/master/install.versioning.sql -- -- -- # NAME -- -- **Versioning** - simplistic take on tracking and applying changes to databases. -- -- # DESCRIPTION -- -- This project strives to provide simple way to manage changes to -- database. -- -- Instead of making changes on development server, then finding -- differences between production and development, deciding which ones -- should be installed on production, and finding a way to install them - -- you start with writing diffs themselves! -- -- # INSTALLATION -- -- To install versioning simply run install.versioning.sql in your database -- (all of them: production, stage, test, devel, ...). -- -- # USAGE -- -- In your files with patches to database, put whole logic in single -- transaction, and use \_v.\* functions - usually \_v.register_patch() at -- least to make sure everything is OK. -- -- For example. Let's assume you have patch files: -- -- ## 0001.sql: -- -- ``` -- create table users (id serial primary key, username text); -- ``` -- -- ## 0002.sql: -- -- ``` -- insert into users (username) values ('depesz'); -- ``` -- To change it to use versioning you would change the files, to this -- state: -- -- 0000.sql: -- -- ``` -- BEGIN; -- select _v.register_patch('000-base', NULL, NULL); -- create table users (id serial primary key, username text); -- COMMIT; -- ``` -- -- ## 0002.sql: -- -- ``` -- BEGIN; -- select _v.register_patch('001-users', ARRAY['000-base'], NULL); -- insert into users (username) values ('depesz'); -- COMMIT; -- ``` -- -- This will make sure that patch 001-users can only be applied after -- 000-base. -- -- # AVAILABLE FUNCTIONS -- -- ## \_v.register_patch( TEXT ) -- -- Registers named patch, or dies if it is already registered. -- -- Returns integer which is id of patch in \_v.patches table - only if it -- succeeded. -- -- ## \_v.register_patch( TEXT, TEXT[] ) -- -- Same as \_v.register_patch( TEXT ), but checks is all given patches (given as -- array in second argument) are already registered. -- -- ## \_v.register_patch( TEXT, TEXT[], TEXT[] ) -- -- Same as \_v.register_patch( TEXT, TEXT[] ), but also checks if there are no conflicts with preexisting patches. -- -- Third argument is array of names of patches that conflict with current one. So -- if any of them is installed - register_patch will error out. -- -- ## \_v.unregister_patch( TEXT ) -- -- Removes information about given patch from the versioning data. -- -- It doesn't remove objects that were created by this patch - just removes -- metainformation. -- -- ## \_v.assert_user_is_superuser() -- -- Make sure that current patch is being loaded by superuser. -- -- If it's not - it will raise exception, and break transaction. -- -- ## \_v.assert_user_is_not_superuser() -- -- Make sure that current patch is not being loaded by superuser. -- -- If it is - it will raise exception, and break transaction. -- -- ## \_v.assert_user_is_one_of(TEXT, TEXT, ... ) -- -- Make sure that current patch is being loaded by one of listed users. -- -- If ```current_user``` is not listed as one of arguments - function will raise -- exception and break the transaction. BEGIN; -- This file adds versioning support to database it will be loaded to. -- It requires that PL/pgSQL is already loaded - will raise exception otherwise. -- All versioning "stuff" (tables, functions) is in "_v" schema. -- All functions are defined as 'RETURNS SETOF INT4' to be able to make them to RETURN literally nothing (0 rows). -- >> RETURNS VOID<< IS similar, but it still outputs "empty line" in psql when calling CREATE SCHEMA IF NOT EXISTS _v; COMMENT ON SCHEMA _v IS 'Schema for versioning data and functionality.'; CREATE TABLE IF NOT EXISTS _v.patches ( patch_name TEXT PRIMARY KEY, applied_tsz TIMESTAMPTZ NOT NULL DEFAULT now(), applied_by TEXT NOT NULL, requires TEXT[], conflicts TEXT[] ); COMMENT ON TABLE _v.patches IS 'Contains information about what patches are currently applied on database.'; COMMENT ON COLUMN _v.patches.patch_name IS 'Name of patch, has to be unique for every patch.'; COMMENT ON COLUMN _v.patches.applied_tsz IS 'When the patch was applied.'; COMMENT ON COLUMN _v.patches.applied_by IS 'Who applied this patch (PostgreSQL username)'; COMMENT ON COLUMN _v.patches.requires IS 'List of patches that are required for given patch.'; COMMENT ON COLUMN _v.patches.conflicts IS 'List of patches that conflict with given patch.'; CREATE OR REPLACE FUNCTION _v.register_patch( IN in_patch_name TEXT, IN in_requirements TEXT[], in_conflicts TEXT[], OUT versioning INT4 ) RETURNS setof INT4 AS $$ DECLARE t_text TEXT; t_text_a TEXT[]; i INT4; BEGIN -- Thanks to this we know only one patch will be applied at a time LOCK TABLE _v.patches IN EXCLUSIVE MODE; SELECT patch_name INTO t_text FROM _v.patches WHERE patch_name = in_patch_name; IF FOUND THEN RAISE EXCEPTION 'Patch % is already applied!', in_patch_name; END IF; t_text_a := ARRAY( SELECT patch_name FROM _v.patches WHERE patch_name = any( in_conflicts ) ); IF array_upper( t_text_a, 1 ) IS NOT NULL THEN RAISE EXCEPTION 'Versioning patches conflict. Conflicting patche(s) installed: %.', array_to_string( t_text_a, ', ' ); END IF; IF array_upper( in_requirements, 1 ) IS NOT NULL THEN t_text_a := '{}'; FOR i IN array_lower( in_requirements, 1 ) .. array_upper( in_requirements, 1 ) LOOP SELECT patch_name INTO t_text FROM _v.patches WHERE patch_name = in_requirements[i]; IF NOT FOUND THEN t_text_a := t_text_a || in_requirements[i]; END IF; END LOOP; IF array_upper( t_text_a, 1 ) IS NOT NULL THEN RAISE EXCEPTION 'Missing prerequisite(s): %.', array_to_string( t_text_a, ', ' ); END IF; END IF; INSERT INTO _v.patches (patch_name, applied_tsz, applied_by, requires, conflicts ) VALUES ( in_patch_name, now(), current_user, coalesce( in_requirements, '{}' ), coalesce( in_conflicts, '{}' ) ); RETURN; END; $$ language plpgsql; COMMENT ON FUNCTION _v.register_patch( TEXT, TEXT[], TEXT[] ) IS 'Function to register patches in database. Raises exception if there are conflicts, prerequisites are not installed or the migration has already been installed.'; CREATE OR REPLACE FUNCTION _v.register_patch( TEXT, TEXT[] ) RETURNS setof INT4 AS $$ SELECT _v.register_patch( $1, $2, NULL ); $$ language sql; COMMENT ON FUNCTION _v.register_patch( TEXT, TEXT[] ) IS 'Wrapper to allow registration of patches without conflicts.'; CREATE OR REPLACE FUNCTION _v.register_patch( TEXT ) RETURNS setof INT4 AS $$ SELECT _v.register_patch( $1, NULL, NULL ); $$ language sql; COMMENT ON FUNCTION _v.register_patch( TEXT ) IS 'Wrapper to allow registration of patches without requirements and conflicts.'; CREATE OR REPLACE FUNCTION _v.unregister_patch( IN in_patch_name TEXT, OUT versioning INT4 ) RETURNS setof INT4 AS $$ DECLARE i INT4; t_text_a TEXT[]; BEGIN -- Thanks to this we know only one patch will be applied at a time LOCK TABLE _v.patches IN EXCLUSIVE MODE; t_text_a := ARRAY( SELECT patch_name FROM _v.patches WHERE in_patch_name = ANY( requires ) ); IF array_upper( t_text_a, 1 ) IS NOT NULL THEN RAISE EXCEPTION 'Cannot uninstall %, as it is required by: %.', in_patch_name, array_to_string( t_text_a, ', ' ); END IF; DELETE FROM _v.patches WHERE patch_name = in_patch_name; GET DIAGNOSTICS i = ROW_COUNT; IF i < 1 THEN RAISE EXCEPTION 'Patch % is not installed, so it can''t be uninstalled!', in_patch_name; END IF; RETURN; END; $$ language plpgsql; COMMENT ON FUNCTION _v.unregister_patch( TEXT ) IS 'Function to unregister patches in database. Dies if the patch is not registered, or if unregistering it would break dependencies.'; CREATE OR REPLACE FUNCTION _v.assert_patch_is_applied( IN in_patch_name TEXT ) RETURNS TEXT as $$ DECLARE t_text TEXT; BEGIN SELECT patch_name INTO t_text FROM _v.patches WHERE patch_name = in_patch_name; IF NOT FOUND THEN RAISE EXCEPTION 'Patch % is not applied!', in_patch_name; END IF; RETURN format('Patch %s is applied.', in_patch_name); END; $$ language plpgsql; COMMENT ON FUNCTION _v.assert_patch_is_applied( TEXT ) IS 'Function that can be used to make sure that patch has been applied.'; CREATE OR REPLACE FUNCTION _v.assert_user_is_superuser() RETURNS TEXT as $$ DECLARE v_super bool; BEGIN SELECT usesuper INTO v_super FROM pg_user WHERE usename = current_user; IF v_super THEN RETURN 'assert_user_is_superuser: OK'; END IF; RAISE EXCEPTION 'Current user is not superuser - cannot continue.'; END; $$ language plpgsql; COMMENT ON FUNCTION _v.assert_user_is_superuser() IS 'Function that can be used to make sure that patch is being applied using superuser account.'; CREATE OR REPLACE FUNCTION _v.assert_user_is_not_superuser() RETURNS TEXT as $$ DECLARE v_super bool; BEGIN SELECT usesuper INTO v_super FROM pg_user WHERE usename = current_user; IF v_super THEN RAISE EXCEPTION 'Current user is superuser - cannot continue.'; END IF; RETURN 'assert_user_is_not_superuser: OK'; END; $$ language plpgsql; COMMENT ON FUNCTION _v.assert_user_is_not_superuser() IS 'Function that can be used to make sure that patch is being applied using normal (not superuser) account.'; CREATE OR REPLACE FUNCTION _v.assert_user_is_one_of(VARIADIC p_acceptable_users TEXT[] ) RETURNS TEXT as $$ DECLARE BEGIN IF current_user = any( p_acceptable_users ) THEN RETURN 'assert_user_is_one_of: OK'; END IF; RAISE EXCEPTION 'User is not one of: % - cannot continue.', p_acceptable_users; END; $$ language plpgsql; COMMENT ON FUNCTION _v.assert_user_is_one_of(TEXT[]) IS 'Function that can be used to make sure that patch is being applied by one of defined users.'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-ebisync-0001.sql0000664000175000017500000000233315122266731024024 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-ebisync-0001', NULL, NULL); CREATE SCHEMA libeufin_ebisync; SET search_path TO libeufin_ebisync; CREATE TABLE kv ( key TEXT NOT NULL PRIMARY KEY, value JSONB NOT NULL ); COMMENT ON TYPE kv IS 'Store key/value data that do not fit well in a traditional relational table.'; CREATE TABLE pending_ebics_transactions ( tx_id TEXT NOT NULL UNIQUE PRIMARY KEY ); COMMENT ON TYPE pending_ebics_transactions IS 'Store pending EBICS transactions ids to cleanly close them on failure.'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0002.sql0000644000175000017500000000203414674637415023543 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0002', NULL, NULL); SET search_path TO libeufin_nexus; -- Add order ID ALTER TABLE initiated_outgoing_transactions ADD order_id TEXT NULL UNIQUE; COMMENT ON COLUMN initiated_outgoing_transactions.order_id IS 'Order ID of the EBICS upload transaction, used to track EBICS order status.'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0001.sql0000644000175000017500000001103014674637415023536 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2023 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0001', NULL, NULL); CREATE SCHEMA libeufin_nexus; SET search_path TO libeufin_nexus; CREATE TYPE taler_amount AS (val INT8, frac INT4); COMMENT ON TYPE taler_amount IS 'Stores an amount, fraction is in units of 1/100000000 of the base value'; CREATE TYPE submission_state AS ENUM ('unsubmitted' ,'transient_failure' ,'permanent_failure' ,'success' ,'never_heard_back' ); COMMENT ON TYPE submission_state IS 'expresses the state of an initiated outgoing transaction, where unsubmitted is the default. transient_failure suggests that the submission should be retried, in contrast to the permanent_failure state. success means that the submission itself was successful, but in no way means that the bank will fulfill the request. That must be asked via camt.5x or pain.002. never_heard_back is a fallback state, in case one successful submission did never get confirmed via camt.5x or pain.002.'; CREATE TABLE incoming_transactions (incoming_transaction_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,amount taler_amount NOT NULL ,wire_transfer_subject TEXT NOT NULL ,execution_time INT8 NOT NULL ,debit_payto_uri TEXT NOT NULL ,bank_id TEXT NOT NULL UNIQUE ); COMMENT ON COLUMN incoming_transactions.bank_id IS 'ISO20022 AccountServicerReference'; CREATE TABLE talerable_incoming_transactions (incoming_transaction_id INT8 NOT NULL UNIQUE REFERENCES incoming_transactions(incoming_transaction_id) ON DELETE CASCADE ,reserve_public_key BYTEA NOT NULL UNIQUE CHECK (LENGTH(reserve_public_key)=32) ); CREATE TABLE outgoing_transactions (outgoing_transaction_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,amount taler_amount NOT NULL ,wire_transfer_subject TEXT ,execution_time INT8 NOT NULL ,credit_payto_uri TEXT ,message_id TEXT NOT NULL UNIQUE ); COMMENT ON COLUMN outgoing_transactions.message_id IS 'ISO20022 MessageIdentification'; CREATE TABLE initiated_outgoing_transactions (initiated_outgoing_transaction_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,amount taler_amount NOT NULL ,wire_transfer_subject TEXT NOT NULL ,initiation_time INT8 NOT NULL ,last_submission_time INT8 ,submission_counter INT NOT NULL DEFAULT 0 ,credit_payto_uri TEXT NOT NULL ,outgoing_transaction_id INT8 UNIQUE REFERENCES outgoing_transactions (outgoing_transaction_id) ,submitted submission_state DEFAULT 'unsubmitted' ,hidden BOOL DEFAULT FALSE -- FIXME: explain this. ,request_uid TEXT NOT NULL UNIQUE CHECK (char_length(request_uid) <= 35) ,failure_message TEXT -- NOTE: that may mix soon failures (those found at initiation time), or late failures (those found out along a fetch operation) ); COMMENT ON COLUMN initiated_outgoing_transactions.outgoing_transaction_id IS 'Points to the bank transaction that was found via nexus-fetch. If "submitted" is false or nexus-fetch could not download this initiation, this column is expected to be NULL.'; COMMENT ON COLUMN initiated_outgoing_transactions.request_uid IS 'Unique identifier of this outgoing transaction initiation. This value could come both from a nexus-httpd client or directly generated when nexus-fetch bounces one payment. In both cases, this value will be used as a unique identifier for its related pain.001 document. For this reason, it must have at most 35 characters'; -- only active in exchange mode. CREATE TABLE bounced_transactions (incoming_transaction_id INT8 NOT NULL UNIQUE REFERENCES incoming_transactions(incoming_transaction_id) ON DELETE CASCADE ,initiated_outgoing_transaction_id INT8 NOT NULL UNIQUE REFERENCES initiated_outgoing_transactions(initiated_outgoing_transaction_id) ON DELETE CASCADE ); CREATE INDEX incoming_transaction_timestamp ON incoming_transactions (execution_time); CREATE INDEX outgoing_transaction_timestamp ON outgoing_transactions (execution_time); COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0014.sql0000664000175000017500000000417615074137503023316 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0014', NULL, NULL); SET search_path TO libeufin_bank; -- Cashout request UID need to be null for code triggered cashouts ALTER TABLE cashout_operations DROP CONSTRAINT cashout_operations_pkey; ALTER TABLE cashout_operations ADD CONSTRAINT request_uid_unique UNIQUE (request_uid); ALTER TABLE cashout_operations ALTER COLUMN request_uid DROP NOT NULL; -- Allow user accounts to have many tan channels ALTER TABLE customers ADD COLUMN tan_channels tan_enum[] NOT NULL DEFAULT ARRAY[]::tan_enum[]; UPDATE customers SET tan_channels = ARRAY[tan_channel] WHERE tan_channel IS NOT NULL; ALTER TABLE customers DROP COLUMN tan_channel; -- Only store salted body hash in challenges TRUNCATE TABLE tan_challenges; ALTER TABLE tan_challenges DROP COLUMN body, ADD COLUMN uuid UUID NOT NULL, ADD COLUMN hbody BYTEA NOT NULL CHECK (LENGTH(hbody)=64), ADD COLUMN salt BYTEA NOT NULL CHECK (LENGTH(salt)=16), ALTER COLUMN tan_channel SET NOT NULL, ALTER COLUMN tan_info SET NOT NULL; COMMENT ON COLUMN tan_challenges.hbody IS 'Salted hash of the body of the original request that triggered the challenge, to be replayed once the challenge is satisfied.'; COMMENT ON COLUMN tan_challenges.salt IS 'Salt used when hashing the original body.'; CREATE INDEX tan_challenges_uuid_index ON tan_challenges (uuid); -- Add new token scope 'observability' ALTER TYPE token_scope_enum ADD VALUE 'observability'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-drop.sql0000644000175000017500000000056514674637415023706 0ustar grothoffgrothoffBEGIN; DO $do$ DECLARE patch text; BEGIN IF EXISTS(SELECT FROM information_schema.schemata WHERE schema_name='_v') THEN FOR patch IN SELECT patch_name FROM _v.patches WHERE patch_name LIKE 'libeufin_bank_%' LOOP PERFORM _v.unregister_patch(patch); END LOOP; END IF; END $do$; DROP SCHEMA IF EXISTS libeufin_bank CASCADE; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0010.sql0000644000175000017500000000321214752333625023532 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0010', NULL, NULL); SET search_path TO libeufin_nexus; -- Better polymorphism schema ALTER TABLE talerable_incoming_transactions ADD COLUMN metadata BYTEA; UPDATE talerable_incoming_transactions SET metadata=COALESCE (reserve_public_key, account_pub, wad_id); ALTER TABLE talerable_incoming_transactions DROP CONSTRAINT incoming_polymorphism, DROP COLUMN reserve_public_key, DROP COLUMN account_pub, DROP COLUMN wad_id, ALTER COLUMN metadata SET NOT NULL, ADD CONSTRAINT polymorphism CHECK( CASE type WHEN 'wad' THEN LENGTH(metadata)=24 AND origin_exchange_url IS NOT NULL ELSE LENGTH(metadata)=32 AND origin_exchange_url IS NULL END ); CREATE INDEX talerable_incoming_polymorphism ON talerable_incoming_transactions (type, metadata); CREATE UNIQUE INDEX talerable_incoming_transactions_unique_reserve_pub ON talerable_incoming_transactions (metadata) WHERE type = 'reserve'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-procedures.sql0000664000175000017500000006327715230517567025351 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2023, 2024, 2025, 2026 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SET search_path TO public; CREATE EXTENSION IF NOT EXISTS pgcrypto; SET search_path TO libeufin_nexus; -- Remove all existing functions DO $do$ DECLARE _sql text; BEGIN SELECT INTO _sql string_agg(format('DROP %s %s CASCADE;' , CASE prokind WHEN 'f' THEN 'FUNCTION' WHEN 'p' THEN 'PROCEDURE' END , oid::regprocedure) , E'\n') FROM pg_proc WHERE pronamespace = 'libeufin_nexus'::regnamespace; IF _sql IS NOT NULL THEN EXECUTE _sql; END IF; END $do$; CREATE FUNCTION ebics_id_gen() RETURNS TEXT LANGUAGE sql AS $$ -- use gen_random_uuid to get some randomness -- remove all - characters as they are not random -- capitalise the UUID as some bank may still be case sensitive -- end with 34 random chars which is valid for EBICS (max 35 chars) SELECT upper(replace(gen_random_uuid()::text, '-', '')); $$; CREATE FUNCTION amount_normalize( IN amount taler_amount ,OUT normalized taler_amount ) LANGUAGE plpgsql IMMUTABLE AS $$ BEGIN normalized.val = amount.val + amount.frac / 100000000; IF (normalized.val > 1::INT8<<52) THEN RAISE EXCEPTION 'amount value overflowed'; END IF; normalized.frac = amount.frac % 100000000; END $$; COMMENT ON FUNCTION amount_normalize IS 'Returns the normalized amount by adding to the .val the value of (.frac / 100000000) and removing the modulus 100000000 from .frac.' 'It raises an exception when the resulting .val is larger than 2^52'; CREATE FUNCTION amount_add( IN l taler_amount ,IN r taler_amount ,OUT sum taler_amount ) LANGUAGE plpgsql IMMUTABLE AS $$ BEGIN sum = (l.val + r.val, l.frac + r.frac); SELECT normalized.val, normalized.frac INTO sum.val, sum.frac FROM amount_normalize(sum) as normalized; END $$; COMMENT ON FUNCTION amount_add IS 'Returns the normalized sum of two amounts. It raises an exception when the resulting .val is larger than 2^52'; CREATE FUNCTION register_outgoing( IN in_amount taler_amount ,IN in_debit_fee taler_amount ,IN in_subject TEXT ,IN in_execution_time INT8 ,IN in_credit_payto TEXT ,IN in_end_to_end_id TEXT ,IN in_msg_id TEXT ,IN in_acct_svcr_ref TEXT ,IN in_wtid BYTEA ,IN in_exchange_url TEXT ,IN in_metadata TEXT ,OUT out_tx_id INT8 ,OUT out_found BOOLEAN ,OUT out_initiated BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE init_id INT8; local_amount taler_amount; local_subject TEXT; local_credit_payto TEXT; local_wtid BYTEA; local_exchange_base_url TEXT; local_metadata TEXT; local_end_to_end_id TEXT; BEGIN -- Check if already registered SELECT outgoing_transaction_id, subject, credit_payto, (amount).val, (amount).frac, wtid, exchange_base_url, metadata INTO out_tx_id, local_subject, local_credit_payto, local_amount.val, local_amount.frac, local_wtid, local_exchange_base_url, local_metadata FROM outgoing_transactions LEFT JOIN talerable_outgoing_transactions USING (outgoing_transaction_id) WHERE end_to_end_id = in_end_to_end_id OR acct_svcr_ref = in_acct_svcr_ref; out_found=FOUND; IF out_found THEN -- Check metadata -- TODO take subject if missing and more detailed credit payto IF in_subject IS NOT NULL AND local_subject != in_subject THEN RAISE NOTICE 'outgoing tx %: stored subject is ''%'' got ''%''', in_end_to_end_id, local_subject, in_subject; END IF; IF in_credit_payto IS NOT NULL AND local_credit_payto != in_credit_payto THEN RAISE NOTICE 'outgoing tx %: stored subject credit payto is % got %', in_end_to_end_id, local_credit_payto, in_credit_payto; END IF; IF local_amount IS DISTINCT FROM in_amount THEN RAISE NOTICE 'outgoing tx %: stored amount is % got %', in_end_to_end_id, local_amount, in_amount; END IF; IF local_wtid IS DISTINCT FROM in_wtid THEN RAISE NOTICE 'outgoing tx %: stored wtid is % got %', in_end_to_end_id, local_wtid, in_wtid; END IF; IF local_exchange_base_url IS DISTINCT FROM in_exchange_url THEN RAISE NOTICE 'outgoing tx %: stored exchange base url is % got %', in_end_to_end_id, local_exchange_base_url, in_exchange_url; END IF; IF local_metadata IS DISTINCT FROM in_metadata THEN RAISE NOTICE 'outgoing tx %: stored metadata is % got %', in_end_to_end_id, local_metadata, in_metadata; END IF; END IF; -- Check if initiated SELECT initiated_outgoing_transaction_id, subject, credit_payto, (amount).val, (amount).frac, wtid, exchange_base_url, metadata INTO init_id, local_subject, local_credit_payto, local_amount.val, local_amount.frac, local_wtid, local_exchange_base_url, local_metadata FROM initiated_outgoing_transactions LEFT JOIN transfer_operations USING (initiated_outgoing_transaction_id) WHERE end_to_end_id = in_end_to_end_id; out_initiated=FOUND; IF out_initiated AND NOT out_found THEN -- Check metadata -- TODO take subject if missing and more detailed credit payto IF in_subject IS NOT NULL AND local_subject != in_subject THEN RAISE NOTICE 'outgoing tx %: initiated subject is ''%'' got ''%''', in_end_to_end_id, local_subject, in_subject; END IF; IF local_credit_payto IS DISTINCT FROM in_credit_payto THEN RAISE NOTICE 'outgoing tx %: initiated subject credit payto is % got %', in_end_to_end_id, local_credit_payto, in_credit_payto; END IF; IF local_amount IS DISTINCT FROM in_amount THEN RAISE NOTICE 'outgoing tx %: initiated amount is % got %', in_end_to_end_id, local_amount, in_amount; END IF; IF in_wtid IS NOT NULL AND local_wtid != in_wtid THEN RAISE NOTICE 'outgoing tx %: initiated wtid is % got %', in_end_to_end_id, local_wtid, in_wtid; END IF; IF in_exchange_url IS NOT NULL AND local_exchange_base_url != in_exchange_url THEN RAISE NOTICE 'outgoing tx %: initiated exchange base url is % got %', in_end_to_end_id, local_exchange_base_url, in_exchange_url; END IF; IF in_metadata IS NOT NULL AND local_metadata != in_metadata THEN RAISE NOTICE 'outgoing tx %: initiated metadata is % got %', in_end_to_end_id, local_metadata, in_metadata; END IF; END IF; IF NOT out_found THEN -- Store the transaction in the database INSERT INTO outgoing_transactions ( amount ,debit_fee ,subject ,execution_time ,credit_payto ,end_to_end_id ,acct_svcr_ref ) VALUES ( in_amount ,in_debit_fee ,in_subject ,in_execution_time ,in_credit_payto ,in_end_to_end_id ,in_acct_svcr_ref ) RETURNING outgoing_transaction_id INTO out_tx_id; -- Register as talerable if contains wtid IF in_wtid IS NOT NULL THEN SELECT end_to_end_id INTO local_end_to_end_id FROM talerable_outgoing_transactions JOIN outgoing_transactions USING (outgoing_transaction_id) WHERE wtid=in_wtid; IF FOUND THEN IF local_end_to_end_id != in_end_to_end_id THEN RAISE NOTICE 'wtid reuse: tx % and tx % have the same wtid %', in_end_to_end_id, local_end_to_end_id, in_wtid; END IF; ELSE INSERT INTO talerable_outgoing_transactions( outgoing_transaction_id, wtid, exchange_base_url, metadata ) VALUES ( out_tx_id, in_wtid, in_exchange_url, in_metadata ); PERFORM pg_notify('nexus_outgoing_tx', out_tx_id::text); END IF; END IF; IF out_initiated THEN -- Reconciles the related initiated transaction UPDATE initiated_outgoing_transactions SET outgoing_transaction_id = out_tx_id ,status = 'success' ,status_msg = null WHERE initiated_outgoing_transaction_id = init_id AND status != 'late_failure'; -- Reconciles the related initiated batch UPDATE initiated_outgoing_batches SET status = 'success', status_msg = null WHERE message_id = in_msg_id AND status NOT IN ('success', 'permanent_failure', 'late_failure'); END IF; END IF; END $$; COMMENT ON FUNCTION register_outgoing IS 'Register an outgoing transaction and optionally reconciles the related initiated transaction with it'; CREATE FUNCTION register_incoming( IN in_amount taler_amount ,IN in_credit_fee taler_amount ,IN in_subject TEXT ,IN in_execution_time INT8 ,IN in_debit_payto TEXT ,IN in_uetr UUID ,IN in_tx_id TEXT ,IN in_acct_svcr_ref TEXT ,IN in_type taler_incoming_type ,IN in_metadata BYTEA ,IN in_qr_reference_number TEXT -- Error status ,OUT out_reserve_pub_reuse BOOLEAN ,OUT out_mapping_reuse BOOLEAN ,OUT out_unknown_mapping BOOLEAN -- Success return ,OUT out_found BOOLEAN ,OUT out_completed BOOLEAN ,OUT out_talerable BOOLEAN ,OUT out_pending BOOLEAN ,OUT out_tx_id INT8 ,OUT out_bounce_id TEXT ) LANGUAGE plpgsql AS $$ DECLARE local_ref TEXT; local_amount taler_amount; local_subject TEXT; local_debit_payto TEXT; local_authorization_pub BYTEA; local_authorization_sig BYTEA; BEGIN IF in_credit_fee = (0, 0)::taler_amount THEN in_credit_fee = NULL; END IF; out_pending=FALSE; -- Check if already registered SELECT incoming_transaction_id, tx.subject, debit_payto, (tx.amount).val, (tx.amount).frac, metadata IS NOT NULL, end_to_end_id INTO out_tx_id, local_subject, local_debit_payto, local_amount.val, local_amount.frac, out_talerable, out_bounce_id FROM incoming_transactions AS tx LEFT JOIN talerable_incoming_transactions USING (incoming_transaction_id) LEFT JOIN bounced_transactions USING (incoming_transaction_id) LEFT JOIN initiated_outgoing_transactions USING (initiated_outgoing_transaction_id) WHERE uetr = in_uetr OR tx_id = in_tx_id OR acct_svcr_ref = in_acct_svcr_ref; out_found=FOUND; IF NOT out_found OR NOT out_talerable THEN -- Resolve mapping logic IF in_type = 'map' OR in_qr_reference_number IS NOT NULL THEN SELECT type, account_pub, authorization_pub, authorization_sig, incoming_transaction_id IS NOT NULL AND NOT recurrent, incoming_transaction_id IS NOT NULL AND recurrent INTO in_type, in_metadata, local_authorization_pub, local_authorization_sig, out_mapping_reuse, out_pending FROM prepared_transfers WHERE authorization_pub = in_metadata OR reference_number = in_qr_reference_number; out_unknown_mapping = NOT FOUND; IF out_unknown_mapping OR out_mapping_reuse THEN RETURN; END IF; END IF; -- Check reserve pub reuse out_reserve_pub_reuse=NOT out_pending AND in_type = 'reserve' AND EXISTS(SELECT FROM talerable_incoming_transactions WHERE metadata = in_metadata AND type = 'reserve'); IF out_reserve_pub_reuse THEN RETURN; END IF; END IF; IF out_found THEN local_ref=COALESCE(in_uetr::text, in_tx_id, in_acct_svcr_ref); -- Check metadata IF in_subject != local_subject THEN RAISE NOTICE 'incoming tx %: stored subject is ''%'' got ''%''', local_ref, local_subject, in_subject; END IF; IF in_debit_payto != local_debit_payto THEN RAISE NOTICE 'incoming tx %: stored subject debit payto is % got %', local_ref, local_debit_payto, in_debit_payto; END IF; IF local_amount != in_amount THEN RAISE NOTICE 'incoming tx %: stored amount is % got %', local_ref, local_amount, in_amount; END IF; UPDATE incoming_transactions SET subject=COALESCE(subject, in_subject), debit_payto=COALESCE(debit_payto, in_debit_payto), uetr=COALESCE(uetr, in_uetr), tx_id=COALESCE(tx_id, in_tx_id), acct_svcr_ref=COALESCE(acct_svcr_ref, in_acct_svcr_ref) WHERE incoming_transaction_id = out_tx_id; out_completed=local_debit_payto IS NULL AND in_debit_payto IS NOT NULL; IF out_completed THEN PERFORM pg_notify('nexus_revenue_tx', out_tx_id::text); END IF; ELSE -- Store the transaction in the database INSERT INTO incoming_transactions ( amount ,credit_fee ,subject ,execution_time ,debit_payto ,uetr ,tx_id ,acct_svcr_ref ) VALUES ( in_amount ,in_credit_fee ,in_subject ,in_execution_time ,in_debit_payto ,in_uetr ,in_tx_id ,in_acct_svcr_ref ) RETURNING incoming_transaction_id INTO out_tx_id; IF in_subject IS NOT NULL AND in_debit_payto IS NOT NULL THEN PERFORM pg_notify('nexus_revenue_tx', out_tx_id::text); END IF; out_talerable=FALSE; END IF; -- Register as talerable if not already registered as such and not already bounced IF in_type IS NOT NULL AND NOT out_talerable AND out_bounce_id IS NULL THEN If out_pending THEN -- Delay talerable registration until mapping again INSERT INTO pending_recurrent_incoming_transactions (incoming_transaction_id, authorization_pub) VALUES (out_tx_id, local_authorization_pub); ELSE UPDATE prepared_transfers SET incoming_transaction_id = out_tx_id WHERE ( incoming_transaction_id IS NULL AND account_pub = in_metadata AND type='reserve' ) OR authorization_pub = local_authorization_pub; -- We cannot use ON CONFLICT here because conversion use a trigger before insertion that isn't idempotent INSERT INTO talerable_incoming_transactions ( incoming_transaction_id ,type ,metadata ,authorization_pub ,authorization_sig ) VALUES ( out_tx_id ,in_type ,in_metadata ,local_authorization_pub ,local_authorization_sig ); PERFORM pg_notify('nexus_incoming_tx', out_tx_id::text); out_talerable=TRUE; END IF; END IF; END $$; CREATE FUNCTION register_and_bounce_incoming( IN in_amount taler_amount ,IN in_credit_fee taler_amount ,IN in_subject TEXT ,IN in_execution_time INT8 ,IN in_debit_payto TEXT ,IN in_uetr UUID ,IN in_tx_id TEXT ,IN in_acct_svcr_ref TEXT ,IN in_bounce_amount taler_amount ,IN in_now_date INT8 ,IN in_bounce_id TEXT ,IN in_cause TEXT -- Error status ,OUT out_talerable BOOLEAN -- Success return ,OUT out_found BOOLEAN ,OUT out_completed BOOLEAN ,OUT out_tx_id INT8 ,OUT out_bounce_id TEXT ) LANGUAGE plpgsql AS $$ DECLARE init_id INT8; bounce_amount taler_amount; BEGIN -- Register incoming transaction SELECT reg.out_found, reg.out_completed, reg.out_tx_id, reg.out_talerable INTO out_found, out_completed, out_tx_id, out_talerable FROM register_incoming(in_amount, in_credit_fee, in_subject, in_execution_time, in_debit_payto, in_uetr, in_tx_id, in_acct_svcr_ref, NULL, NULL, NULL) as reg; -- Cannot bounce a transaction registered as talerable IF out_talerable THEN RETURN; END IF; -- Bounce incoming transaction SELECT bounce.out_bounce_id INTO out_bounce_id FROM bounce_incoming(out_tx_id, in_bounce_amount, in_bounce_id, in_now_date, in_cause) AS bounce; END $$; CREATE FUNCTION bounce_incoming( IN in_tx_id INT8 ,IN in_bounce_amount taler_amount ,IN in_bounce_id TEXT ,IN in_now_date INT8 ,IN in_cause TEXT ,OUT out_bounce_id TEXT ) LANGUAGE plpgsql AS $$ DECLARE local_bank_id TEXT; payto_uri TEXT; init_id INT8; BEGIN -- Check if already bounced SELECT end_to_end_id INTO out_bounce_id FROM libeufin_nexus.initiated_outgoing_transactions JOIN libeufin_nexus.bounced_transactions USING (initiated_outgoing_transaction_id) WHERE incoming_transaction_id = in_tx_id; -- Else initiate the bounce transaction IF NOT FOUND THEN out_bounce_id = in_bounce_id; -- Get incoming transaction bank ID and creditor SELECT COALESCE(uetr::text, tx_id, acct_svcr_ref), debit_payto INTO local_bank_id, payto_uri FROM libeufin_nexus.incoming_transactions WHERE incoming_transaction_id = in_tx_id; -- Initiate the bounce transaction INSERT INTO libeufin_nexus.initiated_outgoing_transactions ( amount ,subject ,credit_payto ,initiation_time ,end_to_end_id ) VALUES ( in_bounce_amount ,'bounce ' || local_bank_id || ': ' || in_cause ,payto_uri ,in_now_date ,in_bounce_id ) RETURNING initiated_outgoing_transaction_id INTO init_id; -- Register the bounce INSERT INTO libeufin_nexus.bounced_transactions (incoming_transaction_id, initiated_outgoing_transaction_id) VALUES (in_tx_id, init_id); END IF; -- Delete from pending if any DELETE FROM libeufin_nexus.pending_recurrent_incoming_transactions WHERE incoming_transaction_id = in_tx_id; END$$; CREATE FUNCTION taler_transfer( IN in_request_uid BYTEA, IN in_wtid BYTEA, IN in_subject TEXT, IN in_amount taler_amount, IN in_exchange_base_url TEXT, IN in_metadata TEXT, IN in_credit_account_payto TEXT, IN in_end_to_end_id TEXT, IN in_timestamp INT8, -- Error status OUT out_request_uid_reuse BOOLEAN, OUT out_wtid_reuse BOOLEAN, -- Success return OUT out_tx_row_id INT8, OUT out_timestamp INT8 ) LANGUAGE plpgsql AS $$ BEGIN -- Check for idempotence and conflict SELECT (amount != in_amount OR credit_payto != in_credit_account_payto OR exchange_base_url != in_exchange_base_url OR metadata != in_metadata OR wtid != in_wtid) ,transfer_operations.initiated_outgoing_transaction_id, initiation_time INTO out_request_uid_reuse, out_tx_row_id, out_timestamp FROM transfer_operations JOIN initiated_outgoing_transactions ON transfer_operations.initiated_outgoing_transaction_id=initiated_outgoing_transactions.initiated_outgoing_transaction_id WHERE transfer_operations.request_uid = in_request_uid; IF FOUND THEN RETURN; END IF; out_wtid_reuse = EXISTS(SELECT FROM transfer_operations WHERE wtid = in_wtid); IF out_wtid_reuse THEN RETURN; END IF; out_timestamp=in_timestamp; -- Initiate bank transfer INSERT INTO initiated_outgoing_transactions ( amount ,subject ,credit_payto ,initiation_time ,end_to_end_id ) VALUES ( in_amount ,in_subject ,in_credit_account_payto ,in_timestamp ,in_end_to_end_id ) RETURNING initiated_outgoing_transaction_id INTO out_tx_row_id; -- Register outgoing transaction INSERT INTO transfer_operations( initiated_outgoing_transaction_id ,request_uid ,wtid ,exchange_base_url ,metadata ) VALUES ( out_tx_row_id ,in_request_uid ,in_wtid ,in_exchange_base_url ,in_metadata ); out_timestamp = in_timestamp; PERFORM pg_notify('nexus_outgoing_tx', out_tx_row_id::text); END $$; CREATE FUNCTION batch_outgoing_transactions( IN in_timestamp INT8, IN batch_ebics_id TEXT, IN require_ack BOOLEAN ) RETURNS void LANGUAGE plpgsql AS $$ DECLARE batch_id INT8; local_sum taler_amount DEFAULT (0, 0)::taler_amount; tx record; BEGIN -- Create a new batch only if some transactions are not batched IF EXISTS(SELECT FROM initiated_outgoing_transactions WHERE initiated_outgoing_batch_id IS NULL AND (NOT require_ack OR NOT awaiting_ack)) THEN -- Create batch INSERT INTO initiated_outgoing_batches (creation_date, message_id) VALUES (in_timestamp, batch_ebics_id) RETURNING initiated_outgoing_batch_id INTO batch_id; -- Link batched payment while computing the sum of amounts FOR tx IN UPDATE initiated_outgoing_transactions SET initiated_outgoing_batch_id=batch_id WHERE initiated_outgoing_batch_id IS NULL AND (NOT require_ack OR NOT awaiting_ack) RETURNING amount LOOP SELECT sum.val, sum.frac INTO local_sum.val, local_sum.frac FROM amount_add(local_sum, tx.amount) AS sum; END LOOP; -- Update the batch with the sum of amounts UPDATE initiated_outgoing_batches SET sum=local_sum WHERE initiated_outgoing_batch_id=batch_id; END IF; END $$; CREATE FUNCTION batch_status_update( IN in_message_id text, IN in_status submission_state, IN in_status_msg text, OUT out_ok BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE local_batch_id INT8; BEGIN -- Check if there is a batch for this message id SELECT initiated_outgoing_batch_id INTO local_batch_id FROM initiated_outgoing_batches WHERE message_id = in_message_id; out_ok=FOUND; IF FOUND THEN -- Update unsettled batch status UPDATE initiated_outgoing_batches SET status = in_status, status_msg = in_status_msg WHERE initiated_outgoing_batch_id = local_batch_id AND status NOT IN ('success', 'permanent_failure', 'late_failure'); -- When a batch succeed it doesn't mean that individual transaction also succeed IF in_status = 'success' THEN in_status = 'pending'; END IF; -- Update unsettled batch's transaction status UPDATE initiated_outgoing_transactions SET status = in_status, status_msg = in_status_msg WHERE initiated_outgoing_batch_id = local_batch_id AND status NOT IN ('success', 'permanent_failure', 'late_failure'); END IF; END $$; CREATE FUNCTION tx_status_update( IN in_end_to_end_id text, IN in_message_id text, IN in_status submission_state, IN in_status_msg text, OUT out_ok BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE local_status submission_state; local_tx_id INT8; BEGIN -- Check current tx status SELECT initiated_outgoing_transaction_id, status INTO local_tx_id, local_status FROM initiated_outgoing_transactions WHERE end_to_end_id = in_end_to_end_id; out_ok=FOUND; IF FOUND THEN -- Update unsettled transaction status IF in_status = 'permanent_failure' OR local_status NOT IN ('success', 'permanent_failure', 'late_failure') THEN IF in_status = 'permanent_failure' AND local_status = 'success' THEN in_status = 'late_failure'; END IF; UPDATE initiated_outgoing_transactions SET status = in_status, status_msg = in_status_msg WHERE initiated_outgoing_transaction_id = local_tx_id; END IF; -- Update unsettled batch status UPDATE initiated_outgoing_batches SET status = 'success', status_msg = NULL WHERE message_id = in_message_id AND status NOT IN ('success', 'permanent_failure', 'late_failure'); END IF; END $$; CREATE FUNCTION register_prepared_transfers ( IN in_type taler_incoming_type, IN in_account_pub BYTEA, IN in_authorization_pub BYTEA, IN in_authorization_sig BYTEA, IN in_recurrent BOOLEAN, IN in_reference_number TEXT, IN in_timestamp INT8, -- Error status OUT out_subject_reuse BOOLEAN, OUT out_reserve_pub_reuse BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE talerable_tx INT8; idempotent BOOLEAN; BEGIN -- Check idempotency SELECT type = in_type AND account_pub = in_account_pub AND recurrent = in_recurrent AND reference_number = in_reference_number INTO idempotent FROM prepared_transfers WHERE authorization_pub = in_authorization_pub; -- Check idempotency and delay garbage collection IF FOUND AND idempotent THEN UPDATE prepared_transfers SET registered_at=in_timestamp WHERE authorization_pub=in_authorization_pub; RETURN; END IF; -- Check reserve pub reuse and reference_number clash out_reserve_pub_reuse=in_type = 'reserve' AND ( EXISTS(SELECT FROM talerable_incoming_transactions WHERE metadata = in_account_pub AND type = 'reserve') OR EXISTS(SELECT FROM prepared_transfers WHERE account_pub = in_account_pub AND type = 'reserve' AND authorization_pub != in_authorization_pub) ); out_subject_reuse=EXISTS(SELECT FROM prepared_transfers WHERE authorization_pub != in_authorization_pub AND reference_number = in_reference_number); IF out_reserve_pub_reuse OR out_subject_reuse THEN RETURN; END IF; IF in_recurrent THEN -- Finalize one pending right now WITH moved_tx AS ( DELETE FROM pending_recurrent_incoming_transactions WHERE incoming_transaction_id = ( SELECT incoming_transaction_id FROM pending_recurrent_incoming_transactions JOIN incoming_transactions USING (incoming_transaction_id) WHERE authorization_pub = in_authorization_pub ORDER BY execution_time ASC LIMIT 1 ) RETURNING incoming_transaction_id ) INSERT INTO talerable_incoming_transactions (incoming_transaction_id, type, metadata, authorization_pub, authorization_sig) SELECT moved_tx.incoming_transaction_id, in_type, in_account_pub, in_authorization_pub, in_authorization_sig FROM moved_tx RETURNING incoming_transaction_id INTO talerable_tx; IF talerable_tx IS NOT NULL THEN PERFORM pg_notify('nexus_incoming_tx', talerable_tx::text); END IF; ELSE -- Bounce all pending PERFORM bounce_incoming(incoming_transaction_id, amount, ebics_id_gen(), in_timestamp, 'cancelled mapping') FROM incoming_transactions JOIN pending_recurrent_incoming_transactions USING (incoming_transaction_id) WHERE authorization_pub = in_authorization_pub; END IF; -- Upsert registration INSERT INTO prepared_transfers ( type, account_pub, authorization_pub, authorization_sig, recurrent, reference_number, registered_at, incoming_transaction_id ) VALUES ( in_type, in_account_pub, in_authorization_pub, in_authorization_sig, in_recurrent, in_reference_number, in_timestamp, talerable_tx ) ON CONFLICT (authorization_pub) DO UPDATE SET type = EXCLUDED.type, account_pub = EXCLUDED.account_pub, recurrent = EXCLUDED.recurrent, reference_number = EXCLUDED.reference_number, registered_at = EXCLUDED.registered_at, incoming_transaction_id = EXCLUDED.incoming_transaction_id, authorization_sig = EXCLUDED.authorization_sig; END $$; CREATE FUNCTION delete_prepared_transfers ( IN in_authorization_pub BYTEA, IN in_timestamp INT8, OUT out_found BOOLEAN ) LANGUAGE plpgsql AS $$ BEGIN -- Bounce all pending PERFORM bounce_incoming(incoming_transaction_id, amount, ebics_id_gen(), in_timestamp, 'cancelled mapping') FROM incoming_transactions JOIN pending_recurrent_incoming_transactions USING (incoming_transaction_id) WHERE authorization_pub = in_authorization_pub; -- Delete registration DELETE FROM prepared_transfers WHERE authorization_pub = in_authorization_pub; out_found = FOUND; END $$;libeufin-1.6.8/database-versioning/libeufin-bank-0001.sql0000644000175000017500000002650414674637415023323 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2023 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0001', NULL, NULL); CREATE SCHEMA libeufin_bank; SET search_path TO libeufin_bank; CREATE TYPE taler_amount AS (val INT8 ,frac INT4); COMMENT ON TYPE taler_amount IS 'Stores an amount, fraction is in units of 1/100000000 of the base value'; -- Indicates whether a transaction is incoming or outgoing. CREATE TYPE direction_enum AS ENUM ('credit', 'debit'); CREATE TYPE token_scope_enum AS ENUM ('readonly', 'readwrite'); CREATE TYPE tan_enum AS ENUM ('sms', 'email'); CREATE TYPE cashout_status_enum AS ENUM ('pending', 'confirmed'); CREATE TYPE subscriber_key_state_enum AS ENUM ('new', 'invalid', 'confirmed'); CREATE TYPE subscriber_state_enum AS ENUM ('new', 'confirmed'); CREATE TYPE stat_timeframe_enum AS ENUM ('hour', 'day', 'month', 'year'); CREATE TYPE rounding_mode AS ENUM ('zero', 'up', 'nearest'); -- FIXME: comments on types (see exchange for example)! -- start of: bank accounts CREATE TABLE customers (customer_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,login TEXT NOT NULL UNIQUE ,password_hash TEXT NOT NULL ,name TEXT ,email TEXT ,phone TEXT ,cashout_payto TEXT ); COMMENT ON COLUMN customers.cashout_payto 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.'; CREATE TABLE bank_accounts (bank_account_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,internal_payto_uri TEXT NOT NULL UNIQUE ,owning_customer_id INT8 NOT NULL UNIQUE -- UNIQUE enforces 1-1 map with customers REFERENCES customers(customer_id) ON DELETE CASCADE ,is_public BOOLEAN DEFAULT FALSE NOT NULL -- privacy by default ,is_taler_exchange BOOLEAN DEFAULT FALSE NOT NULL ,balance taler_amount DEFAULT (0, 0) ,max_debt taler_amount DEFAULT (0, 0) ,has_debt BOOLEAN NOT NULL DEFAULT FALSE ); COMMENT ON TABLE bank_accounts IS 'In Sandbox, usernames (AKA logins) are different entities respect to bank accounts (in contrast to what the Python bank did). The idea was to provide multiple bank accounts to one user. Nonetheless, for simplicity the current version enforces one bank account for one user, and additionally the bank account label matches always the login.'; COMMENT ON COLUMN bank_accounts.has_debt IS 'When true, the balance is negative'; COMMENT ON COLUMN bank_accounts.is_public IS 'Indicates whether the bank account history can be publicly shared'; COMMENT ON COLUMN bank_accounts.owning_customer_id IS 'Login that owns the bank account'; CREATE TABLE bearer_tokens (bearer_token_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,content BYTEA NOT NULL UNIQUE CHECK (LENGTH(content)=32) ,creation_time INT8 ,expiration_time INT8 ,scope token_scope_enum ,is_refreshable BOOLEAN ,bank_customer INT8 NOT NULL REFERENCES customers(customer_id) ON DELETE CASCADE ); COMMENT ON TABLE bearer_tokens IS 'Login tokens associated with one bank customer.'; COMMENT ON COLUMN bearer_tokens.bank_customer IS 'The customer that directly created this token, or the customer that' ' created the very first token that originated all the refreshes until' ' this token was created.'; CREATE TABLE iban_history (iban TEXT PRIMARY KEY ,creation_time INT8 NOT NULL ); COMMENT ON TABLE iban_history IS 'Track all generated iban, some might be unused.'; -- end of: bank accounts -- start of: money transactions CREATE TABLE bank_account_transactions (bank_transaction_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,creditor_payto_uri TEXT NOT NULL ,creditor_name TEXT NOT NULL ,debtor_payto_uri TEXT NOT NULL ,debtor_name TEXT NOT NULL ,subject TEXT NOT NULL ,amount taler_amount NOT NULL ,transaction_date INT8 NOT NULL ,account_servicer_reference TEXT ,payment_information_id TEXT ,end_to_end_id TEXT ,direction direction_enum NOT NULL ,bank_account_id INT8 NOT NULL REFERENCES bank_accounts(bank_account_id) ); COMMENT ON COLUMN bank_account_transactions.direction IS 'Indicates whether the transaction is incoming or outgoing for the bank account associated with this transaction.'; COMMENT ON COLUMN bank_account_transactions.payment_information_id IS 'ISO20022 specific'; COMMENT ON COLUMN bank_account_transactions.end_to_end_id IS 'ISO20022 specific'; COMMENT ON COLUMN bank_account_transactions.bank_account_id IS 'The bank account affected by this transaction.'; -- end of: money transactions -- start of: TAN challenge CREATE TABLE challenges (challenge_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE, code TEXT NOT NULL, creation_date INT8 NOT NULL, expiration_date INT8 NOT NULL, retransmission_date INT8 NOT NULL DEFAULT 0, retry_counter INT4 NOT NULL, confirmation_date INT8 DEFAULT NULL); COMMENT ON TABLE challenges IS 'Stores a code which is checked for the authentication by SMS, E-Mail..'; COMMENT ON COLUMN challenges.code IS 'The pin code which is sent to the user and verified'; COMMENT ON COLUMN challenges.creation_date IS 'Creation date of the code'; COMMENT ON COLUMN challenges.retransmission_date IS 'When did we last transmit the challenge to the user'; COMMENT ON COLUMN challenges.expiration_date IS 'When will the code expire'; COMMENT ON COLUMN challenges.retry_counter IS 'How many tries are left for this code must be > 0'; COMMENT ON COLUMN challenges.confirmation_date IS 'When was this challenge successfully verified, NULL if pending'; -- end of: TAN challenge -- start of: cashout management CREATE TABLE cashout_operations (cashout_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,request_uid BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(request_uid)=32) ,amount_debit taler_amount NOT NULL ,amount_credit taler_amount NOT NULL ,subject TEXT NOT NULL ,creation_time INT8 NOT NULL ,bank_account INT8 NOT NULL REFERENCES bank_accounts(bank_account_id) ,challenge INT8 NOT NULL UNIQUE REFERENCES challenges(challenge_id) ON DELETE SET NULL ,tan_channel TEXT NULL DEFAULT NULL ,tan_info TEXT NULL DEFAULT NULL ,aborted BOOLEAN NOT NULL DEFAULT FALSE ,local_transaction INT8 UNIQUE DEFAULT NULL REFERENCES bank_account_transactions(bank_transaction_id) ON DELETE CASCADE ); COMMENT ON COLUMN cashout_operations.bank_account IS 'Bank amount to debit during confirmation'; COMMENT ON COLUMN cashout_operations.challenge IS 'TAN challenge used to confirm the operation'; COMMENT ON COLUMN cashout_operations.local_transaction IS 'Transaction generated during confirmation'; COMMENT ON COLUMN cashout_operations.tan_channel IS 'Channel of the last successful transmission of the TAN challenge'; COMMENT ON COLUMN cashout_operations.tan_info IS 'Info of the last successful transmission of the TAN challenge'; -- end of: cashout management -- start of: Taler integration CREATE TABLE taler_exchange_outgoing (exchange_outgoing_id INT8 GENERATED BY DEFAULT AS IDENTITY ,request_uid BYTEA UNIQUE CHECK (LENGTH(request_uid)=64) ,wtid BYTEA NOT NULL UNIQUE CHECK (LENGTH(wtid)=32) ,exchange_base_url TEXT NOT NULL ,bank_transaction INT8 UNIQUE NOT NULL REFERENCES bank_account_transactions(bank_transaction_id) ON DELETE CASCADE ,creditor_account_id INT8 NOT NULL REFERENCES bank_accounts(bank_account_id) ); CREATE TABLE taler_exchange_incoming (exchange_incoming_id INT8 GENERATED BY DEFAULT AS IDENTITY ,reserve_pub BYTEA NOT NULL UNIQUE CHECK (LENGTH(reserve_pub)=32) ,bank_transaction INT8 UNIQUE NOT NULL REFERENCES bank_account_transactions(bank_transaction_id) ON DELETE CASCADE ); CREATE TABLE taler_withdrawal_operations (withdrawal_id INT8 GENERATED BY DEFAULT AS IDENTITY ,withdrawal_uuid uuid NOT NULL UNIQUE ,amount taler_amount NOT NULL ,selection_done BOOLEAN DEFAULT FALSE NOT NULL ,aborted BOOLEAN DEFAULT FALSE NOT NULL ,confirmation_done BOOLEAN DEFAULT FALSE NOT NULL ,reserve_pub BYTEA UNIQUE CHECK (LENGTH(reserve_pub)=32) ,subject TEXT ,selected_exchange_payto TEXT ,wallet_bank_account INT8 NOT NULL REFERENCES bank_accounts(bank_account_id) ON DELETE CASCADE ); COMMENT ON COLUMN taler_withdrawal_operations.selection_done IS 'Signals whether the wallet specified the exchange and gave the reserve public key'; COMMENT ON COLUMN taler_withdrawal_operations.confirmation_done IS 'Signals whether the payment to the exchange took place'; -- end of: Taler integration -- start of: Statistics CREATE TABLE bank_stats ( timeframe stat_timeframe_enum NOT NULL ,start_time timestamp NOT NULL ,taler_in_count INT8 NOT NULL DEFAULT 0 ,taler_in_volume taler_amount NOT NULL DEFAULT (0, 0) ,taler_out_count INT8 NOT NULL DEFAULT 0 ,taler_out_volume taler_amount NOT NULL DEFAULT (0, 0) ,cashin_count INT8 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 INT8 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) ); 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.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 paid by the bank to customers in the timeframe'; COMMENT ON COLUMN bank_stats.cashout_fiat_volume IS 'how much fiat currency was paid by the bank to customers in the timeframe'; -- end of: Statistics -- start of: Conversion CREATE TABLE config ( key TEXT NOT NULL PRIMARY KEY, value JSONB NOT NULL ); -- end of: Conversion COMMIT;libeufin-1.6.8/database-versioning/libeufin-bank-0002.sql0000644000175000017500000000723114674637415023320 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2023 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0002', NULL, NULL); SET search_path TO libeufin_bank; -- Forget about all pending operations DELETE FROM cashout_operations WHERE local_transaction IS NULL; -- Remove challenge logic from cashout tables ALTER TABLE cashout_operations DROP COLUMN challenge, DROP COLUMN tan_channel, DROP COLUMN tan_info, DROP COLUMN aborted, ALTER COLUMN local_transaction SET NOT NULL; DROP TABLE challenges; ALTER TABLE customers ADD tan_channel tan_enum NULL; CREATE TYPE op_enum AS ENUM ('account_reconfig', 'account_auth_reconfig', 'account_delete', 'bank_transaction', 'cashout', 'withdrawal'); CREATE TABLE tan_challenges (challenge_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,body TEXT NOT NULL ,op op_enum NOT NULL ,code TEXT NOT NULL ,creation_date INT8 NOT NULL ,expiration_date INT8 NOT NULL ,retransmission_date INT8 NOT NULL DEFAULT 0 ,confirmation_date INT8 DEFAULT NULL ,retry_counter INT4 NOT NULL ,customer INT8 NOT NULL REFERENCES customers(customer_id) ON DELETE CASCADE ,tan_channel tan_enum NULL DEFAULT NULL ,tan_info TEXT NULL DEFAULT NULL ); COMMENT ON TABLE tan_challenges IS 'Stores 2FA challenges'; COMMENT ON COLUMN tan_challenges.op IS 'The protected operation to run after the challenge'; COMMENT ON COLUMN tan_challenges.code IS 'The pin code sent to the user and verified'; COMMENT ON COLUMN tan_challenges.creation_date IS 'Creation date of the code'; COMMENT ON COLUMN tan_challenges.retransmission_date IS 'When did we last transmit the challenge to the user'; COMMENT ON COLUMN tan_challenges.expiration_date IS 'When will the code expire'; COMMENT ON COLUMN tan_challenges.confirmation_date IS 'When was this challenge successfully verified, NULL if pending'; COMMENT ON COLUMN tan_challenges.retry_counter IS 'How many tries are left for this code must be > 0'; COMMENT ON COLUMN tan_challenges.tan_channel IS 'TAN channel to use, if null use customer configured one'; COMMENT ON COLUMN tan_challenges.tan_info IS 'TAN info to use, if null use customer configured one'; CREATE INDEX tan_challenges_expiration_index ON tan_challenges (expiration_date); COMMENT ON INDEX tan_challenges_expiration_index IS 'for garbage collection'; CREATE INDEX bearer_tokens_expiration_index ON bearer_tokens (expiration_time); COMMENT ON INDEX bearer_tokens_expiration_index IS 'for garbage collection'; CREATE INDEX bank_account_transactions_expiration_index ON bank_account_transactions (transaction_date); COMMENT ON INDEX bank_account_transactions_expiration_index IS 'for garbage collection'; ALTER TABLE taler_withdrawal_operations ADD creation_date INT8 NOT NULL DEFAULT (extract(epoch from now())*1000000)::int8; ALTER TABLE taler_withdrawal_operations ALTER creation_date DROP DEFAULT; CREATE INDEX taler_withdrawal_operations_expiration_index ON taler_withdrawal_operations (creation_date); COMMENT ON INDEX taler_withdrawal_operations_expiration_index IS 'for garbage collection'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0009.sql0000644000175000017500000000156514717734207023555 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0009', NULL, NULL); SET search_path TO libeufin_nexus; ALTER TABLE incoming_transactions ADD COLUMN credit_fee taler_amount; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0009.sql0000644000175000017500000000607514707664064023331 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0009', NULL, NULL); SET search_path TO libeufin_bank; -- Add missing unique constraints ALTER TABLE taler_exchange_outgoing ADD UNIQUE (exchange_outgoing_id); ALTER TABLE taler_exchange_incoming ADD UNIQUE (exchange_incoming_id); ALTER TABLE taler_withdrawal_operations ADD UNIQUE (withdrawal_id); CREATE TYPE transfer_status AS ENUM ('permanent_failure' ,'success' ); CREATE TABLE transfer_operations ( transfer_operation_id INT8 GENERATED BY DEFAULT AS IDENTITY UNIQUE ,request_uid BYTEA UNIQUE NOT NULL CHECK (LENGTH(request_uid)=64) ,wtid BYTEA UNIQUE NOT NULL CHECK (LENGTH(wtid)=32) ,amount taler_amount NOT NULL ,exchange_base_url TEXT NOT NULL ,transfer_date INT8 NOT NULL ,exchange_outgoing_id INT8 UNIQUE REFERENCES taler_exchange_outgoing(exchange_outgoing_id) ON DELETE CASCADE ,creditor_payto TEXT NOT NULL ,status transfer_status NOT NULL ,status_msg TEXT ,exchange_id INT8 NOT NULL REFERENCES bank_accounts(bank_account_id) ON DELETE CASCADE ,CONSTRAINT transfer_operations_polymorphism CHECK( CASE status WHEN 'success' THEN exchange_outgoing_id IS NOT NULL ELSE exchange_outgoing_id IS NULL END ) ); COMMENT ON TABLE transfer_operations IS 'Operation table for idempotent wire gateway transfers with status.'; -- Migrate data from taler_exchange_outgoing to transfer_operations INSERT INTO transfer_operations(transfer_operation_id, request_uid, amount, wtid, exchange_base_url, transfer_date, exchange_outgoing_id, creditor_payto, status, status_msg, exchange_id) SELECT bank_transaction_id, request_uid, amount, wtid, exchange_base_url, transaction_date, exchange_outgoing_id, creditor_payto, 'success'::transfer_status, NULL, bank_account_id FROM taler_exchange_outgoing JOIN bank_account_transactions ON bank_transaction = bank_transaction_id; CREATE INDEX transfer_operations_status_index ON transfer_operations (status); COMMENT ON INDEX transfer_operations_status_index IS 'for listing taler transfers by status'; CREATE INDEX transfer_operations_account_index ON transfer_operations (exchange_id); COMMENT ON INDEX transfer_operations_account_index IS 'for listing taler transfers by account'; -- Remove unused columns ALTER TABLE taler_exchange_outgoing DROP COLUMN request_uid, DROP COLUMN creditor_account_id, DROP COLUMN wtid, DROP COLUMN exchange_base_url; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0003.sql0000644000175000017500000000277714674637415023562 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0003', NULL, NULL); SET search_path TO libeufin_nexus; CREATE TABLE talerable_outgoing_transactions ( outgoing_transaction_id INT8 UNIQUE NOT NULL REFERENCES outgoing_transactions(outgoing_transaction_id) ON DELETE CASCADE ,wtid BYTEA NOT NULL UNIQUE CHECK (LENGTH(wtid)=32) ,exchange_base_url TEXT NOT NULL ); CREATE TABLE transfer_operations ( initiated_outgoing_transaction_id INT8 UNIQUE NOT NULL REFERENCES initiated_outgoing_transactions(initiated_outgoing_transaction_id) ON DELETE CASCADE ,request_uid BYTEA UNIQUE NOT NULL CHECK (LENGTH(request_uid)=64) ,wtid BYTEA UNIQUE NOT NULL CHECK (LENGTH(wtid)=32) ,exchange_base_url TEXT NOT NULL ); COMMENT ON TABLE transfer_operations IS 'Operation table for idempotent wire gateway transfers.'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-0011.sql0000644000175000017500000000317414771233107023535 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-nexus-0011', NULL, NULL); SET search_path TO libeufin_nexus; ALTER TABLE outgoing_transactions ADD COLUMN acct_svcr_ref TEXT UNIQUE, ALTER COLUMN end_to_end_id DROP NOT NULL, ADD CONSTRAINT unique_id CHECK(COALESCE(end_to_end_id, acct_svcr_ref) IS NOT NULL); ALTER TABLE incoming_transactions ADD COLUMN uetr UUID UNIQUE, ADD COLUMN tx_id TEXT UNIQUE, ADD COLUMN acct_svcr_ref TEXT UNIQUE; UPDATE incoming_transactions SET uetr = CASE WHEN bank_id ~ E'^[[:xdigit:]]{8}-([[:xdigit:]]{4}-){3}[[:xdigit:]]{12}$' THEN bank_id::uuid ELSE NULL END, tx_id = CASE WHEN bank_id ~ E'^[[:xdigit:]]{8}-([[:xdigit:]]{4}-){3}[[:xdigit:]]{12}$' THEN NULL ELSE bank_id END; ALTER TABLE incoming_transactions DROP COLUMN bank_id, ALTER COLUMN subject DROP NOT NULL, ALTER COLUMN debit_payto DROP NOT NULL, ADD CONSTRAINT unique_id CHECK(COALESCE(uetr::text, tx_id, acct_svcr_ref) IS NOT NULL); COMMIT; libeufin-1.6.8/database-versioning/libeufin-ebisync-drop.sql0000664000175000017500000000207015122266731024406 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2025 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; DO $do$ DECLARE patch text; BEGIN IF EXISTS(SELECT FROM information_schema.schemata WHERE schema_name='_v') THEN FOR patch IN SELECT patch_name FROM _v.patches WHERE patch_name LIKE 'libeufin_ebisync_%' LOOP PERFORM _v.unregister_patch(patch); END LOOP; END IF; END $do$; DROP SCHEMA IF EXISTS libeufin_ebisync CASCADE; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0007.sql0000644000175000017500000000373714674637415023334 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0007', NULL, NULL); SET search_path TO libeufin_bank; -- Make customer not null -- Fill missing name with an empty string. All accounts created using the API already -- have a non-null name, so this only applies to accounts created manually with SQL. UPDATE customers SET name='' WHERE name is NULL; ALTER TABLE customers ALTER COLUMN name SET NOT NULL; -- Support all taler incoming transaction types CREATE TYPE taler_incoming_type AS ENUM ('reserve' ,'kyc', 'wad'); ALTER TABLE taler_exchange_incoming ADD type taler_incoming_type NOT NULL DEFAULT 'reserve', ADD account_pub BYTEA CHECK (LENGTH(account_pub)=32), ADD origin_exchange_url TEXT, ADD wad_id BYTEA CHECK (LENGTH(wad_id)=24), ALTER COLUMN reserve_pub DROP NOT NULL, ADD CONSTRAINT incoming_polymorphism CHECK( CASE type WHEN 'reserve' THEN reserve_pub IS NOT NULL AND account_pub IS NULL AND origin_exchange_url IS NULL AND wad_id IS NULL WHEN 'kyc' THEN reserve_pub IS NULL AND account_pub IS NOT NULL AND origin_exchange_url IS NULL AND wad_id IS NULL WHEN 'wad' THEN reserve_pub IS NULL AND account_pub IS NULL AND origin_exchange_url IS NOT NULL AND wad_id IS NOT NULL END ); ALTER TABLE taler_exchange_incoming ALTER COLUMN type DROP DEFAULT; COMMIT; libeufin-1.6.8/database-versioning/libeufin-nexus-drop.sql0000644000175000017500000000056714674637415024137 0ustar grothoffgrothoffBEGIN; DO $do$ DECLARE patch text; BEGIN IF EXISTS(SELECT FROM information_schema.schemata WHERE schema_name='_v') THEN FOR patch IN SELECT patch_name FROM _v.patches WHERE patch_name LIKE 'libeufin_nexus_%' LOOP PERFORM _v.unregister_patch(patch); END LOOP; END IF; END $do$; DROP SCHEMA IF EXISTS libeufin_nexus CASCADE; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-0010.sql0000664000175000017500000000160715074137503023306 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2024 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SELECT _v.register_patch('libeufin-bank-0010', NULL, NULL); SET search_path TO libeufin_bank; -- Add new token scope 'wiregateway' ALTER TYPE token_scope_enum ADD VALUE 'wiregateway'; COMMIT; libeufin-1.6.8/database-versioning/libeufin-bank-procedures.sql0000664000175000017500000021412615230517567025111 0ustar grothoffgrothoff-- -- This file is part of TALER -- Copyright (C) 2023, 2024, 2025, 2026 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see BEGIN; SET search_path TO libeufin_bank; -- Remove all existing functions DO $do$ DECLARE _sql text; BEGIN SELECT INTO _sql string_agg(format('DROP %s %s CASCADE;' , CASE prokind WHEN 'f' THEN 'FUNCTION' WHEN 'p' THEN 'PROCEDURE' END , oid::regprocedure) , E'\n') FROM pg_proc WHERE pronamespace = 'libeufin_bank'::regnamespace; IF _sql IS NOT NULL THEN EXECUTE _sql; END IF; END $do$; CREATE FUNCTION url_encode(input TEXT) RETURNS TEXT LANGUAGE plpgsql IMMUTABLE AS $$ DECLARE result TEXT := ''; char TEXT; BEGIN FOR i IN 1..length(input) LOOP char := substring(input FROM i FOR 1); IF char ~ '[A-Za-z0-9\-._~]' THEN result := result || char; ELSE result := result || '%' || lpad(upper(to_hex(ascii(char))), 2, '0'); END IF; END LOOP; RETURN result; END; $$; CREATE OR REPLACE FUNCTION sort_uniq(anyarray) RETURNS anyarray LANGUAGE SQL IMMUTABLE AS $$ SELECT COALESCE(array_agg(DISTINCT x ORDER BY x), $1[0:0]) FROM unnest($1) AS t(x); $$; CREATE FUNCTION amount_normalize( IN amount taler_amount ,OUT normalized taler_amount ) LANGUAGE plpgsql IMMUTABLE AS $$ BEGIN normalized.val = amount.val + amount.frac / 100000000; IF (normalized.val > 1::INT8<<52) THEN RAISE EXCEPTION 'amount value overflowed'; END IF; normalized.frac = amount.frac % 100000000; END $$; COMMENT ON FUNCTION amount_normalize IS 'Returns the normalized amount by adding to the .val the value of (.frac / 100000000) and removing the modulus 100000000 from .frac.' 'It raises an exception when the resulting .val is larger than 2^52'; CREATE FUNCTION amount_add( IN l taler_amount ,IN r taler_amount ,OUT sum taler_amount ) LANGUAGE plpgsql IMMUTABLE AS $$ BEGIN sum = (l.val + r.val, l.frac + r.frac); SELECT normalized.val, normalized.frac INTO sum.val, sum.frac FROM amount_normalize(sum) as normalized; END $$; COMMENT ON FUNCTION amount_add IS 'Returns the normalized sum of two amounts. It raises an exception when the resulting .val is larger than 2^52'; CREATE FUNCTION amount_left_minus_right( IN l taler_amount ,IN r taler_amount ,OUT diff taler_amount ,OUT ok BOOLEAN ) LANGUAGE plpgsql IMMUTABLE AS $$ BEGIN diff = l; IF diff.frac < r.frac THEN IF diff.val <= 0 THEN diff = (-1, -1); ok = FALSE; RETURN; END IF; diff.frac = diff.frac + 100000000; diff.val = diff.val - 1; END IF; IF diff.val < r.val THEN diff = (-1, -1); ok = FALSE; RETURN; END IF; diff.val = diff.val - r.val; diff.frac = diff.frac - r.frac; ok = TRUE; END $$; COMMENT ON FUNCTION amount_left_minus_right IS 'Subtracts the right amount from the left and returns the difference and TRUE, if the left amount is larger than the right, or an invalid amount and FALSE otherwise.'; CREATE FUNCTION account_balance_is_sufficient( IN in_account_id INT8, IN in_amount taler_amount, IN in_wire_transfer_fees taler_amount, IN in_min_amount taler_amount, IN in_max_amount taler_amount, OUT out_balance_insufficient BOOLEAN, OUT out_bad_amount BOOLEAN ) LANGUAGE plpgsql STABLE AS $$ DECLARE account_has_debt BOOLEAN; account_balance taler_amount; account_max_debt taler_amount; amount_with_fee taler_amount; BEGIN -- Check min and max SELECT (SELECT in_min_amount IS NOT NULL AND NOT ok FROM amount_left_minus_right(in_amount, in_min_amount)) OR (SELECT in_max_amount IS NOT NULL AND NOT ok FROM amount_left_minus_right(in_max_amount, in_amount)) INTO out_bad_amount; IF out_bad_amount THEN RETURN; END IF; -- Add fees to the amount IF in_wire_transfer_fees IS NOT NULL AND in_wire_transfer_fees != (0, 0)::taler_amount THEN SELECT sum.val, sum.frac INTO amount_with_fee.val, amount_with_fee.frac FROM amount_add(in_amount, in_wire_transfer_fees) as sum; ELSE amount_with_fee = in_amount; END IF; -- Get account info, we expect the account to exist SELECT has_debt, (balance).val, (balance).frac, (max_debt).val, (max_debt).frac INTO account_has_debt, account_balance.val, account_balance.frac, account_max_debt.val, account_max_debt.frac FROM bank_accounts WHERE bank_account_id=in_account_id; -- Check enough funds IF account_has_debt THEN -- debt case: simply checking against the max debt allowed. SELECT sum.val, sum.frac INTO account_balance.val, account_balance.frac FROM amount_add(account_balance, amount_with_fee) as sum; SELECT NOT ok INTO out_balance_insufficient FROM amount_left_minus_right(account_max_debt, account_balance); IF out_balance_insufficient THEN RETURN; END IF; ELSE -- not a debt account SELECT NOT ok INTO out_balance_insufficient FROM amount_left_minus_right(account_balance, amount_with_fee); IF out_balance_insufficient THEN -- debtor will switch to debt: determine their new negative balance. SELECT (diff).val, (diff).frac INTO account_balance.val, account_balance.frac FROM amount_left_minus_right(amount_with_fee, account_balance); SELECT NOT ok INTO out_balance_insufficient FROM amount_left_minus_right(account_max_debt, account_balance); IF out_balance_insufficient THEN RETURN; END IF; END IF; END IF; END $$; COMMENT ON FUNCTION account_balance_is_sufficient IS 'Check if an account have enough fund to transfer an amount.'; CREATE FUNCTION account_max_amount( IN in_account_id INT8, IN in_max_amount taler_amount, OUT out_max_amount taler_amount ) LANGUAGE plpgsql STABLE AS $$ BEGIN -- add balance and max_debt WITH computed AS ( SELECT CASE has_debt WHEN false THEN amount_add(balance, max_debt) ELSE (SELECT diff FROM amount_left_minus_right(max_debt, balance)) END AS amount FROM bank_accounts WHERE bank_account_id=in_account_id ) SELECT (amount).val, (amount).frac INTO out_max_amount.val, out_max_amount.frac FROM computed; IF in_max_amount.val < out_max_amount.val OR (in_max_amount.val = out_max_amount.val AND in_max_amount.frac < out_max_amount.frac) THEN out_max_amount = in_max_amount; END IF; END $$; CREATE FUNCTION create_token( IN in_username TEXT, IN in_content BYTEA, IN in_creation_time INT8, IN in_expiration_time INT8, IN in_scope token_scope_enum, IN in_refreshable BOOLEAN, IN in_description TEXT, IN in_is_tan BOOLEAN, OUT out_tan_required BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE local_customer_id INT8; BEGIN -- Get account id and check if 2FA is required SELECT customer_id, NOT in_is_tan AND cardinality(tan_channels) > 0 INTO local_customer_id, out_tan_required FROM customers JOIN bank_accounts ON owning_customer_id = customer_id WHERE username = in_username AND deleted_at IS NULL; IF out_tan_required THEN RETURN; END IF; INSERT INTO bearer_tokens ( content, creation_time, expiration_time, scope, bank_customer, is_refreshable, description, last_access ) VALUES ( in_content, in_creation_time, in_expiration_time, in_scope, local_customer_id, in_refreshable, in_description, in_creation_time ); END $$; CREATE FUNCTION bank_wire_transfer( IN in_creditor_account_id INT8, IN in_debtor_account_id INT8, IN in_subject TEXT, IN in_amount taler_amount, IN in_timestamp INT8, IN in_wire_transfer_fees taler_amount, IN in_min_amount taler_amount, IN in_max_amount taler_amount, -- Error status OUT out_balance_insufficient BOOLEAN, OUT out_bad_amount BOOLEAN, -- Success return OUT out_credit_row_id INT8, OUT out_debit_row_id INT8 ) LANGUAGE plpgsql AS $$ DECLARE has_fee BOOLEAN; amount_with_fee taler_amount; admin_account_id INT8; admin_has_debt BOOLEAN; admin_balance taler_amount; admin_payto TEXT; admin_name TEXT; debtor_has_debt BOOLEAN; debtor_balance taler_amount; debtor_max_debt taler_amount; debtor_payto TEXT; debtor_name TEXT; creditor_has_debt BOOLEAN; creditor_balance taler_amount; creditor_payto TEXT; creditor_name TEXT; tmp_balance taler_amount; BEGIN -- Check min and max SELECT (SELECT in_min_amount IS NOT NULL AND NOT ok FROM amount_left_minus_right(in_amount, in_min_amount)) OR (SELECT in_max_amount IS NOT NULL AND NOT ok FROM amount_left_minus_right(in_max_amount, in_amount)) INTO out_bad_amount; IF out_bad_amount THEN RETURN; END IF; has_fee = in_wire_transfer_fees IS NOT NULL AND in_wire_transfer_fees != (0, 0)::taler_amount; IF has_fee THEN -- Retrieve admin info SELECT bank_account_id, has_debt, (balance).val, (balance).frac, internal_payto, customers.name INTO admin_account_id, admin_has_debt, admin_balance.val, admin_balance.frac, admin_payto, admin_name FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username = 'admin'; IF NOT FOUND THEN RAISE EXCEPTION 'No admin'; END IF; END IF; -- Retrieve debtor info SELECT has_debt, (balance).val, (balance).frac, (max_debt).val, (max_debt).frac, internal_payto, customers.name INTO debtor_has_debt, debtor_balance.val, debtor_balance.frac, debtor_max_debt.val, debtor_max_debt.frac, debtor_payto, debtor_name FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE bank_account_id=in_debtor_account_id; IF NOT FOUND THEN RAISE EXCEPTION 'Unknown debtor %', in_debtor_account_id; END IF; -- Retrieve creditor info SELECT has_debt, (balance).val, (balance).frac, internal_payto, customers.name INTO creditor_has_debt, creditor_balance.val, creditor_balance.frac, creditor_payto, creditor_name FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE bank_account_id=in_creditor_account_id; IF NOT FOUND THEN RAISE EXCEPTION 'Unknown creditor %', in_creditor_account_id; END IF; -- Add fees to the amount IF has_fee AND admin_account_id != in_debtor_account_id THEN SELECT sum.val, sum.frac INTO amount_with_fee.val, amount_with_fee.frac FROM amount_add(in_amount, in_wire_transfer_fees) as sum; ELSE has_fee=false; amount_with_fee = in_amount; END IF; -- DEBTOR SIDE -- check debtor has enough funds. IF debtor_has_debt THEN -- debt case: simply checking against the max debt allowed. SELECT sum.val, sum.frac INTO debtor_balance.val, debtor_balance.frac FROM amount_add(debtor_balance, amount_with_fee) as sum; SELECT NOT ok INTO out_balance_insufficient FROM amount_left_minus_right(debtor_max_debt, debtor_balance); IF out_balance_insufficient THEN RETURN; END IF; ELSE -- not a debt account SELECT NOT ok, (diff).val, (diff).frac INTO out_balance_insufficient, tmp_balance.val, tmp_balance.frac FROM amount_left_minus_right(debtor_balance, amount_with_fee); IF NOT out_balance_insufficient THEN -- debtor has enough funds in the (positive) balance. debtor_balance=tmp_balance; ELSE -- debtor will switch to debt: determine their new negative balance. SELECT (diff).val, (diff).frac INTO debtor_balance.val, debtor_balance.frac FROM amount_left_minus_right(amount_with_fee, debtor_balance); debtor_has_debt=TRUE; SELECT NOT ok INTO out_balance_insufficient FROM amount_left_minus_right(debtor_max_debt, debtor_balance); IF out_balance_insufficient THEN RETURN; END IF; END IF; END IF; -- CREDITOR SIDE. -- Here we figure out whether the creditor would switch -- from debit to a credit situation, and adjust the balance -- accordingly. IF NOT creditor_has_debt THEN -- easy case. SELECT sum.val, sum.frac INTO creditor_balance.val, creditor_balance.frac FROM amount_add(creditor_balance, in_amount) as sum; ELSE -- creditor had debit but MIGHT switch to credit. SELECT (diff).val, (diff).frac, NOT ok INTO tmp_balance.val, tmp_balance.frac, creditor_has_debt FROM amount_left_minus_right(in_amount, creditor_balance); IF NOT creditor_has_debt THEN creditor_balance=tmp_balance; ELSE -- the amount is not enough to bring the receiver -- to a credit state, switch operators to calculate the new balance. SELECT (diff).val, (diff).frac INTO creditor_balance.val, creditor_balance.frac FROM amount_left_minus_right(creditor_balance, in_amount); END IF; END IF; -- ADMIN SIDE. -- Here we figure out whether the administrator would switch -- from debit to a credit situation, and adjust the balance -- accordingly. IF has_fee THEN IF NOT admin_has_debt THEN -- easy case. SELECT sum.val, sum.frac INTO admin_balance.val, admin_balance.frac FROM amount_add(admin_balance, in_wire_transfer_fees) as sum; ELSE -- creditor had debit but MIGHT switch to credit. SELECT (diff).val, (diff).frac, NOT ok INTO tmp_balance.val, tmp_balance.frac, admin_has_debt FROM amount_left_minus_right(in_wire_transfer_fees, admin_balance); IF NOT admin_has_debt THEN admin_balance=tmp_balance; ELSE -- the amount is not enough to bring the receiver -- to a credit state, switch operators to calculate the new balance. SELECT (diff).val, (diff).frac INTO admin_balance.val, admin_balance.frac FROM amount_left_minus_right(admin_balance, in_wire_transfer_fees); END IF; END IF; END IF; -- Lock account in order to prevent deadlocks PERFORM FROM bank_accounts WHERE bank_account_id IN (in_debtor_account_id, in_creditor_account_id, admin_account_id) ORDER BY bank_account_id FOR UPDATE; -- now actually create the bank transaction. -- debtor side: INSERT INTO bank_account_transactions ( creditor_payto ,creditor_name ,debtor_payto ,debtor_name ,subject ,amount ,transaction_date ,direction ,bank_account_id ) VALUES ( creditor_payto, creditor_name, debtor_payto, debtor_name, in_subject, in_amount, in_timestamp, 'debit', in_debtor_account_id ) RETURNING bank_transaction_id INTO out_debit_row_id; -- debtor side: INSERT INTO bank_account_transactions ( creditor_payto ,creditor_name ,debtor_payto ,debtor_name ,subject ,amount ,transaction_date ,direction ,bank_account_id ) VALUES ( creditor_payto, creditor_name, debtor_payto, debtor_name, in_subject, in_amount, in_timestamp, 'credit', in_creditor_account_id ) RETURNING bank_transaction_id INTO out_credit_row_id; -- checks and balances set up, now update bank accounts. UPDATE bank_accounts SET balance=debtor_balance, has_debt=debtor_has_debt WHERE bank_account_id=in_debtor_account_id; UPDATE bank_accounts SET balance=creditor_balance, has_debt=creditor_has_debt WHERE bank_account_id=in_creditor_account_id; -- Fee part IF has_fee THEN INSERT INTO bank_account_transactions ( creditor_payto ,creditor_name ,debtor_payto ,debtor_name ,subject ,amount ,transaction_date ,direction ,bank_account_id ) VALUES ( admin_payto, admin_name, debtor_payto, debtor_name, 'wire transfer fees for tx ' || out_debit_row_id, in_wire_transfer_fees, in_timestamp, 'debit', in_debtor_account_id ), ( admin_payto, admin_name, debtor_payto, debtor_name, 'wire transfer fees for tx ' || out_debit_row_id, in_wire_transfer_fees, in_timestamp, 'credit', admin_account_id ); UPDATE bank_accounts SET balance=admin_balance, has_debt=admin_has_debt WHERE bank_account_id=admin_account_id; END IF; -- notify new transaction PERFORM pg_notify('bank_tx', in_debtor_account_id || ' ' || in_creditor_account_id || ' ' || out_debit_row_id || ' ' || out_credit_row_id); END $$; CREATE FUNCTION account_delete( IN in_username TEXT, IN in_timestamp INT8, IN in_is_tan BOOLEAN, OUT out_not_found BOOLEAN, OUT out_balance_not_zero BOOLEAN, OUT out_tan_required BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE my_customer_id INT8; BEGIN -- check if account exists, has zero balance and if 2FA is required SELECT customer_id ,NOT in_is_tan AND cardinality(tan_channels) > 0 ,(balance).val != 0 OR (balance).frac != 0 INTO my_customer_id ,out_tan_required ,out_balance_not_zero FROM customers JOIN bank_accounts ON owning_customer_id = customer_id WHERE username = in_username AND deleted_at IS NULL; IF NOT FOUND OR out_balance_not_zero OR out_tan_required THEN out_not_found=NOT FOUND; RETURN; END IF; -- actual deletion UPDATE customers SET deleted_at = in_timestamp WHERE customer_id = my_customer_id; END $$; COMMENT ON FUNCTION account_delete IS 'Deletes an account if the balance is zero'; CREATE FUNCTION register_incoming( IN in_tx_row_id INT8, IN in_type taler_incoming_type, IN in_metadata BYTEA, IN in_account_id INT8, IN in_authorization_pub BYTEA, IN in_authorization_sig BYTEA ) RETURNS void LANGUAGE plpgsql AS $$ DECLARE local_amount taler_amount; BEGIN -- Register incoming transaction INSERT INTO taler_exchange_incoming ( metadata, bank_transaction, type, authorization_pub, authorization_sig ) VALUES ( in_metadata, in_tx_row_id, in_type, in_authorization_pub, in_authorization_sig ); -- Update stats IF in_type = 'reserve' THEN SELECT (amount).val, (amount).frac INTO local_amount.val, local_amount.frac FROM bank_account_transactions WHERE bank_transaction_id=in_tx_row_id; CALL stats_register_payment('taler_in', NULL, local_amount, null); END IF; -- Notify new incoming transaction PERFORM pg_notify('bank_incoming_tx', in_account_id || ' ' || in_tx_row_id); END $$; COMMENT ON FUNCTION register_incoming IS 'Register a bank transaction as a taler incoming transaction and announce it'; CREATE FUNCTION bounce( IN in_debtor_account_id INT8, IN in_credit_transaction_id INT8, IN in_bounce_cause TEXT, IN in_timestamp INT8 ) RETURNS void LANGUAGE plpgsql AS $$ DECLARE local_creditor_account_id INT8; local_amount taler_amount; BEGIN -- Load transaction info SELECT (amount).frac, (amount).val, bank_account_id INTO local_amount.frac, local_amount.val, local_creditor_account_id FROM bank_account_transactions WHERE bank_transaction_id=in_credit_transaction_id; -- No error can happens because an opposite transaction already took place in the same transaction PERFORM bank_wire_transfer( in_debtor_account_id, local_creditor_account_id, 'Bounce ' || in_credit_transaction_id || ': ' || in_bounce_cause, local_amount, in_timestamp, NULL, NULL, NULL ); -- Delete from pending if any DELETE FROM pending_recurrent_incoming_transactions WHERE bank_transaction_id = in_credit_transaction_id; END$$; CREATE FUNCTION make_incoming( IN in_creditor_account_id INT8, IN in_debtor_account_id INT8, IN in_subject TEXT, IN in_amount taler_amount, IN in_timestamp INT8, IN in_type taler_incoming_type, IN in_metadata BYTEA, IN in_wire_transfer_fees taler_amount, IN in_min_amount taler_amount, IN in_max_amount taler_amount, -- Error status OUT out_balance_insufficient BOOLEAN, OUT out_bad_amount BOOLEAN, OUT out_reserve_pub_reuse BOOLEAN, OUT out_mapping_reuse BOOLEAN, OUT out_unknown_mapping BOOLEAN, -- Success return OUT out_pending BOOLEAN, OUT out_credit_row_id INT8, OUT out_debit_row_id INT8 ) LANGUAGE plpgsql AS $$ DECLARE local_withdrawal_uuid UUID; local_authorization_pub BYTEA; local_authorization_sig BYTEA; BEGIN out_pending=FALSE; -- Resolve mapping logic IF in_type = 'map' THEN SELECT prepared_transfers.type, account_pub, authorization_pub, authorization_sig, withdrawal_uuid, bank_transaction_id IS NOT NULL AND NOT recurrent, bank_transaction_id IS NOT NULL AND recurrent INTO in_type, in_metadata, local_authorization_pub, local_authorization_sig, local_withdrawal_uuid, out_mapping_reuse, out_pending FROM prepared_transfers LEFT JOIN taler_withdrawal_operations USING (withdrawal_id) WHERE authorization_pub = in_metadata; out_unknown_mapping = NOT FOUND; IF out_unknown_mapping OR out_mapping_reuse THEN RETURN; END IF; END IF; -- Check reserve pub reuse out_reserve_pub_reuse=in_type = 'reserve' AND NOT out_pending AND EXISTS(SELECT FROM taler_exchange_incoming WHERE metadata = in_metadata AND type = 'reserve'); IF out_reserve_pub_reuse THEN RETURN; END IF; -- Perform bank wire transfer SELECT transfer.out_balance_insufficient, transfer.out_bad_amount, transfer.out_credit_row_id, transfer.out_debit_row_id INTO out_balance_insufficient, out_bad_amount, out_credit_row_id, out_debit_row_id FROM bank_wire_transfer( in_creditor_account_id, in_debtor_account_id, in_subject, in_amount, in_timestamp, in_wire_transfer_fees, in_min_amount, in_max_amount ) as transfer; IF out_balance_insufficient OR out_bad_amount THEN RETURN; END IF; IF out_pending THEN -- Delay talerable registration until mapping again INSERT INTO pending_recurrent_incoming_transactions (bank_transaction_id, debtor_account_id, authorization_pub) VALUES (out_credit_row_id, in_debtor_account_id, local_authorization_pub); ELSE UPDATE prepared_transfers SET bank_transaction_id = out_credit_row_id WHERE ( bank_transaction_id IS NULL AND account_pub = in_metadata AND type='reserve' ) OR authorization_pub = local_authorization_pub; IF local_withdrawal_uuid IS NOT NULL THEN PERFORM abort_taler_withdrawal(local_withdrawal_uuid); END IF; PERFORM register_incoming(out_credit_row_id, in_type, in_metadata, in_creditor_account_id, local_authorization_pub, local_authorization_sig); END IF; END $$; CREATE FUNCTION taler_transfer( IN in_request_uid BYTEA, IN in_wtid BYTEA, IN in_subject TEXT, IN in_amount taler_amount, IN in_exchange_base_url TEXT, IN in_metadata TEXT, IN in_credit_account_payto TEXT, IN in_username TEXT, IN in_timestamp INT8, IN in_conversion BOOLEAN, -- Error status OUT out_debtor_not_found BOOLEAN, OUT out_debtor_not_exchange BOOLEAN, OUT out_both_exchanges BOOLEAN, OUT out_creditor_admin BOOLEAN, OUT out_request_uid_reuse BOOLEAN, OUT out_wtid_reuse BOOLEAN, OUT out_exchange_balance_insufficient BOOLEAN, -- Success return OUT out_tx_row_id INT8, OUT out_timestamp INT8 ) LANGUAGE plpgsql AS $$ DECLARE exchange_account_id INT8; creditor_account_id INT8; account_conversion_rate_class_id INT8; creditor_name TEXT; creditor_admin BOOLEAN; credit_row_id INT8; debit_row_id INT8; outgoing_id INT8; bounce_tx INT8; bounce_amount taler_amount; BEGIN -- Check for idempotence and conflict SELECT (amount != in_amount OR creditor_payto != in_credit_account_payto OR exchange_base_url != in_exchange_base_url OR metadata != in_metadata OR wtid != in_wtid) ,transfer_operation_id, transfer_date INTO out_request_uid_reuse, out_tx_row_id, out_timestamp FROM transfer_operations WHERE request_uid = in_request_uid; IF found THEN RETURN; END IF; out_wtid_reuse = EXISTS(SELECT FROM transfer_operations WHERE wtid = in_wtid); IF out_wtid_reuse THEN RETURN; END IF; out_timestamp=in_timestamp; -- Find exchange bank account id SELECT bank_account_id, NOT is_taler_exchange, conversion_rate_class_id INTO exchange_account_id, out_debtor_not_exchange, account_conversion_rate_class_id FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username = in_username AND deleted_at IS NULL; out_debtor_not_found=NOT FOUND; IF out_debtor_not_found OR out_debtor_not_exchange THEN RETURN; END IF; -- Find creditor bank account id SELECT bank_account_id, is_taler_exchange, username = 'admin' INTO creditor_account_id, out_both_exchanges, creditor_admin FROM bank_accounts JOIN customers ON owning_customer_id=customer_id WHERE internal_payto = in_credit_account_payto; IF NOT FOUND THEN -- Register failure INSERT INTO transfer_operations ( request_uid, wtid, amount, exchange_base_url, metadata, transfer_date, exchange_outgoing_id, creditor_payto, status, status_msg, exchange_id ) VALUES ( in_request_uid, in_wtid, in_amount, in_exchange_base_url, in_metadata, in_timestamp, NULL, in_credit_account_payto, 'permanent_failure', 'Unknown account', exchange_account_id ) RETURNING transfer_operation_id INTO out_tx_row_id; RETURN; ELSIF out_both_exchanges THEN RETURN; END IF; IF creditor_admin THEN -- Check if this is a conversion bounce IF NOT in_conversion THEN out_creditor_admin=TRUE; RETURN; END IF; -- Find the bounced transaction SELECT (amount).val, (amount).frac, incoming_transaction_id INTO bounce_amount.val, bounce_amount.frac, bounce_tx FROM libeufin_nexus.incoming_transactions JOIN libeufin_nexus.talerable_incoming_transactions USING (incoming_transaction_id) WHERE metadata=in_wtid AND type='reserve'; IF NOT FOUND THEN -- Register failure INSERT INTO transfer_operations ( request_uid, wtid, amount, exchange_base_url, metadata, transfer_date, exchange_outgoing_id, creditor_payto, status, status_msg, exchange_id ) VALUES ( in_request_uid, in_wtid, in_amount, in_exchange_base_url, in_metadata, in_timestamp, NULL, in_credit_account_payto, 'permanent_failure', 'Unknown bounced transaction', exchange_account_id ) RETURNING transfer_operation_id INTO out_tx_row_id; RETURN; END IF; -- Bounce the transaction PERFORM libeufin_nexus.bounce_incoming( bounce_tx ,((bounce_amount).val, (bounce_amount).frac)::libeufin_nexus.taler_amount ,libeufin_nexus.ebics_id_gen() ,in_timestamp ,'exchange bounced' ); END IF; -- Perform bank transfer SELECT out_balance_insufficient, out_debit_row_id, out_credit_row_id INTO out_exchange_balance_insufficient, debit_row_id, credit_row_id FROM bank_wire_transfer( creditor_account_id, exchange_account_id, in_subject, in_amount, in_timestamp, NULL, NULL, NULL ); IF out_exchange_balance_insufficient THEN RETURN; END IF; -- Register outgoing transaction INSERT INTO taler_exchange_outgoing ( bank_transaction ) VALUES ( debit_row_id ) RETURNING exchange_outgoing_id INTO outgoing_id; -- Update stats CALL stats_register_payment('taler_out', NULL, in_amount, null); -- Register success INSERT INTO transfer_operations ( request_uid, wtid, amount, exchange_base_url, metadata, transfer_date, exchange_outgoing_id, creditor_payto, status, status_msg, exchange_id ) VALUES ( in_request_uid, in_wtid, in_amount, in_exchange_base_url, in_metadata, in_timestamp, outgoing_id, in_credit_account_payto, 'success', NULL, exchange_account_id ) RETURNING transfer_operation_id INTO out_tx_row_id; -- Notify new transaction PERFORM pg_notify('bank_outgoing_tx', exchange_account_id || ' ' || creditor_account_id || ' ' || debit_row_id || ' ' || credit_row_id); IF creditor_admin THEN -- Create cashout operation INSERT INTO cashout_operations ( request_uid ,amount_debit ,amount_credit ,creation_time ,bank_account ,subject ,local_transaction ) VALUES ( NULL ,in_amount ,bounce_amount ,in_timestamp ,exchange_account_id ,in_subject ,debit_row_id ); -- update stats CALL stats_register_payment('cashout', NULL, in_amount, bounce_amount); END IF; END $$; COMMENT ON FUNCTION taler_transfer IS 'Create an outgoing taler transaction and register it'; CREATE FUNCTION taler_add_incoming( IN in_key BYTEA, IN in_subject TEXT, IN in_amount taler_amount, IN in_debit_account_payto TEXT, IN in_username TEXT, IN in_timestamp INT8, IN in_type taler_incoming_type, -- Error status OUT out_creditor_not_found BOOLEAN, OUT out_creditor_not_exchange BOOLEAN, OUT out_debtor_not_found BOOLEAN, OUT out_both_exchanges BOOLEAN, OUT out_reserve_pub_reuse BOOLEAN, OUT out_mapping_reuse BOOLEAN, OUT out_unknown_mapping BOOLEAN, OUT out_debitor_balance_insufficient BOOLEAN, -- Success return OUT out_tx_row_id INT8, OUT out_pending INT8 ) LANGUAGE plpgsql AS $$ DECLARE exchange_bank_account_id INT8; sender_bank_account_id INT8; BEGIN -- Find exchange bank account id SELECT bank_account_id, NOT is_taler_exchange INTO exchange_bank_account_id, out_creditor_not_exchange FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username = in_username AND deleted_at IS NULL; IF NOT FOUND OR out_creditor_not_exchange THEN out_creditor_not_found=NOT FOUND; RETURN; END IF; -- Find sender bank account id SELECT bank_account_id, is_taler_exchange INTO sender_bank_account_id, out_both_exchanges FROM bank_accounts WHERE internal_payto = in_debit_account_payto; IF NOT FOUND OR out_both_exchanges THEN out_debtor_not_found=NOT FOUND; RETURN; END IF; -- Perform bank transfer SELECT out_balance_insufficient, out_credit_row_id, t.out_reserve_pub_reuse, t.out_mapping_reuse, t.out_unknown_mapping INTO out_debitor_balance_insufficient, out_tx_row_id, out_reserve_pub_reuse, out_mapping_reuse, out_unknown_mapping FROM make_incoming( exchange_bank_account_id, sender_bank_account_id, in_subject, in_amount, in_timestamp, in_type, in_key, NULL, NULL, NULL ) as t; END $$; COMMENT ON FUNCTION taler_add_incoming IS 'Create an incoming taler transaction and register it'; CREATE FUNCTION bank_transaction( IN in_credit_account_payto TEXT, IN in_debit_account_username TEXT, IN in_subject TEXT, IN in_amount taler_amount, IN in_timestamp INT8, IN in_is_tan BOOLEAN, IN in_request_uid BYTEA, IN in_wire_transfer_fees taler_amount, IN in_min_amount taler_amount, IN in_max_amount taler_amount, IN in_type taler_incoming_type, IN in_metadata BYTEA, IN in_bounce_cause TEXT, -- Error status OUT out_creditor_not_found BOOLEAN, OUT out_debtor_not_found BOOLEAN, OUT out_same_account BOOLEAN, OUT out_balance_insufficient BOOLEAN, OUT out_creditor_admin BOOLEAN, OUT out_tan_required BOOLEAN, OUT out_request_uid_reuse BOOLEAN, OUT out_bad_amount BOOLEAN, -- Success return OUT out_credit_bank_account_id INT8, OUT out_debit_bank_account_id INT8, OUT out_credit_row_id INT8, OUT out_debit_row_id INT8, OUT out_creditor_is_exchange BOOLEAN, OUT out_debtor_is_exchange BOOLEAN, OUT out_idempotent BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE local_reserve_pub_reuse BOOLEAN; local_mapping_reuse BOOLEAN; local_unknown_mapping BOOLEAN; BEGIN -- Find credit bank account id and check it's not admin SELECT bank_account_id, is_taler_exchange, username='admin' INTO out_credit_bank_account_id, out_creditor_is_exchange, out_creditor_admin FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE internal_payto = in_credit_account_payto AND deleted_at IS NULL; IF NOT FOUND OR out_creditor_admin THEN out_creditor_not_found=NOT FOUND; RETURN; END IF; -- Find debit bank account ID and check it's a different account and if 2FA is required SELECT bank_account_id, is_taler_exchange, out_credit_bank_account_id=bank_account_id, NOT in_is_tan AND cardinality(tan_channels) > 0 INTO out_debit_bank_account_id, out_debtor_is_exchange, out_same_account, out_tan_required FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username = in_debit_account_username AND deleted_at IS NULL; IF NOT FOUND OR out_same_account THEN out_debtor_not_found=NOT FOUND; RETURN; END IF; -- Check for idempotence and conflict IF in_request_uid IS NOT NULL THEN SELECT (amount != in_amount OR subject != in_subject OR bank_account_id != out_debit_bank_account_id), bank_transaction INTO out_request_uid_reuse, out_debit_row_id FROM bank_transaction_operations JOIN bank_account_transactions ON bank_transaction = bank_transaction_id WHERE request_uid = in_request_uid; IF found OR out_tan_required THEN out_idempotent = found AND NOT out_request_uid_reuse; RETURN; END IF; ELSIF out_tan_required THEN RETURN; END IF; -- Try to perform an incoming transfer IF out_creditor_is_exchange AND NOT out_debtor_is_exchange AND in_bounce_cause IS NULL THEN -- Perform an incoming transfer SELECT transfer.out_balance_insufficient, transfer.out_bad_amount, transfer.out_credit_row_id, transfer.out_debit_row_id, out_reserve_pub_reuse, out_mapping_reuse, out_unknown_mapping INTO out_balance_insufficient, out_bad_amount, out_credit_row_id, out_debit_row_id, local_reserve_pub_reuse, local_mapping_reuse, local_unknown_mapping FROM make_incoming( out_credit_bank_account_id, out_debit_bank_account_id, in_subject, in_amount, in_timestamp, in_type, in_metadata, in_wire_transfer_fees, in_min_amount, in_max_amount ) as transfer; IF out_balance_insufficient OR out_bad_amount THEN RETURN; END IF; IF local_reserve_pub_reuse THEN in_bounce_cause = 'reserve public key reuse'; ELSIF local_mapping_reuse THEN in_bounce_cause = 'mapping public key reuse'; ELSIF local_unknown_mapping THEN in_bounce_cause = 'unknown mapping public key'; END IF; END IF; IF out_credit_row_id IS NULL THEN -- Perform common bank transfer SELECT transfer.out_balance_insufficient, transfer.out_bad_amount, transfer.out_credit_row_id, transfer.out_debit_row_id INTO out_balance_insufficient, out_bad_amount, out_credit_row_id, out_debit_row_id FROM bank_wire_transfer( out_credit_bank_account_id, out_debit_bank_account_id, in_subject, in_amount, in_timestamp, in_wire_transfer_fees, in_min_amount, in_max_amount ) as transfer; IF out_balance_insufficient OR out_bad_amount THEN RETURN; END IF; END IF; -- Bounce if necessary IF out_creditor_is_exchange AND in_bounce_cause IS NOT NULL THEN PERFORM bounce(out_debit_bank_account_id, out_credit_row_id, in_bounce_cause, in_timestamp); END IF; -- Store operation IF in_request_uid IS NOT NULL THEN INSERT INTO bank_transaction_operations (request_uid, bank_transaction) VALUES (in_request_uid, out_debit_row_id); END IF; END $$; COMMENT ON FUNCTION bank_transaction IS 'Create a bank transaction'; CREATE FUNCTION create_taler_withdrawal( IN in_account_username TEXT, IN in_withdrawal_uuid UUID, IN in_amount taler_amount, IN in_suggested_amount taler_amount, IN in_no_amount_to_wallet BOOLEAN, IN in_timestamp INT8, IN in_wire_transfer_fees taler_amount, IN in_min_amount taler_amount, IN in_max_amount taler_amount, -- Error status OUT out_account_not_found BOOLEAN, OUT out_account_is_exchange BOOLEAN, OUT out_balance_insufficient BOOLEAN, OUT out_bad_amount BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE account_id INT8; amount_with_fee taler_amount; BEGIN IF in_account_username IS NOT NULL THEN -- Check account exists SELECT bank_account_id, is_taler_exchange INTO account_id, out_account_is_exchange FROM bank_accounts JOIN customers ON bank_accounts.owning_customer_id = customers.customer_id WHERE username=in_account_username AND deleted_at IS NULL; out_account_not_found=NOT FOUND; IF out_account_not_found OR out_account_is_exchange THEN RETURN; END IF; -- Check enough funds IF in_amount IS NOT NULL OR in_suggested_amount IS NOT NULL THEN SELECT test.out_balance_insufficient, test.out_bad_amount FROM account_balance_is_sufficient( account_id, COALESCE(in_amount, in_suggested_amount), in_wire_transfer_fees, in_min_amount, in_max_amount ) AS test INTO out_balance_insufficient, out_bad_amount; IF out_balance_insufficient OR out_bad_amount THEN RETURN; END IF; END IF; END IF; -- Create withdrawal operation INSERT INTO taler_withdrawal_operations ( withdrawal_uuid, wallet_bank_account, amount, suggested_amount, no_amount_to_wallet, type, creation_date ) VALUES ( in_withdrawal_uuid, account_id, in_amount, in_suggested_amount, in_no_amount_to_wallet, 'reserve', in_timestamp ); END $$; COMMENT ON FUNCTION create_taler_withdrawal IS 'Create a new withdrawal operation'; CREATE FUNCTION select_taler_withdrawal( IN in_withdrawal_uuid uuid, IN in_reserve_pub BYTEA, IN in_subject TEXT, IN in_selected_exchange_payto TEXT, IN in_amount taler_amount, IN in_wire_transfer_fees taler_amount, IN in_min_amount taler_amount, IN in_max_amount taler_amount, -- Error status OUT out_no_op BOOLEAN, OUT out_already_selected BOOLEAN, OUT out_reserve_pub_reuse BOOLEAN, OUT out_account_not_found BOOLEAN, OUT out_account_is_not_exchange BOOLEAN, OUT out_amount_differs BOOLEAN, OUT out_balance_insufficient BOOLEAN, OUT out_bad_amount BOOLEAN, OUT out_aborted BOOLEAN, -- Success return OUT out_status TEXT ) LANGUAGE plpgsql AS $$ DECLARE selected BOOLEAN; account_id INT8; exchange_account_id INT8; amount_with_fee taler_amount; BEGIN -- Check exchange account SELECT bank_account_id, NOT is_taler_exchange INTO exchange_account_id, out_account_is_not_exchange FROM bank_accounts WHERE internal_payto=in_selected_exchange_payto; out_account_not_found=NOT FOUND; IF out_account_not_found OR out_account_is_not_exchange THEN RETURN; END IF; -- Check for conflict and idempotence SELECT selection_done, aborted, CASE WHEN confirmation_done THEN 'confirmed' ELSE 'selected' END, selection_done AND (exchange_bank_account != exchange_account_id OR reserve_pub != in_reserve_pub OR amount != in_amount), amount != in_amount, wallet_bank_account INTO selected, out_aborted, out_status, out_already_selected, out_amount_differs, account_id FROM taler_withdrawal_operations WHERE withdrawal_uuid=in_withdrawal_uuid; out_no_op = NOT FOUND; IF out_no_op OR out_aborted OR out_already_selected OR out_amount_differs OR selected THEN RETURN; END IF; -- Check reserve_pub reuse out_reserve_pub_reuse=EXISTS(SELECT FROM taler_exchange_incoming WHERE metadata = in_reserve_pub AND type = 'reserve') OR EXISTS(SELECT FROM taler_withdrawal_operations WHERE reserve_pub = in_reserve_pub AND type = 'reserve'); IF out_reserve_pub_reuse THEN RETURN; END IF; IF in_amount IS NOT NULL THEN SELECT test.out_balance_insufficient, test.out_bad_amount FROM account_balance_is_sufficient( account_id, in_amount, in_wire_transfer_fees, in_min_amount, in_max_amount ) AS test INTO out_balance_insufficient, out_bad_amount; IF out_balance_insufficient OR out_bad_amount THEN RETURN; END IF; END IF; -- Update withdrawal operation UPDATE taler_withdrawal_operations SET exchange_bank_account=exchange_account_id, reserve_pub=in_reserve_pub, subject=in_subject, selection_done=true, amount=COALESCE(amount, in_amount) WHERE withdrawal_uuid=in_withdrawal_uuid; -- Notify status change PERFORM pg_notify('bank_withdrawal_status', in_withdrawal_uuid::text || ' selected'); END $$; COMMENT ON FUNCTION select_taler_withdrawal IS 'Set details of a withdrawal operation'; CREATE FUNCTION abort_taler_withdrawal( IN in_withdrawal_uuid uuid, OUT out_no_op BOOLEAN, OUT out_already_confirmed BOOLEAN ) LANGUAGE plpgsql AS $$ BEGIN UPDATE taler_withdrawal_operations SET aborted = NOT confirmation_done WHERE withdrawal_uuid=in_withdrawal_uuid RETURNING confirmation_done INTO out_already_confirmed; IF NOT FOUND OR out_already_confirmed THEN out_no_op=NOT FOUND; RETURN; END IF; -- Notify status change PERFORM pg_notify('bank_withdrawal_status', in_withdrawal_uuid::text || ' aborted'); END $$; COMMENT ON FUNCTION abort_taler_withdrawal IS 'Abort a withdrawal operation.'; CREATE FUNCTION confirm_taler_withdrawal( IN in_username TEXT, IN in_withdrawal_uuid uuid, IN in_timestamp INT8, IN in_is_tan BOOLEAN, IN in_wire_transfer_fees taler_amount, IN in_min_amount taler_amount, IN in_max_amount taler_amount, IN in_amount taler_amount, OUT out_no_op BOOLEAN, OUT out_balance_insufficient BOOLEAN, OUT out_reserve_pub_reuse BOOLEAN, OUT out_bad_amount BOOLEAN, OUT out_creditor_not_found BOOLEAN, OUT out_not_selected BOOLEAN, OUT out_missing_amount BOOLEAN, OUT out_amount_differs BOOLEAN, OUT out_aborted BOOLEAN, OUT out_tan_required BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE already_confirmed BOOLEAN; subject_local TEXT; reserve_pub_local BYTEA; wallet_bank_account_local INT8; amount_local taler_amount; exchange_bank_account_id INT8; local_type taler_incoming_type; BEGIN -- Load account info SELECT bank_account_id, NOT in_is_tan AND cardinality(tan_channels) > 0 INTO wallet_bank_account_local, out_tan_required FROM bank_accounts JOIN customers ON owning_customer_id=customer_id WHERE username=in_username AND deleted_at IS NULL; -- Check op exists and conflict SELECT confirmation_done, aborted, NOT selection_done, reserve_pub, subject, type, exchange_bank_account, (amount).val, (amount).frac, amount IS NULL AND in_amount IS NULL, amount != in_amount INTO already_confirmed, out_aborted, out_not_selected, reserve_pub_local, subject_local, local_type, exchange_bank_account_id, amount_local.val, amount_local.frac, out_missing_amount, out_amount_differs FROM taler_withdrawal_operations WHERE withdrawal_uuid=in_withdrawal_uuid; out_no_op=NOT FOUND; IF out_no_op OR already_confirmed OR out_aborted OR out_not_selected OR out_missing_amount OR out_amount_differs OR out_tan_required THEN RETURN; ELSIF in_amount IS NOT NULL THEN amount_local = in_amount; END IF; SELECT -- not checking for accounts existence, as it was done above. transfer.out_balance_insufficient, transfer.out_bad_amount, transfer.out_reserve_pub_reuse INTO out_balance_insufficient, out_bad_amount, out_reserve_pub_reuse FROM make_incoming( exchange_bank_account_id, wallet_bank_account_local, subject_local, amount_local, in_timestamp, local_type, reserve_pub_local, in_wire_transfer_fees, in_min_amount, in_max_amount ) as transfer; IF out_balance_insufficient OR out_reserve_pub_reuse OR out_bad_amount THEN RETURN; END IF; -- Confirm operation and update amount UPDATE taler_withdrawal_operations SET amount=amount_local, confirmation_done=true WHERE withdrawal_uuid=in_withdrawal_uuid; -- Notify status change PERFORM pg_notify('bank_withdrawal_status', in_withdrawal_uuid::text || ' confirmed'); END $$; COMMENT ON FUNCTION confirm_taler_withdrawal IS 'Set a withdrawal operation as confirmed and wire the funds to the exchange.'; CREATE FUNCTION cashin( IN in_timestamp INT8, IN in_reserve_pub BYTEA, IN in_amount taler_amount, IN in_subject TEXT, -- Error status OUT out_no_account BOOLEAN, OUT out_too_small BOOLEAN, OUT out_balance_insufficient BOOLEAN ) LANGUAGE plpgsql AS $$ DECLARE converted_amount taler_amount; admin_account_id INT8; exchange_account_id INT8; exchange_conversion_rate_class_id INT8; tx_row_id INT8; BEGIN -- TODO check reserve_pub reuse ? -- Recover exchange account info SELECT bank_account_id, conversion_rate_class_id INTO exchange_account_id, exchange_conversion_rate_class_id FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username = 'exchange'; IF NOT FOUND THEN out_no_account = true; RETURN; END IF; -- Retrieve admin account id SELECT bank_account_id INTO admin_account_id FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username = 'admin'; -- Perform conversion SELECT (converted).val, (converted).frac, too_small INTO converted_amount.val, converted_amount.frac, out_too_small FROM conversion_to(in_amount, 'cashin'::text, exchange_conversion_rate_class_id); IF out_too_small THEN RETURN; END IF; -- Perform incoming transaction SELECT transfer.out_balance_insufficient, transfer.out_credit_row_id INTO out_balance_insufficient, tx_row_id FROM make_incoming( exchange_account_id, admin_account_id, in_subject, converted_amount, in_timestamp, 'reserve'::taler_incoming_type, in_reserve_pub, NULL, NULL, NULL ) as transfer; IF out_balance_insufficient THEN RETURN; END IF; -- update stats CALL stats_register_payment('cashin', NULL, converted_amount, in_amount); END $$; COMMENT ON FUNCTION cashin IS 'Perform a cashin operation'; CREATE FUNCTION cashout_create( IN in_username TEXT, IN in_request_uid BYTEA, IN in_amount_debit taler_amount, IN in_amount_credit taler_amount, IN in_subject TEXT, IN in_timestamp INT8, IN in_is_tan BOOLEAN, -- Error status OUT out_bad_conversion BOOLEAN, OUT out_account_not_found BOOLEAN, OUT out_account_is_exchange BOOLEAN, OUT out_balance_insufficient BOOLEAN, OUT out_request_uid_reuse BOOLEAN, OUT out_no_cashout_payto BOOLEAN, OUT out_tan_required BOOLEAN, OUT out_under_min BOOLEAN, -- Success return OUT out_cashout_id INT8 ) LANGUAGE plpgsql AS $$ DECLARE account_id INT8; account_conversion_rate_class_id INT8; account_cashout_payto TEXT; admin_account_id INT8; tx_id INT8; BEGIN -- Check account exists, has all info and if 2FA is required SELECT bank_account_id, is_taler_exchange, conversion_rate_class_id, -- Remove potential residual query string an add the receiver_name split_part(cashout_payto, '?', 1) || '?receiver-name=' || url_encode(name), NOT in_is_tan AND cardinality(tan_channels) > 0 INTO account_id, out_account_is_exchange, account_conversion_rate_class_id, account_cashout_payto, out_tan_required FROM bank_accounts JOIN customers ON owning_customer_id=customer_id WHERE username=in_username; IF NOT FOUND THEN out_account_not_found=TRUE; RETURN; ELSIF account_cashout_payto IS NULL THEN out_no_cashout_payto=TRUE; RETURN; ELSIF out_account_is_exchange THEN RETURN; END IF; -- check conversion SELECT under_min, too_small OR in_amount_credit!=converted INTO out_under_min, out_bad_conversion FROM conversion_to(in_amount_debit, 'cashout'::text, account_conversion_rate_class_id); IF out_bad_conversion THEN RETURN; END IF; -- Retrieve admin account id SELECT bank_account_id INTO admin_account_id FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE username = 'admin'; -- Check for idempotence and conflict SELECT (amount_debit != in_amount_debit OR subject != in_subject OR bank_account != account_id) , cashout_id INTO out_request_uid_reuse, out_cashout_id FROM cashout_operations WHERE request_uid = in_request_uid; IF found OR out_request_uid_reuse OR out_tan_required THEN RETURN; END IF; -- Perform bank wire transfer SELECT transfer.out_balance_insufficient, out_debit_row_id INTO out_balance_insufficient, tx_id FROM bank_wire_transfer( admin_account_id, account_id, in_subject, in_amount_debit, in_timestamp, NULL, NULL, NULL ) as transfer; IF out_balance_insufficient THEN RETURN; END IF; -- Create cashout operation INSERT INTO cashout_operations ( request_uid ,amount_debit ,amount_credit ,creation_time ,bank_account ,subject ,local_transaction ) VALUES ( in_request_uid ,in_amount_debit ,in_amount_credit ,in_timestamp ,account_id ,in_subject ,tx_id ) RETURNING cashout_id INTO out_cashout_id; -- Initiate libeufin-nexus transaction INSERT INTO libeufin_nexus.initiated_outgoing_transactions ( amount ,subject ,credit_payto ,initiation_time ,end_to_end_id ) VALUES ( ((in_amount_credit).val, (in_amount_credit).frac)::libeufin_nexus.taler_amount ,in_subject ,account_cashout_payto ,in_timestamp ,libeufin_nexus.ebics_id_gen() ); -- update stats CALL stats_register_payment('cashout', NULL, in_amount_debit, in_amount_credit); END $$; CREATE FUNCTION tan_challenge_mark_sent ( IN in_uuid UUID, IN in_timestamp INT8, IN in_retransmission_period INT8 ) RETURNS void LANGUAGE sql AS $$ UPDATE tan_challenges SET retransmission_date = in_timestamp + in_retransmission_period WHERE uuid = in_uuid; $$; COMMENT ON FUNCTION tan_challenge_mark_sent IS 'Register a challenge as successfully sent'; CREATE FUNCTION tan_challenge_try ( IN in_uuid UUID, IN in_code TEXT, IN in_timestamp INT8, -- Error status OUT out_ok BOOLEAN, OUT out_no_op BOOLEAN, OUT out_no_retry BOOLEAN, OUT out_expired BOOLEAN, -- Success return OUT out_op op_enum, OUT out_channel tan_enum, OUT out_info TEXT ) LANGUAGE plpgsql as $$ DECLARE account_id INT8; token_creation BOOLEAN; BEGIN -- Try to solve challenge UPDATE tan_challenges SET confirmation_date = CASE WHEN (retry_counter > 0 AND in_timestamp < expiration_date AND code = in_code) THEN in_timestamp ELSE confirmation_date END, retry_counter = retry_counter - 1 WHERE uuid = in_uuid RETURNING confirmation_date IS NOT NULL, retry_counter <= 0 AND confirmation_date IS NULL, in_timestamp >= expiration_date AND confirmation_date IS NULL, op = 'create_token', customer INTO out_ok, out_no_retry, out_expired, token_creation, account_id; out_no_op = NOT FOUND; IF NOT out_ok AND token_creation THEN UPDATE customers SET token_creation_counter=token_creation_counter+1 WHERE customer_id=account_id; END IF; IF out_no_op OR NOT out_ok OR out_no_retry OR out_expired THEN RETURN; END IF; -- Recover body and op from challenge SELECT op, tan_channel, tan_info INTO out_op, out_channel, out_info FROM tan_challenges WHERE uuid = in_uuid; END $$; COMMENT ON FUNCTION tan_challenge_try IS 'Try to confirm a challenge, return true if the challenge have been confirmed'; CREATE FUNCTION stats_get_frame( IN date TIMESTAMP, IN in_timeframe stat_timeframe_enum, OUT cashin_count INT8, OUT cashin_regional_volume taler_amount, OUT cashin_fiat_volume taler_amount, OUT cashout_count INT8, OUT cashout_regional_volume taler_amount, OUT cashout_fiat_volume taler_amount, OUT taler_in_count INT8, OUT taler_in_volume taler_amount, OUT taler_out_count INT8, OUT taler_out_volume taler_amount ) LANGUAGE plpgsql AS $$ BEGIN date = date_trunc(in_timeframe::text, date); SELECT s.cashin_count ,(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_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 ,s.taler_out_count ,(s.taler_out_volume).val ,(s.taler_out_volume).frac INTO cashin_count ,cashin_regional_volume.val ,cashin_regional_volume.frac ,cashin_fiat_volume.val ,cashin_fiat_volume.frac ,cashout_count ,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 ,taler_out_count ,taler_out_volume.val ,taler_out_volume.frac FROM bank_stats AS s WHERE s.timeframe = in_timeframe AND s.start_time = date; END $$; CREATE PROCEDURE stats_register_payment( IN name TEXT, IN now TIMESTAMP, IN regional_amount taler_amount, IN fiat_amount taler_amount ) LANGUAGE plpgsql AS $$ BEGIN IF now IS NULL THEN now = timezone('utc', now())::TIMESTAMP; END IF; IF name = 'taler_in' THEN INSERT INTO bank_stats AS s ( timeframe, start_time, taler_in_count, taler_in_volume ) SELECT frame, date_trunc(frame::text, now), 1, regional_amount FROM unnest(enum_range(null::stat_timeframe_enum)) AS frame ON CONFLICT (timeframe, start_time) DO UPDATE SET taler_in_count=s.taler_in_count+1, taler_in_volume=(SELECT amount_add(s.taler_in_volume, regional_amount)); ELSIF name = 'taler_out' THEN INSERT INTO bank_stats AS s ( timeframe, start_time, taler_out_count, taler_out_volume ) SELECT frame, date_trunc(frame::text, now), 1, regional_amount FROM unnest(enum_range(null::stat_timeframe_enum)) AS frame ON CONFLICT (timeframe, start_time) DO UPDATE SET taler_out_count=s.taler_out_count+1, taler_out_volume=(SELECT amount_add(s.taler_out_volume, regional_amount)); ELSIF name = 'cashin' THEN INSERT INTO bank_stats AS s ( timeframe, start_time, cashin_count, cashin_regional_volume, cashin_fiat_volume ) SELECT frame, date_trunc(frame::text, now), 1, regional_amount, fiat_amount FROM unnest(enum_range(null::stat_timeframe_enum)) AS frame ON CONFLICT (timeframe, start_time) DO UPDATE SET cashin_count=s.cashin_count+1, cashin_regional_volume=(SELECT amount_add(s.cashin_regional_volume, regional_amount)), cashin_fiat_volume=(SELECT amount_add(s.cashin_fiat_volume, fiat_amount)); ELSIF name = 'cashout' THEN INSERT INTO bank_stats AS s ( timeframe, start_time, cashout_count, cashout_regional_volume, cashout_fiat_volume ) SELECT frame, date_trunc(frame::text, now), 1, regional_amount, fiat_amount FROM unnest(enum_range(null::stat_timeframe_enum)) AS frame ON CONFLICT (timeframe, start_time) DO UPDATE SET cashout_count=s.cashout_count+1, cashout_regional_volume=(SELECT amount_add(s.cashout_regional_volume, regional_amount)), cashout_fiat_volume=(SELECT amount_add(s.cashout_fiat_volume, fiat_amount)); ELSE RAISE EXCEPTION 'Unknown stat %', name; END IF; END $$; CREATE FUNCTION conversion_apply_ratio( IN amount taler_amount ,IN ratio taler_amount ,IN fee taler_amount ,IN tiny taler_amount -- Result is rounded to this amount ,IN rounding rounding_mode -- With this rounding mode ,OUT result taler_amount ,OUT out_too_small BOOLEAN ) LANGUAGE plpgsql IMMUTABLE AS $$ DECLARE amount_numeric NUMERIC(33, 8); -- 16 digit for val, 8 for frac and 1 for rounding error tiny_numeric NUMERIC(24); BEGIN -- Handle no config case IF ratio = (0, 0)::taler_amount THEN out_too_small=TRUE; RETURN; END IF; -- Perform multiplication using big numbers amount_numeric = (amount.val::numeric(24) * 100000000 + amount.frac::numeric(24)) * (ratio.val::numeric(24, 8) + ratio.frac::numeric(24, 8) / 100000000); -- Apply fees amount_numeric = amount_numeric - (fee.val::numeric(24) * 100000000 + fee.frac::numeric(24)); IF (sign(amount_numeric) != 1) THEN out_too_small = TRUE; result = (0, 0); RETURN; END IF; -- Round to tiny amounts tiny_numeric = (tiny.val::numeric(24) * 100000000 + tiny.frac::numeric(24)); case rounding when 'zero' then amount_numeric = trunc(amount_numeric / tiny_numeric) * tiny_numeric; when 'up' then amount_numeric = ceil(amount_numeric / tiny_numeric) * tiny_numeric; when 'nearest' then amount_numeric = round(amount_numeric / tiny_numeric) * tiny_numeric; end case; -- Extract product parts result = (trunc(amount_numeric / 100000000)::int8, (amount_numeric % 100000000)::int4); IF (result.val > 1::INT8<<52) THEN RAISE EXCEPTION 'amount value overflowed'; END IF; END $$; COMMENT ON FUNCTION conversion_apply_ratio IS 'Apply a ratio to an amount rounding the result to a tiny amount following a rounding mode. It raises an exception when the resulting .val is larger than 2^52'; CREATE FUNCTION conversion_revert_ratio( IN amount taler_amount ,IN ratio taler_amount ,IN fee taler_amount ,IN tiny taler_amount -- Result is rounded to this amount ,IN rounding rounding_mode -- With this rounding mode ,IN reverse_tiny taler_amount ,OUT result taler_amount ,OUT bad_value BOOLEAN ) LANGUAGE plpgsql IMMUTABLE AS $$ DECLARE amount_numeric NUMERIC(33, 8); -- 16 digit for val, 8 for frac and 1 for rounding error tiny_numeric NUMERIC(24); roundtrip BOOLEAN; BEGIN -- Handle no config case IF ratio = (0, 0)::taler_amount THEN bad_value=TRUE; RETURN; END IF; -- Apply fees amount_numeric = (amount.val::numeric(24) * 100000000 + amount.frac::numeric(24)) + (fee.val::numeric(24) * 100000000 + fee.frac::numeric(24)); -- Perform division using big numbers amount_numeric = amount_numeric / (ratio.val::numeric(24, 8) + ratio.frac::numeric(24, 8) / 100000000); -- Round to input digits tiny_numeric = (reverse_tiny.val::numeric(24) * 100000000 + reverse_tiny.frac::numeric(24)); amount_numeric = trunc(amount_numeric / tiny_numeric) * tiny_numeric; -- Extract division parts result = (trunc(amount_numeric / 100000000)::int8, (amount_numeric % 100000000)::int4); -- Recover potentially lost tiny amount during rounding -- There must be a clever way to compute this but I am a little limited with math -- and revert ratio computation is not a hot function so I just use the apply ratio -- function to be conservative and correct SELECT ok INTO roundtrip FROM amount_left_minus_right((SELECT conversion_apply_ratio.result FROM conversion_apply_ratio(result, ratio, fee, tiny, rounding)), amount); IF NOT roundtrip THEN amount_numeric = amount_numeric + tiny_numeric; result = (trunc(amount_numeric / 100000000)::int8, (amount_numeric % 100000000)::int4); END IF; IF (result.val > 1::INT8<<52) THEN RAISE EXCEPTION 'amount value overflowed'; END IF; END $$; COMMENT ON FUNCTION conversion_revert_ratio IS 'Revert the application of a ratio. This function does not always return the smallest possible amount. It raises an exception when the resulting .val is larger than 2^52'; CREATE FUNCTION conversion_to( IN amount taler_amount, IN direction TEXT, IN conversion_rate_class_id INT8, OUT converted taler_amount, OUT too_small BOOLEAN, OUT under_min BOOLEAN ) LANGUAGE plpgsql STABLE AS $$ DECLARE at_ratio taler_amount; out_fee taler_amount; tiny_amount taler_amount; min_amount taler_amount; mode rounding_mode; BEGIN -- Load rate IF direction='cashin' THEN SELECT (cashin_ratio).val, (cashin_ratio).frac, (cashin_fee).val, (cashin_fee).frac, (cashin_tiny_amount).val, (cashin_tiny_amount).frac, (cashin_min_amount).val, (cashin_min_amount).frac, cashin_rounding_mode INTO at_ratio.val, at_ratio.frac, out_fee.val, out_fee.frac, tiny_amount.val, tiny_amount.frac, min_amount.val, min_amount.frac, mode FROM get_conversion_class_rate(conversion_rate_class_id); ELSE SELECT (cashout_ratio).val, (cashout_ratio).frac, (cashout_fee).val, (cashout_fee).frac, (cashout_tiny_amount).val, (cashout_tiny_amount).frac, (cashout_min_amount).val, (cashout_min_amount).frac, cashout_rounding_mode INTO at_ratio.val, at_ratio.frac, out_fee.val, out_fee.frac, tiny_amount.val, tiny_amount.frac, min_amount.val, min_amount.frac, mode FROM get_conversion_class_rate(conversion_rate_class_id); END IF; -- Check min amount SELECT NOT ok INTO too_small FROM amount_left_minus_right(amount, min_amount); IF too_small THEN under_min = true; converted = (0, 0); RETURN; END IF; -- Perform conversion SELECT (result).val, (result).frac, out_too_small INTO converted.val, converted.frac, too_small FROM conversion_apply_ratio(amount, at_ratio, out_fee, tiny_amount, mode); END $$; CREATE FUNCTION conversion_from( IN amount taler_amount, IN direction TEXT, IN conversion_rate_class_id INT8, OUT converted taler_amount, OUT too_small BOOLEAN, OUT under_min BOOLEAN ) LANGUAGE plpgsql STABLE AS $$ DECLARE ratio taler_amount; out_fee taler_amount; tiny_amount taler_amount; reverse_tiny_amount taler_amount; min_amount taler_amount; mode rounding_mode; BEGIN -- Load rate IF direction='cashin' THEN SELECT (cashin_ratio).val, (cashin_ratio).frac, (cashin_fee).val, (cashin_fee).frac, (cashin_tiny_amount).val, (cashin_tiny_amount).frac, (cashout_tiny_amount).val, (cashout_tiny_amount).frac, (cashin_min_amount).val, (cashin_min_amount).frac, cashin_rounding_mode INTO ratio.val, ratio.frac, out_fee.val, out_fee.frac, tiny_amount.val, tiny_amount.frac, reverse_tiny_amount.val, reverse_tiny_amount.frac, min_amount.val, min_amount.frac, mode FROM get_conversion_class_rate(conversion_rate_class_id); ELSE SELECT (cashout_ratio).val, (cashout_ratio).frac, (cashout_fee).val, (cashout_fee).frac, (cashout_tiny_amount).val, (cashout_tiny_amount).frac, (cashin_tiny_amount).val, (cashin_tiny_amount).frac, (cashout_min_amount).val, (cashout_min_amount).frac, cashout_rounding_mode INTO ratio.val, ratio.frac, out_fee.val, out_fee.frac, tiny_amount.val, tiny_amount.frac, reverse_tiny_amount.val, reverse_tiny_amount.frac, min_amount.val, min_amount.frac, mode FROM get_conversion_class_rate(conversion_rate_class_id); END IF; -- Perform conversion SELECT (result).val, (result).frac, bad_value INTO converted.val, converted.frac, too_small FROM conversion_revert_ratio(amount, ratio, out_fee, tiny_amount, mode, reverse_tiny_amount); IF too_small THEN RETURN; END IF; -- Check min amount SELECT NOT ok INTO too_small FROM amount_left_minus_right(converted, min_amount); IF too_small THEN under_min = true; converted = (0, 0); END IF; END $$; CREATE FUNCTION config_get_conversion_rate() RETURNS TABLE ( cashin_ratio taler_amount, cashin_fee taler_amount, cashin_tiny_amount taler_amount, cashin_min_amount taler_amount, cashin_rounding_mode rounding_mode, cashout_ratio taler_amount, cashout_fee taler_amount, cashout_tiny_amount taler_amount, cashout_min_amount taler_amount, cashout_rounding_mode rounding_mode ) LANGUAGE sql STABLE AS $$ SELECT (value->'cashin'->'ratio'->'val', value->'cashin'->'ratio'->'frac')::taler_amount, (value->'cashin'->'fee'->'val', value->'cashin'->'fee'->'frac')::taler_amount, (value->'cashin'->'tiny_amount'->'val', value->'cashin'->'tiny_amount'->'frac')::taler_amount, (value->'cashin'->'min_amount'->'val', value->'cashin'->'min_amount'->'frac')::taler_amount, (value->'cashin'->>'rounding_mode')::rounding_mode, (value->'cashout'->'ratio'->'val', value->'cashout'->'ratio'->'frac')::taler_amount, (value->'cashout'->'fee'->'val', value->'cashout'->'fee'->'frac')::taler_amount, (value->'cashout'->'tiny_amount'->'val', value->'cashout'->'tiny_amount'->'frac')::taler_amount, (value->'cashout'->'min_amount'->'val', value->'cashout'->'min_amount'->'frac')::taler_amount, (value->'cashout'->>'rounding_mode')::rounding_mode FROM config WHERE key='conversion_rate' UNION ALL SELECT (0, 0)::taler_amount, (0, 0)::taler_amount, (0, 1000000)::taler_amount, (0, 0)::taler_amount, 'zero'::rounding_mode, (0, 0)::taler_amount, (0, 0)::taler_amount, (0, 1000000)::taler_amount, (0, 0)::taler_amount, 'zero'::rounding_mode LIMIT 1 $$; CREATE FUNCTION get_conversion_class_rate( IN in_conversion_rate_class_id INT8 ) RETURNS TABLE ( cashin_ratio taler_amount, cashin_fee taler_amount, cashin_tiny_amount taler_amount, cashin_min_amount taler_amount, cashin_rounding_mode rounding_mode, cashout_ratio taler_amount, cashout_fee taler_amount, cashout_tiny_amount taler_amount, cashout_min_amount taler_amount, cashout_rounding_mode rounding_mode ) LANGUAGE sql STABLE AS $$ SELECT COALESCE(class.cashin_ratio, cfg.cashin_ratio), COALESCE(class.cashin_fee, cfg.cashin_fee), cashin_tiny_amount, COALESCE(class.cashin_min_amount, cfg.cashin_min_amount), COALESCE(class.cashin_rounding_mode, cfg.cashin_rounding_mode), COALESCE(class.cashout_ratio, cfg.cashout_ratio), COALESCE(class.cashout_fee, cfg.cashout_fee), cashout_tiny_amount, COALESCE(class.cashout_min_amount, cfg.cashout_min_amount), COALESCE(class.cashout_rounding_mode, cfg.cashout_rounding_mode) FROM config_get_conversion_rate() as cfg LEFT JOIN conversion_rate_classes as class ON (conversion_rate_class_id=in_conversion_rate_class_id) $$; CREATE PROCEDURE config_set_conversion_rate( IN cashin_ratio taler_amount, IN cashin_fee taler_amount, IN cashin_tiny_amount taler_amount, IN cashin_min_amount taler_amount, IN cashin_rounding_mode rounding_mode, IN cashout_ratio taler_amount, IN cashout_fee taler_amount, IN cashout_tiny_amount taler_amount, IN cashout_min_amount taler_amount, IN cashout_rounding_mode rounding_mode ) LANGUAGE sql AS $$ INSERT INTO config (key, value) VALUES ('conversion_rate', jsonb_build_object( 'cashin', jsonb_build_object( 'ratio', jsonb_build_object('val', cashin_ratio.val, 'frac', cashin_ratio.frac), 'fee', jsonb_build_object('val', cashin_fee.val, 'frac', cashin_fee.frac), 'tiny_amount', jsonb_build_object('val', cashin_tiny_amount.val, 'frac', cashin_tiny_amount.frac), 'min_amount', jsonb_build_object('val', cashin_min_amount.val, 'frac', cashin_min_amount.frac), 'rounding_mode', cashin_rounding_mode ), 'cashout', jsonb_build_object( 'ratio', jsonb_build_object('val', cashout_ratio.val, 'frac', cashout_ratio.frac), 'fee', jsonb_build_object('val', cashout_fee.val, 'frac', cashout_fee.frac), 'tiny_amount', jsonb_build_object('val', cashout_tiny_amount.val, 'frac', cashout_tiny_amount.frac), 'min_amount', jsonb_build_object('val', cashout_min_amount.val, 'frac', cashout_min_amount.frac), 'rounding_mode', cashout_rounding_mode ) )) ON CONFLICT (key) DO UPDATE SET value = excluded.value $$; CREATE FUNCTION register_prepared_transfers ( IN in_credit_account TEXT, IN in_type taler_incoming_type, IN in_account_pub BYTEA, IN in_authorization_pub BYTEA, IN in_authorization_sig BYTEA, IN in_recurrent BOOLEAN, IN in_amount taler_amount, IN in_timestamp INT8, IN in_subject TEXT, -- Error status OUT out_unknown_creditor BOOLEAN, OUT out_not_exchange BOOLEAN, OUT out_reserve_pub_reuse BOOLEAN, -- Success status OUT out_withdrawal_uuid UUID ) LANGUAGE plpgsql AS $$ DECLARE local_withdrawal_id INT8; exchange_account_id INT8; talerable_tx INT8; idempotent BOOLEAN; BEGIN -- Retrieve exchange account if SELECT bank_account_id, NOT is_taler_exchange INTO exchange_account_id, out_not_exchange FROM bank_accounts JOIN customers ON customer_id=owning_customer_id WHERE internal_payto = in_credit_account; out_unknown_creditor=NOT FOUND; if out_unknown_creditor OR out_not_exchange THEN RETURN; END IF; -- Check idempotency SELECT withdrawal_uuid, prepared_transfers.type = in_type AND account_pub = in_account_pub AND recurrent = in_recurrent AND amount = in_amount INTO out_withdrawal_uuid, idempotent FROM prepared_transfers LEFT JOIN taler_withdrawal_operations USING (withdrawal_id) WHERE authorization_pub = in_authorization_pub; -- Check idempotency and delay garbage collection IF FOUND AND idempotent THEN UPDATE prepared_transfers SET registered_at=in_timestamp WHERE authorization_pub=in_authorization_pub; RETURN; END IF; -- Check reserve pub reuse out_reserve_pub_reuse=in_type = 'reserve' AND ( EXISTS(SELECT FROM taler_exchange_incoming WHERE metadata = in_account_pub AND type = 'reserve') ); IF out_reserve_pub_reuse THEN RETURN; END IF; -- Create/replace withdrawal IF out_withdrawal_uuid IS NOT NULL THEN PERFORM abort_taler_withdrawal(out_withdrawal_uuid); END IF; out_withdrawal_uuid=null; IF in_recurrent THEN -- Finalize one pending right now DELETE FROM pending_recurrent_incoming_transactions WHERE bank_transaction_id = ( SELECT bank_transaction_id FROM pending_recurrent_incoming_transactions JOIN bank_account_transactions USING (bank_transaction_id) WHERE authorization_pub = in_authorization_pub ORDER BY transaction_date ASC LIMIT 1 ) RETURNING bank_transaction_id INTO talerable_tx; IF FOUND THEN PERFORM register_incoming(talerable_tx, in_type, in_account_pub, exchange_account_id, in_authorization_pub, in_authorization_sig); END IF; ELSE -- Bounce all pending PERFORM bounce(debtor_account_id, bank_transaction_id, 'cancelled mapping', in_timestamp) FROM pending_recurrent_incoming_transactions WHERE authorization_pub = in_authorization_pub; -- Create withdrawal INSERT INTO taler_withdrawal_operations ( withdrawal_uuid, wallet_bank_account, amount, suggested_amount, no_amount_to_wallet, exchange_bank_account, type, reserve_pub, subject, selection_done, creation_date ) VALUES ( gen_random_uuid(), NULL, in_amount, NULL, true, exchange_account_id, 'map', in_account_pub, in_subject, true, in_timestamp ) RETURNING withdrawal_uuid, withdrawal_id INTO out_withdrawal_uuid, local_withdrawal_id; END IF; -- Upsert registration INSERT INTO prepared_transfers ( type, account_pub, authorization_pub, authorization_sig, recurrent, registered_at, bank_transaction_id, withdrawal_id ) VALUES ( in_type, in_account_pub, in_authorization_pub, in_authorization_sig, in_recurrent, in_timestamp, talerable_tx, local_withdrawal_id ) ON CONFLICT (authorization_pub) DO UPDATE SET type = EXCLUDED.type, account_pub = EXCLUDED.account_pub, recurrent = EXCLUDED.recurrent, registered_at = EXCLUDED.registered_at, bank_transaction_id = EXCLUDED.bank_transaction_id, withdrawal_id = EXCLUDED.withdrawal_id, authorization_sig = EXCLUDED.authorization_sig; END $$; CREATE FUNCTION delete_prepared_transfers ( IN in_authorization_pub BYTEA, IN in_timestamp INT8, OUT out_found BOOLEAN ) LANGUAGE plpgsql AS $$ BEGIN -- Bounce all pending PERFORM bounce(debtor_account_id, bank_transaction_id, 'cancelled mapping', in_timestamp) FROM pending_recurrent_incoming_transactions WHERE authorization_pub = in_authorization_pub; -- Delete registration DELETE FROM prepared_transfers WHERE authorization_pub = in_authorization_pub; out_found = FOUND; -- TODO abort withdrawal END $$; COMMIT;libeufin-1.6.8/libeufin-common/0000775000175000017500000000000015236145704016635 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/0000775000175000017500000000000015236145704017424 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/0000775000175000017500000000000015236145704020350 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/kotlin/0000775000175000017500000000000015236145704021650 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/kotlin/TalerCommon.kt0000664000175000017500000006667215221677432024453 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import io.ktor.http.* import io.ktor.server.plugins.* import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* import kotlinx.serialization.json.* import java.time.Instant import java.time.Duration import java.time.temporal.ChronoUnit import java.util.concurrent.TimeUnit import java.nio.ByteBuffer import java.nio.ByteOrder import org.bouncycastle.math.ec.rfc8032.Ed25519 import io.github.smiley4.schemakenerator.core.annotations.Description import kotlinx.io.bytestring.putByteString sealed class CommonError(msg: String) : Exception(msg) { class AmountFormat(msg: String) : CommonError(msg) class AmountNumberTooBig(msg: String) : CommonError(msg) class Payto(msg: String) : CommonError(msg) } /** * Internal representation of relative times. The * "forever" case is represented with Long.MAX_VALUE. */ @Description("Relative time duration, serialized as microseconds or 'forever'") @JvmInline @Serializable(with = RelativeTime.Serializer::class) value class RelativeTime(val duration: Duration) { internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = buildClassSerialDescriptor("RelativeTime") { element("d_us") } override fun serialize(encoder: Encoder, value: RelativeTime) { val composite = encoder.beginStructure(descriptor) if (value.duration == ChronoUnit.FOREVER.duration) { composite.encodeStringElement(descriptor, 0, "forever") } else { composite.encodeLongElement(descriptor, 0, TimeUnit.MICROSECONDS.convert(value.duration)) } composite.endStructure(descriptor) } override fun deserialize(decoder: Decoder): RelativeTime { val dec = decoder.beginStructure(descriptor) val jsonInput = dec as? JsonDecoder ?: error("Can be deserialized only by JSON") lateinit var maybeDUs: JsonPrimitive loop@ while (true) { when (val index = dec.decodeElementIndex(descriptor)) { 0 -> maybeDUs = jsonInput.decodeJsonElement().jsonPrimitive CompositeDecoder.DECODE_DONE -> break@loop else -> throw SerializationException("Unexpected index: $index") } } dec.endStructure(descriptor) if (maybeDUs.isString) { if (maybeDUs.content != "forever") throw badRequest("Only 'forever' allowed for d_us as string, but '${maybeDUs.content}' was found") return RelativeTime(ChronoUnit.FOREVER.duration) } val dUs: Long = maybeDUs.longOrNull ?: throw badRequest("Could not convert d_us: '${maybeDUs.content}' to a number") when { dUs < 0 -> throw badRequest("Negative duration specified.") dUs > MAX_SAFE_INTEGER -> throw badRequest("d_us value $dUs exceed cap (2^53-1)") else -> return RelativeTime(Duration.of(dUs, ChronoUnit.MICROS)) } } } companion object { const val MAX_SAFE_INTEGER = 9007199254740991L // 2^53 - 1 } } /** Timestamp containing the number of seconds since epoch */ @Description("Timestamp as seconds since Unix epoch, or 'never'") @JvmInline @Serializable(with = TalerTimestamp.Serializer::class) value class TalerTimestamp constructor(val instant: Instant) { internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Timestamp") { element("t_s") } override fun serialize(encoder: Encoder, value: TalerTimestamp) { val composite = encoder.beginStructure(descriptor) if (value.instant == Instant.MAX) { composite.encodeStringElement(descriptor, 0, "never") } else { composite.encodeLongElement(descriptor, 0, value.instant.epochSecond) } composite.endStructure(descriptor) } override fun deserialize(decoder: Decoder): TalerTimestamp { val dec = decoder.beginStructure(descriptor) val jsonInput = dec as? JsonDecoder ?: error("Can be deserialized only by JSON") lateinit var maybeTs: JsonPrimitive loop@ while (true) { when (val index = dec.decodeElementIndex(descriptor)) { 0 -> maybeTs = jsonInput.decodeJsonElement().jsonPrimitive CompositeDecoder.DECODE_DONE -> break@loop else -> throw SerializationException("Unexpected index: $index") } } dec.endStructure(descriptor) if (maybeTs.isString) { if (maybeTs.content != "never") throw badRequest("Only 'never' allowed for t_s as string, but '${maybeTs.content}' was found") return TalerTimestamp(Instant.MAX) } val ts: Long = maybeTs.longOrNull ?: throw badRequest("Could not convert t_s '${maybeTs.content}' to a number") when { ts < 0 -> throw badRequest("Negative timestamp not allowed") ts > Instant.MAX.epochSecond -> throw badRequest("Timestamp $ts too big to be represented in Kotlin") else -> return TalerTimestamp(Instant.ofEpochSecond(ts)) } } } companion object { fun never(): TalerTimestamp = TalerTimestamp(Instant.MAX) } } @Description("Base URL string ending with a trailing slash") @JvmInline @Serializable(with = BaseURL.Serializer::class) value class BaseURL private constructor(val url: Url) { companion object { fun parse(raw: String): BaseURL { val url = URLBuilder(raw) if (url.protocolOrNull == null) { throw badRequest("missing protocol in baseURL got '${url}'") } else if (url.protocol.name !in setOf("http", "https")) { throw badRequest("only 'http' and 'https' are accepted for baseURL got '${url.protocol.name}'") } else if (url.host.isEmpty()) { throw badRequest("missing host in baseURL got '${url}'") } else if (!url.parameters.isEmpty()) { throw badRequest("require no query in baseURL got '${url.encodedParameters}'") } else if (url.fragment.isNotEmpty()) { throw badRequest("require no fragments in baseURL got '${url.fragment}'") } else if (!url.encodedPath.endsWith('/')) { throw badRequest("baseURL path must end with / got '${url.encodedPath}'") } return BaseURL(url.build()) } } override fun toString(): String = url.toString() internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BaseURL", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: BaseURL) { encoder.encodeString(value.url.toString()) } override fun deserialize(decoder: Decoder): BaseURL { return BaseURL.parse(decoder.decodeString()) } } } @Serializable(with = DecimalNumber.Serializer::class) class DecimalNumber { val value: Long val frac: Int constructor(value: Long, frac: Int) { this.value = value this.frac = frac } constructor(encoded: String) { val match = PATTERN.matchEntire(encoded) ?: throw badRequest("Invalid decimal number format") val (value, frac) = match.destructured this.value = value.toLongOrNull() ?: throw badRequest("Invalid value") if (this.value > TalerAmount.MAX_VALUE) throw badRequest("Value specified in decimal number is too large") this.frac = if (frac.isEmpty()) { 0 } else { var tmp = frac.toIntOrNull() ?: throw badRequest("Invalid fractional value") if (tmp > TalerAmount.FRACTION_BASE) throw badRequest("Fractional value specified in decimal number is too large") repeat(8 - frac.length) { tmp *= 10 } tmp } } fun isZero(): Boolean = value == 0L && frac == 0 override fun equals(other: Any?): Boolean { return other is DecimalNumber && other.value == this.value && other.frac == this.frac } override fun toString(): String { return if (frac == 0) { "$value" } else { "$value.${frac.toString().padStart(8, '0')}" .dropLastWhile { it == '0' } // Trim useless fractional trailing 0 } } internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("DecimalNumber", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: DecimalNumber) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): DecimalNumber { return DecimalNumber(decoder.decodeString()) } } companion object { val ZERO = DecimalNumber(0, 0) private val PATTERN = Regex("([0-9]+)(?:\\.([0-9]{1,8}))?") } } @Serializable(with = TalerAmount.Serializer::class) class TalerAmount : Comparable { val value: Long val frac: Int val currency: String constructor(value: Long, frac: Int, currency: String) { this.value = value this.frac = frac this.currency = currency } constructor(encoded: String) { val match = PATTERN.matchEntire(encoded) ?: throw CommonError.AmountFormat("Invalid amount format") val (currency, value, frac) = match.destructured this.currency = currency this.value = value.toLongOrNull() ?: throw CommonError.AmountFormat("Invalid value") if (this.value > MAX_VALUE) throw CommonError.AmountNumberTooBig("Value specified in amount is too large") this.frac = if (frac.isEmpty()) { 0 } else { var tmp = frac.toIntOrNull() ?: throw CommonError.AmountFormat("Invalid fractional value") if (tmp > FRACTION_BASE) throw CommonError.AmountFormat("Fractional value specified in amount is too large") repeat(8 - frac.length) { tmp *= 10 } tmp } } fun number(): DecimalNumber = DecimalNumber(value, frac) /* Check if zero */ fun isZero(): Boolean = value == 0L && frac == 0 fun notZeroOrNull(): TalerAmount? = if (isZero()) null else this /* Check is amount has fractional amount < 0.01 */ fun isSubCent(): Boolean = (frac % CENT_FRACTION) > 0 /* Network bytes */ fun nbo(): ByteArray = ByteBuffer.allocate(24).apply { order(ByteOrder.BIG_ENDIAN) putLong(value) putInt(frac) val curr = currency.encodeToByteArray() put(curr) repeat(12 - curr.size) { put(0) } }.array() override fun equals(other: Any?): Boolean { return other is TalerAmount && other.value == this.value && other.frac == this.frac && other.currency == this.currency } override fun toString(): String { return if (frac == 0) { "$currency:$value" } else { "$currency:$value.${frac.toString().padStart(8, '0')}" .dropLastWhile { it == '0' } // Trim useless fractional trailing 0 } } fun normalize(): TalerAmount { val value = Math.addExact(this.value, (this.frac / FRACTION_BASE).toLong()) val frac = this.frac % FRACTION_BASE if (value > MAX_VALUE) throw ArithmeticException("amount value overflowed") return TalerAmount(value, frac, currency) } override operator fun compareTo(other: TalerAmount) = compareValuesBy(this, other, { it.value }, { it.frac }) operator fun plus(increment: TalerAmount): TalerAmount { require(this.currency == increment.currency) { "currency mismatch ${this.currency} != ${increment.currency}" } val value = Math.addExact(this.value, increment.value) val frac = Math.addExact(this.frac, increment.frac) return TalerAmount(value, frac, currency).normalize() } operator fun minus(decrement: TalerAmount): TalerAmount { require(this.currency == decrement.currency) { "currency mismatch ${this.currency} != ${decrement.currency}" } var frac = this.frac var value = this.value if (frac < decrement.frac) { if (value <= 0) { throw ArithmeticException("negative result") } frac += FRACTION_BASE value -= 1 } if (value < decrement.value) { throw ArithmeticException("negative result") } return TalerAmount(value - decrement.value, frac - decrement.frac, currency).normalize() } internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("TalerAmount", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: TalerAmount) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): TalerAmount = TalerAmount(decoder.decodeString()) } companion object { const val FRACTION_BASE = 100000000 const val CENT_FRACTION = 1000000 const val MAX_VALUE = 4503599627370496L // 2^52 private val PATTERN = Regex("([A-Z]{1,11}):([0-9]+)(?:\\.([0-9]{1,8}))?") fun zero(currency: String) = TalerAmount(0, 0, currency) fun max(currency: String) = TalerAmount(MAX_VALUE, FRACTION_BASE - 1, currency) } } @Serializable(with = Payto.Serializer::class) sealed class Payto { abstract val parsed: Url abstract val canonical: String abstract val amount: TalerAmount? abstract val message: String? abstract val receiverName: String? /** Transform a payto URI to its bank form, using [name] as the receiver-name and the bank [ctx] */ fun bank(name: String?, ctx: BankPaytoCtx): String = when (this) { is IbanPayto -> IbanPayto.build(iban.toString(), ctx.bic, name) is XTalerBankPayto -> { val name = if (name != null) "?receiver-name=${name.encodeURLParameter()}" else "" "payto://x-taler-bank/${ctx.hostname}/$username$name" } } fun expectIbanFull(): IbanPayto { val payto = expectIban() if (payto.receiverName == null) { throw CommonError.Payto("expected a full IBAN payto got no receiver-name") } return payto } fun expectIban(): IbanPayto { return when (this) { is IbanPayto -> this else -> throw CommonError.Payto("expected an IBAN payto URI got '${parsed.host}'") } } fun expectXTalerBank(): XTalerBankPayto { return when (this) { is XTalerBankPayto -> this else -> throw CommonError.Payto("expected a x-taler-bank payto URI got '${parsed.host}'") } } override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is Payto) return false return this.parsed == other.parsed } internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Payto", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: Payto) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): Payto { return parse(decoder.decodeString()) } } companion object { private val HEX_PATTERN: Regex = Regex("%(?![0-9a-fA-F]{2})") fun parse(input: String): Payto { val raw = input.replace(HEX_PATTERN, "%25") val parsed = try { Url(raw) } catch (e: Exception) { throw CommonError.Payto("expected a valid URI") } if (parsed.protocol.name != "payto") throw CommonError.Payto("expect a payto URI got '${parsed.protocol.name}'") val amount = parsed.parameters["amount"]?.run { TalerAmount(this) } val message = parsed.parameters["message"] val receiverName = parsed.parameters["receiver-name"] return when (parsed.host) { "iban" -> { val segments = parsed.segments val (bic, rawIban) = when (segments.size) { 1 -> Pair(null, segments[0]) 2 -> Pair(segments[0], segments[1]) else -> throw CommonError.Payto("too many path segments for an IBAN payto URI") } val iban = IBAN.parse(rawIban) IbanPayto( parsed, "payto://iban/$iban", amount, message, receiverName, parsed.parameters["ch-qrr"], bic, iban, ) } "x-taler-bank" -> { val segments = parsed.segments if (segments.size != 2) throw CommonError.Payto("bad number of path segments for a x-taler-bank payto URI") val username = segments[1] XTalerBankPayto( parsed, "payto://x-taler-bank/localhost/$username", amount, message, receiverName, username ) } else -> throw CommonError.Payto("unsupported payto URI kind '${parsed.host}'") } } } } @Serializable(with = IbanPayto.Serializer::class) class IbanPayto internal constructor( override val parsed: Url, override val canonical: String, override val amount: TalerAmount?, override val message: String?, override val receiverName: String?, val chQrr: String?, val bic: String?, val iban: IBAN ) : Payto() { override fun toString(): String = parsed.toString() /** Format an IbanPayto in a more human readable way */ fun fmt(): String = buildString { append('(') append(iban) if (bic != null) { append(' ') append(bic) } if (receiverName != null) { append(' ') append(receiverName) } append(')') } /** Transform an IBAN payto URI to its simple form without any query */ fun simple(): String = build(iban.toString(), bic, null) /** Transform an IBAN payto URI to its full form, using [name] as its receiver-name */ fun full(name: String): String = build(iban.toString(), bic, name) internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("IbanPayto", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: IbanPayto) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): IbanPayto { return parse(decoder.decodeString()).expectIban() } } companion object { fun build(iban: String, bic: String?, name: String?): String { val bic = if (bic != null) "$bic/" else "" val name = if (name != null) "?receiver-name=${name.encodeURLParameter()}" else "" return "payto://iban/$bic$iban$name" } fun rand(name: String? = null, country: Country = Country.DE): IbanPayto = parse( "payto://iban/${IBAN.rand(country)}${ if (name != null) { "?receiver-name=${name.encodeURLParameter()}" } else { "" } }" ).expectIban() } } class XTalerBankPayto internal constructor( override val parsed: Url, override val canonical: String, override val amount: TalerAmount?, override val message: String?, override val receiverName: String?, val username: String ) : Payto() { override fun toString(): String = parsed.toString() companion object { fun forUsername(username: String): XTalerBankPayto { return parse("payto://x-taler-bank/hostname/$username").expectXTalerBank() } } } /** Context specific data necessary to create a bank payto URI from a canonical payto URI */ data class BankPaytoCtx( val bic: String?, val hostname: String ) /** 16-byte Crockford's Base32 encoded data */ @Serializable(with = Base32Crockford16B.Serializer::class) class Base32Crockford16B { private var encoded: String? = null val raw: ByteArray constructor(encoded: String) { val decoded = try { Base32Crockford.decode(encoded) } catch (e: IllegalArgumentException) { null } require(decoded != null && decoded.size == 16) { "expected 16 bytes encoded in Crockford's base32" } this.raw = decoded this.encoded = encoded } constructor(raw: ByteArray) { require(raw.size == 16) { "encoded data should be 16 bytes long" } this.raw = raw } fun encoded(): String { val tmp = encoded ?: Base32Crockford.encode(raw) encoded = tmp return tmp } override fun toString(): String { return encoded() } override fun equals(other: Any?) = (other is Base32Crockford16B) && raw.contentEquals(other.raw) internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Base32Crockford16B", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: Base32Crockford16B) { encoder.encodeString(value.encoded()) } override fun deserialize(decoder: Decoder): Base32Crockford16B { return Base32Crockford16B(decoder.decodeString()) } } companion object { fun rand(): Base32Crockford16B = Base32Crockford16B(ByteArray(16).rand()) fun secureRand(): Base32Crockford16B = Base32Crockford16B(ByteArray(16).secureRand()) } } /** 32-byte Crockford's Base32 encoded data */ @Description("32-byte Crockford Base32 encoded data") @Serializable(with = Base32Crockford32B.Serializer::class) class Base32Crockford32B { private var encoded: String? = null val raw: ByteArray constructor(encoded: String) { val decoded = try { Base32Crockford.decode(encoded) } catch (e: IllegalArgumentException) { null } require(decoded != null && decoded.size == 32) { "expected 32 bytes encoded in Crockford's base32" } this.raw = decoded this.encoded = encoded } constructor(raw: ByteArray) { require(raw.size == 32) { "encoded data should be 32 bytes long" } this.raw = raw } fun encoded(): String { val tmp = encoded ?: Base32Crockford.encode(raw) encoded = tmp return tmp } override fun toString(): String { return encoded() } override fun equals(other: Any?) = (other is Base32Crockford32B) && raw.contentEquals(other.raw) internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Base32Crockford32B", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: Base32Crockford32B) { encoder.encodeString(value.encoded()) } override fun deserialize(decoder: Decoder): Base32Crockford32B { return Base32Crockford32B(decoder.decodeString()) } } companion object { fun rand(): Base32Crockford32B = Base32Crockford32B(ByteArray(32).rand()) fun secureRand(): Base32Crockford32B = Base32Crockford32B(ByteArray(32).secureRand()) fun randEdsaKey(): EddsaPublicKey = randEdsaKeyPair().second fun randEdsaKeyPair(): Pair { val secretKey = ByteArray(32) Ed25519.generatePrivateKey(SECURE_RNG.get(), secretKey) val publicKey = ByteArray(32) Ed25519.generatePublicKey(secretKey, 0, publicKey, 0) return Pair(secretKey, Base32Crockford32B(publicKey)) } } } /** 64-byte Crockford's Base32 encoded data */ @Description("64-byte Crockford Base32 encoded data") @Serializable(with = Base32Crockford64B.Serializer::class) class Base32Crockford64B { private var encoded: String? = null val raw: ByteArray constructor(encoded: String) { val decoded = try { Base32Crockford.decode(encoded) } catch (e: IllegalArgumentException) { null } require(decoded != null && decoded.size == 64) { "expected 64 bytes encoded in Crockford's base32" } this.raw = decoded this.encoded = encoded } constructor(raw: ByteArray) { require(raw.size == 64) { "encoded data should be 64 bytes long" } this.raw = raw } fun encoded(): String { val tmp = encoded ?: Base32Crockford.encode(raw) encoded = tmp return tmp } override fun toString(): String { return encoded() } override fun equals(other: Any?) = (other is Base32Crockford64B) && raw.contentEquals(other.raw) internal object Serializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Base32Crockford64B", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: Base32Crockford64B) { encoder.encodeString(value.encoded()) } override fun deserialize(decoder: Decoder): Base32Crockford64B { return Base32Crockford64B(decoder.decodeString()) } } companion object { fun rand(): Base32Crockford64B = Base32Crockford64B(ByteArray(64).rand()) } } /** 32-byte hash code */ typealias ShortHashCode = Base32Crockford32B /** 64-byte hash code */ typealias HashCode = Base32Crockford64B typealias EddsaSignature = Base32Crockford64B /** * EdDSA and ECDHE public keys always point on Curve25519 * and represented using the standard 256 bits Ed25519 compact format, * converted to Crockford Base32. */ typealias EddsaPublicKey = Base32Crockford32B libeufin-1.6.8/libeufin-common/src/main/kotlin/api/0000775000175000017500000000000015236145704022421 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/kotlin/api/auth.kt0000664000175000017500000000437415122266731023730 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.api import io.ktor.http.* import io.ktor.server.response.* import io.ktor.server.routing.* import tech.libeufin.common.* import tech.libeufin.common.api.intercept /** Apply authentication api configuration for a route */ fun Route.apiAuth(auth: AuthMethod, callback: Route.() -> Unit): Route = intercept("Auth", callback) { if (auth != AuthMethod.None) { val header = this.request.headers[HttpHeaders.Authorization] val (expectedScheme, token) = when (auth) { is AuthMethod.Basic -> "Basic" to auth.token is AuthMethod.Bearer -> "Bearer" to auth.token else -> throw UnsupportedOperationException() } if (header == null) { this.response.header(HttpHeaders.WWWAuthenticate, expectedScheme) throw unauthorized( "Authorization header not found", TalerErrorCode.GENERIC_PARAMETER_MISSING ) } val (scheme, content) = header.splitOnce(" ") ?: throw badRequest( "Authorization is invalid", TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED ) if (scheme == expectedScheme) { if (content != token) { throw unauthorized("Unknown token", TalerErrorCode.GENERIC_TOKEN_UNKNOWN) } } else { throw unauthorized("Expected scheme $expectedScheme got '$scheme'") } } }libeufin-1.6.8/libeufin-common/src/main/kotlin/api/server.kt0000664000175000017500000003634115204341712024266 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.api import io.github.smiley4.ktoropenapi.OpenApi import io.github.smiley4.ktoropenapi.OpenApiPlugin import io.github.smiley4.ktoropenapi.config.* import io.github.smiley4.ktoropenapi.openApi import io.github.smiley4.schemakenerator.serialization.SerializationSteps.analyzeTypeUsingKotlinxSerialization import io.github.smiley4.schemakenerator.swagger.SwaggerSteps.compileReferencingRoot import io.github.smiley4.schemakenerator.swagger.SwaggerSteps.generateSwaggerSchema import io.github.smiley4.schemakenerator.swagger.SwaggerSteps.withTitle import io.github.smiley4.schemakenerator.swagger.SwaggerSteps.RequiredHandling import io.github.smiley4.schemakenerator.core.CoreSteps.addDiscriminatorProperty import io.github.smiley4.schemakenerator.core.CoreSteps.handleNameAnnotation import io.github.smiley4.schemakenerator.swagger.data.* import io.ktor.http.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* import io.ktor.server.engine.* import io.ktor.server.cio.* import io.ktor.server.plugins.* import io.ktor.server.plugins.calllogging.* import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.plugins.forwardedheaders.* import io.ktor.server.plugins.statuspages.* import io.ktor.server.plugins.callid.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.utils.io.* import io.ktor.util.* import io.ktor.util.pipeline.* import io.ktor.http.content.* import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import org.postgresql.util.PSQLState import org.slf4j.Logger import org.slf4j.event.Level import tech.libeufin.common.* import tech.libeufin.common.db.SERIALIZATION_ERROR import java.net.InetAddress import java.sql.SQLException import java.util.zip.DataFormatException import java.util.zip.Inflater /** Used to store the raw body */ private val RAW_BODY = AttributeKey("RAW_BODY") /** Used to set custom body limit */ val BODY_LIMIT = AttributeKey("BODY_LIMIT") /** Get call raw body */ val ApplicationCall.rawBody: ByteArray get() = attributes.getOrNull(RAW_BODY) ?: ByteArray(0) /** * This plugin apply Taler specific logic * It checks for body length limit and inflates the requests that have "Content-Encoding: deflate" * It logs incoming requests and their details */ fun talerPlugin(logger: Logger): ApplicationPlugin { return createApplicationPlugin("TalerPlugin") { onCall { call -> // Handle CORS call.response.header(HttpHeaders.AccessControlAllowOrigin, "*") // Handle CORS preflight if (call.request.httpMethod == HttpMethod.Options) { call.response.header(HttpHeaders.AccessControlAllowHeaders, "*") call.response.header(HttpHeaders.AccessControlAllowMethods, "*") call.respond(HttpStatusCode.NoContent) return@onCall } // Log incoming transaction val requestCall = buildString { val path = call.request.path() append(call.request.httpMethod.value) append(' ') append(call.request.path()) val query = call.request.queryString() if (query.isNotEmpty()) { append('?') append(query) } } logger.info(requestCall) } onCallReceive { call -> val bodyLimit = call.attributes.getOrNull(BODY_LIMIT) ?: MAX_BODY_LENGTH // Check content length if present and wellformed val contentLenght = call.request.headers[HttpHeaders.ContentLength]?.toIntOrNull() if (contentLenght != null && contentLenght > bodyLimit) throw bodyOverflow("Body is suspiciously big > ${bodyLimit}B") // Else check while reading and decompressing the body transformBody { body -> val bytes = ByteArray(bodyLimit + 1) var read = 0 when (val encoding = call.request.headers[HttpHeaders.ContentEncoding]) { "deflate" -> { // Decompress and check decompressed length val inflater = Inflater() while (!body.isClosedForRead) { body.read { buf -> inflater.setInput(buf) try { read += inflater.inflate(bytes, read, bytes.size - read) } catch (e: DataFormatException) { logger.error("Deflated request failed to inflate: ${e.message}") throw badRequest( "Could not inflate request", TalerErrorCode.GENERIC_COMPRESSION_INVALID ) } } if (read > bodyLimit) throw bodyOverflow("Decompressed body is suspiciously big > ${bodyLimit}B") } } null -> { // Check body length while (true) { val new = body.readAvailable(bytes, read, bytes.size - read) if (new == -1) break // Channel is closed read += new if (read > bodyLimit) throw bodyOverflow("Body is suspiciously big > ${bodyLimit}B") } } else -> throw unsupportedMediaType( "Content encoding '$encoding' not supported, expected plain or deflate", TalerErrorCode.GENERIC_COMPRESSION_INVALID ) } logger.trace { "request ${bytes.sliceArray(0 until read).asUtf8()}" } call.attributes.put(RAW_BODY, bytes) ByteReadChannel(bytes, 0, read) } } } } data class OpenApiInfo( val title: String, val version: String, val description: String? = null, val securityConfig: SecurityConfig.() -> Unit ) /** Set up web server handlers for a Taler API */ fun Application.talerApi(logger: Logger, openApiInfo: OpenApiInfo? = null, serveSpec: Boolean = false, routes: Routing.() -> Unit) { if (openApiInfo != null) { install(OpenApi) { info { title = openApiInfo.title version = openApiInfo.version description = openApiInfo.description } server { url = "/" description = "Same host" } security(openApiInfo.securityConfig) outputFormat = OutputFormat.YAML schemas { generator = { type -> type .analyzeTypeUsingKotlinxSerialization() .handleNameAnnotation() .addDiscriminatorProperty("type") .generateSwaggerSchema { nullables = RequiredHandling.NON_REQUIRED optionals = RequiredHandling.REQUIRED } .withTitle(TitleType.MINIMAL) .compileReferencingRoot( explicitNullTypes = false, pathType = RefType.OPENAPI_MINIMAL ) } } } } install(CallId) { generate(10, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") verify { true } } install(CallLogging) { callIdMdc("call-id") level = Level.INFO this.logger = logger format { call -> val status = call.response.status() val msg = call.logMsg() if (msg != null) { "${status?.value} ${call.processingTimeMillis()}ms: $msg" } else { "${status?.value} ${call.processingTimeMillis()}ms" } } } install(XForwardedHeaders) install(talerPlugin(logger)) install(IgnoreTrailingSlash) install(ContentNegotiation) { json(Json { @OptIn(ExperimentalSerializationApi::class) explicitNulls = false encodeDefaults = true ignoreUnknownKeys = true }) } install(StatusPages) { status(HttpStatusCode.NotFound) { call, status -> call.err( status, "There is no endpoint defined for the URL provided by the client. Check if you used the correct URL and/or file a report with the developers of the client software.", TalerErrorCode.GENERIC_ENDPOINT_UNKNOWN, null ) } status(HttpStatusCode.MethodNotAllowed) { call, status -> call.err( status, "The HTTP method used is invalid for this endpoint. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers.", TalerErrorCode.GENERIC_METHOD_INVALID, null ) } exception { call, cause -> logger.debug("", cause) when (cause) { is ApiException -> call.err(cause, null) is SQLException -> { if (SERIALIZATION_ERROR.contains(cause.sqlState)) { call.err( HttpStatusCode.InternalServerError, "Transaction serialization failure", TalerErrorCode.BANK_SOFT_EXCEPTION, cause ) } else { call.err( HttpStatusCode.InternalServerError, "Unexpected sql error with state ${cause.sqlState}", TalerErrorCode.BANK_UNMANAGED_EXCEPTION, cause ) } } is BadRequestException -> { /** * NOTE: extracting the root cause helps with JSON error messages, * because they mention the particular way they are invalid, but OTOH * it loses (by getting null) other error messages, like for example * the one from MissingRequestParameterException. Therefore, in order * to get the most detailed message, we must consider BOTH sides: * the 'cause' AND its root cause! */ var rootCause: Throwable? = cause.cause while (rootCause?.cause != null) rootCause = rootCause.cause // Telling apart invalid JSON vs missing parameter vs invalid parameter. val errorCode = when { cause is MissingRequestParameterException -> TalerErrorCode.GENERIC_PARAMETER_MISSING cause is ParameterConversionException -> TalerErrorCode.GENERIC_PARAMETER_MALFORMED rootCause is CommonError -> when (rootCause) { is CommonError.AmountFormat -> TalerErrorCode.BANK_BAD_FORMAT_AMOUNT is CommonError.AmountNumberTooBig -> TalerErrorCode.BANK_NUMBER_TOO_BIG is CommonError.Payto -> TalerErrorCode.GENERIC_JSON_INVALID } else -> TalerErrorCode.GENERIC_JSON_INVALID } call.err( HttpStatusCode.BadRequest, rootCause?.message, errorCode, null ) } is CommonError -> { val errorCode = when (cause) { is CommonError.AmountFormat -> TalerErrorCode.BANK_BAD_FORMAT_AMOUNT is CommonError.AmountNumberTooBig -> TalerErrorCode.BANK_NUMBER_TOO_BIG is CommonError.Payto -> TalerErrorCode.GENERIC_JSON_INVALID } call.err( HttpStatusCode.BadRequest, cause.message, errorCode, null ) } else -> { call.err( HttpStatusCode.InternalServerError, cause.message, TalerErrorCode.BANK_UNMANAGED_EXCEPTION, cause ) } } } } val phase = PipelinePhase("phase") sendPipeline.insertPhaseBefore(ApplicationSendPipeline.Engine, phase) sendPipeline.intercept(phase) { response -> if (logger.isTraceEnabled) { if (response is OutgoingContent.ByteArrayContent) { logger.trace("response ${String(response.bytes())}") } } } routing { routes() if (serveSpec) { route("openapi.yaml") { openApi() } } } } // Dirty local variable to stop the server in test TODO remove this ugly hack var engine: ApplicationEngine? = null fun serve(cfg: tech.libeufin.common.ServerConfig, logger: Logger, api: Application.() -> Unit) { val server = embeddedServer(CIO, configure = { when (cfg) { is ServerConfig.Tcp -> { for (addr in InetAddress.getAllByName(cfg.addr)) { logger.info("Listening on ${addr.hostAddress}:${cfg.port}") connector { port = cfg.port host = addr.hostAddress } } } is ServerConfig.Unix -> { logger.info("Listening on ${cfg.path}") unixConnector(cfg.path.toString()) } } }, module = api ) engine = server.engine server.start(wait = true) } libeufin-1.6.8/libeufin-common/src/main/kotlin/api/route.kt0000664000175000017500000000270515204341712024113 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.api import io.ktor.server.application.* import io.ktor.server.routing.* import io.ktor.util.pipeline.* fun Route.intercept(name: String, build: Route.() -> Unit, lambda: suspend ApplicationCall.() -> Unit): Route { val plugin = createRouteScopedPlugin(name) { onCall { call -> call.lambda() } } val subRoute = createChild(TransparentRouteSelector()) subRoute.install(plugin) subRoute.build() return subRoute } private class TransparentRouteSelector : RouteSelector() { override suspend fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation = RouteSelectorEvaluation.Transparent override fun toString(): String = "" } libeufin-1.6.8/libeufin-common/src/main/kotlin/Subject.kt0000664000175000017500000002324415156463305023615 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import org.bouncycastle.math.ec.rfc8032.Ed25519 import java.math.BigInteger import java.security.MessageDigest sealed interface IncomingSubject { data class Reserve(val reserve_pub: EddsaPublicKey): IncomingSubject data class Kyc(val account_pub: EddsaPublicKey): IncomingSubject data class Map(val auth_pub: EddsaPublicKey): IncomingSubject data object AdminBalanceAdjust: IncomingSubject val type: IncomingType get() = when (this) { is Reserve -> IncomingType.reserve is Kyc -> IncomingType.kyc is Map -> IncomingType.map AdminBalanceAdjust -> throw IllegalStateException("Admin balance adjust") } val key: EddsaPublicKey get() = when (this) { is Reserve -> this.reserve_pub is Kyc -> this.account_pub is Map -> this.auth_pub AdminBalanceAdjust -> throw IllegalStateException("Admin balance adjust") } } /** Base32 quality by proximity to spec and error probability */ private enum class Base32Quality { /// Both mixed casing and mixed characters, that's weird Mixed, /// Standard but use lowercase, maybe the client shown lowercase in the UI Standard, /// Uppercase but mixed characters, its common when making typos Upper, /// Both uppercase and use the standard alphabet as it should UpperStandard; companion object { fun measure(s: String): Base32Quality { var uppercase = true; var standard = true; for (char in s) { uppercase = uppercase && char.isUpperCase() standard = standard && Base32Crockford.ALPHABET.contains(char) } return if (uppercase && standard) { Base32Quality.UpperStandard } else if (uppercase && !standard) { Base32Quality.Upper } else if (!uppercase && standard) { Base32Quality.Standard } else { Base32Quality.Mixed } } } } private data class Candidate(val subject: IncomingSubject, val quality: Base32Quality) private const val ADMIN_BALANCE_ADJUST = "ADMINBALANCEADJUST" private const val KEY_SIZE = 52; private const val PREFIX_SIZE = KEY_SIZE + 3; private val ALPHA_NUMBERIC_PATTERN = Regex("[0-9a-zA-Z]*") /** * Extract the public key from an unstructured incoming transfer subject. * * When a user enters the transfer object in an unstructured way, for ex in * their banking UI, they may mistakenly enter separators such as ' \n-+' and * make typos. * To parse them while ignoring user errors, we reconstruct valid keys from key * parts, resolving ambiguities where possible. **/ fun parseIncomingSubject(subject: String?): IncomingSubject { if (subject == null || subject.isEmpty()) { throw Exception("missing subject") } /** Parse an incoming subject */ fun parseSingle(str: String): Candidate? { // Check key type val (type, raw) = when (str.length) { ADMIN_BALANCE_ADJUST.length -> if (str.equals(ADMIN_BALANCE_ADJUST, ignoreCase = true)) { return Candidate(IncomingSubject.AdminBalanceAdjust, Base32Quality.UpperStandard) } else { return null } KEY_SIZE -> Pair(IncomingType.reserve, str) PREFIX_SIZE -> if (str.startsWith("KYC")) { Pair(IncomingType.kyc, str.substring(3)) } else if (str.startsWith("MAP")) { Pair(IncomingType.map, str.substring(3)) } else { return null } else -> return null } // Check key validity val key = try { EddsaPublicKey(raw) } catch (e: Exception) { return null } if (!Ed25519.validatePublicKeyFull(key.raw, 0)) { return null } val quality = Base32Quality.measure(raw); val subject = when (type) { IncomingType.map -> IncomingSubject.Map(key) IncomingType.kyc -> IncomingSubject.Kyc(key) IncomingType.reserve -> IncomingSubject.Reserve(key) } return Candidate(subject, quality) } // Find and concatenate valid parts of a keys val parts = mutableListOf(0) val concatenated = StringBuilder() for (match in ALPHA_NUMBERIC_PATTERN.findAll(subject.replace("%20", " "))) { concatenated.append(match.value); parts.add(concatenated.length); } // Find best candidates var best: Candidate? = null // For each part as a starting point for ((i, start) in parts.withIndex()) { // Use progressively longer concatenation for (end in parts.subList(i, parts.size)) { val range = start until end // Until they are to long to be a key if (range.count() > PREFIX_SIZE) { break; } // Parse the concatenated parts val slice = concatenated.substring(range) parseSingle(slice)?.let { other -> if (best != null) { if (best.subject is IncomingSubject.AdminBalanceAdjust) { if (other.subject !is IncomingSubject.AdminBalanceAdjust) { throw Exception("found multiple subject kind") } } else if (other.quality > best.quality // We prefer high quality keys || ( // We prefer prefixed keys over reserve keys best.subject.type == IncomingType.reserve && (other.subject.type == IncomingType.kyc || other.subject.type == IncomingType.map) )) { best = other } else if (best.subject.key != other.subject.key // If keys are different && best.quality == other.quality // Of same quality && !( // And prefixing is different (best.subject.type == IncomingType.kyc || best.subject.type == IncomingType.map) && other.subject.type == IncomingType.reserve )) { throw Exception("found multiple reserve public key") } } else { best = other } } } } return best?.subject ?: throw Exception("missing reserve public key") } /** Extract the reserve public key from an incoming Taler transaction subject */ fun parseOutgoingSubject(subject: String): Triple { var iterator = subject.splitToSequence(' ').iterator(); val first = iterator.next() if (!iterator.hasNext()) throw Exception("malformed outgoing subject") val second = iterator.next() if (iterator.hasNext()) { val third = iterator.next() return Triple(EddsaPublicKey(second), BaseURL.parse(third), first) } else { return Triple(EddsaPublicKey(first), BaseURL.parse(second), null) } } /** Format an outgoing subject */ fun fmtOutgoingSubject(wtid: ShortHashCode, url: BaseURL, metadata: String? = null): String = buildString { if (metadata != null) { append(metadata) append(" ") } append(wtid) append(" ") append(url) } /** Format an incoming subject */ fun fmtIncomingSubject(type: IncomingType, key: EddsaPublicKey): String = buildString { append("Taler ") when (type) { IncomingType.kyc -> append("KYC:") IncomingType.map -> append("MAP:") IncomingType.reserve -> Unit } append(key) } /** Encode a public key as a QR-Bill reference */ fun subjectFmtQrBill(key: EddsaPublicKey): String { // High-Entropy Hash (SHA-256) to ensure even distribution val digest = MessageDigest.getInstance("SHA-256") val hashInt = BigInteger(1, digest.digest(key.raw)) // Modulo 10^26 to fit the Swiss QR data field val divisor = BigInteger.TEN.pow(26) val referenceBase = hashInt.remainder(divisor).toString().padStart(26, '0') // Modulo 10 Recursive calculation val lookupTable = intArrayOf(0, 9, 4, 6, 8, 2, 7, 1, 3, 5) var carry = 0 for (char in referenceBase) { val digit = char.digitToInt() carry = lookupTable[(carry + digit) % 10] } val checksum = (10 - carry) % 10 return referenceBase + checksum } /** Check if a subject is a valid QR-Bill reference */ fun subjectIsQrBill(reference: String): Boolean { // Quick length and numeric check if (reference.length != 27 || !reference.all { it.isDigit() }) { return false } // Modulo 10 Recursive check val lookupTable = intArrayOf(0, 9, 4, 6, 8, 2, 7, 1, 3, 5) var carry = 0 for (char in reference) { val digit = char.digitToInt() carry = lookupTable[(carry + digit) % 10] } // If the check digit was correct, the final carry will be 0 return carry == 0 }libeufin-1.6.8/libeufin-common/src/main/kotlin/log.kt0000664000175000017500000001026415122266731022772 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentHashMap; import org.slf4j.event.Level; import org.slf4j.Logger; import org.slf4j.Marker; import org.slf4j.ILoggerFactory; import org.slf4j.IMarkerFactory; import org.slf4j.helpers.LegacyAbstractLogger; import org.slf4j.helpers.MessageFormatter; import org.slf4j.helpers.BasicMarkerFactory; import org.slf4j.helpers.BasicMDCAdapter; import org.slf4j.spi.MDCAdapter; import org.slf4j.spi.SLF4JServiceProvider; import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.io.PrintStream class TalerLogger(private val loggerName: String): LegacyAbstractLogger() { private fun isLevelEnabled(level: Level): Boolean = level.toInt() >= TalerServiceProvider.currentLevel.toInt() override fun isTraceEnabled(): Boolean = isLevelEnabled(Level.TRACE) override fun isDebugEnabled(): Boolean = isLevelEnabled(Level.DEBUG) override fun isInfoEnabled(): Boolean = isLevelEnabled(Level.INFO) override fun isWarnEnabled(): Boolean = isLevelEnabled(Level.WARN) override fun isErrorEnabled(): Boolean = isLevelEnabled(Level.ERROR) override fun getFullyQualifiedCallerName(): String = loggerName override fun handleNormalizedLoggingCall(level: Level, marker: Marker?, messagePattern: String?, arguments: Array?, throwable: Throwable?) { val name = fullyQualifiedCallerName; if ( !isLevelEnabled(level) || (name.startsWith("io.ktor") && level.toInt() < Level.WARN.toInt()) || name.startsWith("com.zaxxer.hikari") ) return val callId = org.slf4j.MDC.get("call-id") val logEntry = buildString { if (timestampFmt != null) { append(LocalDateTime.now().format(timestampFmt)) append(' ') } if (callId != null) { append(callId) append(' ') } append(level.name.padEnd(5)) append(' ') append(name) append(" - ") append(MessageFormatter.basicArrayFormat(messagePattern, arguments)) throwable?.let { t -> append("${t.javaClass.simpleName}: ${t.message}") t.stackTrace.take(10).forEach { stackElement -> append("\n\tat $stackElement") } } } System.err.println(logEntry) } companion object { // We skip logging timestamp if systemd is used private val skipTimestamp = System.getenv("JOURNAL_STREAM") != null // A null timestamp formatter mean we should skip it private val timestampFmt = if (skipTimestamp) null else DateTimeFormatter.ofPattern("dd-MMM-yyyy'T'HH:mm:ss.SSS") } } class TalerServiceProvider: SLF4JServiceProvider { private val markerFactory = BasicMarkerFactory() private val mdcAdapter = BasicMDCAdapter() override fun getLoggerFactory() = TalerServiceProvider override fun getMarkerFactory() = markerFactory override fun getMDCAdapter() = mdcAdapter override fun getRequestedApiVersion() = "2.0.99" override fun initialize() {} companion object: ILoggerFactory { var currentLevel = Level.TRACE private val loggerMap: ConcurrentMap = ConcurrentHashMap() override fun getLogger(name: String): Logger = loggerMap.computeIfAbsent(name, ::TalerLogger) } }libeufin-1.6.8/libeufin-common/src/main/kotlin/db/0000775000175000017500000000000015236145704022235 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/kotlin/db/schema.kt0000664000175000017500000001044015122266731024032 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.db import org.postgresql.ds.* import org.postgresql.jdbc.PgConnection import java.sql.Connection import kotlin.io.path.Path import kotlin.io.path.exists import kotlin.io.path.readText /** * Only runs versioning.sql if the _v schema is not found. * * @param conn database connection * @param cfg database configuration */ private fun maybeApplyV(conn: PgConnection, cfg: DatabaseConfig) { conn.transaction { val checkVSchema = conn.talerStatement( "SELECT schema_name FROM information_schema.schemata WHERE schema_name = '_v'" ) if (!checkVSchema.executeQueryCheck()) { logger.debug("_v schema not found, applying versioning.sql") val sqlVersioning = Path("${cfg.sqlDir}/versioning.sql").readText() conn.execSQLUpdate(sqlVersioning) } } } private fun migrationsPath(sqlFilePrefix: String): Sequence = sequence { for (n in 1..9999) { val padded = n.toString().padStart(4, '0') yield("$sqlFilePrefix-$padded") } } // sqlFilePrefix is, for example, "libeufin-bank" or "libeufin-nexus" (no trailing dash). private fun initializeDatabaseTables(conn: PgConnection, cfg: DatabaseConfig, sqlFilePrefix: String) { logger.info("doing DB initialization, sqldir ${cfg.sqlDir}") maybeApplyV(conn, cfg) conn.transaction { val checkStmt = conn.talerStatement("SELECT EXISTS(SELECT FROM _v.patches where patch_name = ?)") for (patchName in migrationsPath(sqlFilePrefix)) { checkStmt.bind(patchName) val applied = checkStmt.one { it.getBoolean(1) } if (applied) { logger.debug("patch $patchName already applied") continue } val path = Path("${cfg.sqlDir}/$patchName.sql") if (!path.exists()) { logger.debug("path {} doesn't exist anymore, stopping", path) break } logger.info("applying patch $path") conn.execSQLUpdate(path.readText()) } val sqlProcedures = Path("${cfg.sqlDir}/$sqlFilePrefix-procedures.sql") if (!sqlProcedures.exists()) { logger.warn("no procedures.sql for the SQL collection: $sqlFilePrefix") return@transaction } logger.info("run procedure.sql") conn.execSQLUpdate(sqlProcedures.readText()) } } internal fun checkMigrations(conn: PgConnection, cfg: DatabaseConfig, sqlFilePrefix: String) { val checkStmt = conn.talerStatement("SELECT EXISTS(SELECT FROM _v.patches where patch_name = ?)") for (patchName in migrationsPath(sqlFilePrefix)) { checkStmt.bind(patchName) val path = Path("${cfg.sqlDir}/$patchName.sql") if (!path.exists()) break val applied = checkStmt.one { it.getBoolean(1) } if (!applied) { throw Exception("patch $patchName not applied, run '$sqlFilePrefix dbinit'") } } } // sqlFilePrefix is, for example, "libeufin-bank" or "libeufin-nexus" (no trailing dash). private fun resetDatabaseTables(conn: PgConnection, cfg: DatabaseConfig, sqlFilePrefix: String) { logger.info("reset DB, sqldir ${cfg.sqlDir}") val sqlDrop = Path("${cfg.sqlDir}/$sqlFilePrefix-drop.sql").readText() conn.execSQLUpdate(sqlDrop) } fun PGSimpleDataSource.dbInit(cfg: DatabaseConfig, sqlFilePrefix: String, reset: Boolean) { pgConnection().use { conn -> if (reset) { resetDatabaseTables(conn, cfg, sqlFilePrefix) } initializeDatabaseTables(conn, cfg, sqlFilePrefix) } }libeufin-1.6.8/libeufin-common/src/main/kotlin/db/transaction.kt0000664000175000017500000000510415122266731025120 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.db import org.postgresql.jdbc.PgConnection import org.postgresql.util.PSQLState import tech.libeufin.common.SERIALIZATION_RETRY import java.sql.PreparedStatement import java.sql.ResultSet import java.sql.SQLException val SERIALIZATION_ERROR = setOf( "40001", // serialization_failure "40P01", // deadlock_detected "55P03", // lock_not_available ) /** Executes db logic with automatic retry on serialization errors */ suspend fun retrySerializationError(lambda: suspend () -> R): R { repeat(SERIALIZATION_RETRY) { try { return lambda() } catch (e: SQLException) { if (!SERIALIZATION_ERROR.contains(e.sqlState)) throw e } } return lambda() } fun PgConnection.talerStatement(query: String): TalerStatement = TalerStatement(prepareStatement(query)) /** Run a postgres query using a prepared statement */ inline fun PgConnection.withStatement(query: String, lambda: TalerStatement.() -> R): R = talerStatement(query).use { it.lambda() } /** Run a postgres [transaction] */ fun PgConnection.transaction(transaction: (PgConnection) -> R): R { try { autoCommit = false val result = transaction(this) commit() autoCommit = true return result } catch (e: Exception) { rollback() autoCommit = true throw e } } /** * Execute an update of [table] with a dynamic query generated at runtime. * Every [fields] in each row matching [filter] are updated using values from [bind]. **/ fun PgConnection.dynamicUpdate( table: String, fields: Sequence, filter: String, bind: TalerStatement.() -> Unit, ) { val sql = fields.joinToString() if (sql.isEmpty()) return withStatement("UPDATE $table SET $sql $filter") { bind() executeUpdate() } }libeufin-1.6.8/libeufin-common/src/main/kotlin/db/types.kt0000664000175000017500000001010015156463305023732 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.db import tech.libeufin.common.* import java.sql.* import java.time.* import java.util.* fun optAmount(amount: TalerAmount?): String { if (amount != null) { return "(?,?)::taler_amount" } else { return "NULL" } } fun optDecimal(nb: DecimalNumber?): String { if (nb != null) { return "(?,?)::taler_amount" } else { return "NULL" } } inline fun > ResultSet.getEnum(name: String): T = java.lang.Enum.valueOf(T::class.java, getString(name)) inline fun > ResultSet.getEnum(idx: Int): T = java.lang.Enum.valueOf(T::class.java, getString(idx)) inline fun > ResultSet.getOptEnum(name: String): T? = getString(name)?.run { java.lang.Enum.valueOf(T::class.java, this) } inline fun > ResultSet.getOptEnum(idx: Int): T? = getString(idx)?.run { java.lang.Enum.valueOf(T::class.java, this) } inline fun > ResultSet.getEnumSet(name: String): Set { val sqlArray: java.sql.Array = this.getArray(name) val javaArray: Array = (sqlArray.array as Array) val set: Set = javaArray.map { java.lang.Enum.valueOf(T::class.java, it) }.toSet() sqlArray.free() return set } inline fun ResultSet.getOptObject(column: String): T? { val value = this.getObject(column, T::class.java) return if (this.wasNull()) null else value as T } fun ResultSet.getOptKey(column: String): EddsaPublicKey? { val bytes = this.getBytes(column) return if (this.wasNull()) null else EddsaPublicKey(bytes) } fun ResultSet.getOptSig(column: String): EddsaSignature? { val bytes = this.getBytes(column) return if (this.wasNull()) null else EddsaSignature(bytes) } fun ResultSet.getOptLong(name: String): Long? { val nb = getLong(name) if (wasNull()) return null return nb } fun ResultSet.getAmount(name: String, currency: String): TalerAmount { return TalerAmount( getLong("${name}_val"), getInt("${name}_frac"), currency ) } fun ResultSet.getOptAmount(name: String, currency: String): TalerAmount? { val amount = getAmount(name, currency) if (wasNull()) return null return amount } fun ResultSet.getDecimal(name: String): DecimalNumber { return DecimalNumber( getLong("${name}_val"), getInt("${name}_frac") ) } fun ResultSet.getOptDecimal(name: String): DecimalNumber? { val amount = getDecimal(name) if (wasNull()) return null return amount } fun ResultSet.getTalerTimestamp(name: String): TalerTimestamp{ return TalerTimestamp(getLong(name).asInstant()) } fun ResultSet.getBankPayto(payto: String, name: String?, ctx: BankPaytoCtx): String { return Payto.parse(getString(payto)).bank( name?.let { getString(it) } , ctx) } fun ResultSet.getOptBankPayto(payto: String, name: String?, ctx: BankPaytoCtx): String? { val payto = getString(payto) if (payto == null) return null return Payto.parse(payto).bank( name?.let { getString(it) } , ctx) } fun ResultSet.getOptIbanPayto(payto: String): IbanPayto? { val raw = getString(payto) if (raw == null) return null return Payto.parse(raw).expectIban() } fun ResultSet.getIbanPayto(payto: String): IbanPayto { return Payto.parse(getString(payto)).expectIban() }libeufin-1.6.8/libeufin-common/src/main/kotlin/db/statement.kt0000664000175000017500000001407515122266731024606 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.db import org.slf4j.Logger import org.slf4j.LoggerFactory import org.postgresql.util.PSQLState import tech.libeufin.common.* import java.sql.* import java.time.* import java.util.* internal val logger: Logger = LoggerFactory.getLogger("libeufin-db") class TalerStatement(internal val stmt: PreparedStatement): java.io.Closeable { override fun close() { // Close inner statement stmt.close() } private fun consume() { // Log warnings var current = stmt.getWarnings() while (current != null) { logger.warn(current.message) current = current.getNextWarning() } // Reset params stmt.clearParameters() idx=1 } /* ----- Bindings helpers ----- */ private var idx = 1; fun bind(string: String?) { stmt.setString(idx, string) idx+=1; } fun bind(bool: Boolean) { stmt.setBoolean(idx, bool) idx+=1; } fun bind(nb: Long?) { if (nb != null) { stmt.setLong(idx, nb) } else { stmt.setNull(idx, Types.INTEGER) } idx+=1; } fun bind(nb: Int) { stmt.setInt(idx, nb) idx+=1; } fun bind(amount: TalerAmount?) { bind(amount?.number()) } fun bind(nb: DecimalNumber?) { if (nb != null) { stmt.setLong(idx, nb.value) stmt.setInt(idx+1, nb.frac) idx+=2 } } fun bind(timestamp: Instant) { stmt.setLong(idx, timestamp.micros()) idx+=1 } fun bind(bytes: Base32Crockford64B?) { stmt.setBytes(idx, bytes?.raw) idx+=1 } fun bind(bytes: Base32Crockford32B?) { stmt.setBytes(idx, bytes?.raw) idx+=1 } fun bind(bytes: Base32Crockford16B?) { stmt.setBytes(idx, bytes?.raw) idx+=1 } fun bind(bytes: ByteArray?) { stmt.setBytes(idx, bytes) idx+=1 } fun > bind(enum: T?) { bind(enum?.name) } fun bind(date: LocalDateTime) { stmt.setObject(idx, date) idx+=1 } fun bind(uuid: UUID?) { stmt.setObject(idx, uuid) idx+=1 } fun > bind(array: Array) { val sqlArray = stmt.connection.createArrayOf("text", array) stmt.setArray(idx, sqlArray) idx+=1 } fun bind(array: Array) { val sqlArray = stmt.connection.createArrayOf("text", array) stmt.setArray(idx, sqlArray) idx+=1 } fun bind(array: Array) { val sqlArray = stmt.connection.createArrayOf("uuid", array) stmt.setArray(idx, sqlArray) idx+=1 } /* ----- Transaction helpers ----- */ fun executeQuery(): ResultSet { return try { stmt.executeQuery() } finally { consume() } } fun executeUpdate(): Int { return try { stmt.executeUpdate() } finally { consume() } } /** Read one row or null if none */ fun oneOrNull(lambda: (ResultSet) -> T): T? { return executeQuery().use { if (it.next()) lambda(it) else null } } /** Read one row or throw if none */ fun one(lambda: (ResultSet) -> T): T = requireNotNull(oneOrNull(lambda)) { "Missing result to database query" } /** Read one row or throw [err] in case or unique violation error */ fun oneUniqueViolation(err: T, lambda: (ResultSet) -> T): T { return try { one(lambda) } catch (e: SQLException) { if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) return err throw e // rethrowing, not to hide other types of errors. } } /** Read all rows */ fun all(lambda: (ResultSet) -> T): List { return executeQuery().use { val ret = mutableListOf() while (it.next()) { ret.add(lambda(it)) } ret } } /** Execute a query checking it return a least one row */ fun executeQueryCheck(): Boolean { return executeQuery().use { it.next() } } /** Execute an update checking it update at least one row */ fun executeUpdateCheck(): Boolean { executeUpdate() return stmt.updateCount > 0 } /** Execute an update checking if fail because of unique violation error */ fun executeUpdateViolation(): Boolean { return try { executeUpdateCheck() } catch (e: SQLException) { logger.debug(e.message) if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) return false throw e // rethrowing, not to hide other types of errors. } } /** Execute an update checking if fail because of unique violation error and resetting state */ fun executeProcedureViolation(): Boolean { val savepoint = stmt.connection.setSavepoint() return try { executeUpdate() stmt.connection.releaseSavepoint(savepoint) true } catch (e: SQLException) { stmt.connection.rollback(savepoint) if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) return false throw e // rethrowing, not to hide other types of errors. } } }libeufin-1.6.8/libeufin-common/src/main/kotlin/db/config.kt0000664000175000017500000000633415122266731024046 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.db import io.ktor.http.* import org.postgresql.ds.PGSimpleDataSource import org.postgresql.jdbc.PgConnection import java.net.URI import java.nio.file.Path fun currentUser(): String = System.getProperty("user.name") /** * This function converts postgresql:// URIs to JDBC URIs. * * URIs that are already jdbc: URIs are passed through. * * This avoids the user having to create complex JDBC URIs for postgres connections. * They are especially complex when using unix domain sockets, as they're not really * supported natively by JDBC. */ fun jdbcFromPg(pgConn: String): String { // Pass through jdbc URIs. if (pgConn.startsWith("jdbc:")) { return pgConn } require(pgConn.startsWith("postgresql://") || pgConn.startsWith("postgres://")) { "Not a Postgres connection string: $pgConn" } val uri = URI(pgConn) val params = parseQueryString(uri.query ?: "", decode = false) val host = uri.host ?: params["host"] ?: System.getenv("PGHOST") if (host == null || host.startsWith('/')) { val port = (if (uri.port == -1) null else uri.port.toString()) ?: params["port"] ?: System.getenv("PGPORT") ?: "5432" val user = params["user"] ?: currentUser() val unixPath = (host ?:"/var/run/postgresql") + "/.s.PGSQL.$port" return "jdbc:postgresql://localhost${uri.path}?user=$user&socketFactory=org.newsclub.net.unix." + "AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=$unixPath" } if (pgConn.startsWith("postgres://")) { // The JDBC driver doesn't like postgres://, only postgresql://. // For consistency with other components, we normalize the postgres:// URI // into one that the JDBC driver likes. return "jdbc:postgresql://" + pgConn.removePrefix("postgres://") } logger.info("connecting to database via JDBC string '$pgConn'") return "jdbc:$pgConn" } data class DatabaseConfig( val dbConnStr: String, val sqlDir: Path ) fun pgDataSource(dbConfig: String): PGSimpleDataSource { val jdbcConnStr = jdbcFromPg(dbConfig) logger.debug("connecting to database via JDBC string '$jdbcConnStr'") val pgSource = PGSimpleDataSource() pgSource.setUrl(jdbcConnStr) pgSource.prepareThreshold = 1 return pgSource } fun PGSimpleDataSource.pgConnection(schema: String? = null): PgConnection { val conn = connection.unwrap(PgConnection::class.java) if (schema != null) conn.execSQLUpdate("SET search_path TO $schema") return conn } libeufin-1.6.8/libeufin-common/src/main/kotlin/db/helpers.kt0000664000175000017500000001217115236062741024240 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.db import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeoutOrNull import tech.libeufin.common.HistoryParams import tech.libeufin.common.PageParams import java.sql.PreparedStatement import java.sql.ResultSet import kotlin.math.abs import kotlin.math.min /** * Hard upper bound on the number of records returned by a single * query, regardless of the limit requested by the client. */ private const val MAX_RECORDS: Long = 50_000 /** Apply paging logic to a sql query */ suspend fun DbPool.page( params: PageParams, idName: String, query: String, args: TalerStatement.() -> Unit = {}, map: (ResultSet) -> T ): List { val backward = params.limit < 0 val pageQuery = """ $query $idName ${if (backward) '<' else '>'} ? ORDER BY $idName ${if (backward) "DESC" else "ASC"} LIMIT ? """ return serializable(pageQuery) { args() bind(params.offset) // Widen before abs(): abs(Int.MIN_VALUE) is Int.MIN_VALUE, which would // reach Postgres as a negative LIMIT. bind(min(MAX_RECORDS, abs(params.limit.toLong()))) all { map(it) } } } /** * The following function returns the list of transactions, according * to the history parameters and perform long polling when necessary */ suspend fun DbPool.poolHistory( params: HistoryParams, bankAccountId: Long, listen: suspend (Long, suspend (Flow) -> List) -> List, query: String, accountColumn: String = "bank_account_id", map: (ResultSet) -> T ): List { suspend fun load(): List = page( params.page, "bank_transaction_id", "$query $accountColumn=? AND", { bind(bankAccountId) }, map ) // When going backward there is always at least one transaction or none return if (params.page.limit >= 0 && params.polling.timeout_ms > 0) { listen(bankAccountId) { flow -> coroutineScope { // Start buffering notification before loading transactions to not miss any val polling = launch { withTimeoutOrNull(params.polling.timeout_ms) { flow.first { it > params.page.offset } // Always forward so > } } // Initial loading val init = load() // Long polling if we found no transactions if (init.isEmpty()) { if (polling.join() != null) { load() } else { init } } else { polling.cancel() init } } } } else { load() } } /** * The following function returns the list of transactions, according * to the history parameters and perform long polling when necessary */ suspend fun DbPool.poolHistoryGlobal( params: HistoryParams, listen: suspend (suspend (Flow) -> List) -> List, query: String, idColumnValue: String, map: (ResultSet) -> T ): List { suspend fun load(): List = page( params.page, idColumnValue, query, map=map ) // When going backward there is always at least one transaction or none return if (params.page.limit >= 0 && params.polling.timeout_ms > 0) { listen { flow -> coroutineScope { // Start buffering notification before loading transactions to not miss any val polling = launch { withTimeoutOrNull(params.polling.timeout_ms) { flow.first { it > params.page.offset } // Always forward so > } } // Initial loading val init = load() // Long polling if we found no transactions if (init.isEmpty()) { if (polling.join() != null) { load() } else { init } } else { polling.cancel() init } } } } else { load() } }libeufin-1.6.8/libeufin-common/src/main/kotlin/db/notifications.kt0000664000175000017500000000635115122266731025451 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.db import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.runBlocking import org.postgresql.ds.PGSimpleDataSource import org.slf4j.Logger import tech.libeufin.common.ExpoBackoffDecorr import tech.libeufin.common.fmtLog import java.util.concurrent.ConcurrentHashMap // SharedFlow that are manually counted for manual garbage collection class CountedSharedFlow { val flow: MutableSharedFlow = MutableSharedFlow() var count: Int = 0 } fun watchNotifications( pgSource: PGSimpleDataSource, schema: String, logger: Logger, listeners: Map Unit)> ) { val backoff = ExpoBackoffDecorr() // Run notification logic in a separated thread kotlin.concurrent.thread(isDaemon = true) { runBlocking { while (true) { try { val conn = pgSource.pgConnection(schema) // Listen to all notifications channels for (channel in listeners.keys) { conn.execSQLUpdate("LISTEN $channel") } backoff.reset() while (true) { conn.getNotifications(0) // Block until we receive at least one notification .forEach { // Dispatch try { listeners[it.name]!!(it.parameter) } catch (e: Exception) { throw Exception("channel ${it.name} with input '${it.parameter}'", e) } } } } catch (e: Exception) { e.fmtLog(logger) delay(backoff.next()) } } } } } /** Listen to flow from [map] for [key] using [lambda]*/ suspend fun listen(map: ConcurrentHashMap>, key: K, lambda: suspend (Flow) -> R): R { // Register listener, create a new flow if missing val flow = map.compute(key) { _, v -> val tmp = v ?: CountedSharedFlow() tmp.count++ tmp }!!.flow try { return lambda(flow) } finally { // Unregister listener, removing unused flow map.compute(key) { _, v -> v!! v.count-- if (v.count > 0) v else null } } }libeufin-1.6.8/libeufin-common/src/main/kotlin/db/DbPool.kt0000664000175000017500000000606215122266731023756 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.db import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.postgresql.jdbc.PgConnection import tech.libeufin.common.MIN_VERSION import java.sql.PreparedStatement open class DbPool(cfg: DatabaseConfig, schema: String) : java.io.Closeable { val pgSource = pgDataSource(cfg.dbConnStr) private val pool: HikariDataSource init { val config = HikariConfig() config.dataSource = pgSource config.schema = schema.replace("-", "_") config.transactionIsolation = "TRANSACTION_SERIALIZABLE" pool = HikariDataSource(config) pool.connection.use { con -> val meta = con.metaData val majorVersion = meta.databaseMajorVersion val minorVersion = meta.databaseMinorVersion require(majorVersion >= MIN_VERSION) { "postgres version must be at least $MIN_VERSION.0 got $majorVersion.$minorVersion" } checkMigrations(con.unwrap(PgConnection::class.java), cfg, schema) } } /** Executes a query with automatic retry on serialization errors */ suspend fun serializable(query: String, lambda: TalerStatement.() -> R): R = conn { conn -> // We could explicitly tell Postgres when a request is read-only, // but the performance improvement isn't obvious, it doesn't prevent // stored procedures from modifying the database and it adds a // round-trip during configuration conn.withStatement(query) { retrySerializationError { lambda() } } } /** Executes a transaction with automatic retry on serialization errors */ suspend fun serializableTransaction(transaction: (PgConnection) -> R): R = conn { conn -> retrySerializationError { conn.transaction(transaction) } } /** Run db logic using a connection from the pool */ suspend fun conn(lambda: suspend (PgConnection) -> R): R { // Use a coroutine dispatcher that we can block as JDBC API is blocking return withContext(Dispatchers.IO) { pool.connection.use { lambda(it.unwrap(PgConnection::class.java)) } } } override fun close() { pool.close() } }libeufin-1.6.8/libeufin-common/src/main/kotlin/iban.kt0000664000175000017500000000701415122266731023121 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common @JvmInline value class IBAN private constructor(val value: String) { override fun toString(): String = value companion object { private val SEPARATOR = Regex("[\\ \\-]") fun checksum(iban: String): Int = (iban.substring(4 until iban.length).asSequence() + iban.substring(0 until 4).asSequence()) .fold(0) { acc, char -> if (char.isDigit()) { (acc * 10 + char.code - '0'.code) % 97 } else { (acc * 100 + char.code - 'A'.code + 10) % 97 } } fun parse(raw: String): IBAN { val iban: String = raw.uppercase().replace(SEPARATOR, "") if (iban.length < 5) { throw CommonError.Payto("malformed IBAN, string is too small only ${iban.length} char") } val countryCode = iban.substring(0 until 2) for (c in countryCode) { if (!c.isLetter()) throw CommonError.Payto("malformed IBAN, malformed country code") } for (c in iban.substring(2 until 4)) { if (!c.isDigit()) throw CommonError.Payto("malformed IBAN, malformed check digit") } val country = try { Country.valueOf(countryCode) } catch (e: IllegalArgumentException) { throw CommonError.Payto("malformed IBAN, unknown country $countryCode") } if (country == Country.DE && iban.length != 22) { // This is allowed for retrocompatibility with libeufin-bank malformed DE IBAN } else if (!country.bbanRegex.matches(iban.substring(4))) { throw CommonError.Payto("malformed IBAN, invalid char") } val checksum = checksum(iban) if (checksum != 1) throw CommonError.Payto("malformed IBAN, modulo is $checksum expected 1") return IBAN(iban) } fun rand(country: Country): IBAN { val bban = buildString { for ((repetition, c) in country.rules) { val alphabet = when (c) { IbanC.n -> "0123456789" IbanC.a -> "ABCDEFGHIJKLMNOPQRSTUVWXYZ" IbanC.c -> "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" } repeat(repetition) { append(alphabet.random()) } } } val checkDigits = 98 - checksum("${country.name}00$bban"); return if (checkDigits < 10) { IBAN("${country.name}0$checkDigits$bban") } else { IBAN("${country.name}$checkDigits$bban") } } } }libeufin-1.6.8/libeufin-common/src/main/kotlin/Constants.kt0000664000175000017500000000262315156463305024170 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common // DB const val MIN_VERSION: Int = 14 const val SERIALIZATION_RETRY: Int = 30 // Security const val MAX_BODY_LENGTH: Int = 4 * 1024 // 4kB // API version const val WIRE_GATEWAY_API_VERSION: String = "5:0:0" const val WIRE_TRANSFER_API_VERSION: String = "0:0:0" const val REVENUE_API_VERSION: String = "1:1:1" const val OBSERVABILITY_API_VERSION: String = "0:0:0" // HTTP headers const val TALER_CHALLENGE_IDS: String = "Taler-Challenge-Ids" const val X_FORWARD_PREFIX: String = "X-Forward-Prefix" // Params const val MAX_PAGE_SIZE: Int = 1024 const val MAX_TIMEOUT_MS: Long = 60 * 60 * 1000 // 1h // TODO make MAX_TIMEOUT_MS configurablelibeufin-1.6.8/libeufin-common/src/main/kotlin/client.kt0000664000175000017500000001147015221677432023473 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.encodeToJsonElement import kotlinx.serialization.json.jsonObject import kotlin.test.assertEquals /* ----- Json DSL ----- */ inline fun obj(from: JsonObject = JsonObject(emptyMap()), builderAction: JsonBuilder.() -> Unit): JsonObject { val builder = JsonBuilder(from) builder.apply(builderAction) return JsonObject(builder.content) } class JsonBuilder(from: JsonObject) { val content: MutableMap = from.toMutableMap() inline infix fun String.to(v: T) { val json = Json.encodeToJsonElement(kotlinx.serialization.serializer(), v) content[this] = json } } /* ----- Json body helper ----- */ inline fun HttpRequestBuilder.json(b: B) { val json = Json.encodeToString(kotlinx.serialization.serializer(), b) contentType(ContentType.Application.Json) setBody(json) } inline fun HttpRequestBuilder.json( from: B, builderAction: JsonBuilder.() -> Unit ) { json(obj(Json.encodeToJsonElement(kotlinx.serialization.serializer(), from).jsonObject, builderAction)) } inline fun HttpRequestBuilder.json( from: JsonObject = JsonObject(emptyMap()), builderAction: JsonBuilder.() -> Unit ) { json(obj(from, builderAction)) } suspend inline fun HttpResponse.json(): B = Json.decodeFromString(kotlinx.serialization.serializer(), bodyAsText()) suspend inline fun HttpResponse.assertOkJson(lambda: (B) -> Unit = {}): B { assertOk() val body = json() lambda(body) return body } suspend inline fun HttpResponse.assertAcceptedJson(lambda: (B) -> Unit = {}): B { assertAccepted() val body = json() lambda(body) return body } /* ----- Assert ----- */ suspend fun HttpResponse.isStatus(status: HttpStatusCode, err: TalerErrorCode?): Boolean { if (status != this.status) return false if (err != null) { val body = json() return err.code == body.code } return true } suspend fun HttpResponse.assertStatus(status: HttpStatusCode, err: TalerErrorCode?): HttpResponse { assertEquals(status, this.status, if (err != null) "$err" else err) if (err != null) { val body = json() assertEquals(err.code, body.code) } return this } suspend fun HttpResponse.assertOk(): HttpResponse = assertStatus(HttpStatusCode.OK, null) suspend fun HttpResponse.assertNoContent(err: TalerErrorCode? = null): HttpResponse = assertStatus(HttpStatusCode.NoContent, err) suspend fun HttpResponse.assertAccepted(): HttpResponse = assertStatus(HttpStatusCode.Accepted, null) suspend fun HttpResponse.assertNotFound(err: TalerErrorCode): HttpResponse = assertStatus(HttpStatusCode.NotFound, err) suspend fun HttpResponse.assertUnauthorized(err: TalerErrorCode = TalerErrorCode.GENERIC_UNAUTHORIZED): HttpResponse = assertStatus(HttpStatusCode.Unauthorized, err) suspend fun HttpResponse.assertConflict(err: TalerErrorCode): HttpResponse = assertStatus(HttpStatusCode.Conflict, err) suspend fun HttpResponse.assertBadRequest(err: TalerErrorCode = TalerErrorCode.GENERIC_JSON_INVALID): HttpResponse = assertStatus(HttpStatusCode.BadRequest, err) suspend fun HttpResponse.assertForbidden(err: TalerErrorCode = TalerErrorCode.GENERIC_FORBIDDEN): HttpResponse = assertStatus(HttpStatusCode.Forbidden, err) suspend fun HttpResponse.assertNotImplemented(err: TalerErrorCode = TalerErrorCode.END): HttpResponse = assertStatus(HttpStatusCode.NotImplemented, err) suspend fun HttpResponse.assertTooManyRequests(err: TalerErrorCode): HttpResponse = assertStatus(HttpStatusCode.TooManyRequests, err) suspend fun HttpResponse.assertPayloadTooLarge( err: TalerErrorCode = TalerErrorCode.GENERIC_UPLOAD_EXCEEDS_LIMIT ): HttpResponse = assertStatus(HttpStatusCode.PayloadTooLarge, err)libeufin-1.6.8/libeufin-common/src/main/kotlin/Cli.kt0000664000175000017500000000777315122266731022733 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.groups.OptionGroup import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.enum import com.github.ajalt.clikt.parameters.types.path import kotlinx.coroutines.runBlocking import org.slf4j.Logger import org.slf4j.LoggerFactory import org.slf4j.event.Level private val logger: Logger = LoggerFactory.getLogger("libeufin-config") abstract class TalerCmd(name: String? = null): CliktCommand(name) { val config by option( "--config", "-c", help = "Specifies the configuration file", metavar = "config_file" ).path() val log by option( "--log", "-L", help = "Configure logging to use LOGLEVEL" ).enum().default(Level.INFO) fun cliCmd(logger: Logger, lambda: suspend () -> Unit) { // Set log level TalerServiceProvider.currentLevel = log // Run cli command catching all errors try { runBlocking { lambda() } } catch (e: ProgramResult) { throw e } catch (e: Throwable) { e.fmtLog(logger) throw ProgramResult(1) } } } class CliConfigCmd(configSource: ConfigSource) : TalerCmd("config") { init { subcommands(CliConfigGet(configSource), CliConfigDump(configSource), CliConfigPathsub(configSource)) } override fun help(context: Context) = "Inspect or change the configuration" override fun run() = Unit } private class CliConfigGet(private val configSource: ConfigSource) : TalerCmd("get") { override fun help(context: Context) = "Lookup config value" private val isPath by option( "--filename", "-f", help = "Interpret value as path with dollar-expansion" ).flag() private val section by argument() private val option by argument() override fun run() = cliCmd(logger) { val config = configSource.fromFile(config) val sect = config.section(section) if (isPath) { println(sect.path(option).require()) } else { println(sect.string(option).require()) } } } private class CliConfigPathsub(private val configSource: ConfigSource) : TalerCmd("pathsub") { override fun help(context: Context) = "Substitute variables in a path" private val pathExpr by argument() override fun run() = cliCmd(logger) { val config = configSource.fromFile(config) println(config.pathsub(pathExpr)) } } private class CliConfigDump(private val configSource: ConfigSource) : TalerCmd("dump") { override fun help(context: Context) = "Dump the configuration" override fun run() = cliCmd(logger) { val config = configSource.fromFile(config) println("# install path: ${configSource.installPath()}") println(config.stringify()) } } libeufin-1.6.8/libeufin-common/src/main/kotlin/crypto/0000775000175000017500000000000015236145704023170 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/kotlin/crypto/CryptoUtil.kt0000664000175000017500000003233315221677432025654 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.crypto import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x509.BasicConstraints import org.bouncycastle.asn1.x509.Extension import org.bouncycastle.asn1.x509.KeyUsage import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder import org.bouncycastle.crypto.generators.Argon2BytesGenerator import org.bouncycastle.crypto.generators.BCrypt import org.bouncycastle.crypto.params.Argon2Parameters import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters import org.bouncycastle.crypto.signers.Ed25519Signer import org.bouncycastle.jce.provider.BouncyCastleProvider import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder import tech.libeufin.common.* import java.io.ByteArrayOutputStream import java.io.InputStream import java.math.BigInteger import java.security.KeyFactory import java.security.KeyPairGenerator import java.security.MessageDigest import java.security.Signature import java.security.cert.CertificateFactory import java.security.cert.X509Certificate import java.security.interfaces.RSAPrivateCrtKey import java.security.interfaces.RSAPublicKey import java.security.spec.* import java.util.* import javax.crypto.* import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.PBEKeySpec import javax.crypto.spec.SecretKeySpec interface NBO { fun nbo(): ByteArray fun signNbo(key: ByteArray): EddsaSignature = CryptoUtil.eddsaSign(this.nbo(), key) fun verifyNbo(signature: EddsaSignature, key: EddsaPublicKey): Boolean = CryptoUtil.checkEdssaSignature(this.nbo(), signature, key) } /** Helpers for dealing with cryptographic operations in EBICS / LibEuFin */ object CryptoUtil { private val provider = BouncyCastleProvider() /** Load an RSA private key from its binary PKCS#8 encoding */ fun loadRSAPrivate(encodedPrivateKey: ByteArray): RSAPrivateCrtKey { val spec = PKCS8EncodedKeySpec(encodedPrivateKey) val priv = KeyFactory.getInstance("RSA").generatePrivate(spec) return priv as RSAPrivateCrtKey } /** Load an RSA public key from its binary X509 encoding */ fun loadRSAPublic(encodedPublicKey: ByteArray): RSAPublicKey { val spec = X509EncodedKeySpec(encodedPublicKey) val pub = KeyFactory.getInstance("RSA").generatePublic(spec) return pub as RSAPublicKey } /** Create an RSA public key from its components: [modulus] and [exponent] */ fun RSAPublicFromComponents(modulus: ByteArray, exponent: ByteArray): RSAPublicKey { val modulusBigInt = BigInteger(1, modulus) val exponentBigInt = BigInteger(1, exponent) val spec = RSAPublicKeySpec(modulusBigInt, exponentBigInt) return KeyFactory.getInstance("RSA").generatePublic(spec) as RSAPublicKey } /** Extract an RSA public key from a [raw] X.509 certificate */ fun RSAPublicFromCertificate(raw: ByteArray): RSAPublicKey { val certificate = CertificateFactory.getInstance("X.509").generateCertificate(raw.inputStream()) return certificate.publicKey as RSAPublicKey } /** Generate an RSA public key from a [private] one */ fun RSAPublicFromPrivate(private: RSAPrivateCrtKey): RSAPublicKey { val spec = RSAPublicKeySpec(private.modulus, private.publicExponent) return KeyFactory.getInstance("RSA").generatePublic(spec) as RSAPublicKey } /** Generate a self-signed X.509 certificate from an RSA [private] key */ fun X509CertificateFromRSAPrivate(private: RSAPrivateCrtKey, name: String): X509Certificate { val start = Date() val calendar = Calendar.getInstance() calendar.time = start calendar.add(Calendar.YEAR, 1_000) val end = calendar.time val name = X500Name("CN=$name") val builder = JcaX509v3CertificateBuilder( name, BigInteger(20, Random()), start, end, name, RSAPublicFromPrivate(private) ) builder.addExtension( Extension.keyUsage, true, KeyUsage( KeyUsage.digitalSignature or KeyUsage.nonRepudiation or KeyUsage.keyEncipherment or KeyUsage.dataEncipherment or KeyUsage.keyAgreement or KeyUsage.keyCertSign or KeyUsage.cRLSign or KeyUsage.encipherOnly or KeyUsage.decipherOnly ) ) builder.addExtension(Extension.basicConstraints, true, BasicConstraints(true)) val certificate = JcaContentSignerBuilder("SHA256WithRSA").build(private) return JcaX509CertificateConverter() .setProvider(provider) .getCertificate(builder.build(certificate)) } /** Generate an RSA key pair of [keysize] */ fun genRSAPair(keysize: Int): Pair { val gen = KeyPairGenerator.getInstance("RSA") gen.initialize(keysize) val pair = gen.genKeyPair() return Pair(pair.private as RSAPrivateCrtKey, pair.public as RSAPublicKey) } /** Generate an RSA private key of [keysize] */ fun genRSAPrivate(keysize: Int): RSAPrivateCrtKey = genRSAPair(keysize).first /** Generate an RSA public key of [keysize] */ fun genRSAPublic(keysize: Int): RSAPublicKey = genRSAPair(keysize).second /** * Hash an RSA public key according to the EBICS standard (EBICS 2.5: 4.4.1.2.3). */ fun getEbicsPublicKeyHash(publicKey: RSAPublicKey): ByteArray { val keyBytes = ByteArrayOutputStream() keyBytes.writeBytes(publicKey.publicExponent.encodeHex().trimStart('0').toByteArray()) keyBytes.write(' '.code) keyBytes.writeBytes(publicKey.modulus.encodeHex().trimStart('0').toByteArray()) val digest = MessageDigest.getInstance("SHA-256") return digest.digest(keyBytes.toByteArray()) } fun genEbicsE002Key(encryptionPublicKey: RSAPublicKey): Pair { // Gen transaction key val keygen = KeyGenerator.getInstance("AES", provider) keygen.init(128) val transactionKey = keygen.generateKey() // Encrypt transaction keyA val cipher = Cipher.getInstance( "RSA/None/PKCS1Padding", provider ) cipher.init(Cipher.ENCRYPT_MODE, encryptionPublicKey) val encryptedTransactionKey = cipher.doFinal(transactionKey.encoded) return Pair(transactionKey, encryptedTransactionKey) } /** * Encrypt data according to the EBICS E002 encryption process. */ fun encryptEbicsE002( transactionKey: SecretKey, data: InputStream ): CipherInputStream { val cipher = Cipher.getInstance( "AES/CBC/X9.23Padding", provider ) val ivParameterSpec = IvParameterSpec(ByteArray(16)) cipher.init(Cipher.ENCRYPT_MODE, transactionKey, ivParameterSpec) return CipherInputStream(data, cipher) } fun decryptEbicsE002Key( privateKey: RSAPrivateCrtKey, encryptedTransactionKey: ByteArray ): SecretKeySpec { val cipher = Cipher.getInstance( "RSA/None/PKCS1Padding", provider ) cipher.init(Cipher.DECRYPT_MODE, privateKey) val transactionKeyBytes = cipher.doFinal(encryptedTransactionKey) return SecretKeySpec(transactionKeyBytes, "AES") } fun decryptEbicsE002( transactionKey: SecretKeySpec, encryptedData: InputStream ): CipherInputStream { val cipher = Cipher.getInstance( "AES/CBC/X9.23Padding", provider ) val ivParameterSpec = IvParameterSpec(ByteArray(16)) cipher.init(Cipher.DECRYPT_MODE, transactionKey, ivParameterSpec) return CipherInputStream(encryptedData, cipher) } /** * Signing algorithm corresponding to the EBICS A006 signing process. * * Note that while [data] can be arbitrary-length data, in EBICS, the order * data is *always* hashed *before* passing it to the signing algorithm, which again * uses a hash internally. */ fun signEbicsA006(data: ByteArray, privateKey: RSAPrivateCrtKey): ByteArray { val signature = Signature.getInstance("SHA256withRSA/PSS", provider) signature.setParameter(PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1)) signature.initSign(privateKey) signature.update(data) return signature.sign() } fun verifyEbicsA006(sig: ByteArray, data: ByteArray, publicKey: RSAPublicKey): Boolean { val signature = Signature.getInstance("SHA256withRSA/PSS", provider) signature.setParameter(PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1)) signature.initVerify(publicKey) signature.update(data) return signature.verify(sig) } fun digestEbicsOrderA006(orderData: ByteArray): ByteArray { val digest = MessageDigest.getInstance("SHA-256") for (b in orderData) { when (b) { '\r'.code.toByte(), '\n'.code.toByte(), (26).toByte() -> Unit else -> digest.update(b) } } return digest.digest() } fun decryptKey(data: EncryptedPrivateKeyInfo, passphrase: String): RSAPrivateCrtKey { /* make key out of passphrase */ val pbeKeySpec = PBEKeySpec(passphrase.toCharArray()) val keyFactory = SecretKeyFactory.getInstance(data.algName) val secretKey = keyFactory.generateSecret(pbeKeySpec) /* Make a cipher */ val cipher = Cipher.getInstance(data.algName) cipher.init( Cipher.DECRYPT_MODE, secretKey, data.algParameters // has hash count and salt ) /* Ready to decrypt */ val decryptedKeySpec: PKCS8EncodedKeySpec = data.getKeySpec(cipher) val priv = KeyFactory.getInstance("RSA").generatePrivate(decryptedKeySpec) return priv as RSAPrivateCrtKey } fun hashStringSHA256(input: String): ByteArray = MessageDigest.getInstance("SHA-256").digest(input.toByteArray(Charsets.UTF_8)) fun hashStringNbo(input: String): ByteArray = MessageDigest.getInstance("SHA-512").digest(input.toByteArray(Charsets.UTF_8) + byteArrayOf(0)).sliceArray(0..31) fun bcrypt(password: String, salt: ByteArray, cost: Int): ByteArray { val pwBytes = BCrypt.passwordToByteArray(password.toCharArray()) return BCrypt.generate(pwBytes, salt, cost) } fun hashArgon2id(password: String, salt: ByteArray): ByteArray { // OSWAP recommended config https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id val builder = Argon2Parameters.Builder(Argon2Parameters.ARGON2_id) .withIterations(1) .withMemoryAsKB(47104) .withParallelism(1) .withSalt(salt) val gen = Argon2BytesGenerator() gen.init(builder.build()) val result = ByteArray(32) gen.generateBytes(password.toCharArray(), result, 0, result.size) return result } private fun mfaBodyHash(body: ByteArray, salt: Base32Crockford16B): Base32Crockford64B { val digest = MessageDigest.getInstance("SHA-512") digest.update(salt.raw) val hash = digest.digest(body) return Base32Crockford64B(hash) } fun mfaBodyHashCheck(body: ByteArray, hash: Base32Crockford64B, salt: Base32Crockford16B): Boolean { val check = mfaBodyHash(body, salt) return check == hash } fun mfaBodyHashCreate(body: ByteArray): Pair { val salt = Base32Crockford16B.secureRand() val hash = mfaBodyHash(body, salt) return Pair(hash, salt) } fun checkEdssaSignature(data: ByteArray, signature: EddsaSignature, publicKey: EddsaPublicKey): Boolean { val pubKey = Ed25519PublicKeyParameters(publicKey.raw, 0) val verifier = Ed25519Signer() verifier.init(false, pubKey) verifier.update(data, 0, data.size) return verifier.verifySignature(signature.raw) } fun eddsaSign(data: ByteArray, privateKey: ByteArray): EddsaSignature { val privateKey = Ed25519PrivateKeyParameters(privateKey, 0) val signer = Ed25519Signer() signer.init(true, privateKey) signer.update(data, 0, data.size) return EddsaSignature(signer.generateSignature()) } }libeufin-1.6.8/libeufin-common/src/main/kotlin/crypto/PwCrypto.kt0000664000175000017500000000773415122266731025330 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.crypto import kotlinx.serialization.Serializable import tech.libeufin.common.* @JvmInline value class Password(val pw: String) // NIST Password Guidelines 2024 private const val PASSWORD_MIN_LEN = 8 private const val PASSWORD_MAX_LEN = 64 /** Check if a string is a valid password */ fun String.checkPw(checkQuality: Boolean): Password { if (!checkQuality) return Password(this) val len = this.length return when { len < PASSWORD_MIN_LEN -> throw conflict( "Password is too short, expect at least ${PASSWORD_MIN_LEN} characters got ${len}", TalerErrorCode.BANK_PASSWORD_TOO_SHORT ) len > PASSWORD_MAX_LEN -> throw conflict( "Password is too long, expect at most ${PASSWORD_MAX_LEN} characters got ${len}", TalerErrorCode.BANK_PASSWORD_TOO_LONG ) else -> Password(this) } } data class PasswordHashCheck( val match: Boolean, val outdated: Boolean ) /** Cryptographic operations for secure password storage and verification */ sealed interface PwCrypto { @Serializable data class Bcrypt(val cost: Int = 8): PwCrypto /** Hash [pw] using [cfg] hashing method */ fun hashpw(pw: String): String { when (this) { is Bcrypt -> { val salt = ByteArray(16).secureRand() val pwh = CryptoUtil.bcrypt(pw, salt, cost) return "bcrypt\$$cost\$${salt.encodeBase64()}\$${pwh.encodeBase64()}" } /* TODO Argon2id "argon2id" -> { require(components.size == 3) { "bad password hash format" } val salt = components[1].decodeBase64() val hash = components[2] val pwh = CryptoUtil.hashArgon2id(pw, salt).encodeBase64() PasswordHashCheck(pwh == hash, false) } */ } } /** Check whether [pw] match hashed [storedPwHash] and if it should be rehashed */ fun checkpw(pw: String, storedPwHash: String): PasswordHashCheck { val components = storedPwHash.split('$', limit = 5) return when (val algo = components[0]) { "sha256" -> { require(components.size == 2) { "bad password hash format" } val hash = components[1] val pwh = CryptoUtil.hashStringSHA256(pw).encodeBase64() PasswordHashCheck(pwh == hash, true) } "sha256-salted" -> { require(components.size == 3) { "bad password hash format" } val salt = components[1] val hash = components[2] val pwh = CryptoUtil.hashStringSHA256("$salt|$pw").encodeBase64() PasswordHashCheck(pwh == hash, true) } "bcrypt" -> { require(components.size == 4) { "bad password hash format" } val cost = components[1].toInt() val salt = components[2].decodeBase64() val hash = components[3] val pwh = CryptoUtil.bcrypt(pw, salt, cost).encodeBase64() PasswordHashCheck(pwh == hash, !(this is Bcrypt && this.cost == cost)) } else -> throw Exception("unsupported hash algo: '$algo'") } } }libeufin-1.6.8/libeufin-common/src/main/kotlin/Table.kt0000664000175000017500000000504515122266731023241 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import tech.libeufin.common.ANSI.displayLength import kotlin.math.max data class ColumnStyle( val alignLeft: Boolean = true ) { companion object { val DEFAULT = ColumnStyle() } } fun printTable( columns: List, rows: List>, separator: Char = '|', colStyle: List = listOf() ) { val cols: List> = columns.mapIndexed { i, name -> val maxRow: Int = rows.asSequence().map { it[i].displayLength() }.maxOrNull() ?: 0 Pair(name, max(name.displayLength(), maxRow)) } val table = buildString { fun padding(length: Int) { repeat(length) { append (' ') } } var first = true for ((name, len) in cols) { if (!first) { append(separator) } else { first = false } val pad = len - name.displayLength() padding(pad / 2) append(name) padding(pad / 2 + if (pad % 2 == 0) { 0 } else { 1 }) } append('\n') for (row in rows) { var first = true cols.forEachIndexed { i, met -> val str = row[i] val style = colStyle.getOrNull(i) ?: ColumnStyle.DEFAULT if (!first) { append(separator) } else { first = false } val (_, len) = met val pad = len - str.displayLength() if (style.alignLeft) { append(str) padding(pad) } else { padding(pad) append(str) } } append('\n') } } print(table) }libeufin-1.6.8/libeufin-common/src/main/kotlin/test/0000775000175000017500000000000015236145704022627 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/kotlin/test/cli.kt0000664000175000017500000000213315122266731023733 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.test import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test fun CliktCommand.fail(cmd: String) { val result = test(cmd) require(result.statusCode != 0) { result.output } } fun CliktCommand.succeed(cmd: String) { val result = test(cmd) require(result.statusCode == 0) { result.output } } libeufin-1.6.8/libeufin-common/src/main/kotlin/test/bench.kt0000664000175000017500000000665715156463305024265 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.test import org.postgresql.copy.* import org.postgresql.jdbc.* import tech.libeufin.common.* import kotlin.math.pow import kotlin.math.sqrt import kotlin.time.DurationUnit import kotlin.time.measureTime import kotlin.time.toDuration fun PgConnection.genData(amount: Int, generators: Sequence String>>) { for ((table, generator) in generators) { println("Gen rows for $table") PGCopyOutputStream(this, "COPY $table FROM STDIN", 16 * 1024 * 1024).use { out -> repeat(amount) { val str = generator(it+1) val bytes = str.toByteArray() out.write(bytes) } } } // Update database statistics for better perf this.execSQLUpdate("VACUUM FULL ANALYZE") } class Benchmark(private val iter: Int) { private val WARN = 4.toDuration(DurationUnit.MILLISECONDS) private val ERR = 50.toDuration(DurationUnit.MILLISECONDS) internal val measures: MutableList> = mutableListOf() internal fun fmtMeasures(times: LongArray): List { val min: Long = times.min() val max: Long = times.max() val mean: Long = times.average().toLong() val variance = times.map { (it.toDouble() - mean).pow(2) }.average() val stdVar: Long = sqrt(variance.toDouble()).toLong() return sequenceOf(min, mean, max, stdVar).map { val duration = it.toDuration(DurationUnit.MICROSECONDS) val str = duration.toString() if (duration > ERR) { ANSI.red(str) } else if (duration > WARN) { ANSI.yellow(str) } else { ANSI.green(str) } }.toList() } suspend fun measureAction(name: String, lambda: suspend (Int) -> R): List { println("Measure action $name") val results = mutableListOf() val times = LongArray(iter) { idx -> measureTime { val result = lambda(idx) results.add(result) }.inWholeMicroseconds } measures.add(listOf(ANSI.magenta(name)) + fmtMeasures(times)) return results } } fun bench(lambda: Benchmark.(Int) -> Unit) { val ITER = System.getenv("BENCH_ITER")?.toIntOrNull() ?: 10 val AMOUNT = System.getenv("BENCH_AMOUNT")?.toIntOrNull() ?: 100 println("Bench $ITER times with $AMOUNT rows") val bench = Benchmark(ITER) bench.lambda(AMOUNT) printTable( listOf("benchmark", "min", "mean", "max", "std").map { ANSI.bold(it) }, bench.measures, ' ', listOf(ColumnStyle.DEFAULT) + List(5) { ColumnStyle(false) } ) }libeufin-1.6.8/libeufin-common/src/main/kotlin/test/routines.kt0000664000175000017500000001076215156463305025046 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.test import io.ktor.client.statement.* import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import tech.libeufin.common.assertNoContent import tech.libeufin.common.assertOkJson suspend inline fun abstractHistoryRoutine( crossinline ids: (B) -> List, registered: List Unit>, ignored: List Unit> = listOf(), polling: Boolean = true, crossinline history: suspend (String) -> HttpResponse, ) { // Check history is following specs val assertHistory: suspend HttpResponse.(Int) -> Unit = { size: Int -> assertHistoryIds(size, ids) } // Get latest registered id val latestId: suspend () -> Long = { history("limit=-1").assertOkJson().run { ids(this)[0] } } // Check error when no transactions history("limit=7").assertNoContent() // Run interleaved registered and ignore transactions val registeredIter = registered.iterator() val ignoredIter = ignored.iterator() while (registeredIter.hasNext() || ignoredIter.hasNext()) { if (registeredIter.hasNext()) registeredIter.next()() if (ignoredIter.hasNext()) ignoredIter.next()() } val nbRegistered = registered.size val nbIgnored = ignored.size val nbTotal = nbRegistered + nbIgnored // Check ignored history("limit=$nbTotal").assertHistory(nbRegistered) // Check skip ignored history("limit=$nbRegistered").assertHistory(nbRegistered) if (polling) { // Check no polling when we cannot have more transactions assertTime(0, 500) { history("limit=-${nbRegistered+1}&timeout_ms=1000") .assertHistory(nbRegistered) } // Check no polling when already find transactions even if less than delta assertTime(0, 500) { history("limit=${nbRegistered+1}&timeout_ms=1000") .assertHistory(nbRegistered) } // Check polling coroutineScope { val id = latestId() launch { // Check polling succeed assertTime(100, 500) { history("limit=2&offset=$id&timeout_ms=1000") .assertHistory(1) } } launch { // Check polling timeout assertTime(200, 500) { history("limit=1&offset=${id+nbTotal*3}&timeout_ms=200") .assertNoContent() } } delay(100) registered[0]() } // Test triggers for (register in registered) { coroutineScope { val id = latestId() launch { assertTime(100, 500) { history("limit=7&offset=$id&timeout_ms=1000") .assertHistory(1) } } delay(100) register() } } // Test doesn't trigger coroutineScope { val id = latestId() launch { assertTime(200, 500) { history("limit=7&offset=$id&timeout_ms=200") .assertNoContent() } } delay(100) for (ignore in ignored) { ignore() } } } // Testing ranges. repeat(20) { registered[0]() } val id = latestId() // Default history("").assertHistory(20) // forward range: history("limit=10").assertHistory(10) history("limit=10&offset=4").assertHistory(10) // backward range: history("limit=-10").assertHistory(10) history("limit=-10&offset=${id-4}").assertHistory(10) }libeufin-1.6.8/libeufin-common/src/main/kotlin/test/helpers.kt0000664000175000017500000001540515122266731024634 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common.test import io.ktor.client.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import tech.libeufin.common.* import kotlin.test.assertEquals import kotlinx.serialization.json.* /* ----- Assert ----- */ suspend fun assertTime(min: Int, max: Int, lambda: suspend () -> Unit) { val start = System.currentTimeMillis() lambda() val end = System.currentTimeMillis() val time = end - start assert(time >= min) { "Expected to last at least $min ms, lasted $time" } assert(time <= max) { "Expected to last at most $max ms, lasted $time" } } suspend inline fun HttpResponse.assertHistoryIds(size: Int, ids: (B) -> List): B { assertOk() val body = json() val history = ids(body) val params = PageParams.extract(call.request.url.parameters) // testing the size is like expected. assertEquals(size, history.size, "bad history length: $history") if (params.limit < 0) { // testing that the first id is at most the 'offset' query param. assert(history[0] <= params.offset) { "bad history offset: $params $history" } // testing that the id decreases. if (history.size > 1) assert(history.windowed(2).all { (a, b) -> a > b }) { "bad history order: $history" } } else { // testing that the first id is at least the 'offset' query param. assert(history[0] >= params.offset) { "bad history offset: $params $history" } // testing that the id increases. if (history.size > 1) assert(history.windowed(2).all { (a, b) -> a < b }) { "bad history order: $history" } } return body } /* ----- Auth ----- */ typealias RequestLambda = suspend HttpRequestBuilder.() -> Unit; /** Auto token auth GET request */ suspend fun HttpClient.getA(url: String, builder: RequestLambda = {}): HttpResponse = tokenAuthRequest(url, HttpMethod.Get, null, builder) /** Auto token auth POST request */ suspend fun HttpClient.postA(url: String, builder: RequestLambda = {}): HttpResponse = tokenAuthRequest(url, HttpMethod.Post, null, builder) /** Auto token auth PATCH request */ suspend fun HttpClient.patchA(url: String, builder: RequestLambda = {}): HttpResponse = tokenAuthRequest(url, HttpMethod.Patch, null, builder) /** Auto token auth DELETE request */ suspend fun HttpClient.deleteA(url: String, builder: RequestLambda = {}): HttpResponse = tokenAuthRequest(url, HttpMethod.Delete, null, builder) /** Admin token auth GET request */ suspend fun HttpClient.getAdmin(url: String, builder: RequestLambda = {}): HttpResponse = tokenAuthRequest(url, HttpMethod.Get, "admin", builder) /** Admin token auth PATCH request */ suspend fun HttpClient.patchAdmin(url: String, builder: RequestLambda = {}): HttpResponse = tokenAuthRequest(url, HttpMethod.Patch, "admin", builder) /** Admin token auth POST request */ suspend fun HttpClient.postAdmin(url: String, builder: RequestLambda = {}): HttpResponse = tokenAuthRequest(url, HttpMethod.Post, "admin", builder) /** Admin token auth DELETE request */ suspend fun HttpClient.deleteAdmin(url: String, builder: RequestLambda = {}): HttpResponse = tokenAuthRequest(url, HttpMethod.Delete, "admin", builder) /** Auto pw auth GET request */ suspend fun HttpClient.getPw(url: String, builder: RequestLambda = {}): HttpResponse = pwAuthRequest(url, HttpMethod.Get, null, builder) /** Auto pw auth POST request */ suspend fun HttpClient.postPw(url: String, builder: RequestLambda = {}): HttpResponse = pwAuthRequest(url, HttpMethod.Post, null, builder) /** Auto pw auth PATCH request */ suspend fun HttpClient.patchPw(url: String, builder: RequestLambda = {}): HttpResponse = pwAuthRequest(url, HttpMethod.Patch, null, builder) /** Auto pw auth DELETE request */ suspend fun HttpClient.deletePw(url: String, builder: RequestLambda = {}): HttpResponse = pwAuthRequest(url, HttpMethod.Delete, null, builder) private suspend fun HttpClient.tokenAuthRequest( url: String, method: HttpMethod, username: String?, builder: RequestLambda = {} ): HttpResponse = request(url) { this.method = method tokenAuth(this@tokenAuthRequest, username) builder(this) } private suspend fun HttpClient.pwAuthRequest( url: String, method: HttpMethod, username: String?, builder: RequestLambda = {} ): HttpResponse = request(url) { this.method = method pwAuth(username) builder(this) } private fun HttpRequestBuilder.extractUsername(username: String? = null): String? = when { username != null -> username url.pathSegments.contains("admin") -> "admin" url.pathSegments[1] == "accounts" -> url.pathSegments[2] else -> null } /** Authenticate a request for [username] with basic auth */ fun HttpRequestBuilder.pwAuth(username: String? = null) { val username = extractUsername(username) ?: return basicAuth("$username", "$username-password") } val globalTestTokens = mutableMapOf() /** Get cached token or create it */ suspend fun HttpClient.cachedToken(username: String): String { // Get cached token or create it var token = globalTestTokens.get(username) if (token == null) { val response = this.post("/accounts/$username/token") { pwAuth() json { "scope" to "readwrite" "duration" to obj { "d_us" to "forever" } } }.assertOkJson() token = Json.decodeFromJsonElement(response.get("access_token")!!) globalTestTokens.set(username, token) } return token } /** Authenticate a request for [username] with a bearer token */ suspend fun HttpRequestBuilder.tokenAuth(client: HttpClient, username: String? = null) { // Get username from arg or path val username = extractUsername(username) ?: return // Get cached token or create it var token = client.cachedToken(username) // Set authorization header headers[HttpHeaders.Authorization] = "Bearer $token" }libeufin-1.6.8/libeufin-common/src/main/kotlin/Backoff.kt0000664000175000017500000000242215122266731023541 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import kotlin.random.Random /** Infinite exponential backoff with decorrelated jitter */ class ExpoBackoffDecorr( private val base: Long = 100, // 0.1 second private val max: Long = 60000, // 60 seconds private val factor: Double = 2.0, ) { private var sleep: Long = base fun next() : Long { sleep = Random.nextDouble(base.toDouble(), sleep.toDouble() * factor) .toLong().coerceAtMost(max) return sleep } fun reset() { sleep = base } }libeufin-1.6.8/libeufin-common/src/main/kotlin/ApiError.kt0000664000175000017500000001132415122266731023732 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.response.* import io.ktor.util.* import kotlinx.serialization.Serializable /** * Convenience type to throw errors along the API activity * and that is meant to be caught by Ktor and responded to the * client. */ class ApiException( // Status code that Ktor will set for the response. val httpStatus: HttpStatusCode, // Error detail object, after Taler API. val talerError: TalerError ) : Exception(talerError.hint) /** * Error object to respond to the client. The * 'code' field takes values from the GANA gnu-taler-error-code * specification. 'hint' is a human-readable description * of the error. */ @Serializable data class TalerError( @kotlinx.serialization.Transient val err: TalerErrorCode = TalerErrorCode.END, val code: Int, val hint: String? = null, val detail: String? = null ) private val LOG_MSG = AttributeKey("log_msg") fun ApplicationCall.logMsg(): String? = attributes.getOrNull(LOG_MSG) suspend fun ApplicationCall.err( status: HttpStatusCode, hint: String?, error: TalerErrorCode, cause: Exception? ) { err( ApiException( httpStatus = status, talerError = TalerError( code = error.code, err = error, hint = hint ) ), cause ) } suspend fun ApplicationCall.err( err: ApiException, cause: Exception? ) { val fmt = buildString { append(err.talerError.err.name) append(" ") append(err.talerError.hint) val msg = cause?.message if (msg != null) { append("- ") append(msg) } } attributes.put(LOG_MSG, fmt) respond( status = err.httpStatus, message = err.talerError ) } fun apiError( status: HttpStatusCode, hint: String?, error: TalerErrorCode, detail: String? = null ): ApiException = ApiException( httpStatus = status, talerError = TalerError( code = error.code, err = error, hint = hint, detail = detail ) ) /* ----- HTTP error ----- */ fun forbidden( hint: String, error: TalerErrorCode = TalerErrorCode.GENERIC_FORBIDDEN ): ApiException = apiError(HttpStatusCode.Forbidden, hint, error) fun unauthorized( hint: String, error: TalerErrorCode = TalerErrorCode.GENERIC_UNAUTHORIZED ): ApiException = apiError(HttpStatusCode.Unauthorized, hint, error) fun internalServerError(hint: String?): ApiException = apiError(HttpStatusCode.InternalServerError, hint, TalerErrorCode.GENERIC_INTERNAL_INVARIANT_FAILURE) fun paramsMalformed(hint: String): ApiException = badRequest(hint, TalerErrorCode.GENERIC_PARAMETER_MALFORMED) fun notFound( hint: String, error: TalerErrorCode ): ApiException = apiError(HttpStatusCode.NotFound, hint, error) fun conflict( hint: String, error: TalerErrorCode ): ApiException = apiError(HttpStatusCode.Conflict, hint, error) fun tooManyRequests( hint: String, error: TalerErrorCode ): ApiException = apiError(HttpStatusCode.TooManyRequests, hint, error) fun badRequest( hint: String? = null, error: TalerErrorCode = TalerErrorCode.GENERIC_JSON_INVALID, detail: String? = null ): ApiException = apiError(HttpStatusCode.BadRequest, hint, error, detail) fun unsupportedMediaType( hint: String, error: TalerErrorCode = TalerErrorCode.END, ): ApiException = apiError(HttpStatusCode.UnsupportedMediaType, hint, error) fun notImplemented( hint: String = "API not implemented", error: TalerErrorCode = TalerErrorCode.END, ): ApiException = apiError(HttpStatusCode.NotImplemented, hint, error) fun bodyOverflow( hint: String, error: TalerErrorCode = TalerErrorCode.GENERIC_UPLOAD_EXCEEDS_LIMIT, ): ApiException = apiError(HttpStatusCode.PayloadTooLarge, hint, error) fun badGateway( hint: String, error: TalerErrorCode = TalerErrorCode.GENERIC_UPLOAD_EXCEEDS_LIMIT, ): ApiException = apiError(HttpStatusCode.PayloadTooLarge, hint, error)libeufin-1.6.8/libeufin-common/src/main/kotlin/TalerConfig.kt0000664000175000017500000005615215221677432024420 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023, 2024, 2025, 2026 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import kotlinx.serialization.json.Json import org.slf4j.Logger import org.slf4j.LoggerFactory import java.nio.file.* import java.time.* import java.time.format.* import java.time.temporal.ChronoUnit import kotlin.io.path.* private val logger: Logger = LoggerFactory.getLogger("libeufin-config") /** Config error when analyzing and using the taler configuration format */ class TalerConfigError private constructor (m: String, cause: Throwable? = null) : Exception(m, cause) { companion object { /** Error when a specific option value is missing */ internal fun missing(type: String, section: String, option: String): TalerConfigError = TalerConfigError("Missing $type option '$option' in section '$section'") /** Error when a specific option value is invalid */ internal fun invalid(type: String, section: String, option: String, err: String): TalerConfigError = TalerConfigError("Expected $type option '$option' in section '$section': $err") /** Generic error not linked to a specific option value */ fun generic(msg: String, cause: Throwable? = null): TalerConfigError = TalerConfigError(msg, cause) } } /** Configuration error when converting option value */ class ValueError(val msg: String): Exception(msg) /** Information about how the configuration is loaded */ data class ConfigSource( /** Name of the high-level project */ val projectName: String = "taler", /** Name of the component within the package */ val componentName: String = "taler", /** * Executable name that will be located on $PATH to * find the installation path of the package */ val execName: String = "taler-config" ) { /** Load configuration from string */ fun fromMem(content: String): TalerConfig { val loader = ConfigLoader(this) loader.loadDefaults() loader.loadFromMem(content.lineSequence(), null, 0) return loader.finalize() } /** * Load configuration from [file], if [file] is null load from default configuration file * * The entry point for the default configuration will be the first file from this list: * - $XDG_CONFIG_HOME/$componentName.conf * - $HOME/.config/$componentName.conf * - /etc/$componentName.conf * - /etc/$projectName/$componentName.conf * */ fun fromFile(file: Path?): TalerConfig { /** Search for the default configuration file path */ fun defaultConfigPath(): Path? { return sequence { val xdg = System.getenv("XDG_CONFIG_HOME") if (xdg != null) yield(Path(xdg, "$componentName.conf")) val home = System.getenv("HOME") if (home != null) yield(Path(home, ".config/$componentName.conf")) yield(Path("/etc/$componentName.conf")) yield(Path("/etc/$projectName/$componentName.conf")) }.firstOrNull { it.exists() } } val path = file ?: defaultConfigPath() val loader = ConfigLoader(this) loader.loadDefaults() if (path != null) loader.loadFromFile(path, 0, 0) return loader.finalize() } /** Search for the binary installation path in PATH */ fun installPath(): Path { val pathEnv = System.getenv("PATH") for (entry in pathEnv.splitToSequence(':')) { val path = Path(entry) if (path.resolve(execName).exists()) { val parent = path.parent if (parent != null) { return parent.toRealPath() } } } return Path("/usr") } } /** * Reader for Taler-style configuration files * * The configuration file format is similar to INI files * and fully described in the taler.conf man page. * * @param source information about where to load configuration defaults from **/ private class ConfigLoader( private val source: ConfigSource ) { private val sections: MutableMap> = mutableMapOf() /** * Load configuration defaults from the file system * and populate the PATHS section based on the installation path. */ fun loadDefaults() { val installDir = source.installPath() val section = sections.getOrPut("PATHS") { mutableMapOf() } section["PREFIX"] = "$installDir/" section["BINDIR"] = "$installDir/bin/" section["LIBEXECDIR"] = "$installDir/${source.projectName}/libexec/" section["DOCDIR"] = "$installDir/share/doc/${source.projectName}/" section["ICONDIR"] = "$installDir/share/icons/" section["LOCALEDIR"] = "$installDir/share/locale/" section["LIBDIR"] = "$installDir/lib/${source.projectName}/" section["DATADIR"] = "$installDir/share/${source.projectName}/" val baseConfigDir = installDir.resolve("share/${source.projectName}/config.d") try { baseConfigDir.useDirectoryEntries { for (entry in it) { loadFromFile(entry, 0, 0) } } } catch (e: Exception) { when (e) { is NotDirectoryException -> logger.warn("Base config directory is not a directory") is NoSuchFileException -> logger.warn("Missing base config directory: $baseConfigDir") else -> throw e } } } fun genericError(source: Path?, lineNum: Int, msg: String, cause: String? = null): TalerConfigError { val message = buildString { append(msg) append(" at '") if (source != null) { append(source) } else { append("mem") } append(':') append(lineNum) append('\'') if (cause != null) { append(": ") append(cause) } } return TalerConfigError.generic(message) } fun loadFromFile(file: Path, recursionDepth: Int, lineNum: Int) { if (recursionDepth > 128) { throw genericError(file, lineNum, "Recursion limit in config inlining") } logger.trace("load file at $file") return try { file.useLines { loadFromMem(it, file, recursionDepth+1) } } catch (e: Exception) { when (e) { is NoSuchFileException -> throw TalerConfigError.generic("Could not read config at '$file': no such file") is AccessDeniedException -> throw TalerConfigError.generic("Could not read config at '$file': permission denied") is TalerConfigError -> throw e else -> throw TalerConfigError.generic("Could not read config at '$file'", e) } } } fun loadFromMem(lines: Sequence, source: Path?, recursionDepth: Int) { var currentSection: MutableMap? = null for ((lineNum, line) in lines.withIndex()) { if (RE_LINE_OR_COMMENT.matches(line)) { continue } val directiveMatch = RE_DIRECTIVE.matchEntire(line) if (directiveMatch != null) { if (source == null) throw genericError(source, lineNum, "Directives are only supported when loading from file") val (directiveName, directiveArg) = directiveMatch.destructured when (directiveName.lowercase()) { "inline" -> loadFromFile(source.resolveSibling(directiveArg), recursionDepth, lineNum) "inline-matching" -> { try { val pathMatcher = FileSystems.getDefault().getPathMatcher("glob:$directiveArg") val entries = source.parent.walk() .filter { pathMatcher.matches(source.parent.relativize(it)) } for (entry in entries) { loadFromFile(entry, recursionDepth, lineNum) } } catch (e: Exception) { when (e) { is java.util.regex.PatternSyntaxException -> throw genericError(source, lineNum, "Malformed glob regex", e.message) else -> throw e } } } "inline-secret" -> { val sp = directiveArg.split(" ") if (sp.size != 2) { throw genericError(source, lineNum, "invalid configuration, @inline-secret@ directive requires exactly two arguments") } val sectionName = sp[0] val secretFilename = source.resolveSibling(sp[1]) if (!secretFilename.isReadable()) { logger.warn("unable to read secrets from $secretFilename") } else { loadFromFile(secretFilename, recursionDepth, lineNum) } } else -> throw genericError(source, lineNum, "unsupported directive '$directiveName'") } continue } val secMatch = RE_SECTION.matchEntire(line) if (secMatch != null) { val (sectionName) = secMatch.destructured currentSection = sections.getOrPut(sectionName.uppercase()) { mutableMapOf() } continue } else if (currentSection == null) { throw genericError(source, lineNum, "expected section header") } val paramMatch = RE_PARAM.matchEntire(line) if (paramMatch != null) { var (optName, optVal) = paramMatch.destructured if (optVal.length != 1 && optVal.startsWith('"') && optVal.endsWith('"')) { optVal = optVal.substring(1, optVal.length - 1) } currentSection[optName.uppercase()] = optVal continue } throw genericError(source, lineNum, "expected section header, option assignment or directive") } } fun finalize(): TalerConfig { return TalerConfig(sections) } companion object { private val RE_LINE_OR_COMMENT = Regex("^\\s*(#.*)?$") private val RE_SECTION = Regex("^\\s*\\[\\s*(.*)\\s*\\]\\s*$") private val RE_PARAM = Regex("^\\s*([^=]+?)\\s*=\\s*(.*?)\\s*$") private val RE_DIRECTIVE = Regex("^\\s*@([a-zA-Z-_]+)@\\s*(.*?)\\s*$") } } /** Taler-style configuration */ class TalerConfig internal constructor( private val cfg: Map> ) { val sections: Set get() = cfg.keys /** Create a string representation of the loaded configuration */ fun stringify(): String = buildString { for ((section, options) in cfg) { appendLine("[$section]") for ((key, value) in options) { appendLine("$key = $value") } appendLine() } } /** * Substitute ${...} and $... placeholders in a string * with values from the PATHS section in the * configuration and environment variables * * This substitution is typically only done for paths. */ internal fun pathsub(str: String, recursionDepth: Int = 0): String { /** Lookup for variable value from PATHS section in the configuration and environment variables */ fun lookup(name: String, recursionDepth: Int = 0): String? { val pathRes = section("PATHS").string(name).orNull() if (pathRes != null) { return pathsub(pathRes, recursionDepth + 1) } return System.getenv(name) } if (recursionDepth > 128) { throw ValueError("recursion limit in path substitution exceeded for '$str'") } else if (!str.contains('$')) { // Fast path without variables return str } var cursor = 0 val result = StringBuilder() while (true) { // Look for next variable val dollarIndex = str.indexOf("$", cursor) if (dollarIndex == -1) { // Reached end of string result.append(str, cursor, str.length) break } // Append normal characters result.append(str, cursor, dollarIndex) cursor = dollarIndex + 1 // Check if variable is enclosed val enclosed = if (str[cursor] == '{') { // ${var cursor++ true } else false // $var // Extract variable name val startName = cursor while (cursor < str.length && (str[cursor].isLetterOrDigit() || str[cursor] == '_')) { cursor++ } val name = str.substring(startName, cursor) // Extract variable default if enclosed val default = if (!enclosed) null else { if (str[cursor] == '}') { // ${var} cursor++ null } else if (cursor+1 internal constructor( private val raw: String?, private val option: String, private val type: String, private val section: TalerConfigSection, private val transform: TalerConfigSection.(String) -> T, ) { /** Converted value or null if missing */ fun orNull(): T? { if (raw == null) return null try { return section.transform(raw) } catch (e: ValueError) { throw TalerConfigError.invalid(type, section.section, option, e.msg) } catch (e: Exception) { throw TalerConfigError.invalid(type, section.section, option, e.message ?: e.toString()) } } /** Converted value or null if missing, log a warning if missing */ fun orNull(logger: Logger, warn: String): T? { val value = orNull() if (value == null) { val err = TalerConfigError.missing(type, section.section, option).message logger.warn("$err$warn") } return value } /** Converted value of default if missing */ fun default(default: T): T = orNull() ?: default /** Converted value or default if missing, log a warning if missing */ fun default(default: T, logger: Logger, warn: String): T = orNull(logger, warn) ?: default /** Converted value or throw if missing */ fun require(): T = orNull() ?: throw TalerConfigError.missing(type, section.section, option) } /** Accessor/Converter for Taler-like configuration sections */ class TalerConfigSection internal constructor( private val cfg: TalerConfig, private val entries: Map?, val section: String ) { /** Setup an accessor/converted for a [type] at [option] using [transform] */ fun option(option: String, type: String, transform: TalerConfigSection.(String) -> T): TalerConfigOption { val canonOption = option.uppercase() var raw = entries?.get(canonOption) if (raw == "") raw = null return TalerConfigOption(raw, option, type, this, transform) } /** Access [option] as String */ fun string(option: String) = option(option, "string") { it } /** Access [option] as String with variable substitution */ fun stringsub(option: String) = option(option, "string") { cfg.pathsub(it) } /** Access [option] as Regex */ fun regex(option: String) = option(option, "regex") { Regex(it) } /** Access [option] as hexadecimal bytes */ fun hex(option: String) = option(option, "hex") { it.replace("\\s".toRegex(), "").decodeUpHex() } /** Access [option] as BaseURL */ fun baseURL(option: String) = option(option, "baseURL") { BaseURL.parse(it) } /** Access [option] as IBAN */ fun iban(option: String) = option(option, "IBAN") { IBAN.parse(it) } /** Access [option] as Int */ fun number(option: String) = option(option, "number") { it.toIntOrNull() ?: throw ValueError("'$it' not a valid number") } /** Access [option] as Boolean */ fun boolean(option: String) = option(option, "boolean") { when (it.lowercase()) { "yes" -> true "no" -> false else -> throw ValueError("expected 'YES' or 'NO' got '$it'") } } /** Access [option] as Path */ fun path(option: String) = option(option, "path") { Path(cfg.pathsub(it)) } /** Access [option] as Duration */ fun duration(option: String) = option(option, "temporal") { if (!TEMPORAL_PATTERN.matches(it)) { throw ValueError("'$it' not a valid temporal") } TIME_AMOUNT_PATTERN.findAll(it).map { match -> val (rawAmount, unit) = match.destructured val amount = rawAmount.toLongOrNull() ?: throw ValueError("'$rawAmount' not a valid temporal amount") val value = when (unit) { "us" -> 1 "ms" -> 1000 "s", "second", "seconds", "\"" -> 1000 * 1000L "m", "min", "minute", "minutes", "'" -> 60 * 1000 * 1000L "h", "hour", "hours" -> 60 * 60 * 1000 * 1000L "d", "day", "days" -> 24 * 60 * 60 * 1000L * 1000L "week", "weeks" -> 7 * 24 * 60 * 60 * 1000L * 1000L "year", "years", "a" -> 31536000000000L else -> throw ValueError("'$unit' not a valid temporal unit") } Duration.of(amount * value, ChronoUnit.MICROS) }.fold(Duration.ZERO) { a, b -> a.plus(b) } } /** Access [option] as Instant */ fun date(option: String) = option(option, "date") { try { dateToInstant(it) } catch (e: DateTimeParseException) { val indexFmt = if (e.errorIndex != 0) " at index ${e.errorIndex}" else "" val causeMsg = e.cause?.message val causeFmt = if (causeMsg != null) ": ${causeMsg}" else "" throw ValueError("'$it' not a valid date$indexFmt$causeFmt") } } /** Access [option] as time */ fun time(option: String) = option(option, "time") { try { LocalTime.parse(it, DateTimeFormatter.ISO_LOCAL_TIME) } catch (e: DateTimeParseException) { val indexFmt = if (e.errorIndex != 0) " at index ${e.errorIndex}" else "" val causeMsg = e.cause?.message val causeFmt = if (causeMsg != null) ": ${causeMsg}" else "" throw ValueError("'$it' not a valid time$indexFmt$causeFmt") } } /** Access [option] as JSON object [T] */ inline fun json(option: String, type: String) = option(option, type) { try { Json.decodeFromString(it) } catch (e: Exception) { throw ValueError("'$it' is malformed") } } /** Access [option] as Map */ fun jsonMap(option: String) = json>(option, "json key/value map") /** Access [option] as TalerAmount */ fun amount(option: String, currency: String) = option(option, "amount") { val amount = try { TalerAmount(it) } catch (e: CommonError) { throw ValueError("'$it' is malformed: ${e.message}") } if (amount.currency != currency) { throw ValueError("expected currency $currency got ${amount.currency}") } amount } /** Access a [type] at [option] using a custom [mapper] */ fun map(option: String, type: String, mapper: Map) = option(option, type) { mapper[it] ?: throw ValueError("expected ${fmtEntriesChoice(mapper)} got '$it'") } /** Access a [type] at [option] using a custom [mapper] with code execution */ fun mapLambda(option: String, type: String, mapper: Map T>) = option(option, type) { mapper[it]?.invoke() ?: throw ValueError("expected ${fmtEntriesChoice(mapper)} got '$it'") } companion object { private val TIME_AMOUNT_PATTERN = Regex("([0-9]+) ?([a-z'\"]+)") private val TEMPORAL_PATTERN = Regex(" *([0-9]+ ?[a-z'\"]+ *)+") private val WHITESPACE_PATTERN = Regex("\\s") private fun fmtEntriesChoice(mapper: Map): String { return buildString { val iter = mapper.keys.iterator() var next = iter.next() append("'$next'") while (iter.hasNext()) { next = iter.next() if (iter.hasNext()) { append(", '$next'") } else { append(" or '$next'") } } } } } } libeufin-1.6.8/libeufin-common/src/main/kotlin/time.kt0000664000175000017500000000350015122266731023142 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import org.slf4j.Logger import org.slf4j.LoggerFactory import java.time.Instant import java.time.temporal.ChronoUnit private val logger: Logger = LoggerFactory.getLogger("libeufin-common") /** * Convert Instant to microseconds since the epoch. * * Returns Long.MAX_VALUE if instant is Instant.MAX **/ fun Instant.micros(): Long { if (this == Instant.MAX) return Long.MAX_VALUE try { val micros = ChronoUnit.MICROS.between(Instant.EPOCH, this) if (micros == Long.MAX_VALUE) throw ArithmeticException() return micros } catch (e: ArithmeticException) { throw Exception("$this is too big to be converted to micros resolution", e) } } /** * Convert microsecons to Instant. * * Returns Instant.MAX if microseconds is Long.MAX_VALUE */ fun Long.asInstant(): Instant { if (this == Long.MAX_VALUE) return Instant.MAX return try { Instant.EPOCH.plus(this, ChronoUnit.MICROS) } catch (e: ArithmeticException ) { throw Exception("$this is too big to be converted to Instant", e) } }libeufin-1.6.8/libeufin-common/src/main/kotlin/registry.kt0000664000175000017500000003301315122266731024056 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common /** IBAN ASCII characters rules */ enum class IbanC { /** Digits (0-9) */ n, /** Uppercase (A-Z) */ a, /** Digits or uppercase (0-9 & A-Z) */ c, } enum class Country(val ibanLen: Int, val rules: List>, val bbanRegex: Regex) { AD(24, listOf(Pair(8, IbanC.n),Pair(12, IbanC.c),), Regex("^[0-9]{8}[0-9A-Z]{12}$")), AE(23, listOf(Pair(19, IbanC.n),), Regex("^[0-9]{19}$")), AL(28, listOf(Pair(8, IbanC.n),Pair(16, IbanC.c),), Regex("^[0-9]{8}[0-9A-Z]{16}$")), AT(20, listOf(Pair(16, IbanC.n),), Regex("^[0-9]{16}$")), AZ(28, listOf(Pair(4, IbanC.a),Pair(20, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{20}$")), BA(20, listOf(Pair(16, IbanC.n),), Regex("^[0-9]{16}$")), BE(16, listOf(Pair(12, IbanC.n),), Regex("^[0-9]{12}$")), BG(22, listOf(Pair(4, IbanC.a),Pair(6, IbanC.n),Pair(8, IbanC.c),), Regex("^[A-Z]{4}[0-9]{6}[0-9A-Z]{8}$")), BH(22, listOf(Pair(4, IbanC.a),Pair(14, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{14}$")), BI(27, listOf(Pair(23, IbanC.n),), Regex("^[0-9]{23}$")), BR(29, listOf(Pair(23, IbanC.n),Pair(1, IbanC.a),Pair(1, IbanC.c),), Regex("^[0-9]{23}[A-Z]{1}[0-9A-Z]{1}$")), BY(28, listOf(Pair(4, IbanC.c),Pair(4, IbanC.n),Pair(16, IbanC.c),), Regex("^[0-9A-Z]{4}[0-9]{4}[0-9A-Z]{16}$")), CH(21, listOf(Pair(5, IbanC.n),Pair(12, IbanC.c),), Regex("^[0-9]{5}[0-9A-Z]{12}$")), CR(22, listOf(Pair(18, IbanC.n),), Regex("^[0-9]{18}$")), CY(28, listOf(Pair(8, IbanC.n),Pair(16, IbanC.c),), Regex("^[0-9]{8}[0-9A-Z]{16}$")), CZ(24, listOf(Pair(20, IbanC.n),), Regex("^[0-9]{20}$")), DE(22, listOf(Pair(18, IbanC.n),), Regex("^[0-9]{18}$")), DJ(27, listOf(Pair(23, IbanC.n),), Regex("^[0-9]{23}$")), DK(18, listOf(Pair(14, IbanC.n),), Regex("^[0-9]{14}$")), DO(28, listOf(Pair(4, IbanC.c),Pair(20, IbanC.n),), Regex("^[0-9A-Z]{4}[0-9]{20}$")), EE(20, listOf(Pair(16, IbanC.n),), Regex("^[0-9]{16}$")), EG(29, listOf(Pair(25, IbanC.n),), Regex("^[0-9]{25}$")), ES(24, listOf(Pair(20, IbanC.n),), Regex("^[0-9]{20}$")), FI(18, listOf(Pair(14, IbanC.n),), Regex("^[0-9]{14}$")), FK(18, listOf(Pair(2, IbanC.a),Pair(12, IbanC.n),), Regex("^[A-Z]{2}[0-9]{12}$")), FO(18, listOf(Pair(14, IbanC.n),), Regex("^[0-9]{14}$")), FR(27, listOf(Pair(10, IbanC.n),Pair(11, IbanC.c),Pair(2, IbanC.n),), Regex("^[0-9]{10}[0-9A-Z]{11}[0-9]{2}$")), GB(22, listOf(Pair(4, IbanC.a),Pair(14, IbanC.n),), Regex("^[A-Z]{4}[0-9]{14}$")), GE(22, listOf(Pair(2, IbanC.a),Pair(16, IbanC.n),), Regex("^[A-Z]{2}[0-9]{16}$")), GI(23, listOf(Pair(4, IbanC.a),Pair(15, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{15}$")), GL(18, listOf(Pair(14, IbanC.n),), Regex("^[0-9]{14}$")), GR(27, listOf(Pair(7, IbanC.n),Pair(16, IbanC.c),), Regex("^[0-9]{7}[0-9A-Z]{16}$")), GT(28, listOf(Pair(24, IbanC.c),), Regex("^[0-9A-Z]{24}$")), HN(28, listOf(Pair(4, IbanC.a),Pair(20, IbanC.n),), Regex("^[A-Z]{4}[0-9]{20}$")), HR(21, listOf(Pair(17, IbanC.n),), Regex("^[0-9]{17}$")), HU(28, listOf(Pair(24, IbanC.n),), Regex("^[0-9]{24}$")), IE(22, listOf(Pair(4, IbanC.a),Pair(14, IbanC.n),), Regex("^[A-Z]{4}[0-9]{14}$")), IL(23, listOf(Pair(19, IbanC.n),), Regex("^[0-9]{19}$")), IQ(23, listOf(Pair(4, IbanC.a),Pair(15, IbanC.n),), Regex("^[A-Z]{4}[0-9]{15}$")), IS(26, listOf(Pair(22, IbanC.n),), Regex("^[0-9]{22}$")), IT(27, listOf(Pair(1, IbanC.a),Pair(10, IbanC.n),Pair(12, IbanC.c),), Regex("^[A-Z]{1}[0-9]{10}[0-9A-Z]{12}$")), JO(30, listOf(Pair(4, IbanC.a),Pair(4, IbanC.n),Pair(18, IbanC.c),), Regex("^[A-Z]{4}[0-9]{4}[0-9A-Z]{18}$")), KW(30, listOf(Pair(4, IbanC.a),Pair(22, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{22}$")), KZ(20, listOf(Pair(3, IbanC.n),Pair(13, IbanC.c),), Regex("^[0-9]{3}[0-9A-Z]{13}$")), LB(28, listOf(Pair(4, IbanC.n),Pair(20, IbanC.c),), Regex("^[0-9]{4}[0-9A-Z]{20}$")), LC(32, listOf(Pair(4, IbanC.a),Pair(24, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{24}$")), LI(21, listOf(Pair(5, IbanC.n),Pair(12, IbanC.c),), Regex("^[0-9]{5}[0-9A-Z]{12}$")), LT(20, listOf(Pair(16, IbanC.n),), Regex("^[0-9]{16}$")), LU(20, listOf(Pair(3, IbanC.n),Pair(13, IbanC.c),), Regex("^[0-9]{3}[0-9A-Z]{13}$")), LV(21, listOf(Pair(4, IbanC.a),Pair(13, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{13}$")), LY(25, listOf(Pair(21, IbanC.n),), Regex("^[0-9]{21}$")), MC(27, listOf(Pair(10, IbanC.n),Pair(11, IbanC.c),Pair(2, IbanC.n),), Regex("^[0-9]{10}[0-9A-Z]{11}[0-9]{2}$")), MD(24, listOf(Pair(20, IbanC.c),), Regex("^[0-9A-Z]{20}$")), ME(22, listOf(Pair(18, IbanC.n),), Regex("^[0-9]{18}$")), MK(19, listOf(Pair(3, IbanC.n),Pair(10, IbanC.c),Pair(2, IbanC.n),), Regex("^[0-9]{3}[0-9A-Z]{10}[0-9]{2}$")), MN(20, listOf(Pair(16, IbanC.n),), Regex("^[0-9]{16}$")), MR(27, listOf(Pair(23, IbanC.n),), Regex("^[0-9]{23}$")), MT(31, listOf(Pair(4, IbanC.a),Pair(5, IbanC.n),Pair(18, IbanC.c),), Regex("^[A-Z]{4}[0-9]{5}[0-9A-Z]{18}$")), MU(30, listOf(Pair(4, IbanC.a),Pair(19, IbanC.n),Pair(3, IbanC.a),), Regex("^[A-Z]{4}[0-9]{19}[A-Z]{3}$")), NI(28, listOf(Pair(4, IbanC.a),Pair(20, IbanC.n),), Regex("^[A-Z]{4}[0-9]{20}$")), NL(18, listOf(Pair(4, IbanC.a),Pair(10, IbanC.n),), Regex("^[A-Z]{4}[0-9]{10}$")), NO(15, listOf(Pair(11, IbanC.n),), Regex("^[0-9]{11}$")), OM(23, listOf(Pair(3, IbanC.n),Pair(16, IbanC.c),), Regex("^[0-9]{3}[0-9A-Z]{16}$")), PK(24, listOf(Pair(4, IbanC.a),Pair(16, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{16}$")), PL(28, listOf(Pair(24, IbanC.n),), Regex("^[0-9]{24}$")), PS(29, listOf(Pair(4, IbanC.a),Pair(21, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{21}$")), PT(25, listOf(Pair(21, IbanC.n),), Regex("^[0-9]{21}$")), QA(29, listOf(Pair(4, IbanC.a),Pair(21, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{21}$")), RO(24, listOf(Pair(4, IbanC.a),Pair(16, IbanC.c),), Regex("^[A-Z]{4}[0-9A-Z]{16}$")), RS(22, listOf(Pair(18, IbanC.n),), Regex("^[0-9]{18}$")), RU(33, listOf(Pair(14, IbanC.n),Pair(15, IbanC.c),), Regex("^[0-9]{14}[0-9A-Z]{15}$")), SA(24, listOf(Pair(2, IbanC.n),Pair(18, IbanC.c),), Regex("^[0-9]{2}[0-9A-Z]{18}$")), SC(31, listOf(Pair(4, IbanC.a),Pair(20, IbanC.n),Pair(3, IbanC.a),), Regex("^[A-Z]{4}[0-9]{20}[A-Z]{3}$")), SD(18, listOf(Pair(14, IbanC.n),), Regex("^[0-9]{14}$")), SE(24, listOf(Pair(20, IbanC.n),), Regex("^[0-9]{20}$")), SI(19, listOf(Pair(15, IbanC.n),), Regex("^[0-9]{15}$")), SK(24, listOf(Pair(20, IbanC.n),), Regex("^[0-9]{20}$")), SM(27, listOf(Pair(1, IbanC.a),Pair(10, IbanC.n),Pair(12, IbanC.c),), Regex("^[A-Z]{1}[0-9]{10}[0-9A-Z]{12}$")), SO(23, listOf(Pair(19, IbanC.n),), Regex("^[0-9]{19}$")), ST(25, listOf(Pair(21, IbanC.n),), Regex("^[0-9]{21}$")), SV(28, listOf(Pair(4, IbanC.a),Pair(20, IbanC.n),), Regex("^[A-Z]{4}[0-9]{20}$")), TL(23, listOf(Pair(19, IbanC.n),), Regex("^[0-9]{19}$")), TN(24, listOf(Pair(20, IbanC.n),), Regex("^[0-9]{20}$")), TR(26, listOf(Pair(6, IbanC.n),Pair(16, IbanC.c),), Regex("^[0-9]{6}[0-9A-Z]{16}$")), UA(29, listOf(Pair(6, IbanC.n),Pair(19, IbanC.c),), Regex("^[0-9]{6}[0-9A-Z]{19}$")), VA(22, listOf(Pair(18, IbanC.n),), Regex("^[0-9]{18}$")), VG(24, listOf(Pair(4, IbanC.a),Pair(16, IbanC.n),), Regex("^[A-Z]{4}[0-9]{16}$")), XK(20, listOf(Pair(16, IbanC.n),), Regex("^[0-9]{16}$")), YE(30, listOf(Pair(4, IbanC.a),Pair(4, IbanC.n),Pair(18, IbanC.c),), Regex("^[A-Z]{4}[0-9]{4}[0-9A-Z]{18}$")), ; val bbanLen get() = ibanLen - 4 } val VALID_IBAN = listOf( Pair("AD1200012030200359100100", "00012030200359100100"), Pair("AE070331234567890123456", "0331234567890123456"), Pair("AL47212110090000000235698741", "212110090000000235698741"), Pair("AT611904300234573201", "1904300234573201"), Pair("AZ21NABZ00000000137010001944", "NABZ00000000137010001944"), Pair("BA391290079401028494", "1290079401028494"), Pair("BE68539007547034", "539007547034"), Pair("BG80BNBG96611020345678", "BNBG96611020345678"), Pair("BH67BMAG00001299123456", "BMAG00001299123456"), Pair("BI4210000100010000332045181", "10000100010000332045181"), Pair("BR1800360305000010009795493C1", "00360305000010009795493C1"), Pair("BY13NBRB3600900000002Z00AB00", "NBRB 3600900000002Z00AB00"), Pair("CH9300762011623852957", "00762011623852957"), Pair("CR05015202001026284066", "015202001026284066"), Pair("CY17002001280000001200527600", "002001280000001200527600"), Pair("CZ6508000000192000145399", "08000000192000145399"), Pair("DE89370400440532013000", "370400440532013000"), Pair("DJ2100010000000154000100186", "00010000000154000100186"), Pair("DK5000400440116243", "00400440116243"), Pair("DO28BAGR00000001212453611324", "BAGR00000001212453611324"), Pair("EE382200221020145685", "2200221020145685"), Pair("EG380019000500000000263180002", "0019000500000000263180002"), Pair("ES9121000418450200051332", "21000418450200051332"), Pair("FI2112345600000785", null), Pair("FK88SC123456789012", "SC123456789012"), Pair("FO6264600001631634", "64600001631634"), Pair("FR1420041010050500013M02606", "20041010050500013M02606"), Pair("GB29NWBK60161331926819", "NWBK60161331926819"), Pair("GE29NB0000000101904917", "NB0000000101904917"), Pair("GI75NWBK000000007099453", "NWBK000000007099453"), Pair("GL8964710001000206", "64710001000206"), Pair("GR1601101250000000012300695", "01101250000000012300695"), Pair("GT82TRAJ01020000001210029690", "TRAJ01020000001210029690"), Pair("HN88CABF00000000000250005469", "CABF00000000000250005469"), Pair("HR1210010051863000160", "10010051863000160"), Pair("HU42117730161111101800000000", "117730161111101800000000"), Pair("IE29AIBK93115212345678", "AIBK93115212345678"), Pair("IL620108000000099999999", "0108000000099999999"), Pair("IQ98NBIQ850123456789012", "NBIQ850123456789012"), Pair("IS140159260076545510730339", "0159260076545510730339"), Pair("IT60X0542811101000000123456", "X0542811101000000123456"), Pair("JO94CBJO0010000000000131000302", "CBJO0010000000000131000302"), Pair("KW81CBKU0000000000001234560101", "CBKU0000000000001234560101"), Pair("KZ86125KZT5004100100", "125KZT5004100100"), Pair("LB62099900000001001901229114", "0999 0000 0001 0019 0122 9114"), Pair("LC55HEMM000100010012001200023015", "HEMM000100010012001200023015"), Pair("LI21088100002324013AA", "088100002324013AA"), Pair("LT121000011101001000", "1000011101001000"), Pair("LU280019400644750000", "0019400644750000"), Pair("LV80BANK0000435195001", "BANK0000435195001"), Pair("LY83002048000020100120361", "002048000020100120361"), Pair("MC5811222000010123456789030", "11222 00001 01234567890 30"), Pair("MD24AG000225100013104168", "AG000225100013104168"), Pair("ME25505000012345678951", "505000012345678951"), Pair("MK07250120000058984", "250120000058984"), Pair("MN121234123456789123", "1234123456789123"), Pair("MR1300020001010000123456753", "00020001010000123456753"), Pair("MT84MALT011000012345MTLCAST001S", "MALT011000012345MTLCAST001S"), Pair("MU17BOMM0101101030300200000MUR", "BOMM0101101030300200000MUR"), Pair("NI45BAPR00000013000003558124", "BAPR00000013000003558124"), Pair("NL91ABNA0417164300", "ABNA0417164300"), Pair("NO9386011117947", "86011117947"), Pair("OM810180000001299123456", "0180000001299123456"), Pair("PK36SCBL0000001123456702", "SCBL0000001123456702"), Pair("PL61109010140000071219812874", "109010140000071219812874"), Pair("PS92PALS000000000400123456702", "PALS000000000400123456702"), Pair("PT50000201231234567890154", "000201231234567890154"), Pair("QA58DOHB00001234567890ABCDEFG", "DOHB00001234567890ABCDEFG"), Pair("RO49AAAA1B31007593840000", "AAAA1B31007593840000"), Pair("RS35260005601001611379", "260005601001611379"), Pair("RU0304452522540817810538091310419", "044525225 40817 810 5 3809 1310419"), Pair("SA0380000000608010167519", "80000000608010167519"), Pair("SC18SSCB11010000000000001497USD", "SSCB11010000000000001497USD"), Pair("SD2129010501234001", "29010501234001"), Pair("SE4550000000058398257466", "50000000058398257466"), Pair("SI56263300012039086", "263300012039086"), Pair("SK3112000000198742637541", "12000000198742637541"), Pair("SM86U0322509800000000270100", "U0322509800000000270100"), Pair("SO211000001001000100141", "1000001001000100141"), Pair("ST23000100010051845310146", "000100010051845310146"), Pair("SV62CENR00000000000000700025", "CENR00000000000000700025"), Pair("TL380080012345678910157", "0080012345678910157"), Pair("TN5910006035183598478831", "10006035183598478831"), Pair("TR330006100519786457841326", "0006100519786457841326"), Pair("UA213223130000026007233566001", "3223130000026007233566001"), Pair("VA59001123000012345678", "001123000012345678"), Pair("VG96VPVG0000012345678901", "VPVG0000012345678901"), Pair("XK051212012345678906", "1212012345678906"), Pair("YE15CBYE0001018861234567891234", "CBYE0001018861234567891234"), );libeufin-1.6.8/libeufin-common/src/main/kotlin/params.kt0000664000175000017500000001406715236062741023502 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import io.ktor.http.* import kotlin.math.min import java.util.* fun Parameters.expect(name: String): String = get(name) ?: throw badRequest("Missing '$name' parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING) fun Parameters.int(name: String): Int? = get(name)?.run { toIntOrNull() ?: throw paramsMalformed("Param '$name' not a number") } fun Parameters.expectInt(name: String): Int = int(name) ?: throw badRequest("Missing '$name' number parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING) fun Parameters.long(name: String): Long? = get(name)?.run { toLongOrNull() ?: throw paramsMalformed("Param '$name' not a number") } fun Parameters.expectLong(name: String): Long = long(name) ?: throw badRequest("Missing '$name' number parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING) fun Parameters.uuid(name: String): UUID? = get(name)?.run { try { UUID.fromString(this) } catch (e: Exception) { throw paramsMalformed("Param '$name' not an UUID") } } fun Parameters.expectUuid(name: String): UUID = uuid(name) ?: throw badRequest("Missing '$name' UUID parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING) fun Parameters.payto(name: String): Payto? = get(name)?.run { try { Payto.parse(this) } catch (e: Exception) { throw paramsMalformed("Param '$name' not a valid payto") } } fun Parameters.expectPayto(name: String): Payto = payto(name) ?: throw badRequest("Missing '$name' payto parameter", TalerErrorCode.GENERIC_PARAMETER_MISSING) fun Parameters.amount(name: String): TalerAmount? = get(name)?.run { try { TalerAmount(this) } catch (e: Exception) { throw paramsMalformed("Param '$name' not a taler amount") } } data class PageParams( val limit: Int, val offset: Long ) { companion object { fun extract(params: Parameters): PageParams { val legacy_limit_value = params.int("delta") val new_limit_value = params.int("limit") if (legacy_limit_value != null && new_limit_value != null && legacy_limit_value != new_limit_value) throw paramsMalformed("Param 'limit' cannot be used with param 'delta'") val legacy_offset_value = params.long("start") val new_offset_value = params.long("offset") if (legacy_offset_value != null && new_offset_value != null && legacy_offset_value != new_offset_value) throw paramsMalformed("Param 'offset' cannot be used with param 'start'") val limit: Int = new_limit_value ?: legacy_limit_value ?: -20 if (limit == 0) throw paramsMalformed("Param 'limit' must be non-zero") else if (limit > MAX_PAGE_SIZE) throw paramsMalformed("Param 'limit' must be <= ${MAX_PAGE_SIZE}") // The sign of 'limit' only selects the direction, so the negative // side needs the same bound. Note that abs(Int.MIN_VALUE) silently // returns Int.MIN_VALUE, so an unbounded negative limit would reach // SQL as a negative LIMIT. else if (limit < -MAX_PAGE_SIZE) throw paramsMalformed("Param 'limit' must be >= ${-MAX_PAGE_SIZE}") val offset: Long = new_offset_value ?: legacy_offset_value ?: if (limit >= 0) 0L else Long.MAX_VALUE if (offset < 0) throw paramsMalformed("Param 'offset' must be a positive number") return PageParams(limit, offset) } } } data class TransferParams( val page: PageParams, val status: TransferStatusState? ) { companion object { private val names = TransferStatusState.entries.map { it.name } private val names_fmt = names.joinToString() fun extract(params: Parameters): TransferParams { val status = params["status"]?.let { if (!names.contains(it)) { throw paramsMalformed("Param 'status' must be one of $names_fmt") } TransferStatusState.valueOf(it) } return TransferParams(PageParams.extract(params), status) } } } data class PollingParams( val timeout_ms: Long ) { companion object { fun extract(params: Parameters): PollingParams { val legacy_value = params.long("long_poll_ms") val new_value = params.long("timeout_ms") if (legacy_value != null && new_value != null && legacy_value != new_value) throw paramsMalformed("Param 'timeout_ms' cannot be used with param 'long_poll_ms'") val timeout_ms: Long = min(new_value ?: legacy_value ?: 0, MAX_TIMEOUT_MS) if (timeout_ms < 0) throw paramsMalformed("Param 'timeout_ms' must be a positive number") return PollingParams(timeout_ms) } } } data class HistoryParams( val page: PageParams, val polling: PollingParams ) { companion object { fun extract(params: Parameters): HistoryParams { return HistoryParams(PageParams.extract(params), PollingParams.extract(params)) } } } data class AccountCheckParams( val account: Payto ) { companion object { fun extract(params: Parameters): AccountCheckParams { val account = params.expectPayto("account") return AccountCheckParams(account) } } }libeufin-1.6.8/libeufin-common/src/main/kotlin/Encoding.kt0000664000175000017500000000665415122266731023747 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common /** Crockford's Base32 implementation */ object Base32Crockford { /** Crockford's Base32 alphabet */ const val ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" /** Base32 mark to extract 5 bits chunks */ private const val MASK = 0b11111 /** Crockford's Base32 inversed alphabet */ private val INV = intArrayOf( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 1, 18, 19, 1, 20, 21, 0, 22, 23, 24, 25, 26, 27, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 1, 18, 19, 1, 20, 21, 0, 22, 23, 24, 25, 26, 27, 27, 28, 29, 30, 31, ) fun encode(data: ByteArray): String = buildString(encodedSize(data.size)) { var buffer = 0 var bitsLeft = 0 for (byte in data) { // Read input buffer = (buffer shl 8) or (byte.toInt() and 0xFF) bitsLeft += 8 // Write symbols while (bitsLeft >= 5) { append(ALPHABET[(buffer shr (bitsLeft - 5)) and MASK]) bitsLeft -= 5 } } if (bitsLeft > 0) { // Write remaining bits append(ALPHABET[(buffer shl (5 - bitsLeft)) and MASK]) } } fun decode(encoded: String): ByteArray { val out = ByteArray(decodedSize(encoded.length)) var bitsLeft = 0 var buffer = 0 var cursor = 0 for (char in encoded) { // Read input val index = char - '0' require(index in 0..INV.size) { "invalid Base32 character: $char" } val decoded = INV[index] require(decoded != -1) { "invalid Base32 character: $char" } buffer = (buffer shl 5) or decoded bitsLeft += 5 // Write bytes if (bitsLeft >= 8) { out[cursor++] = (buffer shr (bitsLeft - 8)).toByte() bitsLeft -= 8 // decrease of written bits. } } return out } /** * Compute the length of the resulting string when encoding data of the given size * in bytes. * * @param dataSize size of the data to encode in bytes * @return size of the string that would result from encoding */ fun encodedSize(dataSize: Int): Int { return (dataSize * 8 + 4) / 5 } /** * Compute the length of the resulting data in bytes when decoding a (valid) string of the * given size. * * @param stringSize size of the string to decode * @return size of the resulting data in bytes */ fun decodedSize(stringSize: Int): Int { return (stringSize * 5) / 8 } } libeufin-1.6.8/libeufin-common/src/main/kotlin/AnsiColor.kt0000664000175000017500000000444515122266731024106 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common object ANSI { private val ANSI_PATTERN = Regex("\\u001B\\[[;\\d]*m") enum class Color(val code: Int) { BLACK(0), RED(1), GREEN(2), YELLOW(3), BLUE(4), MAGENTA(5), CYAN(6), WHITE(7) } /** Compute [msg] length without ANSI escape sequences */ fun CharSequence.displayLength(): Int = splitToSequence(ANSI_PATTERN).sumOf { it.length } /** Format a [msg] using optionals [fg] and [bg] colors and optionally make the text [bold] */ fun fmt(msg: String, fg: Color? = null, bg: Color? = null, bold: Boolean = false): String { if (fg == null && bg == null && !bold) return msg return buildString { fun next() { if (last() != '[') { append(';') } } append("\u001b[") if (bold) { append('1') } if (fg != null) { next() append('3') append(fg.code.toString()) } if (bg != null) { next() append('4') append(bg.code.toString()) } append('m') append(msg) append("\u001b[0m") } } fun red(msg: String) = fmt(msg, Color.RED) fun green(msg: String) = fmt(msg, Color.GREEN) fun yellow(msg: String) = fmt(msg, Color.YELLOW) fun magenta(msg: String) = fmt(msg, Color.MAGENTA) fun bold(msg: String) = fmt(msg, bold = true) }libeufin-1.6.8/libeufin-common/src/main/kotlin/TalerMessage.kt0000664000175000017500000004020115221677432024563 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import java.nio.ByteBuffer import java.nio.ByteOrder import java.security.MessageDigest import io.github.smiley4.schemakenerator.core.annotations.Description import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import tech.libeufin.common.crypto.CryptoUtil.hashStringNbo import tech.libeufin.common.crypto.NBO enum class IncomingType { reserve, kyc, map } @Description("State of a wire transfer") enum class TransferStatusState { pending, transient_failure, permanent_failure, success } /** Response GET /taler-wire-gateway/config */ @Serializable @Description("Wire gateway configuration response") data class WireGatewayConfig( @Description("Currency supported by the gateway") val currency: String, @Description("Whether account check is supported") val support_account_check: Boolean ) { @Description("API name identifier") val name: String = "taler-wire-gateway" @Description("API version string") val version: String = WIRE_GATEWAY_API_VERSION } /** Request POST /taler-wire-gateway/transfer */ @Serializable @Description("Wire transfer request") data class TransferRequest( @Description("Unique identifier for this request") val request_uid: HashCode, @Description("Amount to transfer") val amount: TalerAmount, @Description("Base URL of the exchange") val exchange_base_url: BaseURL, @Description("Wire transfer identifier") val wtid: ShortHashCode, @Description("Payto URI of the credit account") val credit_account: Payto, @Description("Optional transfer metadata") val metadata: String? = null, ) { init { if (metadata != null && !METADATA_REGEX.matches(metadata)) throw badRequest("metadata '$metadata' is malformed, must match [a-zA-Z0-9-.+:]{1,40}") } companion object { private val METADATA_REGEX = Regex("^[a-zA-Z0-9-.:]{1,40}$") } } /** Response POST /taler-wire-gateway/transfer */ @Serializable @Description("Wire transfer response") data class TransferResponse( @Description("Timestamp of the transfer") val timestamp: TalerTimestamp, @Description("Database row identifier") val row_id: Long ) /** Request GET /taler-wire-gateway/transfers */ @Serializable @Description("List of wire transfers") data class TransferList( @Description("List of transfer statuses") val transfers: List, @Description("Payto URI of the debit account") val debit_account: String ) @Serializable @Description("Transfer status in a list response") data class TransferListStatus( @Description("Database row identifier") val row_id: Long, @Description("Current transfer status") val status: TransferStatusState, @Description("Transfer amount") val amount: TalerAmount, @Description("Payto URI of the credit account") val credit_account: String, @Description("Timestamp of the transfer") val timestamp: TalerTimestamp ) /** Request GET /taler-wire-gateway/transfers/{ROW_iD} */ @Serializable @Description("Detailed status of a single transfer") data class TransferStatus( @Description("Current transfer status") val status: TransferStatusState, @Description("Optional status message") val status_msg: String? = null, @Description("Transfer amount") val amount: TalerAmount, @Description("URL of the originating exchange") val origin_exchange_url: String, @Description("Optional transfer metadata") val metadata: String? = null, @Description("Wire transfer identifier") val wtid: ShortHashCode, @Description("Payto URI of the credit account") val credit_account: String, @Description("Timestamp of the transfer") val timestamp: TalerTimestamp ) /** Request POST /taler-wire-gateway/admin/add-incoming */ @Serializable @Description("Request to add an incoming transaction") data class AddIncomingRequest( @Description("Amount of the incoming transaction") val amount: TalerAmount, @Description("Reserve public key") val reserve_pub: EddsaPublicKey, @Description("Payto URI of the debit account") val debit_account: Payto ) /** Response POST /taler-wire-gateway/admin/add-incoming */ @Serializable @Description("Response to adding an incoming transaction") data class AddIncomingResponse( @Description("Timestamp of the transaction") val timestamp: TalerTimestamp, @Description("Database row identifier") val row_id: Long ) /** Request POST /taler-wire-gateway/admin/add-kycauth */ @Serializable @Description("Request to add a KYC auth transaction") data class AddKycauthRequest( @Description("Amount of the KYC auth transaction") val amount: TalerAmount, @Description("Account public key for KYC") val account_pub: EddsaPublicKey, @Description("Payto URI of the debit account") val debit_account: Payto ) /** Request POST /taler-wire-gateway/admin/add-mapped */ @Serializable data class AddMappedRequest( val amount: TalerAmount, val authorization_pub: EddsaPublicKey, val debit_account: Payto ) /** Response GET /taler-wire-gateway/history/incoming */ @Serializable @Description("History of incoming transactions") data class IncomingHistory( @Description("List of incoming transactions") val incoming_transactions: List, @Description("Payto URI of the credit account") val credit_account: String ) /** Inner response GET /taler-wire-gateway/history/incoming */ @Serializable @Description("Incoming bank transaction details") sealed interface IncomingBankTransaction { val row_id: Long val date: TalerTimestamp val amount: TalerAmount val debit_account: String val credit_fee: TalerAmount? } @Serializable @SerialName("KYCAUTH") @Description("Incoming KYC authentication transaction") data class IncomingKycAuthTransaction( @Description("Database row identifier") override val row_id: Long, @Description("Timestamp of the transaction") override val date: TalerTimestamp, @Description("Transaction amount") override val amount: TalerAmount, @Description("Optional credit fee") override val credit_fee: TalerAmount? = null, @Description("Payto URI of the debit account") override val debit_account: String, @Description("Account public key for KYC") val account_pub: EddsaPublicKey, @Description("Optional authorization public key") val authorization_pub: EddsaPublicKey? = null, @Description("Optional authorization signature") val authorization_sig: EddsaSignature? = null, ) : IncomingBankTransaction @Serializable @SerialName("RESERVE") @Description("Incoming reserve transaction") data class IncomingReserveTransaction( @Description("Database row identifier") override val row_id: Long, @Description("Timestamp of the transaction") override val date: TalerTimestamp, @Description("Transaction amount") override val amount: TalerAmount, @Description("Optional credit fee") override val credit_fee: TalerAmount? = null, @Description("Payto URI of the debit account") override val debit_account: String, @Description("Reserve public key") val reserve_pub: EddsaPublicKey, @Description("Optional authorization public key") val authorization_pub: EddsaPublicKey? = null, @Description("Optional authorization signature") val authorization_sig: EddsaSignature? = null, ) : IncomingBankTransaction @Serializable @SerialName("WAD") @Description("Incoming WAD transaction") data class IncomingWadTransaction( @Description("Database row identifier") override val row_id: Long, @Description("Timestamp of the transaction") override val date: TalerTimestamp, @Description("Transaction amount") override val amount: TalerAmount, @Description("Optional credit fee") override val credit_fee: TalerAmount? = null, @Description("Payto URI of the debit account") override val debit_account: String, @Description("URL of the originating exchange") val origin_exchange_url: String, @Description("WAD identifier") val wad_id: String // TODO 24 bytes Base32 ) : IncomingBankTransaction /** Response GET /taler-wire-gateway/history/outgoing */ @Serializable @Description("History of outgoing transactions") data class OutgoingHistory( @Description("List of outgoing transactions") val outgoing_transactions: List, @Description("Payto URI of the debit account") val debit_account: String ) /** Inner response GET /taler-wire-gateway/history/outgoing */ @Serializable @Description("Single outgoing transaction details") data class OutgoingTransaction( @Description("Database row identifier") val row_id: Long, // DB row ID of the payment. @Description("Timestamp of the transaction") val date: TalerTimestamp, @Description("Transaction amount") val amount: TalerAmount, @Description("Payto URI of the credit account") val credit_account: String, @Description("Wire transfer identifier") val wtid: ShortHashCode, @Description("Base URL of the exchange") val exchange_base_url: String, @Description("Optional transfer metadata") val metadata: String? = null, @Description("Optional debit fee") val debit_fee: TalerAmount? = null ) /** Response GET /taler-wire-gateway/account/check */ @Serializable @Description("Account information response") class AccountInfo() /** Response GET /taler-prepared-transfer/config */ @Serializable @Description("Prepared transfer configuration") data class PreparedTransferConfig( @Description("Currency supported") val currency: String, @Description("List of supported subject formats") val supported_formats: List ) { @Description("API name identifier") val name: String = "taler-prepared-transfer" @Description("API version string") val version: String = WIRE_TRANSFER_API_VERSION } /** Inner response GET /taler-prepared-transfer/registration */ @Serializable @Description("Transfer subject information") sealed interface TransferSubject { @Serializable @SerialName("SIMPLE") @Description("Simple text transfer subject") data class Simple( @Description("Plain text transfer subject") val subject: String, @Description("Credit amount for the transfer") val credit_amount: TalerAmount ) : TransferSubject @Serializable @SerialName("URI") @Description("URI-based transfer subject") data class Uri( @Description("Taler URI for the transfer") val uri: String, @Description("Credit amount for the transfer") val credit_amount: TalerAmount ) : TransferSubject @Serializable @SerialName("CH_QR_BILL") @Description("Swiss QR bill transfer subject") data class QrBill( @Description("QR reference number for the bill") val qr_reference_number: String, @Description("Credit amount for the transfer") val credit_amount: TalerAmount, ) : TransferSubject } @Serializable @Description("Supported transfer subject format") enum class SubjectFormat { SIMPLE, URI, CH_QR_BILL } @Serializable @Description("Public key algorithm") enum class PublicKeyAlg { EdDSA } @Serializable @Description("Type of wire transfer") enum class TransferType { reserve, kyc } @Serializable @Description("Request to generate a transfer subject") data class SubjectRequest( @Description("Payto URI of the credit account") val credit_account: Payto, @Description("Type of transfer") val type: TransferType, @Description("Whether subject is recurrent") val recurrent: Boolean, @Description("Credit amount for the transfer") val credit_amount: TalerAmount, @Description("Public key algorithm") val alg: PublicKeyAlg, @Description("Account public key") val account_pub: EddsaPublicKey, @Description("Authorization public key") val authorization_pub: EddsaPublicKey, @Description("Authorization signature") val authorization_sig: EddsaSignature, ) : NBO { /* Network bytes */ override fun nbo(): ByteArray = ByteBuffer.allocate(104).apply { order(ByteOrder.BIG_ENDIAN) putInt(capacity()) putInt(1224) put(hashStringNbo(credit_account.toString())) put(credit_amount.nbo()) putInt(when (type) { TransferType.reserve -> 1 TransferType.kyc -> 2 }) putShort(if (recurrent) 2 else 1) putShort(when (alg) { PublicKeyAlg.EdDSA -> 1 }) put(account_pub.raw) }.array() fun sign(priv: ByteArray): SubjectRequest = this.copy(authorization_sig = this.signNbo(priv)) fun verify(): Boolean = this.verifyNbo(this.authorization_sig, this.authorization_pub) } @Serializable @Description("Result of subject generation") data class SubjectResult( @Description("List of generated transfer subjects") val subjects: List, @Description("Expiration timestamp of the subjects") val expiration: TalerTimestamp ) @Serializable @Description("Request to unregister a subject") data class Unregistration( @Description("Timestamp of the unregistration") val timestamp: TalerTimestamp, @Description("Authorization public key") val authorization_pub: EddsaPublicKey, @Description("Authorization signature") val authorization_sig: EddsaSignature ) : NBO { /* Network bytes */ override fun nbo(): ByteArray = ByteBuffer.allocate(16).apply { order(ByteOrder.BIG_ENDIAN) putInt(capacity()) putInt(1225) putLong(timestamp.instant.epochSecond * 1000 * 1000) }.array() fun sign(priv: ByteArray): Unregistration = this.copy(authorization_sig = this.signNbo(priv)) fun verify(): Boolean = this.verifyNbo(this.authorization_sig, this.authorization_pub) } /** Response GET /taler-revenue/config */ @Serializable @Description("Revenue API configuration response") data class RevenueConfig( @Description("Currency supported by the API") val currency: String ) { @Description("API name identifier") val name: String = "taler-revenue" @Description("API version string") val version: String = REVENUE_API_VERSION } /** Request GET /taler-revenue/history */ @Serializable @Description("History of revenue incoming transactions") data class RevenueIncomingHistory( @Description("List of incoming revenue transactions") val incoming_transactions: List, @Description("Payto URI of the credit account") val credit_account: String ) /** Inner request GET /taler-revenue/history */ @Serializable @Description("Single revenue incoming bank transaction") data class RevenueIncomingBankTransaction( @Description("Database row identifier") val row_id: Long, @Description("Timestamp of the transaction") val date: TalerTimestamp, @Description("Transaction amount") val amount: TalerAmount, @Description("Optional credit fee") val credit_fee: TalerAmount? = null, @Description("Payto URI of the debit account") val debit_account: String, @Description("Transaction subject line") val subject: String ) /** Response GET /taler-observability/config */ @Serializable @Description("Observability API configuration response") class TalerObservabilityConfig() { @Description("API name identifier") val name: String = "taler-observability" @Description("API version string") val version: String = OBSERVABILITY_API_VERSION } libeufin-1.6.8/libeufin-common/src/main/kotlin/TalerErrorCode.kt0000664000175000017500000054646515173736052025112 0ustar grothoffgrothoff/* * This file is part of GNU Taler * Copyright (C) 2012-2026 Taler Systems SA * GNU Taler is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * GNU Taler is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * SPDX-License-Identifier: LGPL3.0-or-later * Note: the LGPL does not apply to all components of GNU Taler, * but it does apply to this file. */ package tech.libeufin.common enum class TalerErrorCode(val code: Int, val status: Int, val description: String) { /** Special code to indicate success (no error). */ NONE(0, 0, "Special code to indicate success (no error)."), /** An error response did not include an error code in the format expected by the client. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server. */ INVALID(1, 0, "An error response did not include an error code in the format expected by the client. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server."), /** An internal failure happened on the client side. Details should be in the local logs. Check if you are using the latest available version or file a report with the developers. */ GENERIC_CLIENT_INTERNAL_ERROR(2, 0, "An internal failure happened on the client side. Details should be in the local logs. Check if you are using the latest available version or file a report with the developers."), /** The client does not support the protocol version advertised by the server. */ GENERIC_CLIENT_UNSUPPORTED_PROTOCOL_VERSION(3, 0, "The client does not support the protocol version advertised by the server."), /** The response we got from the server was not in the expected format. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server. */ GENERIC_INVALID_RESPONSE(10, 0, "The response we got from the server was not in the expected format. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server."), /** The operation timed out. Trying again might help. Check the network connection. */ GENERIC_TIMEOUT(11, 0, "The operation timed out. Trying again might help. Check the network connection."), /** The protocol version given by the server does not follow the required format. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server. */ GENERIC_VERSION_MALFORMED(12, 0, "The protocol version given by the server does not follow the required format. Most likely, the server does not speak the GNU Taler protocol. Check the URL and/or the network connection to the server."), /** The service responded with a reply that was in the right data format, but the content did not satisfy the protocol. Please file a bug report. */ GENERIC_REPLY_MALFORMED(13, 0, "The service responded with a reply that was in the right data format, but the content did not satisfy the protocol. Please file a bug report."), /** There is an error in the client-side configuration, for example an option is set to an invalid value. Check the logs and fix the local configuration. */ GENERIC_CONFIGURATION_INVALID(14, 0, "There is an error in the client-side configuration, for example an option is set to an invalid value. Check the logs and fix the local configuration."), /** The client made a request to a service, but received an error response it does not know how to handle. Please file a bug report. */ GENERIC_UNEXPECTED_REQUEST_ERROR(15, 0, "The client made a request to a service, but received an error response it does not know how to handle. Please file a bug report."), /** The token used by the client to authorize the request does not grant the required permissions for the request. Check the requirements and obtain a suitable authorization token to proceed. */ GENERIC_TOKEN_PERMISSION_INSUFFICIENT(16, 403, "The token used by the client to authorize the request does not grant the required permissions for the request. Check the requirements and obtain a suitable authorization token to proceed."), /** The HTTP method used is invalid for this endpoint. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_METHOD_INVALID(20, 405, "The HTTP method used is invalid for this endpoint. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers."), /** There is no endpoint defined for the URL provided by the client. Check if you used the correct URL and/or file a report with the developers of the client software. */ GENERIC_ENDPOINT_UNKNOWN(21, 404, "There is no endpoint defined for the URL provided by the client. Check if you used the correct URL and/or file a report with the developers of the client software."), /** The JSON in the client's request was malformed. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_JSON_INVALID(22, 400, "The JSON in the client's request was malformed. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers."), /** Some of the HTTP headers provided by the client were malformed and caused the server to not be able to handle the request. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_HTTP_HEADERS_MALFORMED(23, 400, "Some of the HTTP headers provided by the client were malformed and caused the server to not be able to handle the request. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers."), /** The payto:// URI provided by the client is malformed. Check that you are using the correct syntax as of RFC 8905 and/or that you entered the bank account number correctly. */ GENERIC_PAYTO_URI_MALFORMED(24, 400, "The payto:// URI provided by the client is malformed. Check that you are using the correct syntax as of RFC 8905 and/or that you entered the bank account number correctly."), /** A required parameter in the request was missing. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_PARAMETER_MISSING(25, 400, "A required parameter in the request was missing. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers."), /** A parameter in the request was malformed. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_PARAMETER_MALFORMED(26, 400, "A parameter in the request was malformed. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers."), /** The reserve public key was malformed. */ GENERIC_RESERVE_PUB_MALFORMED(27, 400, "The reserve public key was malformed."), /** The body in the request could not be decompressed by the server. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_COMPRESSION_INVALID(28, 400, "The body in the request could not be decompressed by the server. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers."), /** A segment in the path of the URL provided by the client is malformed. Check that you are using the correct encoding for the URL. */ GENERIC_PATH_SEGMENT_MALFORMED(29, 400, "A segment in the path of the URL provided by the client is malformed. Check that you are using the correct encoding for the URL."), /** The currency involved in the operation is not acceptable for this server. Check your configuration and make sure the currency specified for a given service provider is one of the currencies supported by that provider. */ GENERIC_CURRENCY_MISMATCH(30, 400, "The currency involved in the operation is not acceptable for this server. Check your configuration and make sure the currency specified for a given service provider is one of the currencies supported by that provider."), /** The URI is longer than the longest URI the HTTP server is willing to parse. If you believe this was a legitimate request, contact the server administrators and/or the software developers to increase the limit. */ GENERIC_URI_TOO_LONG(31, 414, "The URI is longer than the longest URI the HTTP server is willing to parse. If you believe this was a legitimate request, contact the server administrators and/or the software developers to increase the limit."), /** The body is too large to be permissible for the endpoint. If you believe this was a legitimate request, contact the server administrators and/or the software developers to increase the limit. */ GENERIC_UPLOAD_EXCEEDS_LIMIT(32, 413, "The body is too large to be permissible for the endpoint. If you believe this was a legitimate request, contact the server administrators and/or the software developers to increase the limit."), /** A parameter in the request was given that must not be present. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_PARAMETER_EXTRA(33, 400, "A parameter in the request was given that must not be present. This is likely a bug in the client implementation. Check if you are using the latest available version and/or file a report with the developers."), /** The service refused the request due to lack of proper authorization. Accessing this endpoint requires an access token from the account owner. */ GENERIC_UNAUTHORIZED(40, 401, "The service refused the request due to lack of proper authorization. Accessing this endpoint requires an access token from the account owner."), /** The service refused the request as the given authorization token is unknown. You should request a valid access token from the account owner. */ GENERIC_TOKEN_UNKNOWN(41, 401, "The service refused the request as the given authorization token is unknown. You should request a valid access token from the account owner."), /** The service refused the request as the given authorization token expired. You should request a fresh authorization token from the account owner. */ GENERIC_TOKEN_EXPIRED(42, 401, "The service refused the request as the given authorization token expired. You should request a fresh authorization token from the account owner."), /** The service refused the request as the given authorization token is invalid or malformed. You should check that you have the right credentials. */ GENERIC_TOKEN_MALFORMED(43, 401, "The service refused the request as the given authorization token is invalid or malformed. You should check that you have the right credentials."), /** The service refused the request due to lack of proper rights on the resource. You may need different credentials to be allowed to perform this operation. */ GENERIC_FORBIDDEN(44, 403, "The service refused the request due to lack of proper rights on the resource. You may need different credentials to be allowed to perform this operation."), /** The service failed initialize its connection to the database. The system administrator should check that the service has permissions to access the database and that the database is running. */ GENERIC_DB_SETUP_FAILED(50, 500, "The service failed initialize its connection to the database. The system administrator should check that the service has permissions to access the database and that the database is running."), /** The service encountered an error event to just start the database transaction. The system administrator should check that the database is running. */ GENERIC_DB_START_FAILED(51, 500, "The service encountered an error event to just start the database transaction. The system administrator should check that the database is running."), /** The service failed to store information in its database. The system administrator should check that the database is running and review the service logs. */ GENERIC_DB_STORE_FAILED(52, 500, "The service failed to store information in its database. The system administrator should check that the database is running and review the service logs."), /** The service failed to fetch information from its database. The system administrator should check that the database is running and review the service logs. */ GENERIC_DB_FETCH_FAILED(53, 500, "The service failed to fetch information from its database. The system administrator should check that the database is running and review the service logs."), /** The service encountered an unrecoverable error trying to commit a transaction to the database. The system administrator should check that the database is running and review the service logs. */ GENERIC_DB_COMMIT_FAILED(54, 500, "The service encountered an unrecoverable error trying to commit a transaction to the database. The system administrator should check that the database is running and review the service logs."), /** The service encountered an error event to commit the database transaction, even after repeatedly retrying it there was always a conflicting transaction. This indicates a repeated serialization error; it should only happen if some client maliciously tries to create conflicting concurrent transactions. It could also be a sign of a missing index. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_DB_SOFT_FAILURE(55, 500, "The service encountered an error event to commit the database transaction, even after repeatedly retrying it there was always a conflicting transaction. This indicates a repeated serialization error; it should only happen if some client maliciously tries to create conflicting concurrent transactions. It could also be a sign of a missing index. Check if you are using the latest available version and/or file a report with the developers."), /** The service's database is inconsistent and violates service-internal invariants. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_DB_INVARIANT_FAILURE(56, 500, "The service's database is inconsistent and violates service-internal invariants. Check if you are using the latest available version and/or file a report with the developers."), /** The HTTP server experienced an internal invariant failure (bug). Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_INTERNAL_INVARIANT_FAILURE(60, 500, "The HTTP server experienced an internal invariant failure (bug). Check if you are using the latest available version and/or file a report with the developers."), /** The service could not compute a cryptographic hash over some JSON value. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_FAILED_COMPUTE_JSON_HASH(61, 500, "The service could not compute a cryptographic hash over some JSON value. Check if you are using the latest available version and/or file a report with the developers."), /** The service could not compute an amount. Check if you are using the latest available version and/or file a report with the developers. */ GENERIC_FAILED_COMPUTE_AMOUNT(62, 500, "The service could not compute an amount. Check if you are using the latest available version and/or file a report with the developers."), /** The HTTP server had insufficient memory to parse the request. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate. */ GENERIC_PARSER_OUT_OF_MEMORY(70, 500, "The HTTP server had insufficient memory to parse the request. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate."), /** The HTTP server failed to allocate memory. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate. */ GENERIC_ALLOCATION_FAILURE(71, 500, "The HTTP server failed to allocate memory. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate."), /** The HTTP server failed to allocate memory for building JSON reply. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate. */ GENERIC_JSON_ALLOCATION_FAILURE(72, 500, "The HTTP server failed to allocate memory for building JSON reply. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate."), /** The HTTP server failed to allocate memory for making a CURL request. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate. */ GENERIC_CURL_ALLOCATION_FAILURE(73, 500, "The HTTP server failed to allocate memory for making a CURL request. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate."), /** The backend could not locate a required template to generate an HTML reply. The system administrator should check if the resource files are installed in the correct location and are readable to the service. */ GENERIC_FAILED_TO_LOAD_TEMPLATE(74, 406, "The backend could not locate a required template to generate an HTML reply. The system administrator should check if the resource files are installed in the correct location and are readable to the service."), /** The backend could not expand the template to generate an HTML reply. The system administrator should investigate the logs and check if the templates are well-formed. */ GENERIC_FAILED_TO_EXPAND_TEMPLATE(75, 500, "The backend could not expand the template to generate an HTML reply. The system administrator should investigate the logs and check if the templates are well-formed."), /** The requested feature is not implemented by the server. The system administrator of the server may try to update the software or build it with other options to enable the feature. */ GENERIC_FEATURE_NOT_IMPLEMENTED(76, 501, "The requested feature is not implemented by the server. The system administrator of the server may try to update the software or build it with other options to enable the feature."), /** The operating system failed to allocate required resources. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate. */ GENERIC_OS_RESOURCE_ALLOCATION_FAILURE(77, 500, "The operating system failed to allocate required resources. Restarting services periodically can help, especially if Postgres is using excessive amounts of memory. Check with the system administrator to investigate."), /** Exchange is badly configured and thus cannot operate. */ EXCHANGE_GENERIC_BAD_CONFIGURATION(1000, 500, "Exchange is badly configured and thus cannot operate."), /** Operation specified unknown for this endpoint. */ EXCHANGE_GENERIC_OPERATION_UNKNOWN(1001, 404, "Operation specified unknown for this endpoint."), /** The number of segments included in the URI does not match the number of segments expected by the endpoint. */ EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS(1002, 404, "The number of segments included in the URI does not match the number of segments expected by the endpoint."), /** The same coin was already used with a different denomination previously. */ EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY(1003, 409, "The same coin was already used with a different denomination previously."), /** The public key of given to a \"/coins/\" endpoint of the exchange was malformed. */ EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB(1004, 400, "The public key of given to a \"/coins/\" endpoint of the exchange was malformed."), /** The exchange is not aware of the denomination key the wallet requested for the operation. */ EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN(1005, 404, "The exchange is not aware of the denomination key the wallet requested for the operation."), /** The signature of the denomination key over the coin is not valid. */ EXCHANGE_DENOMINATION_SIGNATURE_INVALID(1006, 403, "The signature of the denomination key over the coin is not valid."), /** The exchange failed to perform the operation as it could not find the private keys. This is a problem with the exchange setup, not with the client's request. */ EXCHANGE_GENERIC_KEYS_MISSING(1007, 503, "The exchange failed to perform the operation as it could not find the private keys. This is a problem with the exchange setup, not with the client's request."), /** Validity period of the denomination lies in the future. */ EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE(1008, 412, "Validity period of the denomination lies in the future."), /** Denomination key of the coin is past its expiration time for the requested operation. */ EXCHANGE_GENERIC_DENOMINATION_EXPIRED(1009, 410, "Denomination key of the coin is past its expiration time for the requested operation."), /** Denomination key of the coin has been revoked. */ EXCHANGE_GENERIC_DENOMINATION_REVOKED(1010, 410, "Denomination key of the coin has been revoked."), /** An operation where the exchange interacted with a security module timed out. */ EXCHANGE_GENERIC_SECMOD_TIMEOUT(1011, 500, "An operation where the exchange interacted with a security module timed out."), /** The respective coin did not have sufficient residual value for the operation. The \"history\" in this response provides the \"residual_value\" of the coin, which may be less than its \"original_value\". */ EXCHANGE_GENERIC_INSUFFICIENT_FUNDS(1012, 409, "The respective coin did not have sufficient residual value for the operation. The \"history\" in this response provides the \"residual_value\" of the coin, which may be less than its \"original_value\"."), /** The exchange had an internal error reconstructing the transaction history of the coin that was being processed. */ EXCHANGE_GENERIC_COIN_HISTORY_COMPUTATION_FAILED(1013, 500, "The exchange had an internal error reconstructing the transaction history of the coin that was being processed."), /** The exchange failed to obtain the transaction history of the given coin from the database while generating an insufficient funds errors. */ EXCHANGE_GENERIC_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS(1014, 500, "The exchange failed to obtain the transaction history of the given coin from the database while generating an insufficient funds errors."), /** The same coin was already used with a different age hash previously. */ EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH(1015, 409, "The same coin was already used with a different age hash previously."), /** The requested operation is not valid for the cipher used by the selected denomination. */ EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION(1016, 400, "The requested operation is not valid for the cipher used by the selected denomination."), /** The provided arguments for the operation use inconsistent ciphers. */ EXCHANGE_GENERIC_CIPHER_MISMATCH(1017, 400, "The provided arguments for the operation use inconsistent ciphers."), /** The number of denominations specified in the request exceeds the limit of the exchange. */ EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE(1018, 400, "The number of denominations specified in the request exceeds the limit of the exchange."), /** The coin is not known to the exchange (yet). */ EXCHANGE_GENERIC_COIN_UNKNOWN(1019, 404, "The coin is not known to the exchange (yet)."), /** The time at the server is too far off from the time specified in the request. Most likely the client system time is wrong. */ EXCHANGE_GENERIC_CLOCK_SKEW(1020, 400, "The time at the server is too far off from the time specified in the request. Most likely the client system time is wrong."), /** The specified amount for the coin is higher than the value of the denomination of the coin. */ EXCHANGE_GENERIC_AMOUNT_EXCEEDS_DENOMINATION_VALUE(1021, 400, "The specified amount for the coin is higher than the value of the denomination of the coin."), /** The exchange was not properly configured with global fees. */ EXCHANGE_GENERIC_GLOBAL_FEES_MISSING(1022, 500, "The exchange was not properly configured with global fees."), /** The exchange was not properly configured with wire fees. */ EXCHANGE_GENERIC_WIRE_FEES_MISSING(1023, 500, "The exchange was not properly configured with wire fees."), /** The purse public key was malformed. */ EXCHANGE_GENERIC_PURSE_PUB_MALFORMED(1024, 400, "The purse public key was malformed."), /** The purse is unknown. */ EXCHANGE_GENERIC_PURSE_UNKNOWN(1025, 404, "The purse is unknown."), /** The purse has expired. */ EXCHANGE_GENERIC_PURSE_EXPIRED(1026, 410, "The purse has expired."), /** The exchange has no information about the \"reserve_pub\" that was given. */ EXCHANGE_GENERIC_RESERVE_UNKNOWN(1027, 404, "The exchange has no information about the \"reserve_pub\" that was given."), /** The exchange is not allowed to proceed with the operation until the client has satisfied a KYC check. */ EXCHANGE_GENERIC_KYC_REQUIRED(1028, 451, "The exchange is not allowed to proceed with the operation until the client has satisfied a KYC check."), /** Inconsistency between provided age commitment and attest: either none or both must be provided */ EXCHANGE_PURSE_DEPOSIT_COIN_CONFLICTING_ATTEST_VS_AGE_COMMITMENT(1029, 400, "Inconsistency between provided age commitment and attest: either none or both must be provided"), /** The provided attestation for the minimum age couldn't be verified by the exchange. */ EXCHANGE_PURSE_DEPOSIT_COIN_AGE_ATTESTATION_FAILURE(1030, 400, "The provided attestation for the minimum age couldn't be verified by the exchange."), /** The purse was deleted. */ EXCHANGE_GENERIC_PURSE_DELETED(1031, 410, "The purse was deleted."), /** The public key of the AML officer in the URL was malformed. */ EXCHANGE_GENERIC_AML_OFFICER_PUB_MALFORMED(1032, 400, "The public key of the AML officer in the URL was malformed."), /** The signature affirming the GET request of the AML officer is invalid. */ EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID(1033, 403, "The signature affirming the GET request of the AML officer is invalid."), /** The specified AML officer does not have access at this time. */ EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED(1034, 403, "The specified AML officer does not have access at this time."), /** The requested operation is denied pending the resolution of an anti-money laundering investigation by the exchange operator. This is a manual process, please wait and retry later. */ EXCHANGE_GENERIC_AML_PENDING(1035, 451, "The requested operation is denied pending the resolution of an anti-money laundering investigation by the exchange operator. This is a manual process, please wait and retry later."), /** The requested operation is denied as the account was frozen on suspicion of money laundering. Please contact the exchange operator. */ EXCHANGE_GENERIC_AML_FROZEN(1036, 451, "The requested operation is denied as the account was frozen on suspicion of money laundering. Please contact the exchange operator."), /** The exchange failed to start a KYC attribute conversion helper process. It is likely configured incorrectly. */ EXCHANGE_GENERIC_KYC_CONVERTER_FAILED(1037, 500, "The exchange failed to start a KYC attribute conversion helper process. It is likely configured incorrectly."), /** The KYC operation failed. This could be because the KYC provider rejected the KYC data provided, or because the user aborted the KYC process. */ EXCHANGE_GENERIC_KYC_FAILED(1038, 500, "The KYC operation failed. This could be because the KYC provider rejected the KYC data provided, or because the user aborted the KYC process."), /** A fallback measure for a KYC operation failed. This is a bug. Users should contact the exchange operator. */ EXCHANGE_GENERIC_KYC_FALLBACK_FAILED(1039, 500, "A fallback measure for a KYC operation failed. This is a bug. Users should contact the exchange operator."), /** The specified fallback measure for a KYC operation is unknown. This is a bug. Users should contact the exchange operator. */ EXCHANGE_GENERIC_KYC_FALLBACK_UNKNOWN(1040, 500, "The specified fallback measure for a KYC operation is unknown. This is a bug. Users should contact the exchange operator."), /** The exchange is not aware of the bank account (payto URI or hash thereof) specified in the request and thus cannot perform the requested operation. The client should check that the select account is correct. */ EXCHANGE_GENERIC_BANK_ACCOUNT_UNKNOWN(1041, 404, "The exchange is not aware of the bank account (payto URI or hash thereof) specified in the request and thus cannot perform the requested operation. The client should check that the select account is correct."), /** The AML processing at the exchange did not terminate in an adequate timeframe. This is likely a configuration problem at the payment service provider. Users should contact the exchange operator. */ EXCHANGE_GENERIC_AML_PROGRAM_RECURSION_DETECTED(1042, 500, "The AML processing at the exchange did not terminate in an adequate timeframe. This is likely a configuration problem at the payment service provider. Users should contact the exchange operator."), /** A check against sanction lists failed. This is indicative of an internal error in the sanction list processing logic. This needs to be investigated by the exchange operator. */ EXCHANGE_GENERIC_KYC_SANCTION_LIST_CHECK_FAILED(1043, 500, "A check against sanction lists failed. This is indicative of an internal error in the sanction list processing logic. This needs to be investigated by the exchange operator."), /** The process to generate a PDF from a template failed. A likely cause is a syntactic error in the template. This needs to be investigated by the exchange operator. */ EXCHANGE_GENERIC_TYPST_TEMPLATE_FAILURE(1044, 500, "The process to generate a PDF from a template failed. A likely cause is a syntactic error in the template. This needs to be investigated by the exchange operator."), /** A process to combine multiple PDFs into one larger document failed. A likely cause is a resource exhaustion problem on the server. This needs to be investigated by the exchange operator. */ EXCHANGE_GENERIC_PDFTK_FAILURE(1045, 500, "A process to combine multiple PDFs into one larger document failed. A likely cause is a resource exhaustion problem on the server. This needs to be investigated by the exchange operator."), /** The process to generate a PDF from a template crashed. A likely cause is a bug in the Typst software. This needs to be investigated by the exchange operator. */ EXCHANGE_GENERIC_TYPST_CRASH(1046, 500, "The process to generate a PDF from a template crashed. A likely cause is a bug in the Typst software. This needs to be investigated by the exchange operator."), /** The process to combine multiple PDFs into a larger document crashed. A likely cause is a bug in the pdftk software. This needs to be investigated by the exchange operator. */ EXCHANGE_GENERIC_PDFTK_CRASH(1047, 500, "The process to combine multiple PDFs into a larger document crashed. A likely cause is a bug in the pdftk software. This needs to be investigated by the exchange operator."), /** One of the binaries needed to generate the PDF is not installed. If this feature is required, the system administrator should make sure Typst and pdftk are both installed. */ EXCHANGE_GENERIC_NO_TYPST_OR_PDFTK(1048, 501, "One of the binaries needed to generate the PDF is not installed. If this feature is required, the system administrator should make sure Typst and pdftk are both installed."), /** The exchange is not aware of the given target account. The specified account is not a customer of this service. */ EXCHANGE_GENERIC_TARGET_ACCOUNT_UNKNOWN(1049, 404, "The exchange is not aware of the given target account. The specified account is not a customer of this service."), /** The exchange did not find information about the specified transaction in the database. */ EXCHANGE_DEPOSITS_GET_NOT_FOUND(1100, 404, "The exchange did not find information about the specified transaction in the database."), /** The wire hash of given to a \"/deposits/\" handler was malformed. */ EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE(1101, 400, "The wire hash of given to a \"/deposits/\" handler was malformed."), /** The merchant key of given to a \"/deposits/\" handler was malformed. */ EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB(1102, 400, "The merchant key of given to a \"/deposits/\" handler was malformed."), /** The hash of the contract terms given to a \"/deposits/\" handler was malformed. */ EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS(1103, 400, "The hash of the contract terms given to a \"/deposits/\" handler was malformed."), /** The coin public key of given to a \"/deposits/\" handler was malformed. */ EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB(1104, 400, "The coin public key of given to a \"/deposits/\" handler was malformed."), /** The signature returned by the exchange in a /deposits/ request was malformed. */ EXCHANGE_DEPOSITS_GET_INVALID_SIGNATURE_BY_EXCHANGE(1105, 0, "The signature returned by the exchange in a /deposits/ request was malformed."), /** The signature of the merchant is invalid. */ EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID(1106, 403, "The signature of the merchant is invalid."), /** The provided policy data was not accepted */ EXCHANGE_DEPOSITS_POLICY_NOT_ACCEPTED(1107, 400, "The provided policy data was not accepted"), /** The given reserve does not have sufficient funds to admit the requested withdraw operation at this time. The response includes the current \"balance\" of the reserve as well as the transaction \"history\" that lead to this balance. */ EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS(1150, 409, "The given reserve does not have sufficient funds to admit the requested withdraw operation at this time. The response includes the current \"balance\" of the reserve as well as the transaction \"history\" that lead to this balance."), /** The given reserve does not have sufficient funds to admit the requested age-withdraw operation at this time. The response includes the current \"balance\" of the reserve as well as the transaction \"history\" that lead to this balance. */ EXCHANGE_AGE_WITHDRAW_INSUFFICIENT_FUNDS(1151, 409, "The given reserve does not have sufficient funds to admit the requested age-withdraw operation at this time. The response includes the current \"balance\" of the reserve as well as the transaction \"history\" that lead to this balance."), /** The amount to withdraw together with the fee exceeds the numeric range for Taler amounts. This is not a client failure, as the coin value and fees come from the exchange's configuration. */ EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW(1152, 500, "The amount to withdraw together with the fee exceeds the numeric range for Taler amounts. This is not a client failure, as the coin value and fees come from the exchange's configuration."), /** The exchange failed to create the signature using the denomination key. */ EXCHANGE_WITHDRAW_SIGNATURE_FAILED(1153, 500, "The exchange failed to create the signature using the denomination key."), /** The signature of the reserve is not valid. */ EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID(1154, 403, "The signature of the reserve is not valid."), /** When computing the reserve history, we ended up with a negative overall balance, which should be impossible. */ EXCHANGE_RESERVE_HISTORY_ERROR_INSUFFICIENT_FUNDS(1155, 500, "When computing the reserve history, we ended up with a negative overall balance, which should be impossible."), /** The reserve did not have sufficient funds in it to pay for a full reserve history statement. */ EXCHANGE_GET_RESERVE_HISTORY_ERROR_INSUFFICIENT_BALANCE(1156, 409, "The reserve did not have sufficient funds in it to pay for a full reserve history statement."), /** Withdraw period of the coin to be withdrawn is in the past. */ EXCHANGE_WITHDRAW_DENOMINATION_KEY_LOST(1158, 410, "Withdraw period of the coin to be withdrawn is in the past."), /** The client failed to unblind the blind signature. */ EXCHANGE_WITHDRAW_UNBLIND_FAILURE(1159, 0, "The client failed to unblind the blind signature."), /** The client reused a withdraw nonce, which is not allowed. */ EXCHANGE_WITHDRAW_NONCE_REUSE(1160, 409, "The client reused a withdraw nonce, which is not allowed."), /** The client provided an unknown commitment for an age-withdraw request. */ EXCHANGE_WITHDRAW_COMMITMENT_UNKNOWN(1161, 400, "The client provided an unknown commitment for an age-withdraw request."), /** The total sum of amounts from the denominations did overflow. */ EXCHANGE_WITHDRAW_AMOUNT_OVERFLOW(1162, 500, "The total sum of amounts from the denominations did overflow."), /** The total sum of value and fees from the denominations differs from the committed amount with fees. */ EXCHANGE_AGE_WITHDRAW_AMOUNT_INCORRECT(1163, 400, "The total sum of value and fees from the denominations differs from the committed amount with fees."), /** The original commitment differs from the calculated hash */ EXCHANGE_WITHDRAW_REVEAL_INVALID_HASH(1164, 400, "The original commitment differs from the calculated hash"), /** The maximum age in the commitment is too large for the reserve */ EXCHANGE_WITHDRAW_MAXIMUM_AGE_TOO_LARGE(1165, 409, "The maximum age in the commitment is too large for the reserve"), /** The withdraw operation included the same planchet more than once. This is not allowed. */ EXCHANGE_WITHDRAW_IDEMPOTENT_PLANCHET(1175, 400, "The withdraw operation included the same planchet more than once. This is not allowed."), /** The signature made by the coin over the deposit permission is not valid. */ EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID(1205, 403, "The signature made by the coin over the deposit permission is not valid."), /** The same coin was already deposited for the same merchant and contract with other details. */ EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT(1206, 409, "The same coin was already deposited for the same merchant and contract with other details."), /** The stated value of the coin after the deposit fee is subtracted would be negative. */ EXCHANGE_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE(1207, 400, "The stated value of the coin after the deposit fee is subtracted would be negative."), /** The stated refund deadline is after the wire deadline. */ EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE(1208, 400, "The stated refund deadline is after the wire deadline."), /** The stated wire deadline is \"never\", which makes no sense. */ EXCHANGE_DEPOSIT_WIRE_DEADLINE_IS_NEVER(1209, 400, "The stated wire deadline is \"never\", which makes no sense."), /** The exchange failed to canonicalize and hash the given wire format. For example, the merchant failed to provide the \"salt\" or a valid payto:// URI in the wire details. Note that while the exchange will do some basic sanity checking on the wire details, it cannot warrant that the banking system will ultimately be able to route to the specified address, even if this check passed. */ EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_JSON(1210, 400, "The exchange failed to canonicalize and hash the given wire format. For example, the merchant failed to provide the \"salt\" or a valid payto:// URI in the wire details. Note that while the exchange will do some basic sanity checking on the wire details, it cannot warrant that the banking system will ultimately be able to route to the specified address, even if this check passed."), /** The hash of the given wire address does not match the wire hash specified in the proposal data. */ EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT(1211, 400, "The hash of the given wire address does not match the wire hash specified in the proposal data."), /** The signature provided by the exchange is not valid. */ EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE(1221, 0, "The signature provided by the exchange is not valid."), /** The deposited amount is smaller than the deposit fee, which would result in a negative contribution. */ EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT(1222, 400, "The deposited amount is smaller than the deposit fee, which would result in a negative contribution."), /** The proof of policy fulfillment was invalid. */ EXCHANGE_EXTENSIONS_INVALID_FULFILLMENT(1240, 400, "The proof of policy fulfillment was invalid."), /** The coin history was requested with a bad signature. */ EXCHANGE_COIN_HISTORY_BAD_SIGNATURE(1251, 403, "The coin history was requested with a bad signature."), /** The reserve history was requested with a bad signature. */ EXCHANGE_RESERVE_HISTORY_BAD_SIGNATURE(1252, 403, "The reserve history was requested with a bad signature."), /** The exchange encountered melt fees exceeding the melted coin's contribution. */ EXCHANGE_MELT_FEES_EXCEED_CONTRIBUTION(1302, 400, "The exchange encountered melt fees exceeding the melted coin's contribution."), /** The signature made with the coin to be melted is invalid. */ EXCHANGE_MELT_COIN_SIGNATURE_INVALID(1303, 403, "The signature made with the coin to be melted is invalid."), /** The denomination of the given coin has past its expiration date and it is also not a valid zombie (that is, was not refreshed with the fresh coin being subjected to recoup). */ EXCHANGE_MELT_COIN_EXPIRED_NO_ZOMBIE(1305, 400, "The denomination of the given coin has past its expiration date and it is also not a valid zombie (that is, was not refreshed with the fresh coin being subjected to recoup)."), /** The signature returned by the exchange in a melt request was malformed. */ EXCHANGE_MELT_INVALID_SIGNATURE_BY_EXCHANGE(1306, 0, "The signature returned by the exchange in a melt request was malformed."), /** The provided transfer keys do not match up with the original commitment. Information about the original commitment is included in the response. */ EXCHANGE_REFRESHES_REVEAL_COMMITMENT_VIOLATION(1353, 409, "The provided transfer keys do not match up with the original commitment. Information about the original commitment is included in the response."), /** Failed to produce the blinded signatures over the coins to be returned. */ EXCHANGE_REFRESHES_REVEAL_SIGNING_ERROR(1354, 500, "Failed to produce the blinded signatures over the coins to be returned."), /** The exchange is unaware of the refresh session specified in the request. */ EXCHANGE_REFRESHES_REVEAL_SESSION_UNKNOWN(1355, 404, "The exchange is unaware of the refresh session specified in the request."), /** The size of the cut-and-choose dimension of the private transfer keys request does not match #TALER_CNC_KAPPA - 1. */ EXCHANGE_REFRESHES_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID(1356, 400, "The size of the cut-and-choose dimension of the private transfer keys request does not match #TALER_CNC_KAPPA - 1."), /** The number of envelopes given does not match the number of denomination keys given. */ EXCHANGE_REFRESHES_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISMATCH(1358, 400, "The number of envelopes given does not match the number of denomination keys given."), /** The exchange encountered a numeric overflow totaling up the cost for the refresh operation. */ EXCHANGE_REFRESHES_REVEAL_COST_CALCULATION_OVERFLOW(1359, 500, "The exchange encountered a numeric overflow totaling up the cost for the refresh operation."), /** The exchange's cost calculation shows that the melt amount is below the costs of the transaction. */ EXCHANGE_REFRESHES_REVEAL_AMOUNT_INSUFFICIENT(1360, 400, "The exchange's cost calculation shows that the melt amount is below the costs of the transaction."), /** The signature made with the coin over the link data is invalid. */ EXCHANGE_REFRESHES_REVEAL_LINK_SIGNATURE_INVALID(1361, 403, "The signature made with the coin over the link data is invalid."), /** The refresh session hash given to a /refreshes/ handler was malformed. */ EXCHANGE_REFRESHES_REVEAL_INVALID_RCH(1362, 400, "The refresh session hash given to a /refreshes/ handler was malformed."), /** Operation specified invalid for this endpoint. */ EXCHANGE_REFRESHES_REVEAL_OPERATION_INVALID(1363, 400, "Operation specified invalid for this endpoint."), /** The client provided age commitment data, but age restriction is not supported on this server. */ EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_NOT_SUPPORTED(1364, 400, "The client provided age commitment data, but age restriction is not supported on this server."), /** The client provided invalid age commitment data: missing, not an array, or array of invalid size. */ EXCHANGE_REFRESHES_REVEAL_AGE_RESTRICTION_COMMITMENT_INVALID(1365, 400, "The client provided invalid age commitment data: missing, not an array, or array of invalid size."), /** The coin specified in the link request is unknown to the exchange. */ EXCHANGE_LINK_COIN_UNKNOWN(1400, 404, "The coin specified in the link request is unknown to the exchange."), /** The public key of given to a /transfers/ handler was malformed. */ EXCHANGE_TRANSFERS_GET_WTID_MALFORMED(1450, 400, "The public key of given to a /transfers/ handler was malformed."), /** The exchange did not find information about the specified wire transfer identifier in the database. */ EXCHANGE_TRANSFERS_GET_WTID_NOT_FOUND(1451, 404, "The exchange did not find information about the specified wire transfer identifier in the database."), /** The exchange did not find information about the wire transfer fees it charged. */ EXCHANGE_TRANSFERS_GET_WIRE_FEE_NOT_FOUND(1452, 500, "The exchange did not find information about the wire transfer fees it charged."), /** The exchange found a wire fee that was above the total transfer value (and thus could not have been charged). */ EXCHANGE_TRANSFERS_GET_WIRE_FEE_INCONSISTENT(1453, 500, "The exchange found a wire fee that was above the total transfer value (and thus could not have been charged)."), /** The wait target of the URL was not in the set of expected values. */ EXCHANGE_PURSES_INVALID_WAIT_TARGET(1475, 400, "The wait target of the URL was not in the set of expected values."), /** The signature on the purse status returned by the exchange was invalid. */ EXCHANGE_PURSES_GET_INVALID_SIGNATURE_BY_EXCHANGE(1476, 0, "The signature on the purse status returned by the exchange was invalid."), /** The exchange knows literally nothing about the coin we were asked to refund. But without a transaction history, we cannot issue a refund. This is kind-of OK, the owner should just refresh it directly without executing the refund. */ EXCHANGE_REFUND_COIN_NOT_FOUND(1500, 404, "The exchange knows literally nothing about the coin we were asked to refund. But without a transaction history, we cannot issue a refund. This is kind-of OK, the owner should just refresh it directly without executing the refund."), /** We could not process the refund request as the coin's transaction history does not permit the requested refund because then refunds would exceed the deposit amount. The \"history\" in the response proves this. */ EXCHANGE_REFUND_CONFLICT_DEPOSIT_INSUFFICIENT(1501, 409, "We could not process the refund request as the coin's transaction history does not permit the requested refund because then refunds would exceed the deposit amount. The \"history\" in the response proves this."), /** The exchange knows about the coin we were asked to refund, but not about the specific /deposit operation. Hence, we cannot issue a refund (as we do not know if this merchant public key is authorized to do a refund). */ EXCHANGE_REFUND_DEPOSIT_NOT_FOUND(1502, 404, "The exchange knows about the coin we were asked to refund, but not about the specific /deposit operation. Hence, we cannot issue a refund (as we do not know if this merchant public key is authorized to do a refund)."), /** The exchange can no longer refund the customer/coin as the money was already transferred (paid out) to the merchant. (It should be past the refund deadline.) */ EXCHANGE_REFUND_MERCHANT_ALREADY_PAID(1503, 410, "The exchange can no longer refund the customer/coin as the money was already transferred (paid out) to the merchant. (It should be past the refund deadline.)"), /** The refund fee specified for the request is lower than the refund fee charged by the exchange for the given denomination key of the refunded coin. */ EXCHANGE_REFUND_FEE_TOO_LOW(1504, 400, "The refund fee specified for the request is lower than the refund fee charged by the exchange for the given denomination key of the refunded coin."), /** The refunded amount is smaller than the refund fee, which would result in a negative refund. */ EXCHANGE_REFUND_FEE_ABOVE_AMOUNT(1505, 400, "The refunded amount is smaller than the refund fee, which would result in a negative refund."), /** The signature of the merchant is invalid. */ EXCHANGE_REFUND_MERCHANT_SIGNATURE_INVALID(1506, 403, "The signature of the merchant is invalid."), /** Merchant backend failed to create the refund confirmation signature. */ EXCHANGE_REFUND_MERCHANT_SIGNING_FAILED(1507, 500, "Merchant backend failed to create the refund confirmation signature."), /** The signature returned by the exchange in a refund request was malformed. */ EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE(1508, 0, "The signature returned by the exchange in a refund request was malformed."), /** The failure proof returned by the exchange is incorrect. */ EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE(1509, 0, "The failure proof returned by the exchange is incorrect."), /** Conflicting refund granted before with different amount but same refund transaction ID. */ EXCHANGE_REFUND_INCONSISTENT_AMOUNT(1510, 424, "Conflicting refund granted before with different amount but same refund transaction ID."), /** The given coin signature is invalid for the request. */ EXCHANGE_RECOUP_SIGNATURE_INVALID(1550, 403, "The given coin signature is invalid for the request."), /** The exchange could not find the corresponding withdraw operation. The request is denied. */ EXCHANGE_RECOUP_WITHDRAW_NOT_FOUND(1551, 404, "The exchange could not find the corresponding withdraw operation. The request is denied."), /** The coin's remaining balance is zero. The request is denied. */ EXCHANGE_RECOUP_COIN_BALANCE_ZERO(1552, 403, "The coin's remaining balance is zero. The request is denied."), /** The exchange failed to reproduce the coin's blinding. */ EXCHANGE_RECOUP_BLINDING_FAILED(1553, 500, "The exchange failed to reproduce the coin's blinding."), /** The coin's remaining balance is zero. The request is denied. */ EXCHANGE_RECOUP_COIN_BALANCE_NEGATIVE(1554, 500, "The coin's remaining balance is zero. The request is denied."), /** The coin's denomination has not been revoked yet. */ EXCHANGE_RECOUP_NOT_ELIGIBLE(1555, 404, "The coin's denomination has not been revoked yet."), /** The given coin signature is invalid for the request. */ EXCHANGE_RECOUP_REFRESH_SIGNATURE_INVALID(1575, 403, "The given coin signature is invalid for the request."), /** The exchange could not find the corresponding melt operation. The request is denied. */ EXCHANGE_RECOUP_REFRESH_MELT_NOT_FOUND(1576, 404, "The exchange could not find the corresponding melt operation. The request is denied."), /** The exchange failed to reproduce the coin's blinding. */ EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED(1578, 500, "The exchange failed to reproduce the coin's blinding."), /** The coin's denomination has not been revoked yet. */ EXCHANGE_RECOUP_REFRESH_NOT_ELIGIBLE(1580, 404, "The coin's denomination has not been revoked yet."), /** This exchange does not allow clients to request /keys for times other than the current (exchange) time. */ EXCHANGE_KEYS_TIMETRAVEL_FORBIDDEN(1600, 403, "This exchange does not allow clients to request /keys for times other than the current (exchange) time."), /** A signature in the server's response was malformed. */ EXCHANGE_WIRE_SIGNATURE_INVALID(1650, 0, "A signature in the server's response was malformed."), /** No bank accounts are enabled for the exchange. The administrator should enable-account using the taler-exchange-offline tool. */ EXCHANGE_WIRE_NO_ACCOUNTS_CONFIGURED(1651, 500, "No bank accounts are enabled for the exchange. The administrator should enable-account using the taler-exchange-offline tool."), /** The payto:// URI stored in the exchange database for its bank account is malformed. */ EXCHANGE_WIRE_INVALID_PAYTO_CONFIGURED(1652, 500, "The payto:// URI stored in the exchange database for its bank account is malformed."), /** No wire fees are configured for an enabled wire method of the exchange. The administrator must set the wire-fee using the taler-exchange-offline tool. */ EXCHANGE_WIRE_FEES_NOT_CONFIGURED(1653, 500, "No wire fees are configured for an enabled wire method of the exchange. The administrator must set the wire-fee using the taler-exchange-offline tool."), /** This purse was previously created with different meta data. */ EXCHANGE_RESERVES_PURSE_CREATE_CONFLICTING_META_DATA(1675, 409, "This purse was previously created with different meta data."), /** This purse was previously merged with different meta data. */ EXCHANGE_RESERVES_PURSE_MERGE_CONFLICTING_META_DATA(1676, 409, "This purse was previously merged with different meta data."), /** The reserve has insufficient funds to create another purse. */ EXCHANGE_RESERVES_PURSE_CREATE_INSUFFICIENT_FUNDS(1677, 409, "The reserve has insufficient funds to create another purse."), /** The purse fee specified for the request is lower than the purse fee charged by the exchange at this time. */ EXCHANGE_RESERVES_PURSE_FEE_TOO_LOW(1678, 400, "The purse fee specified for the request is lower than the purse fee charged by the exchange at this time."), /** The payment request cannot be deleted anymore, as it either already completed or timed out. */ EXCHANGE_PURSE_DELETE_ALREADY_DECIDED(1679, 409, "The payment request cannot be deleted anymore, as it either already completed or timed out."), /** The signature affirming the purse deletion is invalid. */ EXCHANGE_PURSE_DELETE_SIGNATURE_INVALID(1680, 403, "The signature affirming the purse deletion is invalid."), /** Withdrawal from the reserve requires age restriction to be set. */ EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED(1681, 403, "Withdrawal from the reserve requires age restriction to be set."), /** The exchange failed to talk to the process responsible for its private denomination keys or the helpers had no denominations (properly) configured. */ EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE(1700, 502, "The exchange failed to talk to the process responsible for its private denomination keys or the helpers had no denominations (properly) configured."), /** The response from the denomination key helper process was malformed. */ EXCHANGE_DENOMINATION_HELPER_BUG(1701, 500, "The response from the denomination key helper process was malformed."), /** The helper refuses to sign with the key, because it is too early: the validity period has not yet started. */ EXCHANGE_DENOMINATION_HELPER_TOO_EARLY(1702, 400, "The helper refuses to sign with the key, because it is too early: the validity period has not yet started."), /** The signature of the exchange on the reply was invalid. */ EXCHANGE_PURSE_DEPOSIT_EXCHANGE_SIGNATURE_INVALID(1725, 0, "The signature of the exchange on the reply was invalid."), /** The exchange failed to talk to the process responsible for its private signing keys. */ EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE(1750, 502, "The exchange failed to talk to the process responsible for its private signing keys."), /** The response from the online signing key helper process was malformed. */ EXCHANGE_SIGNKEY_HELPER_BUG(1751, 500, "The response from the online signing key helper process was malformed."), /** The helper refuses to sign with the key, because it is too early: the validity period has not yet started. */ EXCHANGE_SIGNKEY_HELPER_TOO_EARLY(1752, 400, "The helper refuses to sign with the key, because it is too early: the validity period has not yet started."), /** The signatures from the master exchange public key are missing, thus the exchange cannot currently sign its API responses. The exchange operator must use taler-exchange-offline to sign the current key material. */ EXCHANGE_SIGNKEY_HELPER_OFFLINE_MISSING(1753, 500, "The signatures from the master exchange public key are missing, thus the exchange cannot currently sign its API responses. The exchange operator must use taler-exchange-offline to sign the current key material."), /** The purse expiration time is in the past at the time of its creation. */ EXCHANGE_RESERVES_PURSE_EXPIRATION_BEFORE_NOW(1775, 400, "The purse expiration time is in the past at the time of its creation."), /** The purse expiration time is set to never, which is not allowed. */ EXCHANGE_RESERVES_PURSE_EXPIRATION_IS_NEVER(1776, 400, "The purse expiration time is set to never, which is not allowed."), /** The signature affirming the merge of the purse is invalid. */ EXCHANGE_RESERVES_PURSE_MERGE_SIGNATURE_INVALID(1777, 403, "The signature affirming the merge of the purse is invalid."), /** The signature by the reserve affirming the merge is invalid. */ EXCHANGE_RESERVES_RESERVE_MERGE_SIGNATURE_INVALID(1778, 403, "The signature by the reserve affirming the merge is invalid."), /** The signature by the reserve affirming the open operation is invalid. */ EXCHANGE_RESERVES_OPEN_BAD_SIGNATURE(1785, 403, "The signature by the reserve affirming the open operation is invalid."), /** The signature by the reserve affirming the close operation is invalid. */ EXCHANGE_RESERVES_CLOSE_BAD_SIGNATURE(1786, 403, "The signature by the reserve affirming the close operation is invalid."), /** The signature by the reserve affirming the attestion request is invalid. */ EXCHANGE_RESERVES_ATTEST_BAD_SIGNATURE(1787, 403, "The signature by the reserve affirming the attestion request is invalid."), /** The exchange does not know an origin account to which the remaining reserve balance could be wired to, and the wallet failed to provide one. */ EXCHANGE_RESERVES_CLOSE_NO_TARGET_ACCOUNT(1788, 409, "The exchange does not know an origin account to which the remaining reserve balance could be wired to, and the wallet failed to provide one."), /** The reserve balance is insufficient to pay for the open operation. */ EXCHANGE_RESERVES_OPEN_INSUFFICIENT_FUNDS(1789, 409, "The reserve balance is insufficient to pay for the open operation."), /** The auditor that was supposed to be disabled is unknown to this exchange. */ EXCHANGE_MANAGEMENT_AUDITOR_NOT_FOUND(1800, 404, "The auditor that was supposed to be disabled is unknown to this exchange."), /** The exchange has a more recently signed conflicting instruction and is thus refusing the current change (replay detected). */ EXCHANGE_MANAGEMENT_AUDITOR_MORE_RECENT_PRESENT(1801, 409, "The exchange has a more recently signed conflicting instruction and is thus refusing the current change (replay detected)."), /** The signature to add or enable the auditor does not validate. */ EXCHANGE_MANAGEMENT_AUDITOR_ADD_SIGNATURE_INVALID(1802, 403, "The signature to add or enable the auditor does not validate."), /** The signature to disable the auditor does not validate. */ EXCHANGE_MANAGEMENT_AUDITOR_DEL_SIGNATURE_INVALID(1803, 403, "The signature to disable the auditor does not validate."), /** The signature to revoke the denomination does not validate. */ EXCHANGE_MANAGEMENT_DENOMINATION_REVOKE_SIGNATURE_INVALID(1804, 403, "The signature to revoke the denomination does not validate."), /** The signature to revoke the online signing key does not validate. */ EXCHANGE_MANAGEMENT_SIGNKEY_REVOKE_SIGNATURE_INVALID(1805, 403, "The signature to revoke the online signing key does not validate."), /** The exchange has a more recently signed conflicting instruction and is thus refusing the current change (replay detected). */ EXCHANGE_MANAGEMENT_WIRE_MORE_RECENT_PRESENT(1806, 409, "The exchange has a more recently signed conflicting instruction and is thus refusing the current change (replay detected)."), /** The signingkey specified is unknown to the exchange. */ EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_UNKNOWN(1807, 404, "The signingkey specified is unknown to the exchange."), /** The signature to publish wire account does not validate. */ EXCHANGE_MANAGEMENT_WIRE_DETAILS_SIGNATURE_INVALID(1808, 403, "The signature to publish wire account does not validate."), /** The signature to add the wire account does not validate. */ EXCHANGE_MANAGEMENT_WIRE_ADD_SIGNATURE_INVALID(1809, 403, "The signature to add the wire account does not validate."), /** The signature to disable the wire account does not validate. */ EXCHANGE_MANAGEMENT_WIRE_DEL_SIGNATURE_INVALID(1810, 403, "The signature to disable the wire account does not validate."), /** The wire account to be disabled is unknown to the exchange. */ EXCHANGE_MANAGEMENT_WIRE_NOT_FOUND(1811, 404, "The wire account to be disabled is unknown to the exchange."), /** The signature to affirm wire fees does not validate. */ EXCHANGE_MANAGEMENT_WIRE_FEE_SIGNATURE_INVALID(1812, 403, "The signature to affirm wire fees does not validate."), /** The signature conflicts with a previous signature affirming different fees. */ EXCHANGE_MANAGEMENT_WIRE_FEE_MISMATCH(1813, 409, "The signature conflicts with a previous signature affirming different fees."), /** The signature affirming the denomination key is invalid. */ EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID(1814, 403, "The signature affirming the denomination key is invalid."), /** The signature affirming the signing key is invalid. */ EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID(1815, 403, "The signature affirming the signing key is invalid."), /** The signature conflicts with a previous signature affirming different fees. */ EXCHANGE_MANAGEMENT_GLOBAL_FEE_MISMATCH(1816, 409, "The signature conflicts with a previous signature affirming different fees."), /** The signature affirming the fee structure is invalid. */ EXCHANGE_MANAGEMENT_GLOBAL_FEE_SIGNATURE_INVALID(1817, 403, "The signature affirming the fee structure is invalid."), /** The signature affirming the profit drain is invalid. */ EXCHANGE_MANAGEMENT_DRAIN_PROFITS_SIGNATURE_INVALID(1818, 403, "The signature affirming the profit drain is invalid."), /** The signature affirming the AML decision is invalid. */ EXCHANGE_AML_DECISION_ADD_SIGNATURE_INVALID(1825, 403, "The signature affirming the AML decision is invalid."), /** The AML officer specified is not allowed to make AML decisions right now. */ EXCHANGE_AML_DECISION_INVALID_OFFICER(1826, 403, "The AML officer specified is not allowed to make AML decisions right now."), /** There is a more recent AML decision on file. The decision was rejected as timestamps of AML decisions must be monotonically increasing. */ EXCHANGE_AML_DECISION_MORE_RECENT_PRESENT(1827, 409, "There is a more recent AML decision on file. The decision was rejected as timestamps of AML decisions must be monotonically increasing."), /** There AML decision would impose an AML check of a type that is not provided by any KYC provider known to the exchange. */ EXCHANGE_AML_DECISION_UNKNOWN_CHECK(1828, 400, "There AML decision would impose an AML check of a type that is not provided by any KYC provider known to the exchange."), /** The signature affirming the change in the AML officer status is invalid. */ EXCHANGE_MANAGEMENT_UPDATE_AML_OFFICER_SIGNATURE_INVALID(1830, 403, "The signature affirming the change in the AML officer status is invalid."), /** A more recent decision about the AML officer status is known to the exchange. */ EXCHANGE_MANAGEMENT_AML_OFFICERS_MORE_RECENT_PRESENT(1831, 409, "A more recent decision about the AML officer status is known to the exchange."), /** The exchange already has this denomination key configured, but with different meta data. This should not be possible, contact the developers for support. */ EXCHANGE_MANAGEMENT_CONFLICTING_DENOMINATION_META_DATA(1832, 409, "The exchange already has this denomination key configured, but with different meta data. This should not be possible, contact the developers for support."), /** The exchange already has this signing key configured, but with different meta data. This should not be possible, contact the developers for support. */ EXCHANGE_MANAGEMENT_CONFLICTING_SIGNKEY_META_DATA(1833, 409, "The exchange already has this signing key configured, but with different meta data. This should not be possible, contact the developers for support."), /** The purse was previously created with different meta data. */ EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA(1850, 409, "The purse was previously created with different meta data."), /** The purse was previously created with a different contract. */ EXCHANGE_PURSE_CREATE_CONFLICTING_CONTRACT_STORED(1851, 409, "The purse was previously created with a different contract."), /** A coin signature for a deposit into the purse is invalid. */ EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID(1852, 403, "A coin signature for a deposit into the purse is invalid."), /** The purse expiration time is in the past. */ EXCHANGE_PURSE_CREATE_EXPIRATION_BEFORE_NOW(1853, 400, "The purse expiration time is in the past."), /** The purse expiration time is \"never\". */ EXCHANGE_PURSE_CREATE_EXPIRATION_IS_NEVER(1854, 400, "The purse expiration time is \"never\"."), /** The purse signature over the purse meta data is invalid. */ EXCHANGE_PURSE_CREATE_SIGNATURE_INVALID(1855, 403, "The purse signature over the purse meta data is invalid."), /** The signature over the encrypted contract is invalid. */ EXCHANGE_PURSE_ECONTRACT_SIGNATURE_INVALID(1856, 403, "The signature over the encrypted contract is invalid."), /** The signature from the exchange over the confirmation is invalid. */ EXCHANGE_PURSE_CREATE_EXCHANGE_SIGNATURE_INVALID(1857, 0, "The signature from the exchange over the confirmation is invalid."), /** The coin was previously deposited with different meta data. */ EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA(1858, 409, "The coin was previously deposited with different meta data."), /** The encrypted contract was previously uploaded with different meta data. */ EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA(1859, 409, "The encrypted contract was previously uploaded with different meta data."), /** The deposited amount is less than the purse fee. */ EXCHANGE_CREATE_PURSE_NEGATIVE_VALUE_AFTER_FEE(1860, 400, "The deposited amount is less than the purse fee."), /** The signature using the merge key is invalid. */ EXCHANGE_PURSE_MERGE_INVALID_MERGE_SIGNATURE(1876, 403, "The signature using the merge key is invalid."), /** The signature using the reserve key is invalid. */ EXCHANGE_PURSE_MERGE_INVALID_RESERVE_SIGNATURE(1877, 403, "The signature using the reserve key is invalid."), /** The targeted purse is not yet full and thus cannot be merged. Retrying the request later may succeed. */ EXCHANGE_PURSE_NOT_FULL(1878, 409, "The targeted purse is not yet full and thus cannot be merged. Retrying the request later may succeed."), /** The signature from the exchange over the confirmation is invalid. */ EXCHANGE_PURSE_MERGE_EXCHANGE_SIGNATURE_INVALID(1879, 0, "The signature from the exchange over the confirmation is invalid."), /** The exchange of the target account is not a partner of this exchange. */ EXCHANGE_MERGE_PURSE_PARTNER_UNKNOWN(1880, 404, "The exchange of the target account is not a partner of this exchange."), /** The signature affirming the new partner is invalid. */ EXCHANGE_MANAGEMENT_ADD_PARTNER_SIGNATURE_INVALID(1890, 403, "The signature affirming the new partner is invalid."), /** Conflicting data for the partner already exists with the exchange. */ EXCHANGE_MANAGEMENT_ADD_PARTNER_DATA_CONFLICT(1891, 409, "Conflicting data for the partner already exists with the exchange."), /** The auditor signature over the denomination meta data is invalid. */ EXCHANGE_AUDITORS_AUDITOR_SIGNATURE_INVALID(1900, 403, "The auditor signature over the denomination meta data is invalid."), /** The auditor that was specified is unknown to this exchange. */ EXCHANGE_AUDITORS_AUDITOR_UNKNOWN(1901, 412, "The auditor that was specified is unknown to this exchange."), /** The auditor that was specified is no longer used by this exchange. */ EXCHANGE_AUDITORS_AUDITOR_INACTIVE(1902, 410, "The auditor that was specified is no longer used by this exchange."), /** The exchange tried to run an AML program, but that program did not terminate on time. Contact the exchange operator to address the AML program bug or performance issue. If it is not a performance issue, the timeout might have to be increased (requires changes to the source code). */ EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT(1918, 500, "The exchange tried to run an AML program, but that program did not terminate on time. Contact the exchange operator to address the AML program bug or performance issue. If it is not a performance issue, the timeout might have to be increased (requires changes to the source code)."), /** The KYC info access token is not recognized. Hence the request was denied. */ EXCHANGE_KYC_INFO_AUTHORIZATION_FAILED(1919, 403, "The KYC info access token is not recognized. Hence the request was denied."), /** The exchange got stuck in a long series of (likely recursive) KYC rules without user-inputs that did not result in a timely conclusion. This is a configuration failure. Please contact the administrator. */ EXCHANGE_KYC_RECURSIVE_RULE_DETECTED(1920, 500, "The exchange got stuck in a long series of (likely recursive) KYC rules without user-inputs that did not result in a timely conclusion. This is a configuration failure. Please contact the administrator."), /** The submitted KYC data lacks an attribute that is required by the KYC form. Please submit the complete form. */ EXCHANGE_KYC_AML_FORM_INCOMPLETE(1921, 400, "The submitted KYC data lacks an attribute that is required by the KYC form. Please submit the complete form."), /** The request requires an AML program which is no longer configured at the exchange. Contact the exchange operator to address the configuration issue. */ EXCHANGE_KYC_GENERIC_AML_PROGRAM_GONE(1922, 500, "The request requires an AML program which is no longer configured at the exchange. Contact the exchange operator to address the configuration issue."), /** The given check is not of type 'form' and thus using this handler for form submission is incorrect. */ EXCHANGE_KYC_NOT_A_FORM(1923, 400, "The given check is not of type 'form' and thus using this handler for form submission is incorrect."), /** The request requires a check which is no longer configured at the exchange. Contact the exchange operator to address the configuration issue. */ EXCHANGE_KYC_GENERIC_CHECK_GONE(1924, 500, "The request requires a check which is no longer configured at the exchange. Contact the exchange operator to address the configuration issue."), /** The signature affirming the wallet's KYC request was invalid. */ EXCHANGE_KYC_WALLET_SIGNATURE_INVALID(1925, 403, "The signature affirming the wallet's KYC request was invalid."), /** The exchange received an unexpected malformed response from its KYC backend. */ EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE(1926, 502, "The exchange received an unexpected malformed response from its KYC backend."), /** The backend signaled an unexpected failure. */ EXCHANGE_KYC_PROOF_BACKEND_ERROR(1927, 502, "The backend signaled an unexpected failure."), /** The backend signaled an authorization failure. */ EXCHANGE_KYC_PROOF_BACKEND_AUTHORIZATION_FAILED(1928, 403, "The backend signaled an authorization failure."), /** The exchange is unaware of having made an the authorization request. */ EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN(1929, 404, "The exchange is unaware of having made an the authorization request."), /** The KYC authorization signature was invalid. Hence the request was denied. */ EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED(1930, 403, "The KYC authorization signature was invalid. Hence the request was denied."), /** The request used a logic specifier that is not known to the exchange. */ EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN(1931, 404, "The request used a logic specifier that is not known to the exchange."), /** The request requires a logic which is no longer configured at the exchange. */ EXCHANGE_KYC_GENERIC_LOGIC_GONE(1932, 500, "The request requires a logic which is no longer configured at the exchange."), /** The logic plugin had a bug in its interaction with the KYC provider. */ EXCHANGE_KYC_GENERIC_LOGIC_BUG(1933, 500, "The logic plugin had a bug in its interaction with the KYC provider."), /** The exchange could not process the request with its KYC provider because the provider refused access to the service. This indicates some configuration issue at the Taler exchange operator. */ EXCHANGE_KYC_GENERIC_PROVIDER_ACCESS_REFUSED(1934, 511, "The exchange could not process the request with its KYC provider because the provider refused access to the service. This indicates some configuration issue at the Taler exchange operator."), /** There was a timeout in the interaction between the exchange and the KYC provider. The most likely cause is some networking problem. Trying again later might succeed. */ EXCHANGE_KYC_GENERIC_PROVIDER_TIMEOUT(1935, 504, "There was a timeout in the interaction between the exchange and the KYC provider. The most likely cause is some networking problem. Trying again later might succeed."), /** The KYC provider responded with a status that was completely unexpected by the KYC logic of the exchange. */ EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY(1936, 502, "The KYC provider responded with a status that was completely unexpected by the KYC logic of the exchange."), /** The rate limit of the exchange at the KYC provider has been exceeded. Trying much later might work. */ EXCHANGE_KYC_GENERIC_PROVIDER_RATE_LIMIT_EXCEEDED(1937, 503, "The rate limit of the exchange at the KYC provider has been exceeded. Trying much later might work."), /** The request to the webhook lacked proper authorization or authentication data. */ EXCHANGE_KYC_WEBHOOK_UNAUTHORIZED(1938, 401, "The request to the webhook lacked proper authorization or authentication data."), /** The exchange is unaware of the requested payto URI with respect to the KYC status. */ EXCHANGE_KYC_CHECK_REQUEST_UNKNOWN(1939, 404, "The exchange is unaware of the requested payto URI with respect to the KYC status."), /** The exchange has no account public key to check the KYC authorization signature against. Hence the request was denied. The user should do a wire transfer to the exchange with the KYC authorization key in the subject. */ EXCHANGE_KYC_CHECK_AUTHORIZATION_KEY_UNKNOWN(1940, 409, "The exchange has no account public key to check the KYC authorization signature against. Hence the request was denied. The user should do a wire transfer to the exchange with the KYC authorization key in the subject."), /** The form has been previously uploaded, and may only be filed once. The user should be redirected to their main KYC page and see if any other steps need to be taken. */ EXCHANGE_KYC_FORM_ALREADY_UPLOADED(1941, 409, "The form has been previously uploaded, and may only be filed once. The user should be redirected to their main KYC page and see if any other steps need to be taken."), /** The internal state of the exchange specifying KYC measures is malformed. Please contact technical support. */ EXCHANGE_KYC_MEASURES_MALFORMED(1942, 500, "The internal state of the exchange specifying KYC measures is malformed. Please contact technical support."), /** The specified index does not refer to a valid KYC measure. Please check the URL. */ EXCHANGE_KYC_MEASURE_INDEX_INVALID(1943, 404, "The specified index does not refer to a valid KYC measure. Please check the URL."), /** The operation is not supported by the selected KYC logic. This is either caused by a configuration change or some invalid use of the API. Please contact technical support. */ EXCHANGE_KYC_INVALID_LOGIC_TO_CHECK(1944, 409, "The operation is not supported by the selected KYC logic. This is either caused by a configuration change or some invalid use of the API. Please contact technical support."), /** The AML program failed. This is either caused by a configuration change or a bug. Please contact technical support. */ EXCHANGE_KYC_AML_PROGRAM_FAILURE(1945, 500, "The AML program failed. This is either caused by a configuration change or a bug. Please contact technical support."), /** The AML program returned a malformed result. This is a bug. Please contact technical support. */ EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT(1946, 500, "The AML program returned a malformed result. This is a bug. Please contact technical support."), /** The response from the KYC provider lacked required attributes. Please contact technical support. */ EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_REPLY(1947, 502, "The response from the KYC provider lacked required attributes. Please contact technical support."), /** The context of the KYC check lacked required fields. This is a bug. Please contact technical support. */ EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_CONTEXT(1948, 500, "The context of the KYC check lacked required fields. This is a bug. Please contact technical support."), /** The logic plugin had a bug in its AML processing. This is a bug. Please contact technical support. */ EXCHANGE_KYC_GENERIC_AML_LOGIC_BUG(1949, 500, "The logic plugin had a bug in its AML processing. This is a bug. Please contact technical support."), /** The exchange does not know a contract under the given contract public key. */ EXCHANGE_CONTRACTS_UNKNOWN(1950, 404, "The exchange does not know a contract under the given contract public key."), /** The URL does not encode a valid exchange public key in its path. */ EXCHANGE_CONTRACTS_INVALID_CONTRACT_PUB(1951, 400, "The URL does not encode a valid exchange public key in its path."), /** The returned encrypted contract did not decrypt. */ EXCHANGE_CONTRACTS_DECRYPTION_FAILED(1952, 0, "The returned encrypted contract did not decrypt."), /** The signature on the encrypted contract did not validate. */ EXCHANGE_CONTRACTS_SIGNATURE_INVALID(1953, 0, "The signature on the encrypted contract did not validate."), /** The decrypted contract was malformed. */ EXCHANGE_CONTRACTS_DECODING_FAILED(1954, 0, "The decrypted contract was malformed."), /** A coin signature for a deposit into the purse is invalid. */ EXCHANGE_PURSE_DEPOSIT_COIN_SIGNATURE_INVALID(1975, 403, "A coin signature for a deposit into the purse is invalid."), /** It is too late to deposit coins into the purse. */ EXCHANGE_PURSE_DEPOSIT_DECIDED_ALREADY(1976, 410, "It is too late to deposit coins into the purse."), /** The exchange is currently processing the KYC status and is not able to return a response yet. */ EXCHANGE_KYC_INFO_BUSY(1977, 202, "The exchange is currently processing the KYC status and is not able to return a response yet."), /** TOTP key is not valid. */ EXCHANGE_TOTP_KEY_INVALID(1980, 0, "TOTP key is not valid."), /** The backend could not find the merchant instance specified in the request. */ MERCHANT_GENERIC_INSTANCE_UNKNOWN(2000, 404, "The backend could not find the merchant instance specified in the request."), /** The start and end-times in the wire fee structure leave a hole. This is not allowed. */ MERCHANT_GENERIC_HOLE_IN_WIRE_FEE_STRUCTURE(2001, 0, "The start and end-times in the wire fee structure leave a hole. This is not allowed."), /** The master key of the exchange does not match the one configured for this merchant. As a result, we refuse to do business with this exchange. The administrator should check if they configured the exchange correctly in the merchant backend. */ MERCHANT_GENERIC_EXCHANGE_MASTER_KEY_MISMATCH(2002, 502, "The master key of the exchange does not match the one configured for this merchant. As a result, we refuse to do business with this exchange. The administrator should check if they configured the exchange correctly in the merchant backend."), /** The product category is not known to the backend. */ MERCHANT_GENERIC_CATEGORY_UNKNOWN(2003, 404, "The product category is not known to the backend."), /** The unit referenced in the request is not known to the backend. */ MERCHANT_GENERIC_UNIT_UNKNOWN(2004, 404, "The unit referenced in the request is not known to the backend."), /** The proposal is not known to the backend. */ MERCHANT_GENERIC_ORDER_UNKNOWN(2005, 404, "The proposal is not known to the backend."), /** The order provided to the backend could not be completed, because a product to be completed via inventory data is not actually in our inventory. */ MERCHANT_GENERIC_PRODUCT_UNKNOWN(2006, 404, "The order provided to the backend could not be completed, because a product to be completed via inventory data is not actually in our inventory."), /** The reward ID is unknown. This could happen if the reward has expired. */ MERCHANT_GENERIC_REWARD_ID_UNKNOWN(2007, 404, "The reward ID is unknown. This could happen if the reward has expired."), /** The contract obtained from the merchant backend was malformed. */ MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID(2008, 500, "The contract obtained from the merchant backend was malformed."), /** The order we found does not match the provided contract hash. */ MERCHANT_GENERIC_CONTRACT_HASH_DOES_NOT_MATCH_ORDER(2009, 403, "The order we found does not match the provided contract hash."), /** The exchange failed to provide a valid response to the merchant's /keys request. */ MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE(2010, 502, "The exchange failed to provide a valid response to the merchant's /keys request."), /** The exchange failed to respond to the merchant on time. */ MERCHANT_GENERIC_EXCHANGE_TIMEOUT(2011, 504, "The exchange failed to respond to the merchant on time."), /** The merchant failed to talk to the exchange. */ MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE(2012, 500, "The merchant failed to talk to the exchange."), /** The exchange returned a maformed response. */ MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED(2013, 502, "The exchange returned a maformed response."), /** The exchange returned an unexpected response status. */ MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS(2014, 502, "The exchange returned an unexpected response status."), /** The merchant refused the request due to lack of authorization. */ MERCHANT_GENERIC_UNAUTHORIZED(2015, 401, "The merchant refused the request due to lack of authorization."), /** The merchant instance specified in the request was deleted. */ MERCHANT_GENERIC_INSTANCE_DELETED(2016, 404, "The merchant instance specified in the request was deleted."), /** The backend could not find the inbound wire transfer specified in the request. */ MERCHANT_GENERIC_TRANSFER_UNKNOWN(2017, 404, "The backend could not find the inbound wire transfer specified in the request."), /** The backend could not find the template(id) because it is not exist. */ MERCHANT_GENERIC_TEMPLATE_UNKNOWN(2018, 404, "The backend could not find the template(id) because it is not exist."), /** The backend could not find the webhook(id) because it is not exist. */ MERCHANT_GENERIC_WEBHOOK_UNKNOWN(2019, 404, "The backend could not find the webhook(id) because it is not exist."), /** The backend could not find the webhook(serial) because it is not exist. */ MERCHANT_GENERIC_PENDING_WEBHOOK_UNKNOWN(2020, 404, "The backend could not find the webhook(serial) because it is not exist."), /** The backend could not find the OTP device(id) because it is not exist. */ MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN(2021, 404, "The backend could not find the OTP device(id) because it is not exist."), /** The account is not known to the backend. */ MERCHANT_GENERIC_ACCOUNT_UNKNOWN(2022, 404, "The account is not known to the backend."), /** The wire hash was malformed. */ MERCHANT_GENERIC_H_WIRE_MALFORMED(2023, 400, "The wire hash was malformed."), /** The currency specified in the operation does not work with the current state of the given resource. */ MERCHANT_GENERIC_CURRENCY_MISMATCH(2024, 409, "The currency specified in the operation does not work with the current state of the given resource."), /** The exchange specified in the operation is not trusted by this exchange. The client should limit its operation to exchanges enabled by the merchant, or ask the merchant to enable additional exchanges in the configuration. */ MERCHANT_GENERIC_EXCHANGE_UNTRUSTED(2025, 400, "The exchange specified in the operation is not trusted by this exchange. The client should limit its operation to exchanges enabled by the merchant, or ask the merchant to enable additional exchanges in the configuration."), /** The token family is not known to the backend. */ MERCHANT_GENERIC_TOKEN_FAMILY_UNKNOWN(2026, 404, "The token family is not known to the backend."), /** The token family key is not known to the backend. Check the local system time on the client, maybe an expired (or not yet valid) token was used. */ MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN(2027, 404, "The token family key is not known to the backend. Check the local system time on the client, maybe an expired (or not yet valid) token was used."), /** The merchant backend is not configured to support the DONAU protocol. */ MERCHANT_GENERIC_DONAU_NOT_CONFIGURED(2028, 501, "The merchant backend is not configured to support the DONAU protocol."), /** The public signing key given in the exchange response is not in the current keys response. It is possible that the operation will succeed later after the merchant has downloaded an updated keys response. */ MERCHANT_EXCHANGE_SIGN_PUB_UNKNOWN(2029, 0, "The public signing key given in the exchange response is not in the current keys response. It is possible that the operation will succeed later after the merchant has downloaded an updated keys response."), /** The merchant backend does not support the requested feature. */ MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE(2030, 501, "The merchant backend does not support the requested feature."), /** This operation requires multi-factor authorization and the respective instance does not have a sufficient number of factors that could be validated configured. You need to ask the system administrator to perform this operation. */ MERCHANT_GENERIC_MFA_MISSING(2031, 403, "This operation requires multi-factor authorization and the respective instance does not have a sufficient number of factors that could be validated configured. You need to ask the system administrator to perform this operation."), /** A donation authority (Donau) provided an invalid response. This should be analyzed by the administrator. Trying again later may help. */ MERCHANT_GENERIC_DONAU_INVALID_RESPONSE(2032, 502, "A donation authority (Donau) provided an invalid response. This should be analyzed by the administrator. Trying again later may help."), /** The unit referenced in the request is builtin and cannot be modified or deleted. */ MERCHANT_GENERIC_UNIT_BUILTIN(2033, 409, "The unit referenced in the request is builtin and cannot be modified or deleted."), /** The report ID provided to the backend is not known to the backend. */ MERCHANT_GENERIC_REPORT_UNKNOWN(2034, 404, "The report ID provided to the backend is not known to the backend."), /** The report ID provided to the backend is not known to the backend. */ MERCHANT_GENERIC_REPORT_GENERATOR_UNCONFIGURED(2035, 501, "The report ID provided to the backend is not known to the backend."), /** The product group ID provided to the backend is not known to the backend. */ MERCHANT_GENERIC_PRODUCT_GROUP_UNKNOWN(2036, 404, "The product group ID provided to the backend is not known to the backend."), /** The money pod ID provided to the backend is not known to the backend. */ MERCHANT_GENERIC_MONEY_POT_UNKNOWN(2037, 404, "The money pod ID provided to the backend is not known to the backend."), /** The session ID provided to the backend is not known to the backend. */ MERCHANT_GENERIC_SESSION_UNKNOWN(2038, 404, "The session ID provided to the backend is not known to the backend."), /** The merchant does not have a charity associated with the selected Donau. As a result, it cannot generate the requested donation receipt. This could happen if the charity was removed from the backend between order creation and payment. */ MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN(2039, 404, "The merchant does not have a charity associated with the selected Donau. As a result, it cannot generate the requested donation receipt. This could happen if the charity was removed from the backend between order creation and payment."), /** The merchant does not expect any transfer with the given ID and can thus not return any details about it. */ MERCHANT_GENERIC_EXPECTED_TRANSFER_UNKNOWN(2040, 404, "The merchant does not expect any transfer with the given ID and can thus not return any details about it."), /** The Donau is not known to the backend. */ MERCHANT_GENERIC_DONAU_UNKNOWN(2041, 404, "The Donau is not known to the backend."), /** The access token is not known to the backend. */ MERCHANT_GENERIC_ACCESS_TOKEN_UNKNOWN(2042, 404, "The access token is not known to the backend."), /** One of the binaries needed to generate the PDF is not installed. If this feature is required, the system administrator should make sure Typst and pdftk are both installed. */ MERCHANT_GENERIC_NO_TYPST_OR_PDFTK(2048, 501, "One of the binaries needed to generate the PDF is not installed. If this feature is required, the system administrator should make sure Typst and pdftk are both installed."), /** The exchange failed to provide a valid answer to the tracking request, thus those details are not in the response. */ MERCHANT_GET_ORDERS_EXCHANGE_TRACKING_FAILURE(2100, 200, "The exchange failed to provide a valid answer to the tracking request, thus those details are not in the response."), /** The merchant backend failed to construct the request for tracking to the exchange, thus tracking details are not in the response. */ MERCHANT_GET_ORDERS_ID_EXCHANGE_REQUEST_FAILURE(2103, 500, "The merchant backend failed to construct the request for tracking to the exchange, thus tracking details are not in the response."), /** The merchant backend failed trying to contact the exchange for tracking details, thus those details are not in the response. */ MERCHANT_GET_ORDERS_ID_EXCHANGE_LOOKUP_START_FAILURE(2104, 500, "The merchant backend failed trying to contact the exchange for tracking details, thus those details are not in the response."), /** The claim token used to authenticate the client is invalid for this order. */ MERCHANT_GET_ORDERS_ID_INVALID_TOKEN(2105, 403, "The claim token used to authenticate the client is invalid for this order."), /** The contract terms hash used to authenticate the client is invalid for this order. */ MERCHANT_GET_ORDERS_ID_INVALID_CONTRACT_HASH(2106, 403, "The contract terms hash used to authenticate the client is invalid for this order."), /** The contract terms version is not understood by the merchant backend. Most likely the merchant backend was downgraded to a version incompatible with the content of the database. */ MERCHANT_GET_ORDERS_ID_INVALID_CONTRACT_VERSION(2107, 500, "The contract terms version is not understood by the merchant backend. Most likely the merchant backend was downgraded to a version incompatible with the content of the database."), /** The provided TAN code is invalid for this challenge. */ MERCHANT_TAN_CHALLENGE_FAILED(2125, 409, "The provided TAN code is invalid for this challenge."), /** The backend is not aware of the specified MFA challenge. */ MERCHANT_TAN_CHALLENGE_UNKNOWN(2126, 404, "The backend is not aware of the specified MFA challenge."), /** There have been too many attempts to solve the challenge. A new TAN must be requested. */ MERCHANT_TAN_TOO_MANY_ATTEMPTS(2127, 429, "There have been too many attempts to solve the challenge. A new TAN must be requested."), /** The backend failed to launch a helper process required for the multi-factor authentication step. The backend operator should check the logs and fix the Taler merchant backend configuration. */ MERCHANT_TAN_MFA_HELPER_EXEC_FAILED(2128, 502, "The backend failed to launch a helper process required for the multi-factor authentication step. The backend operator should check the logs and fix the Taler merchant backend configuration."), /** The challenge was already solved. Thus, we refuse to send it again. */ MERCHANT_TAN_CHALLENGE_SOLVED(2129, 410, "The challenge was already solved. Thus, we refuse to send it again."), /** It is too early to request another transmission of the challenge. The client should wait and see if they received the previous challenge. */ MERCHANT_TAN_TOO_EARLY(2130, 429, "It is too early to request another transmission of the challenge. The client should wait and see if they received the previous challenge."), /** There have been too many attempts to solve MFA. The client may attempt again in the future. */ MERCHANT_MFA_FORBIDDEN(2131, 403, "There have been too many attempts to solve MFA. The client may attempt again in the future."), /** The exchange responded saying that funds were insufficient (for example, due to double-spending). */ MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS(2150, 409, "The exchange responded saying that funds were insufficient (for example, due to double-spending)."), /** The denomination key used for payment is not listed among the denomination keys of the exchange. */ MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND(2151, 400, "The denomination key used for payment is not listed among the denomination keys of the exchange."), /** The denomination key used for payment is not audited by an auditor approved by the merchant. */ MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_AUDITOR_FAILURE(2152, 400, "The denomination key used for payment is not audited by an auditor approved by the merchant."), /** There was an integer overflow totaling up the amounts or deposit fees in the payment. */ MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW(2153, 500, "There was an integer overflow totaling up the amounts or deposit fees in the payment."), /** The deposit fees exceed the total value of the payment. */ MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT(2154, 400, "The deposit fees exceed the total value of the payment."), /** After considering deposit and wire fees, the payment is insufficient to satisfy the required amount for the contract. The client should revisit the logic used to calculate fees it must cover. */ MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES(2155, 400, "After considering deposit and wire fees, the payment is insufficient to satisfy the required amount for the contract. The client should revisit the logic used to calculate fees it must cover."), /** Even if we do not consider deposit and wire fees, the payment is insufficient to satisfy the required amount for the contract. */ MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT(2156, 400, "Even if we do not consider deposit and wire fees, the payment is insufficient to satisfy the required amount for the contract."), /** The signature over the contract of one of the coins was invalid. */ MERCHANT_POST_ORDERS_ID_PAY_COIN_SIGNATURE_INVALID(2157, 403, "The signature over the contract of one of the coins was invalid."), /** When we tried to find information about the exchange to issue the deposit, we failed. This usually only happens if the merchant backend is somehow unable to get its own HTTP client logic to work. */ MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LOOKUP_FAILED(2158, 500, "When we tried to find information about the exchange to issue the deposit, we failed. This usually only happens if the merchant backend is somehow unable to get its own HTTP client logic to work."), /** The refund deadline in the contract is after the transfer deadline. */ MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE(2159, 500, "The refund deadline in the contract is after the transfer deadline."), /** The order was already paid (maybe by another wallet). */ MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID(2160, 409, "The order was already paid (maybe by another wallet)."), /** The payment is too late, the offer has expired. */ MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED(2161, 410, "The payment is too late, the offer has expired."), /** The \"merchant\" field is missing in the proposal data. This is an internal error as the proposal is from the merchant's own database at this point. */ MERCHANT_POST_ORDERS_ID_PAY_MERCHANT_FIELD_MISSING(2162, 500, "The \"merchant\" field is missing in the proposal data. This is an internal error as the proposal is from the merchant's own database at this point."), /** Failed to locate merchant's account information matching the wire hash given in the proposal. */ MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN(2163, 500, "Failed to locate merchant's account information matching the wire hash given in the proposal."), /** The deposit time for the denomination has expired. */ MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED(2165, 410, "The deposit time for the denomination has expired."), /** The exchange of the deposited coin charges a wire fee that could not be added to the total (total amount too high). */ MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED(2166, 500, "The exchange of the deposited coin charges a wire fee that could not be added to the total (total amount too high)."), /** The contract was not fully paid because of refunds. Note that clients MAY treat this as paid if, for example, contracts must be executed despite of refunds. */ MERCHANT_POST_ORDERS_ID_PAY_REFUNDED(2167, 402, "The contract was not fully paid because of refunds. Note that clients MAY treat this as paid if, for example, contracts must be executed despite of refunds."), /** According to our database, we have refunded more than we were paid (which should not be possible). */ MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS(2168, 500, "According to our database, we have refunded more than we were paid (which should not be possible)."), /** The refund request is too late because it is past the wire transfer deadline of the order. The merchant must find a different way to pay back the money to the customer. */ MERCHANT_PRIVATE_POST_REFUND_AFTER_WIRE_DEADLINE(2169, 410, "The refund request is too late because it is past the wire transfer deadline of the order. The merchant must find a different way to pay back the money to the customer."), /** The payment failed at the exchange. */ MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_FAILED(2170, 502, "The payment failed at the exchange."), /** The payment required a minimum age but one of the coins (of a denomination with support for age restriction) did not provide any age_commitment. */ MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING(2171, 400, "The payment required a minimum age but one of the coins (of a denomination with support for age restriction) did not provide any age_commitment."), /** The payment required a minimum age but one of the coins provided an age_commitment that contained a wrong number of public keys compared to the number of age groups defined in the denomination of the coin. */ MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH(2172, 400, "The payment required a minimum age but one of the coins provided an age_commitment that contained a wrong number of public keys compared to the number of age groups defined in the denomination of the coin."), /** The payment required a minimum age but one of the coins provided a minimum_age_sig that couldn't be verified with the given age_commitment for that particular minimum age. */ MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED(2173, 400, "The payment required a minimum age but one of the coins provided a minimum_age_sig that couldn't be verified with the given age_commitment for that particular minimum age."), /** The payment required no minimum age but one of the coins (of a denomination with support for age restriction) did not provide the required h_age_commitment. */ MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING(2174, 400, "The payment required no minimum age but one of the coins (of a denomination with support for age restriction) did not provide the required h_age_commitment."), /** The exchange does not support the selected bank account of the merchant. Likely the merchant had stale data on the bank accounts of the exchange and thus selected an inappropriate exchange when making the offer. */ MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED(2175, 409, "The exchange does not support the selected bank account of the merchant. Likely the merchant had stale data on the bank accounts of the exchange and thus selected an inappropriate exchange when making the offer."), /** The payment requires the wallet to select a choice from the choices array and pass it in the 'choice_index' field of the request. */ MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING(2176, 400, "The payment requires the wallet to select a choice from the choices array and pass it in the 'choice_index' field of the request."), /** The 'choice_index' field is invalid. */ MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS(2177, 400, "The 'choice_index' field is invalid."), /** The provided 'tokens' array does not match with the required input tokens of the order. */ MERCHANT_POST_ORDERS_ID_PAY_INPUT_TOKENS_MISMATCH(2178, 400, "The provided 'tokens' array does not match with the required input tokens of the order."), /** Invalid token issue signature (blindly signed by merchant) for provided token. */ MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID(2179, 400, "Invalid token issue signature (blindly signed by merchant) for provided token."), /** Invalid token use signature (EdDSA, signed by wallet) for provided token. */ MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID(2180, 400, "Invalid token use signature (EdDSA, signed by wallet) for provided token."), /** The provided number of tokens does not match the required number. */ MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH(2181, 400, "The provided number of tokens does not match the required number."), /** The provided number of token envelopes does not match the specified number. */ MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH(2182, 400, "The provided number of token envelopes does not match the specified number."), /** Invalid token because it was already used, is expired or not yet valid. */ MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID(2183, 409, "Invalid token because it was already used, is expired or not yet valid."), /** The payment violates a transaction limit configured at the given exchange. The wallet has a bug in that it failed to check exchange limits during coin selection. Please report the bug to your wallet developer. */ MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION(2184, 400, "The payment violates a transaction limit configured at the given exchange. The wallet has a bug in that it failed to check exchange limits during coin selection. Please report the bug to your wallet developer."), /** The donation amount provided in the BKPS does not match the amount of the order choice. */ MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH(2185, 409, "The donation amount provided in the BKPS does not match the amount of the order choice."), /** Some of the exchanges involved refused the request for reasons related to legitimization. The wallet should try with coins of different exchanges. The merchant should check if they have some legitimization process pending at the exchange. */ MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED(2186, 451, "Some of the exchanges involved refused the request for reasons related to legitimization. The wallet should try with coins of different exchanges. The merchant should check if they have some legitimization process pending at the exchange."), /** The contract hash does not match the given order ID. */ MERCHANT_POST_ORDERS_ID_PAID_CONTRACT_HASH_MISMATCH(2200, 400, "The contract hash does not match the given order ID."), /** The signature of the merchant is not valid for the given contract hash. */ MERCHANT_POST_ORDERS_ID_PAID_COIN_SIGNATURE_INVALID(2201, 403, "The signature of the merchant is not valid for the given contract hash."), /** A token family with this ID but conflicting data exists. */ MERCHANT_POST_TOKEN_FAMILY_CONFLICT(2225, 409, "A token family with this ID but conflicting data exists."), /** The backend is unaware of a token family with the given ID. */ MERCHANT_PATCH_TOKEN_FAMILY_NOT_FOUND(2226, 404, "The backend is unaware of a token family with the given ID."), /** The merchant failed to send the exchange the refund request. */ MERCHANT_POST_ORDERS_ID_ABORT_EXCHANGE_REFUND_FAILED(2251, 500, "The merchant failed to send the exchange the refund request."), /** The merchant failed to find the exchange to process the lookup. */ MERCHANT_POST_ORDERS_ID_ABORT_EXCHANGE_LOOKUP_FAILED(2252, 500, "The merchant failed to find the exchange to process the lookup."), /** The merchant could not find the contract. */ MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_NOT_FOUND(2253, 404, "The merchant could not find the contract."), /** The payment was already completed and thus cannot be aborted anymore. */ MERCHANT_POST_ORDERS_ID_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE(2254, 412, "The payment was already completed and thus cannot be aborted anymore."), /** The hash provided by the wallet does not match the order. */ MERCHANT_POST_ORDERS_ID_ABORT_CONTRACT_HASH_MISSMATCH(2255, 403, "The hash provided by the wallet does not match the order."), /** The array of coins cannot be empty. */ MERCHANT_POST_ORDERS_ID_ABORT_COINS_ARRAY_EMPTY(2256, 400, "The array of coins cannot be empty."), /** We are waiting for the exchange to provide us with key material before checking the wire transfer. */ MERCHANT_EXCHANGE_TRANSFERS_AWAITING_KEYS(2258, 202, "We are waiting for the exchange to provide us with key material before checking the wire transfer."), /** We are waiting for the exchange to provide us with the list of aggregated transactions. */ MERCHANT_EXCHANGE_TRANSFERS_AWAITING_LIST(2259, 202, "We are waiting for the exchange to provide us with the list of aggregated transactions."), /** The endpoint indicated in the wire transfer does not belong to a GNU Taler exchange. */ MERCHANT_EXCHANGE_TRANSFERS_FATAL_NO_EXCHANGE(2260, 200, "The endpoint indicated in the wire transfer does not belong to a GNU Taler exchange."), /** The exchange indicated in the wire transfer claims to know nothing about the wire transfer. */ MERCHANT_EXCHANGE_TRANSFERS_FATAL_NOT_FOUND(2261, 0, "The exchange indicated in the wire transfer claims to know nothing about the wire transfer."), /** The interaction with the exchange is delayed due to rate limiting. */ MERCHANT_EXCHANGE_TRANSFERS_RATE_LIMITED(2262, 202, "The interaction with the exchange is delayed due to rate limiting."), /** We experienced a transient failure in our interaction with the exchange. */ MERCHANT_EXCHANGE_TRANSFERS_TRANSIENT_FAILURE(2263, 202, "We experienced a transient failure in our interaction with the exchange."), /** The response from the exchange was unacceptable and should be reviewed with an auditor. */ MERCHANT_EXCHANGE_TRANSFERS_HARD_FAILURE(2264, 200, "The response from the exchange was unacceptable and should be reviewed with an auditor."), /** The merchant backend failed to reach the banking gateway to shorten the wire transfer subject. This probably means that the banking gateway of the exchange is currently down. Contact the exchange operator or simply retry again later. */ MERCHANT_POST_ACCOUNTS_KYCAUTH_BANK_GATEWAY_UNREACHABLE(2275, 502, "The merchant backend failed to reach the banking gateway to shorten the wire transfer subject. This probably means that the banking gateway of the exchange is currently down. Contact the exchange operator or simply retry again later."), /** The merchant backend failed to reach the banking gateway to shorten the wire transfer subject. This probably means that the banking gateway of the exchange is currently down. Contact the exchange operator or simply retry again later. */ MERCHANT_POST_ACCOUNTS_EXCHANGE_TOO_OLD(2276, 502, "The merchant backend failed to reach the banking gateway to shorten the wire transfer subject. This probably means that the banking gateway of the exchange is currently down. Contact the exchange operator or simply retry again later."), /** The merchant backend failed to reach the specified exchange. This probably means that the exchange is currently down. Contact the exchange operator or simply retry again later. */ MERCHANT_POST_ACCOUNTS_KYCAUTH_EXCHANGE_UNREACHABLE(2277, 502, "The merchant backend failed to reach the specified exchange. This probably means that the exchange is currently down. Contact the exchange operator or simply retry again later."), /** We could not claim the order because the backend is unaware of it. */ MERCHANT_POST_ORDERS_ID_CLAIM_NOT_FOUND(2300, 404, "We could not claim the order because the backend is unaware of it."), /** We could not claim the order because someone else claimed it first. */ MERCHANT_POST_ORDERS_ID_CLAIM_ALREADY_CLAIMED(2301, 409, "We could not claim the order because someone else claimed it first."), /** The client-side experienced an internal failure. */ MERCHANT_POST_ORDERS_ID_CLAIM_CLIENT_INTERNAL_FAILURE(2302, 0, "The client-side experienced an internal failure."), /** The unclaim signature of the wallet is not valid for the given contract hash. */ MERCHANT_POST_ORDERS_UNCLAIM_SIGNATURE_INVALID(2303, 403, "The unclaim signature of the wallet is not valid for the given contract hash."), /** The backend failed to sign the refund request. */ MERCHANT_POST_ORDERS_ID_REFUND_SIGNATURE_FAILED(2350, 0, "The backend failed to sign the refund request."), /** The client failed to unblind the signature returned by the merchant. */ MERCHANT_REWARD_PICKUP_UNBLIND_FAILURE(2400, 0, "The client failed to unblind the signature returned by the merchant."), /** The exchange returned a failure code for the withdraw operation. */ MERCHANT_REWARD_PICKUP_EXCHANGE_ERROR(2403, 502, "The exchange returned a failure code for the withdraw operation."), /** The merchant failed to add up the amounts to compute the pick up value. */ MERCHANT_REWARD_PICKUP_SUMMATION_FAILED(2404, 500, "The merchant failed to add up the amounts to compute the pick up value."), /** The reward expired. */ MERCHANT_REWARD_PICKUP_HAS_EXPIRED(2405, 410, "The reward expired."), /** The requested withdraw amount exceeds the amount remaining to be picked up. */ MERCHANT_REWARD_PICKUP_AMOUNT_EXCEEDS_REWARD_REMAINING(2406, 400, "The requested withdraw amount exceeds the amount remaining to be picked up."), /** The merchant did not find the specified denomination key in the exchange's key set. */ MERCHANT_REWARD_PICKUP_DENOMINATION_UNKNOWN(2407, 409, "The merchant did not find the specified denomination key in the exchange's key set."), /** The merchant instance has no active bank accounts configured. However, at least one bank account must be available to create new orders. */ MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE(2500, 404, "The merchant instance has no active bank accounts configured. However, at least one bank account must be available to create new orders."), /** The proposal had no timestamp and the merchant backend failed to obtain the current local time. */ MERCHANT_PRIVATE_POST_ORDERS_NO_LOCALTIME(2501, 500, "The proposal had no timestamp and the merchant backend failed to obtain the current local time."), /** The order provided to the backend could not be parsed; likely some required fields were missing or ill-formed. */ MERCHANT_PRIVATE_POST_ORDERS_PROPOSAL_PARSE_ERROR(2502, 400, "The order provided to the backend could not be parsed; likely some required fields were missing or ill-formed."), /** A conflicting order (sharing the same order identifier) already exists at this merchant backend instance. */ MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS(2503, 409, "A conflicting order (sharing the same order identifier) already exists at this merchant backend instance."), /** The order creation request is invalid because the given wire deadline is before the refund deadline. */ MERCHANT_PRIVATE_POST_ORDERS_REFUND_AFTER_WIRE_DEADLINE(2504, 400, "The order creation request is invalid because the given wire deadline is before the refund deadline."), /** The order creation request is invalid because the delivery date given is in the past. */ MERCHANT_PRIVATE_POST_ORDERS_DELIVERY_DATE_IN_PAST(2505, 400, "The order creation request is invalid because the delivery date given is in the past."), /** The order creation request is invalid because a wire deadline of \"never\" is not allowed. */ MERCHANT_PRIVATE_POST_ORDERS_WIRE_DEADLINE_IS_NEVER(2506, 400, "The order creation request is invalid because a wire deadline of \"never\" is not allowed."), /** The order creation request is invalid because the given payment deadline is in the past. */ MERCHANT_PRIVATE_POST_ORDERS_PAY_DEADLINE_IN_PAST(2507, 400, "The order creation request is invalid because the given payment deadline is in the past."), /** The order creation request is invalid because the given refund deadline is in the past. */ MERCHANT_PRIVATE_POST_ORDERS_REFUND_DEADLINE_IN_PAST(2508, 400, "The order creation request is invalid because the given refund deadline is in the past."), /** The backend does not trust any exchange that would allow funds to be wired to any bank account of this instance using the wire method specified with the order. (Note that right now, we do not support the use of exchange bank accounts with mandatory currency conversion.) One likely cause for this is that the taler-merchant-exchangekeyupdate process is not running. */ MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGES_FOR_WIRE_METHOD(2509, 409, "The backend does not trust any exchange that would allow funds to be wired to any bank account of this instance using the wire method specified with the order. (Note that right now, we do not support the use of exchange bank accounts with mandatory currency conversion.) One likely cause for this is that the taler-merchant-exchangekeyupdate process is not running."), /** One of the paths to forget is malformed. */ MERCHANT_PRIVATE_PATCH_ORDERS_ID_FORGET_PATH_SYNTAX_INCORRECT(2510, 400, "One of the paths to forget is malformed."), /** One of the paths to forget was not marked as forgettable. */ MERCHANT_PRIVATE_PATCH_ORDERS_ID_FORGET_PATH_NOT_FORGETTABLE(2511, 409, "One of the paths to forget was not marked as forgettable."), /** The refund amount would violate a refund transaction limit configured at the given exchange. Please find another way to refund the customer, and inquire with your legislator why they make strange banking regulations. */ MERCHANT_POST_ORDERS_ID_REFUND_EXCHANGE_TRANSACTION_LIMIT_VIOLATION(2512, 451, "The refund amount would violate a refund transaction limit configured at the given exchange. Please find another way to refund the customer, and inquire with your legislator why they make strange banking regulations."), /** The total order amount exceeds hard legal transaction limits from the available exchanges, thus a customer could never legally make this payment. You may try to increase your limits by passing legitimization checks with exchange operators. You could also inquire with your legislator why the limits are prohibitively low for your business. */ MERCHANT_PRIVATE_POST_ORDERS_AMOUNT_EXCEEDS_LEGAL_LIMITS(2513, 451, "The total order amount exceeds hard legal transaction limits from the available exchanges, thus a customer could never legally make this payment. You may try to increase your limits by passing legitimization checks with exchange operators. You could also inquire with your legislator why the limits are prohibitively low for your business."), /** A currency specified to be paid in the contract is not supported by any exchange that this instance can currently use. Possible solutions include (1) specifying a different currency, (2) adding additional suitable exchange operators to the merchant backend configuration, or (3) satisfying compliance rules of an configured exchange to begin using the service of that provider. */ MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGE_FOR_CURRENCY(2514, 409, "A currency specified to be paid in the contract is not supported by any exchange that this instance can currently use. Possible solutions include (1) specifying a different currency, (2) adding additional suitable exchange operators to the merchant backend configuration, or (3) satisfying compliance rules of an configured exchange to begin using the service of that provider."), /** The order provided to the backend could not be deleted, our offer is still valid and awaiting payment. Deletion may work later after the offer has expired if it remains unpaid. */ MERCHANT_PRIVATE_DELETE_ORDERS_AWAITING_PAYMENT(2520, 409, "The order provided to the backend could not be deleted, our offer is still valid and awaiting payment. Deletion may work later after the offer has expired if it remains unpaid."), /** The order provided to the backend could not be deleted as the order was already paid. */ MERCHANT_PRIVATE_DELETE_ORDERS_ALREADY_PAID(2521, 409, "The order provided to the backend could not be deleted as the order was already paid."), /** The client requested a report granularity that is not available at the backend. Possible solutions include extending the backend code and/or the database statistic triggers to support the desired data granularity. Alternatively, the client could request a different granularity. */ MERCHANT_PRIVATE_GET_STATISTICS_REPORT_GRANULARITY_UNAVAILABLE(2525, 410, "The client requested a report granularity that is not available at the backend. Possible solutions include extending the backend code and/or the database statistic triggers to support the desired data granularity. Alternatively, the client could request a different granularity."), /** The amount to be refunded is inconsistent: either is lower than the previous amount being awarded, or it exceeds the original price paid by the customer. */ MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_INCONSISTENT_AMOUNT(2530, 409, "The amount to be refunded is inconsistent: either is lower than the previous amount being awarded, or it exceeds the original price paid by the customer."), /** Only paid orders can be refunded, and the frontend specified an unpaid order to issue a refund for. */ MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_ORDER_UNPAID(2531, 409, "Only paid orders can be refunded, and the frontend specified an unpaid order to issue a refund for."), /** The refund delay was set to 0 and thus no refunds are ever allowed for this order. */ MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_NOT_ALLOWED_BY_CONTRACT(2532, 403, "The refund delay was set to 0 and thus no refunds are ever allowed for this order."), /** The token family slug provided in this order could not be found in the merchant database. */ MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_SLUG_UNKNOWN(2533, 404, "The token family slug provided in this order could not be found in the merchant database."), /** A token family referenced in this order is either expired or not valid yet. */ MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_NOT_VALID(2534, 409, "A token family referenced in this order is either expired or not valid yet."), /** The exchange says it does not know this transfer. */ MERCHANT_PRIVATE_POST_TRANSFERS_EXCHANGE_UNKNOWN(2550, 502, "The exchange says it does not know this transfer."), /** We internally failed to execute the /track/transfer request. */ MERCHANT_PRIVATE_POST_TRANSFERS_REQUEST_ERROR(2551, 502, "We internally failed to execute the /track/transfer request."), /** The amount transferred differs between what was submitted and what the exchange claimed. */ MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_TRANSFERS(2552, 409, "The amount transferred differs between what was submitted and what the exchange claimed."), /** The exchange gave conflicting information about a coin which has been wire transferred. */ MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_REPORTS(2553, 409, "The exchange gave conflicting information about a coin which has been wire transferred."), /** The exchange charged a different wire fee than what it originally advertised, and it is higher. */ MERCHANT_PRIVATE_POST_TRANSFERS_BAD_WIRE_FEE(2554, 502, "The exchange charged a different wire fee than what it originally advertised, and it is higher."), /** We did not find the account that the transfer was made to. */ MERCHANT_PRIVATE_POST_TRANSFERS_ACCOUNT_NOT_FOUND(2555, 404, "We did not find the account that the transfer was made to."), /** The backend could not delete the transfer as the echange already replied to our inquiry about it and we have integrated the result. */ MERCHANT_PRIVATE_DELETE_TRANSFERS_ALREADY_CONFIRMED(2556, 409, "The backend could not delete the transfer as the echange already replied to our inquiry about it and we have integrated the result."), /** The backend could not persist the wire transfer due to the state of the backend. This usually means that a wire transfer with the same wire transfer subject but a different amount was previously submitted to the backend. */ MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_SUBMISSION(2557, 409, "The backend could not persist the wire transfer due to the state of the backend. This usually means that a wire transfer with the same wire transfer subject but a different amount was previously submitted to the backend."), /** The target bank account given by the exchange is not (or no longer) known at the merchant instance. */ MERCHANT_EXCHANGE_TRANSFERS_TARGET_ACCOUNT_UNKNOWN(2558, 0, "The target bank account given by the exchange is not (or no longer) known at the merchant instance."), /** The amount transferred differs between what was submitted and what the exchange claimed. */ MERCHANT_EXCHANGE_TRANSFERS_CONFLICTING_TRANSFERS(2563, 0, "The amount transferred differs between what was submitted and what the exchange claimed."), /** The report ID provided to the backend is not known to the backend. */ MERCHANT_REPORT_GENERATOR_FAILED(2570, 501, "The report ID provided to the backend is not known to the backend."), /** Failed to fetch the data for the report from the backend. */ MERCHANT_REPORT_FETCH_FAILED(2571, 502, "Failed to fetch the data for the report from the backend."), /** The merchant backend cannot create an instance under the given identifier as one already exists. Use PATCH to modify the existing entry. */ MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS(2600, 409, "The merchant backend cannot create an instance under the given identifier as one already exists. Use PATCH to modify the existing entry."), /** The merchant backend cannot create an instance because the authentication configuration field is malformed. */ MERCHANT_PRIVATE_POST_INSTANCES_BAD_AUTH(2601, 400, "The merchant backend cannot create an instance because the authentication configuration field is malformed."), /** The merchant backend cannot update an instance's authentication settings because the provided authentication settings are malformed. */ MERCHANT_PRIVATE_POST_INSTANCE_AUTH_BAD_AUTH(2602, 400, "The merchant backend cannot update an instance's authentication settings because the provided authentication settings are malformed."), /** The merchant backend cannot create an instance under the given identifier, the previous one was deleted but must be purged first. */ MERCHANT_PRIVATE_POST_INSTANCES_PURGE_REQUIRED(2603, 409, "The merchant backend cannot create an instance under the given identifier, the previous one was deleted but must be purged first."), /** The merchant backend cannot update an instance under the given identifier, the previous one was deleted but must be purged first. */ MERCHANT_PRIVATE_PATCH_INSTANCES_PURGE_REQUIRED(2625, 409, "The merchant backend cannot update an instance under the given identifier, the previous one was deleted but must be purged first."), /** The bank account referenced in the requested operation was not found. */ MERCHANT_PRIVATE_ACCOUNT_DELETE_UNKNOWN_ACCOUNT(2626, 404, "The bank account referenced in the requested operation was not found."), /** The bank account specified in the request already exists at the merchant. */ MERCHANT_PRIVATE_ACCOUNT_EXISTS(2627, 409, "The bank account specified in the request already exists at the merchant."), /** The bank account specified is not acceptable for this exchange. The exchange either does not support the wire method or something else about the specific account. Consult the exchange account constraints and specify a different bank account if you want to use this exchange. */ MERCHANT_PRIVATE_ACCOUNT_NOT_ELIGIBLE_FOR_EXCHANGE(2628, 409, "The bank account specified is not acceptable for this exchange. The exchange either does not support the wire method or something else about the specific account. Consult the exchange account constraints and specify a different bank account if you want to use this exchange."), /** The product ID exists. */ MERCHANT_PRIVATE_POST_PRODUCTS_CONFLICT_PRODUCT_EXISTS(2650, 409, "The product ID exists."), /** A category with the same name exists already. */ MERCHANT_PRIVATE_POST_CATEGORIES_CONFLICT_CATEGORY_EXISTS(2651, 409, "A category with the same name exists already."), /** The update would have reduced the total amount of product lost, which is not allowed. */ MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_REDUCED(2660, 409, "The update would have reduced the total amount of product lost, which is not allowed."), /** The update would have mean that more stocks were lost than what remains from total inventory after sales, which is not allowed. */ MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_LOST_EXCEEDS_STOCKS(2661, 400, "The update would have mean that more stocks were lost than what remains from total inventory after sales, which is not allowed."), /** The update would have reduced the total amount of product in stock, which is not allowed. */ MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_STOCKED_REDUCED(2662, 409, "The update would have reduced the total amount of product in stock, which is not allowed."), /** The update would have reduced the total amount of product sold, which is not allowed. */ MERCHANT_PRIVATE_PATCH_PRODUCTS_TOTAL_SOLD_REDUCED(2663, 409, "The update would have reduced the total amount of product sold, which is not allowed."), /** The lock request is for more products than we have left (unlocked) in stock. */ MERCHANT_PRIVATE_POST_PRODUCTS_LOCK_INSUFFICIENT_STOCKS(2670, 410, "The lock request is for more products than we have left (unlocked) in stock."), /** The deletion request is for a product that is locked. The product cannot be deleted until the existing offer to expires. */ MERCHANT_PRIVATE_DELETE_PRODUCTS_CONFLICTING_LOCK(2680, 409, "The deletion request is for a product that is locked. The product cannot be deleted until the existing offer to expires."), /** The proposed name for the product group is already in use. You should select a different name. */ MERCHANT_PRIVATE_PRODUCT_GROUP_CONFLICTING_NAME(2690, 409, "The proposed name for the product group is already in use. You should select a different name."), /** The proposed name for the money pot is already in use. You should select a different name. */ MERCHANT_PRIVATE_MONEY_POT_CONFLICTING_NAME(2691, 409, "The proposed name for the money pot is already in use. You should select a different name."), /** The total amount in the money pot is different from the amount required by the request. The client should fetch the current pot total and retry with the latest amount to succeed. */ MERCHANT_PRIVATE_MONEY_POT_CONFLICTING_TOTAL(2692, 409, "The total amount in the money pot is different from the amount required by the request. The client should fetch the current pot total and retry with the latest amount to succeed."), /** The requested wire method is not supported by the exchange. */ MERCHANT_PRIVATE_POST_RESERVES_UNSUPPORTED_WIRE_METHOD(2700, 409, "The requested wire method is not supported by the exchange."), /** The requested exchange does not allow rewards. */ MERCHANT_PRIVATE_POST_RESERVES_REWARDS_NOT_ALLOWED(2701, 409, "The requested exchange does not allow rewards."), /** The reserve could not be deleted because it is unknown. */ MERCHANT_PRIVATE_DELETE_RESERVES_NO_SUCH_RESERVE(2710, 404, "The reserve could not be deleted because it is unknown."), /** The reserve that was used to fund the rewards has expired. */ MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_EXPIRED(2750, 410, "The reserve that was used to fund the rewards has expired."), /** The reserve that was used to fund the rewards was not found in the DB. */ MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_UNKNOWN(2751, 503, "The reserve that was used to fund the rewards was not found in the DB."), /** The backend knows the instance that was supposed to support the reward, and it was configured for rewardping. However, the funds remaining are insufficient to cover the reward, and the merchant should top up the reserve. */ MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_INSUFFICIENT_FUNDS(2752, 0, "The backend knows the instance that was supposed to support the reward, and it was configured for rewardping. However, the funds remaining are insufficient to cover the reward, and the merchant should top up the reserve."), /** The backend failed to find a reserve needed to authorize the reward. */ MERCHANT_PRIVATE_POST_REWARD_AUTHORIZE_RESERVE_NOT_FOUND(2753, 503, "The backend failed to find a reserve needed to authorize the reward."), /** The merchant backend encountered a failure in computing the deposit total. */ MERCHANT_PRIVATE_GET_ORDERS_ID_AMOUNT_ARITHMETIC_FAILURE(2800, 200, "The merchant backend encountered a failure in computing the deposit total."), /** The template ID already exists. */ MERCHANT_PRIVATE_POST_TEMPLATES_CONFLICT_TEMPLATE_EXISTS(2850, 409, "The template ID already exists."), /** The OTP device ID already exists. */ MERCHANT_PRIVATE_POST_OTP_DEVICES_CONFLICT_OTP_DEVICE_EXISTS(2851, 409, "The OTP device ID already exists."), /** Amount given in the using template and in the template contract. There is a conflict. */ MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT(2860, 409, "Amount given in the using template and in the template contract. There is a conflict."), /** Subject given in the using template and in the template contract. There is a conflict. */ MERCHANT_POST_USING_TEMPLATES_SUMMARY_CONFLICT_TEMPLATES_CONTRACT_SUBJECT(2861, 409, "Subject given in the using template and in the template contract. There is a conflict."), /** Amount not given in the using template and in the template contract. There is a conflict. */ MERCHANT_POST_USING_TEMPLATES_NO_AMOUNT(2862, 409, "Amount not given in the using template and in the template contract. There is a conflict."), /** Subject not given in the using template and in the template contract. There is a conflict. */ MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY(2863, 409, "Subject not given in the using template and in the template contract. There is a conflict."), /** The selected template has a different type than the one specified in the request of the client. This may happen if the template was updated since the last time the client fetched it. The client should re-fetch the current template and send a request of the correct type. */ MERCHANT_POST_USING_TEMPLATES_WRONG_TYPE(2864, 409, "The selected template has a different type than the one specified in the request of the client. This may happen if the template was updated since the last time the client fetched it. The client should re-fetch the current template and send a request of the correct type."), /** The selected template does not allow one of the specified products to be included in the order. This may happen if the template was updated since the last time the client fetched it. The client should re-fetch the current template and send a request of the correct type. */ MERCHANT_POST_USING_TEMPLATES_WRONG_PRODUCT(2865, 409, "The selected template does not allow one of the specified products to be included in the order. This may happen if the template was updated since the last time the client fetched it. The client should re-fetch the current template and send a request of the correct type."), /** The selected combination of products does not allow the backend to compute a price for the order in any of the supported currencies. This may happen if the template was updated since the last time the client fetched it or if the wallet assembled an unsupported combination of products. The site administrator might want to specify additional prices for products, while the client should re-fetch the current template and send a request with a combination of products for which prices exist in the same currency. */ MERCHANT_POST_USING_TEMPLATES_NO_CURRENCY(2866, 409, "The selected combination of products does not allow the backend to compute a price for the order in any of the supported currencies. This may happen if the template was updated since the last time the client fetched it or if the wallet assembled an unsupported combination of products. The site administrator might want to specify additional prices for products, while the client should re-fetch the current template and send a request with a combination of products for which prices exist in the same currency."), /** The webhook ID elready exists. */ MERCHANT_PRIVATE_POST_WEBHOOKS_CONFLICT_WEBHOOK_EXISTS(2900, 409, "The webhook ID elready exists."), /** The webhook serial elready exists. */ MERCHANT_PRIVATE_POST_PENDING_WEBHOOKS_CONFLICT_PENDING_WEBHOOK_EXISTS(2910, 409, "The webhook serial elready exists."), /** The auditor refused the connection due to a lack of authorization. */ AUDITOR_GENERIC_UNAUTHORIZED(3001, 401, "The auditor refused the connection due to a lack of authorization."), /** This method is not allowed here. */ AUDITOR_GENERIC_METHOD_NOT_ALLOWED(3002, 405, "This method is not allowed here."), /** The signature from the exchange on the deposit confirmation is invalid. */ AUDITOR_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID(3100, 403, "The signature from the exchange on the deposit confirmation is invalid."), /** The exchange key used for the signature on the deposit confirmation was revoked. */ AUDITOR_EXCHANGE_SIGNING_KEY_REVOKED(3101, 410, "The exchange key used for the signature on the deposit confirmation was revoked."), /** The requested resource could not be found. */ AUDITOR_RESOURCE_NOT_FOUND(3102, 404, "The requested resource could not be found."), /** The URI is missing a path component. */ AUDITOR_URI_MISSING_PATH_COMPONENT(3103, 400, "The URI is missing a path component."), /** Wire transfer attempted with credit and debit party being the same bank account. */ BANK_SAME_ACCOUNT(5101, 400, "Wire transfer attempted with credit and debit party being the same bank account."), /** Wire transfer impossible, due to financial limitation of the party that attempted the payment. */ BANK_UNALLOWED_DEBIT(5102, 409, "Wire transfer impossible, due to financial limitation of the party that attempted the payment."), /** Negative numbers are not allowed (as value and/or fraction) to instantiate an amount object. */ BANK_NEGATIVE_NUMBER_AMOUNT(5103, 400, "Negative numbers are not allowed (as value and/or fraction) to instantiate an amount object."), /** A too big number was used (as value and/or fraction) to instantiate an amount object. */ BANK_NUMBER_TOO_BIG(5104, 400, "A too big number was used (as value and/or fraction) to instantiate an amount object."), /** The bank account referenced in the requested operation was not found. */ BANK_UNKNOWN_ACCOUNT(5106, 404, "The bank account referenced in the requested operation was not found."), /** The transaction referenced in the requested operation (typically a reject operation), was not found. */ BANK_TRANSACTION_NOT_FOUND(5107, 404, "The transaction referenced in the requested operation (typically a reject operation), was not found."), /** Bank received a malformed amount string. */ BANK_BAD_FORMAT_AMOUNT(5108, 400, "Bank received a malformed amount string."), /** The client does not own the account credited by the transaction which is to be rejected, so it has no rights do reject it. */ BANK_REJECT_NO_RIGHTS(5109, 403, "The client does not own the account credited by the transaction which is to be rejected, so it has no rights do reject it."), /** This error code is returned when no known exception types captured the exception. */ BANK_UNMANAGED_EXCEPTION(5110, 500, "This error code is returned when no known exception types captured the exception."), /** This error code is used for all those exceptions that do not really need a specific error code to return to the client. Used for example when a client is trying to register with a unavailable username. */ BANK_SOFT_EXCEPTION(5111, 500, "This error code is used for all those exceptions that do not really need a specific error code to return to the client. Used for example when a client is trying to register with a unavailable username."), /** The request UID for a request to transfer funds has already been used, but with different details for the transfer. */ BANK_TRANSFER_REQUEST_UID_REUSED(5112, 409, "The request UID for a request to transfer funds has already been used, but with different details for the transfer."), /** The withdrawal operation already has a reserve selected. The current request conflicts with the existing selection. */ BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT(5113, 409, "The withdrawal operation already has a reserve selected. The current request conflicts with the existing selection."), /** The wire transfer subject duplicates an existing reserve public key. But wire transfer subjects must be unique. */ BANK_DUPLICATE_RESERVE_PUB_SUBJECT(5114, 409, "The wire transfer subject duplicates an existing reserve public key. But wire transfer subjects must be unique."), /** The client requested a transaction that is so far in the past, that it has been forgotten by the bank. */ BANK_ANCIENT_TRANSACTION_GONE(5115, 410, "The client requested a transaction that is so far in the past, that it has been forgotten by the bank."), /** The client attempted to abort a transaction that was already confirmed. */ BANK_ABORT_CONFIRM_CONFLICT(5116, 409, "The client attempted to abort a transaction that was already confirmed."), /** The client attempted to confirm a transaction that was already aborted. */ BANK_CONFIRM_ABORT_CONFLICT(5117, 409, "The client attempted to confirm a transaction that was already aborted."), /** The client attempted to register an account with the same name. */ BANK_REGISTER_CONFLICT(5118, 409, "The client attempted to register an account with the same name."), /** The client attempted to confirm a withdrawal operation before the wallet posted the required details. */ BANK_POST_WITHDRAWAL_OPERATION_REQUIRED(5119, 400, "The client attempted to confirm a withdrawal operation before the wallet posted the required details."), /** The client tried to register a new account under a reserved username (like 'admin' for example). */ BANK_RESERVED_USERNAME_CONFLICT(5120, 409, "The client tried to register a new account under a reserved username (like 'admin' for example)."), /** The client tried to register a new account with an username already in use. */ BANK_REGISTER_USERNAME_REUSE(5121, 409, "The client tried to register a new account with an username already in use."), /** The client tried to register a new account with a payto:// URI already in use. */ BANK_REGISTER_PAYTO_URI_REUSE(5122, 409, "The client tried to register a new account with a payto:// URI already in use."), /** The client tried to delete an account with a non null balance. */ BANK_ACCOUNT_BALANCE_NOT_ZERO(5123, 409, "The client tried to delete an account with a non null balance."), /** The client tried to create a transaction or an operation that credit an unknown account. */ BANK_UNKNOWN_CREDITOR(5124, 409, "The client tried to create a transaction or an operation that credit an unknown account."), /** The client tried to create a transaction or an operation that debit an unknown account. */ BANK_UNKNOWN_DEBTOR(5125, 409, "The client tried to create a transaction or an operation that debit an unknown account."), /** The client tried to perform an action prohibited for exchange accounts. */ BANK_ACCOUNT_IS_EXCHANGE(5126, 409, "The client tried to perform an action prohibited for exchange accounts."), /** The client tried to perform an action reserved for exchange accounts. */ BANK_ACCOUNT_IS_NOT_EXCHANGE(5127, 409, "The client tried to perform an action reserved for exchange accounts."), /** Received currency conversion is wrong. */ BANK_BAD_CONVERSION(5128, 409, "Received currency conversion is wrong."), /** The account referenced in this operation is missing tan info for the chosen channel. */ BANK_MISSING_TAN_INFO(5129, 409, "The account referenced in this operation is missing tan info for the chosen channel."), /** The client attempted to confirm a transaction with incomplete info. */ BANK_CONFIRM_INCOMPLETE(5130, 409, "The client attempted to confirm a transaction with incomplete info."), /** The request rate is too high. The server is refusing requests to guard against brute-force attacks. */ BANK_TAN_RATE_LIMITED(5131, 429, "The request rate is too high. The server is refusing requests to guard against brute-force attacks."), /** This TAN channel is not supported. */ BANK_TAN_CHANNEL_NOT_SUPPORTED(5132, 501, "This TAN channel is not supported."), /** Failed to send TAN using the helper script. Either script is not found, or script timeout, or script terminated with a non-successful result. */ BANK_TAN_CHANNEL_SCRIPT_FAILED(5133, 500, "Failed to send TAN using the helper script. Either script is not found, or script timeout, or script terminated with a non-successful result."), /** The client's response to the challenge was invalid. */ BANK_TAN_CHALLENGE_FAILED(5134, 403, "The client's response to the challenge was invalid."), /** A non-admin user has tried to change their legal name. */ BANK_NON_ADMIN_PATCH_LEGAL_NAME(5135, 409, "A non-admin user has tried to change their legal name."), /** A non-admin user has tried to change their debt limit. */ BANK_NON_ADMIN_PATCH_DEBT_LIMIT(5136, 409, "A non-admin user has tried to change their debt limit."), /** A non-admin user has tried to change their password whihout providing the current one. */ BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD(5137, 409, "A non-admin user has tried to change their password whihout providing the current one."), /** Provided old password does not match current password. */ BANK_PATCH_BAD_OLD_PASSWORD(5138, 409, "Provided old password does not match current password."), /** An admin user has tried to become an exchange. */ BANK_PATCH_ADMIN_EXCHANGE(5139, 409, "An admin user has tried to become an exchange."), /** A non-admin user has tried to change their cashout account. */ BANK_NON_ADMIN_PATCH_CASHOUT(5140, 409, "A non-admin user has tried to change their cashout account."), /** A non-admin user has tried to change their contact info. */ BANK_NON_ADMIN_PATCH_CONTACT(5141, 409, "A non-admin user has tried to change their contact info."), /** The client tried to create a transaction that credit the admin account. */ BANK_ADMIN_CREDITOR(5142, 409, "The client tried to create a transaction that credit the admin account."), /** The referenced challenge was not found. */ BANK_CHALLENGE_NOT_FOUND(5143, 404, "The referenced challenge was not found."), /** The referenced challenge has expired. */ BANK_TAN_CHALLENGE_EXPIRED(5144, 409, "The referenced challenge has expired."), /** A non-admin user has tried to create an account with 2fa. */ BANK_NON_ADMIN_SET_TAN_CHANNEL(5145, 409, "A non-admin user has tried to create an account with 2fa."), /** A non-admin user has tried to set their minimum cashout amount. */ BANK_NON_ADMIN_SET_MIN_CASHOUT(5146, 409, "A non-admin user has tried to set their minimum cashout amount."), /** Amount of currency conversion it less than the minimum allowed. */ BANK_CONVERSION_AMOUNT_TO_SMALL(5147, 409, "Amount of currency conversion it less than the minimum allowed."), /** Specified amount will not work for this withdrawal. */ BANK_AMOUNT_DIFFERS(5148, 409, "Specified amount will not work for this withdrawal."), /** The backend requires an amount to be specified. */ BANK_AMOUNT_REQUIRED(5149, 409, "The backend requires an amount to be specified."), /** Provided password is too short. */ BANK_PASSWORD_TOO_SHORT(5150, 409, "Provided password is too short."), /** Provided password is too long. */ BANK_PASSWORD_TOO_LONG(5151, 409, "Provided password is too long."), /** Bank account is locked and cannot authenticate using his password. */ BANK_ACCOUNT_LOCKED(5152, 403, "Bank account is locked and cannot authenticate using his password."), /** The client attempted to update a transaction' details that was already aborted. */ BANK_UPDATE_ABORT_CONFLICT(5153, 409, "The client attempted to update a transaction' details that was already aborted."), /** The wtid for a request to transfer funds has already been used, but with a different request unpaid. */ BANK_TRANSFER_WTID_REUSED(5154, 409, "The wtid for a request to transfer funds has already been used, but with a different request unpaid."), /** A non-admin user has tried to set their conversion rate class */ BANK_NON_ADMIN_SET_CONVERSION_RATE_CLASS(5155, 409, "A non-admin user has tried to set their conversion rate class"), /** The referenced conversion rate class was not found */ BANK_CONVERSION_RATE_CLASS_UNKNOWN(5156, 409, "The referenced conversion rate class was not found"), /** The client tried to use an already taken name. */ BANK_NAME_REUSE(5157, 409, "The client tried to use an already taken name."), /** This subject format is not supported. */ BANK_UNSUPPORTED_SUBJECT_FORMAT(5158, 409, "This subject format is not supported."), /** The derived subject is already used. */ BANK_DERIVATION_REUSE(5159, 409, "The derived subject is already used."), /** The provided signature is invalid. */ BANK_BAD_SIGNATURE(5160, 409, "The provided signature is invalid."), /** The provided timestamp is too old. */ BANK_OLD_TIMESTAMP(5161, 409, "The provided timestamp is too old."), /** The authorization_pub for a request to transfer funds has already been used for another non recurrent transfer. */ BANK_TRANSFER_MAPPING_REUSED(5162, 409, "The authorization_pub for a request to transfer funds has already been used for another non recurrent transfer."), /** The authorization_pub for a request to transfer funds is not currently registered. */ BANK_TRANSFER_MAPPING_UNKNOWN(5163, 409, "The authorization_pub for a request to transfer funds is not currently registered."), /** The sync service failed find the account in its database. */ SYNC_ACCOUNT_UNKNOWN(6100, 404, "The sync service failed find the account in its database."), /** The SHA-512 hash provided in the If-None-Match header is malformed. */ SYNC_BAD_IF_NONE_MATCH(6101, 400, "The SHA-512 hash provided in the If-None-Match header is malformed."), /** The SHA-512 hash provided in the If-Match header is malformed or missing. */ SYNC_BAD_IF_MATCH(6102, 400, "The SHA-512 hash provided in the If-Match header is malformed or missing."), /** The signature provided in the \"Sync-Signature\" header is malformed or missing. */ SYNC_BAD_SYNC_SIGNATURE(6103, 400, "The signature provided in the \"Sync-Signature\" header is malformed or missing."), /** The signature provided in the \"Sync-Signature\" header does not match the account, old or new Etags. */ SYNC_INVALID_SIGNATURE(6104, 403, "The signature provided in the \"Sync-Signature\" header does not match the account, old or new Etags."), /** The \"Content-length\" field for the upload is not a number. */ SYNC_MALFORMED_CONTENT_LENGTH(6105, 400, "The \"Content-length\" field for the upload is not a number."), /** The \"Content-length\" field for the upload is too big based on the server's terms of service. */ SYNC_EXCESSIVE_CONTENT_LENGTH(6106, 413, "The \"Content-length\" field for the upload is too big based on the server's terms of service."), /** The server is out of memory to handle the upload. Trying again later may succeed. */ SYNC_OUT_OF_MEMORY_ON_CONTENT_LENGTH(6107, 413, "The server is out of memory to handle the upload. Trying again later may succeed."), /** The uploaded data does not match the Etag. */ SYNC_INVALID_UPLOAD(6108, 400, "The uploaded data does not match the Etag."), /** HTTP server experienced a timeout while awaiting promised payment. */ SYNC_PAYMENT_GENERIC_TIMEOUT(6109, 408, "HTTP server experienced a timeout while awaiting promised payment."), /** Sync could not setup the payment request with its own backend. */ SYNC_PAYMENT_CREATE_BACKEND_ERROR(6110, 500, "Sync could not setup the payment request with its own backend."), /** The sync service failed find the backup to be updated in its database. */ SYNC_PREVIOUS_BACKUP_UNKNOWN(6111, 404, "The sync service failed find the backup to be updated in its database."), /** The \"Content-length\" field for the upload is missing. */ SYNC_MISSING_CONTENT_LENGTH(6112, 400, "The \"Content-length\" field for the upload is missing."), /** Sync had problems communicating with its payment backend. */ SYNC_GENERIC_BACKEND_ERROR(6113, 502, "Sync had problems communicating with its payment backend."), /** Sync experienced a timeout communicating with its payment backend. */ SYNC_GENERIC_BACKEND_TIMEOUT(6114, 504, "Sync experienced a timeout communicating with its payment backend."), /** The wallet does not implement a version of the exchange protocol that is compatible with the protocol version of the exchange. */ WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE(7000, 501, "The wallet does not implement a version of the exchange protocol that is compatible with the protocol version of the exchange."), /** The wallet encountered an unexpected exception. This is likely a bug in the wallet implementation. */ WALLET_UNEXPECTED_EXCEPTION(7001, 500, "The wallet encountered an unexpected exception. This is likely a bug in the wallet implementation."), /** The wallet received a response from a server, but the response can't be parsed. */ WALLET_RECEIVED_MALFORMED_RESPONSE(7002, 0, "The wallet received a response from a server, but the response can't be parsed."), /** The wallet tried to make a network request, but it received no response. */ WALLET_NETWORK_ERROR(7003, 0, "The wallet tried to make a network request, but it received no response."), /** The wallet tried to make a network request, but it was throttled. */ WALLET_HTTP_REQUEST_THROTTLED(7004, 0, "The wallet tried to make a network request, but it was throttled."), /** The wallet made a request to a service, but received an error response it does not know how to handle. */ WALLET_UNEXPECTED_REQUEST_ERROR(7005, 0, "The wallet made a request to a service, but received an error response it does not know how to handle."), /** The denominations offered by the exchange are insufficient. Likely the exchange is badly configured or not maintained. */ WALLET_EXCHANGE_DENOMINATIONS_INSUFFICIENT(7006, 0, "The denominations offered by the exchange are insufficient. Likely the exchange is badly configured or not maintained."), /** The wallet does not support the operation requested by a client. */ WALLET_CORE_API_OPERATION_UNKNOWN(7007, 0, "The wallet does not support the operation requested by a client."), /** The given taler://pay URI is invalid. */ WALLET_INVALID_TALER_PAY_URI(7008, 0, "The given taler://pay URI is invalid."), /** The signature on a coin by the exchange's denomination key is invalid after unblinding it. */ WALLET_EXCHANGE_COIN_SIGNATURE_INVALID(7009, 0, "The signature on a coin by the exchange's denomination key is invalid after unblinding it."), /** The wallet core service is not available. */ WALLET_CORE_NOT_AVAILABLE(7011, 0, "The wallet core service is not available."), /** The bank has aborted a withdrawal operation, and thus a withdrawal can't complete. */ WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK(7012, 0, "The bank has aborted a withdrawal operation, and thus a withdrawal can't complete."), /** An HTTP request made by the wallet timed out. */ WALLET_HTTP_REQUEST_GENERIC_TIMEOUT(7013, 0, "An HTTP request made by the wallet timed out."), /** The order has already been claimed by another wallet. */ WALLET_ORDER_ALREADY_CLAIMED(7014, 0, "The order has already been claimed by another wallet."), /** A group of withdrawal operations (typically for the same reserve at the same exchange) has errors and will be tried again later. */ WALLET_WITHDRAWAL_GROUP_INCOMPLETE(7015, 0, "A group of withdrawal operations (typically for the same reserve at the same exchange) has errors and will be tried again later."), /** The signature on a coin by the exchange's denomination key (obtained through the merchant via a reward) is invalid after unblinding it. */ WALLET_REWARD_COIN_SIGNATURE_INVALID(7016, 0, "The signature on a coin by the exchange's denomination key (obtained through the merchant via a reward) is invalid after unblinding it."), /** The wallet does not implement a version of the bank integration API that is compatible with the version offered by the bank. */ WALLET_BANK_INTEGRATION_PROTOCOL_VERSION_INCOMPATIBLE(7017, 0, "The wallet does not implement a version of the bank integration API that is compatible with the version offered by the bank."), /** The wallet processed a taler://pay URI, but the merchant base URL in the downloaded contract terms does not match the merchant base URL derived from the URI. */ WALLET_CONTRACT_TERMS_BASE_URL_MISMATCH(7018, 0, "The wallet processed a taler://pay URI, but the merchant base URL in the downloaded contract terms does not match the merchant base URL derived from the URI."), /** The merchant's signature on the contract terms is invalid. */ WALLET_CONTRACT_TERMS_SIGNATURE_INVALID(7019, 0, "The merchant's signature on the contract terms is invalid."), /** The contract terms given by the merchant are malformed. */ WALLET_CONTRACT_TERMS_MALFORMED(7020, 0, "The contract terms given by the merchant are malformed."), /** A pending operation failed, and thus the request can't be completed. */ WALLET_PENDING_OPERATION_FAILED(7021, 0, "A pending operation failed, and thus the request can't be completed."), /** A payment was attempted, but the merchant had an internal server error (5xx). */ WALLET_PAY_MERCHANT_SERVER_ERROR(7022, 0, "A payment was attempted, but the merchant had an internal server error (5xx)."), /** The crypto worker failed. */ WALLET_CRYPTO_WORKER_ERROR(7023, 0, "The crypto worker failed."), /** The crypto worker received a bad request. */ WALLET_CRYPTO_WORKER_BAD_REQUEST(7024, 0, "The crypto worker received a bad request."), /** A KYC step is required before withdrawal can proceed. */ WALLET_WITHDRAWAL_KYC_REQUIRED(7025, 0, "A KYC step is required before withdrawal can proceed."), /** The wallet does not have sufficient balance to create a deposit group. */ WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE(7026, 0, "The wallet does not have sufficient balance to create a deposit group."), /** The wallet does not have sufficient balance to create a peer push payment. */ WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE(7027, 0, "The wallet does not have sufficient balance to create a peer push payment."), /** The wallet does not have sufficient balance to pay for an invoice. */ WALLET_PEER_PULL_PAYMENT_INSUFFICIENT_BALANCE(7028, 0, "The wallet does not have sufficient balance to pay for an invoice."), /** A group of refresh operations has errors and will be tried again later. */ WALLET_REFRESH_GROUP_INCOMPLETE(7029, 0, "A group of refresh operations has errors and will be tried again later."), /** The exchange's self-reported base URL does not match the one that the wallet is using. */ WALLET_EXCHANGE_BASE_URL_MISMATCH(7030, 0, "The exchange's self-reported base URL does not match the one that the wallet is using."), /** The order has already been paid by another wallet. */ WALLET_ORDER_ALREADY_PAID(7031, 0, "The order has already been paid by another wallet."), /** An exchange that is required for some request is currently not available. */ WALLET_EXCHANGE_UNAVAILABLE(7032, 0, "An exchange that is required for some request is currently not available."), /** An exchange entry is still used by the exchange, thus it can't be deleted without purging. */ WALLET_EXCHANGE_ENTRY_USED(7033, 0, "An exchange entry is still used by the exchange, thus it can't be deleted without purging."), /** The wallet database is unavailable and the wallet thus is not operational. */ WALLET_DB_UNAVAILABLE(7034, 0, "The wallet database is unavailable and the wallet thus is not operational."), /** A taler:// URI is malformed and can't be parsed. */ WALLET_TALER_URI_MALFORMED(7035, 0, "A taler:// URI is malformed and can't be parsed."), /** A wallet-core request was cancelled and thus can't provide a response. */ WALLET_CORE_REQUEST_CANCELLED(7036, 0, "A wallet-core request was cancelled and thus can't provide a response."), /** A wallet-core request failed because the user needs to first accept the exchange's terms of service. */ WALLET_EXCHANGE_TOS_NOT_ACCEPTED(7037, 0, "A wallet-core request failed because the user needs to first accept the exchange's terms of service."), /** An exchange entry could not be updated, as the exchange's new details conflict with the new details. */ WALLET_EXCHANGE_ENTRY_UPDATE_CONFLICT(7038, 0, "An exchange entry could not be updated, as the exchange's new details conflict with the new details."), /** The wallet's information about the exchange is outdated. */ WALLET_EXCHANGE_ENTRY_OUTDATED(7039, 0, "The wallet's information about the exchange is outdated."), /** The merchant needs to do KYC first, the payment could not be completed. */ WALLET_PAY_MERCHANT_KYC_MISSING(7040, 0, "The merchant needs to do KYC first, the payment could not be completed."), /** A peer-pull-debit transaction was aborted because the exchange reported the purse as gone. */ WALLET_PEER_PULL_DEBIT_PURSE_GONE(7041, 0, "A peer-pull-debit transaction was aborted because the exchange reported the purse as gone."), /** A transaction was aborted on explicit request by the user. */ WALLET_TRANSACTION_ABORTED_BY_USER(7042, 0, "A transaction was aborted on explicit request by the user."), /** A transaction was abandoned on explicit request by the user. */ WALLET_TRANSACTION_ABANDONED_BY_USER(7043, 0, "A transaction was abandoned on explicit request by the user."), /** A payment was attempted, but the merchant claims the order is gone (likely expired). */ WALLET_PAY_MERCHANT_ORDER_GONE(7044, 0, "A payment was attempted, but the merchant claims the order is gone (likely expired)."), /** The wallet does not have an entry for the requested exchange. */ WALLET_EXCHANGE_ENTRY_NOT_FOUND(7045, 0, "The wallet does not have an entry for the requested exchange."), /** The wallet is not able to process the request due to the transaction's state. */ WALLET_REQUEST_TRANSACTION_STATE_UNSUPPORTED(7046, 0, "The wallet is not able to process the request due to the transaction's state."), /** A transaction could not be processed due to an unrecoverable protocol violation. */ WALLET_TRANSACTION_PROTOCOL_VIOLATION(7047, 0, "A transaction could not be processed due to an unrecoverable protocol violation."), /** A parameter in the request is malformed or missing. */ WALLET_CORE_API_BAD_REQUEST(7048, 0, "A parameter in the request is malformed or missing."), /** The order could not be found. Maybe the merchant deleted it. */ WALLET_MERCHANT_ORDER_NOT_FOUND(7049, 0, "The order could not be found. Maybe the merchant deleted it."), /** We encountered a timeout with our payment backend. */ ANASTASIS_GENERIC_BACKEND_TIMEOUT(8000, 504, "We encountered a timeout with our payment backend."), /** The backend requested payment, but the request is malformed. */ ANASTASIS_GENERIC_INVALID_PAYMENT_REQUEST(8001, 0, "The backend requested payment, but the request is malformed."), /** The backend got an unexpected reply from the payment processor. */ ANASTASIS_GENERIC_BACKEND_ERROR(8002, 502, "The backend got an unexpected reply from the payment processor."), /** The \"Content-length\" field for the upload is missing. */ ANASTASIS_GENERIC_MISSING_CONTENT_LENGTH(8003, 400, "The \"Content-length\" field for the upload is missing."), /** The \"Content-length\" field for the upload is malformed. */ ANASTASIS_GENERIC_MALFORMED_CONTENT_LENGTH(8004, 400, "The \"Content-length\" field for the upload is malformed."), /** The backend failed to setup an order with the payment processor. */ ANASTASIS_GENERIC_ORDER_CREATE_BACKEND_ERROR(8005, 502, "The backend failed to setup an order with the payment processor."), /** The backend was not authorized to check for payment with the payment processor. */ ANASTASIS_GENERIC_PAYMENT_CHECK_UNAUTHORIZED(8006, 500, "The backend was not authorized to check for payment with the payment processor."), /** The backend could not check payment status with the payment processor. */ ANASTASIS_GENERIC_PAYMENT_CHECK_START_FAILED(8007, 500, "The backend could not check payment status with the payment processor."), /** The Anastasis provider could not be reached. */ ANASTASIS_GENERIC_PROVIDER_UNREACHABLE(8008, 0, "The Anastasis provider could not be reached."), /** HTTP server experienced a timeout while awaiting promised payment. */ ANASTASIS_PAYMENT_GENERIC_TIMEOUT(8009, 408, "HTTP server experienced a timeout while awaiting promised payment."), /** The key share is unknown to the provider. */ ANASTASIS_TRUTH_UNKNOWN(8108, 404, "The key share is unknown to the provider."), /** The authorization method used for the key share is no longer supported by the provider. */ ANASTASIS_TRUTH_AUTHORIZATION_METHOD_NO_LONGER_SUPPORTED(8109, 500, "The authorization method used for the key share is no longer supported by the provider."), /** The client needs to respond to the challenge. */ ANASTASIS_TRUTH_CHALLENGE_RESPONSE_REQUIRED(8110, 403, "The client needs to respond to the challenge."), /** The client's response to the challenge was invalid. */ ANASTASIS_TRUTH_CHALLENGE_FAILED(8111, 403, "The client's response to the challenge was invalid."), /** The backend is not aware of having issued the provided challenge code. Either this is the wrong code, or it has expired. */ ANASTASIS_TRUTH_CHALLENGE_UNKNOWN(8112, 404, "The backend is not aware of having issued the provided challenge code. Either this is the wrong code, or it has expired."), /** The backend failed to initiate the authorization process. */ ANASTASIS_TRUTH_AUTHORIZATION_START_FAILED(8114, 500, "The backend failed to initiate the authorization process."), /** The authorization succeeded, but the key share is no longer available. */ ANASTASIS_TRUTH_KEY_SHARE_GONE(8115, 404, "The authorization succeeded, but the key share is no longer available."), /** The backend forgot the order we asked the client to pay for */ ANASTASIS_TRUTH_ORDER_DISAPPEARED(8116, 502, "The backend forgot the order we asked the client to pay for"), /** The backend itself reported a bad exchange interaction. */ ANASTASIS_TRUTH_BACKEND_EXCHANGE_BAD(8117, 502, "The backend itself reported a bad exchange interaction."), /** The backend reported a payment status we did not expect. */ ANASTASIS_TRUTH_UNEXPECTED_PAYMENT_STATUS(8118, 500, "The backend reported a payment status we did not expect."), /** The backend failed to setup the order for payment. */ ANASTASIS_TRUTH_PAYMENT_CREATE_BACKEND_ERROR(8119, 502, "The backend failed to setup the order for payment."), /** The decryption of the key share failed with the provided key. */ ANASTASIS_TRUTH_DECRYPTION_FAILED(8120, 400, "The decryption of the key share failed with the provided key."), /** The request rate is too high. The server is refusing requests to guard against brute-force attacks. */ ANASTASIS_TRUTH_RATE_LIMITED(8121, 429, "The request rate is too high. The server is refusing requests to guard against brute-force attacks."), /** A request to issue a challenge is not valid for this authentication method. */ ANASTASIS_TRUTH_CHALLENGE_WRONG_METHOD(8123, 400, "A request to issue a challenge is not valid for this authentication method."), /** The backend failed to store the key share because the UUID is already in use. */ ANASTASIS_TRUTH_UPLOAD_UUID_EXISTS(8150, 409, "The backend failed to store the key share because the UUID is already in use."), /** The backend failed to store the key share because the authorization method is not supported. */ ANASTASIS_TRUTH_UPLOAD_METHOD_NOT_SUPPORTED(8151, 400, "The backend failed to store the key share because the authorization method is not supported."), /** The provided phone number is not an acceptable number. */ ANASTASIS_SMS_PHONE_INVALID(8200, 409, "The provided phone number is not an acceptable number."), /** Failed to run the SMS transmission helper process. */ ANASTASIS_SMS_HELPER_EXEC_FAILED(8201, 500, "Failed to run the SMS transmission helper process."), /** Provider failed to send SMS. Helper terminated with a non-successful result. */ ANASTASIS_SMS_HELPER_COMMAND_FAILED(8202, 500, "Provider failed to send SMS. Helper terminated with a non-successful result."), /** The provided email address is not an acceptable address. */ ANASTASIS_EMAIL_INVALID(8210, 409, "The provided email address is not an acceptable address."), /** Failed to run the E-mail transmission helper process. */ ANASTASIS_EMAIL_HELPER_EXEC_FAILED(8211, 500, "Failed to run the E-mail transmission helper process."), /** Provider failed to send E-mail. Helper terminated with a non-successful result. */ ANASTASIS_EMAIL_HELPER_COMMAND_FAILED(8212, 500, "Provider failed to send E-mail. Helper terminated with a non-successful result."), /** The provided postal address is not an acceptable address. */ ANASTASIS_POST_INVALID(8220, 409, "The provided postal address is not an acceptable address."), /** Failed to run the mail transmission helper process. */ ANASTASIS_POST_HELPER_EXEC_FAILED(8221, 500, "Failed to run the mail transmission helper process."), /** Provider failed to send mail. Helper terminated with a non-successful result. */ ANASTASIS_POST_HELPER_COMMAND_FAILED(8222, 500, "Provider failed to send mail. Helper terminated with a non-successful result."), /** The provided IBAN address is not an acceptable IBAN. */ ANASTASIS_IBAN_INVALID(8230, 409, "The provided IBAN address is not an acceptable IBAN."), /** The provider has not yet received the IBAN wire transfer authorizing the disclosure of the key share. */ ANASTASIS_IBAN_MISSING_TRANSFER(8231, 403, "The provider has not yet received the IBAN wire transfer authorizing the disclosure of the key share."), /** The backend did not find a TOTP key in the data provided. */ ANASTASIS_TOTP_KEY_MISSING(8240, 409, "The backend did not find a TOTP key in the data provided."), /** The key provided does not satisfy the format restrictions for an Anastasis TOTP key. */ ANASTASIS_TOTP_KEY_INVALID(8241, 409, "The key provided does not satisfy the format restrictions for an Anastasis TOTP key."), /** The given if-none-match header is malformed. */ ANASTASIS_POLICY_BAD_IF_NONE_MATCH(8301, 400, "The given if-none-match header is malformed."), /** The server is out of memory to handle the upload. Trying again later may succeed. */ ANASTASIS_POLICY_OUT_OF_MEMORY_ON_CONTENT_LENGTH(8304, 413, "The server is out of memory to handle the upload. Trying again later may succeed."), /** The signature provided in the \"Anastasis-Policy-Signature\" header is malformed or missing. */ ANASTASIS_POLICY_BAD_SIGNATURE(8305, 400, "The signature provided in the \"Anastasis-Policy-Signature\" header is malformed or missing."), /** The given if-match header is malformed. */ ANASTASIS_POLICY_BAD_IF_MATCH(8306, 400, "The given if-match header is malformed."), /** The uploaded data does not match the Etag. */ ANASTASIS_POLICY_INVALID_UPLOAD(8307, 400, "The uploaded data does not match the Etag."), /** The provider is unaware of the requested policy. */ ANASTASIS_POLICY_NOT_FOUND(8350, 404, "The provider is unaware of the requested policy."), /** The given action is invalid for the current state of the reducer. */ ANASTASIS_REDUCER_ACTION_INVALID(8400, 0, "The given action is invalid for the current state of the reducer."), /** The given state of the reducer is invalid. */ ANASTASIS_REDUCER_STATE_INVALID(8401, 0, "The given state of the reducer is invalid."), /** The given input to the reducer is invalid. */ ANASTASIS_REDUCER_INPUT_INVALID(8402, 0, "The given input to the reducer is invalid."), /** The selected authentication method does not work for the Anastasis provider. */ ANASTASIS_REDUCER_AUTHENTICATION_METHOD_NOT_SUPPORTED(8403, 0, "The selected authentication method does not work for the Anastasis provider."), /** The given input and action do not work for the current state. */ ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE(8404, 0, "The given input and action do not work for the current state."), /** We experienced an unexpected failure interacting with the backend. */ ANASTASIS_REDUCER_BACKEND_FAILURE(8405, 0, "We experienced an unexpected failure interacting with the backend."), /** The contents of a resource file did not match our expectations. */ ANASTASIS_REDUCER_RESOURCE_MALFORMED(8406, 0, "The contents of a resource file did not match our expectations."), /** A required resource file is missing. */ ANASTASIS_REDUCER_RESOURCE_MISSING(8407, 0, "A required resource file is missing."), /** An input did not match the regular expression. */ ANASTASIS_REDUCER_INPUT_REGEX_FAILED(8408, 0, "An input did not match the regular expression."), /** An input did not match the custom validation logic. */ ANASTASIS_REDUCER_INPUT_VALIDATION_FAILED(8409, 0, "An input did not match the custom validation logic."), /** Our attempts to download the recovery document failed with all providers. Most likely the personal information you entered differs from the information you provided during the backup process and you should go back to the previous step. Alternatively, if you used a backup provider that is unknown to this application, you should add that provider manually. */ ANASTASIS_REDUCER_POLICY_LOOKUP_FAILED(8410, 0, "Our attempts to download the recovery document failed with all providers. Most likely the personal information you entered differs from the information you provided during the backup process and you should go back to the previous step. Alternatively, if you used a backup provider that is unknown to this application, you should add that provider manually."), /** Anastasis provider reported a fatal failure. */ ANASTASIS_REDUCER_BACKUP_PROVIDER_FAILED(8411, 0, "Anastasis provider reported a fatal failure."), /** Anastasis provider failed to respond to the configuration request. */ ANASTASIS_REDUCER_PROVIDER_CONFIG_FAILED(8412, 0, "Anastasis provider failed to respond to the configuration request."), /** The policy we downloaded is malformed. Must have been a client error while creating the backup. */ ANASTASIS_REDUCER_POLICY_MALFORMED(8413, 0, "The policy we downloaded is malformed. Must have been a client error while creating the backup."), /** We failed to obtain the policy, likely due to a network issue. */ ANASTASIS_REDUCER_NETWORK_FAILED(8414, 0, "We failed to obtain the policy, likely due to a network issue."), /** The recovered secret did not match the required syntax. */ ANASTASIS_REDUCER_SECRET_MALFORMED(8415, 0, "The recovered secret did not match the required syntax."), /** The challenge data provided is too large for the available providers. */ ANASTASIS_REDUCER_CHALLENGE_DATA_TOO_BIG(8416, 0, "The challenge data provided is too large for the available providers."), /** The provided core secret is too large for some of the providers. */ ANASTASIS_REDUCER_SECRET_TOO_BIG(8417, 0, "The provided core secret is too large for some of the providers."), /** The provider returned in invalid configuration. */ ANASTASIS_REDUCER_PROVIDER_INVALID_CONFIG(8418, 0, "The provider returned in invalid configuration."), /** The reducer encountered an internal error, likely a bug that needs to be reported. */ ANASTASIS_REDUCER_INTERNAL_ERROR(8419, 0, "The reducer encountered an internal error, likely a bug that needs to be reported."), /** The reducer already synchronized with all providers. */ ANASTASIS_REDUCER_PROVIDERS_ALREADY_SYNCED(8420, 0, "The reducer already synchronized with all providers."), /** The Donau failed to perform the operation as it could not find the private keys. This is a problem with the Donau setup, not with the client's request. */ DONAU_GENERIC_KEYS_MISSING(8607, 503, "The Donau failed to perform the operation as it could not find the private keys. This is a problem with the Donau setup, not with the client's request."), /** The signature of the charity key is not valid. */ DONAU_CHARITY_SIGNATURE_INVALID(8608, 403, "The signature of the charity key is not valid."), /** The charity is unknown. */ DONAU_CHARITY_NOT_FOUND(8609, 404, "The charity is unknown."), /** The donation amount specified in the request exceeds the limit of the charity. */ DONAU_EXCEEDING_DONATION_LIMIT(8610, 400, "The donation amount specified in the request exceeds the limit of the charity."), /** The Donau is not aware of the donation unit requested for the operation. */ DONAU_GENERIC_DONATION_UNIT_UNKNOWN(8611, 404, "The Donau is not aware of the donation unit requested for the operation."), /** The Donau failed to talk to the process responsible for its private donation unit keys or the helpers had no donation units (properly) configured. */ DONAU_DONATION_UNIT_HELPER_UNAVAILABLE(8612, 502, "The Donau failed to talk to the process responsible for its private donation unit keys or the helpers had no donation units (properly) configured."), /** The Donau failed to talk to the process responsible for its private signing keys. */ DONAU_SIGNKEY_HELPER_UNAVAILABLE(8613, 502, "The Donau failed to talk to the process responsible for its private signing keys."), /** The response from the online signing key helper process was malformed. */ DONAU_SIGNKEY_HELPER_BUG(8614, 500, "The response from the online signing key helper process was malformed."), /** The number of segments included in the URI does not match the number of segments expected by the endpoint. */ DONAU_GENERIC_WRONG_NUMBER_OF_SEGMENTS(8615, 404, "The number of segments included in the URI does not match the number of segments expected by the endpoint."), /** The signature of the donation receipt is not valid. */ DONAU_DONATION_RECEIPT_SIGNATURE_INVALID(8616, 403, "The signature of the donation receipt is not valid."), /** The client reused a unique donor identifier nonce, which is not allowed. */ DONAU_DONOR_IDENTIFIER_NONCE_REUSE(8617, 409, "The client reused a unique donor identifier nonce, which is not allowed."), /** A charity with the same public key is already registered. */ DONAU_CHARITY_PUB_EXISTS(8618, 404, "A charity with the same public key is already registered."), /** A generic error happened in the LibEuFin nexus. See the enclose details JSON for more information. */ LIBEUFIN_NEXUS_GENERIC_ERROR(9000, 0, "A generic error happened in the LibEuFin nexus. See the enclose details JSON for more information."), /** An uncaught exception happened in the LibEuFin nexus service. */ LIBEUFIN_NEXUS_UNCAUGHT_EXCEPTION(9001, 500, "An uncaught exception happened in the LibEuFin nexus service."), /** A generic error happened in the LibEuFin sandbox. See the enclose details JSON for more information. */ LIBEUFIN_SANDBOX_GENERIC_ERROR(9500, 0, "A generic error happened in the LibEuFin sandbox. See the enclose details JSON for more information."), /** An uncaught exception happened in the LibEuFin sandbox service. */ LIBEUFIN_SANDBOX_UNCAUGHT_EXCEPTION(9501, 500, "An uncaught exception happened in the LibEuFin sandbox service."), /** This validation method is not supported by the service. */ TALDIR_METHOD_NOT_SUPPORTED(9600, 404, "This validation method is not supported by the service."), /** Number of allowed attempts for initiating a challenge exceeded. */ TALDIR_REGISTER_RATE_LIMITED(9601, 429, "Number of allowed attempts for initiating a challenge exceeded."), /** The client is unknown or unauthorized. */ CHALLENGER_GENERIC_CLIENT_UNKNOWN(9750, 404, "The client is unknown or unauthorized."), /** The client is not authorized to use the given redirect URI. */ CHALLENGER_GENERIC_CLIENT_FORBIDDEN_BAD_REDIRECT_URI(9751, 403, "The client is not authorized to use the given redirect URI."), /** The service failed to execute its helper process to send the challenge. */ CHALLENGER_HELPER_EXEC_FAILED(9752, 500, "The service failed to execute its helper process to send the challenge."), /** The grant is unknown to the service (it could also have expired). */ CHALLENGER_GRANT_UNKNOWN(9753, 404, "The grant is unknown to the service (it could also have expired)."), /** The code given is not even well-formed. */ CHALLENGER_CLIENT_FORBIDDEN_BAD_CODE(9754, 403, "The code given is not even well-formed."), /** The service is not aware of the referenced validation process. */ CHALLENGER_GENERIC_VALIDATION_UNKNOWN(9755, 404, "The service is not aware of the referenced validation process."), /** The code given is not valid. */ CHALLENGER_CLIENT_FORBIDDEN_INVALID_CODE(9756, 403, "The code given is not valid."), /** Too many attempts have been made, validation is temporarily disabled for this address. */ CHALLENGER_TOO_MANY_ATTEMPTS(9757, 429, "Too many attempts have been made, validation is temporarily disabled for this address."), /** The PIN code provided is incorrect. */ CHALLENGER_INVALID_PIN(9758, 403, "The PIN code provided is incorrect."), /** The token cannot be valid as no address was ever provided by the client. */ CHALLENGER_MISSING_ADDRESS(9759, 409, "The token cannot be valid as no address was ever provided by the client."), /** The client is not allowed to change the address being validated. */ CHALLENGER_CLIENT_FORBIDDEN_READ_ONLY(9760, 403, "The client is not allowed to change the address being validated."), /** End of error code range. */ END(9999, 0, "End of error code range."), } libeufin-1.6.8/libeufin-common/src/main/kotlin/security.kt0000664000175000017500000000204515122266731024056 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import java.security.Security fun setupSecurityProperties() { // Enable certificate revocation check System.setProperty("com.sun.net.ssl.checkRevocation", "true"); System.setProperty("com.sun.security.enableCRLDP", "true"); Security.setProperty("ocsp.enable", "true"); }libeufin-1.6.8/libeufin-common/src/main/kotlin/config.kt0000664000175000017500000000454015140725607023460 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import org.slf4j.Logger import org.slf4j.LoggerFactory import java.nio.file.Path private val logger: Logger = LoggerFactory.getLogger("libeufin-config") sealed interface ServerConfig { data class Unix(val path: Path): ServerConfig data class Tcp(val addr: String, val port: Int): ServerConfig } fun TalerConfig.loadServerConfig(section: String): ServerConfig { val sect = section(section) return sect.mapLambda("serve", "server method", mapOf( "tcp" to { ServerConfig.Tcp(sect.string("address").orNull() ?: sect.string("bind_to").require(), sect.number("port").require()) }, "unix" to { ServerConfig.Unix(sect.path("unixpath").require()) } )).require() } fun TalerConfigSection.requireAuthMethod(): AuthMethod { return mapLambda("auth_method", "auth method", mapOf( "none" to { AuthMethod.None }, "bearer-token" to { logger.warn("Deprecated auth method option 'auth_method' used deprecated value 'bearer-token'") val token = string("auth_bearer_token").require() AuthMethod.Bearer(token) }, "bearer" to { val token = string("token").require() AuthMethod.Bearer(token) }, "basic" to { val username = string("username").require() val password = string("password").require() AuthMethod.Basic("$username:$password".encodeBase64()) } )).require() } sealed interface AuthMethod { data object None: AuthMethod data class Bearer(val token: String): AuthMethod data class Basic(val token: String): AuthMethod }libeufin-1.6.8/libeufin-common/src/main/kotlin/helpers.kt0000664000175000017500000001421115122266731023647 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.common import io.ktor.server.application.* import org.slf4j.Logger import java.io.ByteArrayOutputStream import java.io.FilterInputStream import java.io.InputStream import java.math.BigInteger import java.security.SecureRandom import java.time.Instant import java.time.LocalDate import java.time.LocalDateTime import java.time.ZoneOffset import java.time.format.DateTimeFormatter import java.util.* import java.util.zip.DeflaterInputStream import java.util.zip.InflaterInputStream import java.util.zip.ZipInputStream import kotlin.random.Random /* ----- String ----- */ /** Decode a base64 encoded string */ fun String.decodeBase64(): ByteArray = Base64.getDecoder().decode(this) /** Encode a string as base64 */ fun String.encodeBase64(): String = toByteArray().encodeBase64() /** Decode a hexadecimal uppercase encoded string */ fun String.decodeUpHex(): ByteArray = HexFormat.of().withUpperCase().parseHex(this) fun String.splitOnce(pat: String): Pair? { val split = splitToSequence(pat, limit=2).iterator() val first = split.next() if (!split.hasNext()) return null return Pair(first, split.next()) } /** Format a string with a space every two characters */ fun String.fmtChunkByTwo() = buildString { this@fmtChunkByTwo.forEachIndexed { pos, c -> if (pos != 0 && pos % 2 == 0) append(' ') append(c) } } /* ----- Date & Time ----- */ /** Converting YYYY-MM-DD to Instant */ fun dateToInstant(date: String): Instant = LocalDate.parse(date, DateTimeFormatter.ISO_DATE).atStartOfDay().toInstant(ZoneOffset.UTC) /** Converting YYYY-MM-DDTHH:MM:SS to Instant */ fun dateTimeToInstant(date: String): Instant = LocalDateTime.parse(date, DateTimeFormatter.ISO_DATE_TIME).toInstant(ZoneOffset.UTC) private val DATE_TIME_PATH = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HHmmss") /** Converting Instant to YYYY-MM-DDTHHMMSS */ fun Instant.toDateTimeFilePath(): String = this.atOffset(ZoneOffset.UTC).format(DATE_TIME_PATH) /* ----- BigInteger -----*/ fun BigInteger.encodeHex(): String = this.toByteArray().encodeHex() fun BigInteger.encodeBase64(): String = this.toByteArray().encodeBase64() /* ----- Random ----- */ /** Thread local cryptographically strong random number generator */ val SECURE_RNG = ThreadLocal.withInitial { SecureRandom() } /* ----- ByteArray ----- */ fun ByteArray.rand(rng: Random = Random): ByteArray { rng.nextBytes(this) return this } fun ByteArray.secureRand(): ByteArray { SECURE_RNG.get().nextBytes(this) return this } fun ByteArray.encodeHex(): String = HexFormat.of().formatHex(this) fun ByteArray.encodeUpHex(): String = HexFormat.of().withUpperCase().formatHex(this) fun ByteArray.encodeBase64(): String = Base64.getEncoder().encodeToString(this) fun ByteArray.asUtf8(): String = this.toString(Charsets.UTF_8) fun ByteArrayOutputStream.asUtf8(): String = this.toString(Charsets.UTF_8) /* ----- InputStream ----- */ /** Unzip an input stream and run [lambda] over each entry */ inline fun InputStream.unzipEach(lambda: (String, InputStream) -> Unit) { ZipInputStream(this).use { zip -> while (true) { val entry = zip.getNextEntry() ?: break val entryStream = object: FilterInputStream(zip) { override fun close() { zip.closeEntry() } } lambda(entry.name, entryStream) } } } /** Decode a base64 encoded input stream */ fun InputStream.decodeBase64(): InputStream = Base64.getDecoder().wrap(this) /** Encode an input stream as base64 */ fun InputStream.encodeBase64(): String { val w = ByteArrayOutputStream() val encoded = Base64.getEncoder().wrap(w) transferTo(encoded) encoded.close() return w.asUtf8() } /** Deflate an input stream */ fun InputStream.deflate(): DeflaterInputStream = DeflaterInputStream(this) /** Inflate an input stream */ fun InputStream.inflate(): InflaterInputStream = InflaterInputStream(this) /** Read an input stream as UTF8 text */ fun InputStream.readText(): String = this.reader().readText() /* ----- Throwable ----- */ fun Throwable.fmt(): String = buildString { append(message ?: this@fmt::class.simpleName) var cause = cause while (cause != null) { append(": ") append(cause.message ?: cause::class.simpleName) cause = cause.cause } } fun Throwable.fmtLog(logger: Logger) { logger.error(this.fmt()) logger.trace("", this) } /* ----- Logger ----- */ inline fun Logger.debug(lambda: () -> String) { if (isDebugEnabled) debug(lambda()) } inline fun Logger.trace(lambda: () -> String) { if (isTraceEnabled) trace(lambda()) } /* ----- KTOR ----- */ fun ApplicationCall.uuidPath(name: String): UUID { val value = parameters[name]!! try { return UUID.fromString(value) } catch (e: Exception) { throw badRequest("UUID uri component malformed: ${e.message}", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // TODO better error ? } } fun ApplicationCall.longPath(name: String): Long { val value = parameters[name]!! try { return value.toLong() } catch (e: Exception) { throw badRequest("Long uri component malformed: ${e.message}", TalerErrorCode.GENERIC_PARAMETER_MALFORMED) // TODO better error ? } } /* ----- Payto ----- */ fun ibanPayto(iban: String, name: String? = null): IbanPayto { return Payto.parse(IbanPayto.build(iban, null, name)).expectIban() }libeufin-1.6.8/libeufin-common/src/main/resources/0000775000175000017500000000000015236145704022362 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/resources/version.txt0000664000175000017500000000002315122266731024601 0ustar grothoffgrothoffv1.0.6-git-942f58a3libeufin-1.6.8/libeufin-common/src/main/resources/xsd/0000775000175000017500000000000015236145704023160 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_types_H004.xsd0000664000175000017500000025364415122266731026720 0ustar grothoffgrothoff ebics_types_H004.xsd enthält einfache Typdefinitionen für EBICS. Datentyp für EBICS-Versionsnummern. Datentyp für EBICS-Revisionsnummern. Datentyp für Versionsnummern zur Verschlüsselung. Datentyp für Versionsnummern zur Elektronischen Unterschrift (EU). Datentyp für Versionsnummern zur Authentifikation. Datentyp für Versionsnummern zur Verschlüsselung, Signatur und Authentifkation. Datentyp für Währungen (Grundtyp). dreistelliger Währungscode gemäß ISO 4217. Afghanistan: Afghani Albanien: Lek Armenien: Dram Niederländische Antillen: Gulden Angola: Kwanza Argentinien: Peso Australien: Dollar Aruba: Florin Aserbaidschan: Manat Bosnien und Herzegowina: Konvertible Mark Barbados: Dollar Bangladesch: Taka Bulgarien: Lew Bahrain: Dinar Bermuda: Dollar Brunei: Dollar Bolivien: Boliviano Brasilien: Real Bahamas: Dollar Bhutan: Ngultrum Botswana: Pula Weißrussland (Belarus): Rubel Belize: Dollar Kanada: Dollar Demokratische Republik Kongo: Franc Schweiz: Franken Chile: Peso China (Volksrepublik): Renminbi Yuan Kolumbien: Peso Costa Rica: Colón Serbien: Dinar Kuba: Peso Kap Verde: Escudo Zypern (griechischer Teil): Pfund Tschechien: Krone Dschibuti: Franc Dänemark: Krone Dominikanische Republik: Peso Algerien: Dinar Ecuador (bis 2000): Sucre Estland: Krone Ägypten: Pfund Äthiopien: Birr Europäische Währungsunion: Euro Fidschi: Dollar Falklandinseln: Pfund Vereinigtes Königreich: Pfund Georgien: Lari Ghana: Cedi Gibraltar: Pfund Gambia: Dalasi Guinea: Franc Guatemala: Quetzal Guyana: Dollar Hongkong: Dollar Honduras: Lempira Kroatien: Kuna Haiti: Gourde Ungarn: Forint Indonesien: Rupiah Israel: Schekel Indien: Rupie Irak: Dinar Iran: Rial Island: Krone Jamaika: Dollar Jordanien: Dinar Japan: Yen Kenia: Schilling Kirgisistan: Som Kambodscha: Riel Komoren: Franc Nordkorea: Won Südkorea: Won Kuwait: Dinar Kaimaninseln: Dollar Kasachstan: Tenge Laos: Kip Libanon: Pfund Sri Lanka: Rupie Liberia: Dollar Lesotho: Loti Litauen: Litas Lettland: Lats Libyen: Dinar Marokko: Dirham Moldawien: Leu Madagaskar: Franc Mazedonien: Denar Myanmar: Kyat Mongolei: Tugrik Macau: Pataca Mauretanien: Ouguiya Malta: Lira Mauritius: Rupie Malediven: Rufiyaa Malawi: Kwacha Mexiko: Peso Malaysia: Ringgit Mosambik: Metical Namibia: Dollar Nigeria: Naira Nicaragua: Cordoba Oro Norwegen: Krone Nepal: Rupie Neuseeland: Dollar Oman: Rial Panama: Balboa Peru: Nuevo Sol Papua-Neuguinea: Kina Philippinen: Peso Pakistan: Rupie Polen: Zloty Paraguay: Guaraní Katar: Riyal Rumänien: Leu Russland: Rubel Ruanda: Franc Saudi-Arabien: Riyal Salomonen: Dollar Seychellen: Rupie Sudan: Dinar Schweden: Krone Singapur: Dollar St. Helena: Pfund Slowenien: Tolar Slowakei: Krone Sierra Leone: Leone Somalia: Schilling Suriname: Dollar São Tomé und Príncipe: Dobra El Salvador: Colón Syrien: Pfund Swasiland: Lilangeni Thailand: Baht Tadschikistan: Somoni Turkmenistan: Manat Tunesien: Dinar Tonga: Pa'anga Türkei: Lira Türkei: Neue Lira (ab 2005) Trinidad und Tobago: Dollar Taiwan: Dollar Tansania: Schilling Ukraine: Hrywnja Uganda: Shilling USA: Dollar Uruguay: Peso Usbekistan: Sum Venezuela: Bolivar Vietnam: Dong Vanuatu: Vatu Samoa: Tala Zentralafrikanische Wirtschafts- und Währungsunion: CFA-Franc Ostkaribische Währungsunion: Dollar Westafrikanische Wirtschafts- und Währungsunion: CFA-Franc Neukaledonien: CFP-Franc Spezialcode für Testzwecke; keine existierende Währung keine Währung Jemen: Rial Südafrika: Rand Sambia: Kwacha Simbabwe: Dollar Datentyp für einen Betragswert (ohne Währung). Datentyp für einen Betrag inkl. Währungscode-Attribut (Default = "EUR"). Währungscode, Default="EUR". Currency code, default setting is "EUR". Datentyp für die Transaktions-ID. Datentyp für Nonces. Datentyp für die Instituts-ID. Datentyp für die Host-ID. Datentyp für die Kundenprodukt-ID. Datentyp für das Sprachkennzeichen des Kundenprodukts. Datentyp für allgemeine Auftragsarten (Grundtyp). Listentyp für allgemeine Auftragsarten. Datentyp für zulässige Auftragsarten im EBICS-Kontext. Senden der Public Keys für Authentifikation und Verschlüsselung, bankfachlich signiert mit FTAM-Signaturschlüssel Senden der Public Keys zur Authentifikation und zur Verschlüsselung Abholen der Public Keys der Bank Ändern der Public Keys zur Authentifikation und zur Verschlüsselung Abholen Bankparameter für internetbasierten Standard Abholen VEU Übersicht Abholen VEU Auftragsdaten (Daten-trägerbegleitzettel) Abholen VEU Auftragsdaten ( Transakti-onsdetails gemäß Parametervorgabe) Senden EU zu bestehendem VEU-Auftrag Senden Stornierung für bestehenden VEU-Auftrag Abholen Konfigurationsdaten des Teilnehmers Abholen Übersicht zu abrufbaren Aufträgen VEU-Übersicht abholen VEU-Status abrufen VEU-Transaktion-Details abrufen EU hinzufügen VEU-Stornierung Senden Importakkreditiv Änderung Senden Exportakkreditive Senden Import-Akkreditive Avisierung Abholen Import-Akkreditive AWV-Meldung senden AZV im Magnetbandformat senden (Satzlänge variabel) AZV im Diskettenformat senden AZV im Magnetbandformat senden (Satzlängenfeld 2 Bytes) AZV im Magnetbandformat senden (Satzlängenfeld 4 Bytes) Abholen Devisenhandelsbestätigung Senden Devisenhandelsbestätigung Eilauftrag (IZV im DTAUS0-Format) senden IZV-Datei abholen MCV-Datei abholen (Format analog MCV) Zahlungsverkehrsdateien von Service-Rechenzentren senden MC2-Datei abholen (Format analog MC2) MC4-Datei abholen (Format analog MC4) Exportakkreditive abholen Senden electronic-cash Lastschriftdatei Senden Maestro-Lastschriftdatei EDIFACT abholen ASCII EDIFACT abholen EBCDIC Ausführungsanzeige (Exportinkasso) Bank an Kunde abholen Senden Exportinkassi EDIFACT senden ASCII EU-Standardüberweisung (Zahlungsart 13) im Magnetbandformat (Satzlängenfeld 4 Bytes) Einreichung von EDIFACT-Lastschriften EDIFACT senden EBCDIC EU-Standardüberweisung (Zahlungsart 13) Taggleiche grenzüberschreitende Euro-Eilzahlung Abholen Garantien Senden Garantien GeldKarte-Umsatz senden (Datenaufbau gemäß GeldKarte-Spezifikation) Internationale Lastschriften Abholen Importinkassi Senden Importinkassi Internationaler Zahlungsverkehr Inlandszahlungsverkehrsauftrag senden (nur Gutschriften) Inlandszahlungsverkehrsauftrag senden (nur Lastschriften) Inlandszahlungsverkehrsauftrag senden Abholen Magnetband-Datei aus optischer Beleglesung Senden IZV-Magnetbandformat (Satzlängenfeld 4 Bytes) Senden IZV-Magnetbandformat (Satzlängenfeld 2 Bytes) Senden IZV-Magnetbandformat (Satzlänge variabel) Senden POZ-Datei Rücklastschrift an Kunde Request for Transfer Abholen Swift-Tagesauszüge Abholen kurzfristige Vormerkposten Abholen Wertpapierabrechnung Abholen Wertpapierausführungsanzeige Abholen Depotaufstellung Abholen sonstige WP-Umsätze Initialisierung der bankfachlichen EU des Teilnehmers. Abholen Kundenprotokoll Senden Public Key zur Unterschriftenverifizierung Änderung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung Sperren der Zugangsberechtigung Abholen Public Key der Bank zur Verschlüsselung EDIFACT-FINPAY senden Informationen von Zentralstellen ec-Karten-Sperrdatei Teilausnutzung Importakkreditiv (Kreditinstitut an Kunde) Auftragsart für elektronische Kontoauszüge Barzahlungskarte Devisenkursinformationen abholen (Euro) Abholen Devisenmarktinformationen Abholen Devisenswapinformationen ESG-Datei für Elektronische Zweitunterschrift abholen ESP-Datei für Elektronische Zweitunterschrift senden Abholen/Senden beliebige Datei Freie Textdatei senden/abholen Abholen Institutsbestätigungsdatei (Komplettbestand) Abholen Institutsbestätigungsdatei (Komplettbestand weitere Datei) Abholen Institutsbestätigungsdatei (tägliches Update) Senden Institutskonten (Komplettbestand begrenzt auf 170 MB) Senden Institutskonten (tägliches Update) Senden Institutskonten (Komplettbestand weitere Datei) KTOHIN: Automatisiertes Verfahren für die Änderung von Kontonummern und Bankleitzahlen KTORUECK: Automatisiertes Verfahren für die Änderung von Kontonummern und Bankleitzahlen Kontenkonzentration und Saldenausgleich Senden/Abholen Testdatei (ASCII) Updates abholen Datentyp für eine Auftragsnummer lt. DFÜ-Abkommen. Datentyp für ein einzelnes Auftragsattributkennzeichen (Grundtyp). Datentyp für Auftragsattributkennzeichen gemäß DFÜ-Abkommen. Auftragsdaten mit Unterschrift, ZIP-komprimiert, hybrid verschlüsselt Unterschrift, ZIP-komprimiert, hybrid verschlüsselt Auftragsdaten ohne Unterschrift, ZIP-komprimiert, hybrid verschlüsselt Datentyp für das Sicherheitsmedium. Datentyp für die Segmentnummer. Datentyp für die Gesamtsegmentanzahl. Datentyp für die Gesamtanzahl der Einzelauftraginfos. Datentyp für die Transaktionsphase. Transaktionsinitialisierung Auftragsdatentransfer Quittungstransfer Datentyp für Zeitstempel. Datentyp für Datumswerte. Datentyp für eine Teilnehmer-ID. Datentyp für eine Kunden-ID. Datentyp für eine Konten-ID. Datentyp für eine Kontonummer (national/international). Datentyp für eine Bankleitzahl (national/international). Datentyp für ein nationales BLZ-Präfix. Datentyp für eine Kontonummer (freies Format). Datentyp für eine Bankleitzahl (freies Format). Datentyp für den Namen des Kontoinhabers. Datentyp für die Kontobeschreibung. Datentyp für Kontoinformationen. Kontonummer (deutsches Format und/oder international als IBAN). Account number (German format and/or international=IBAN). Ist die Kontonummer im deutschen Format (international=false) oder im internationalen Format (international=true, IBAN) angegeben? Is the account number specified using the national=German or the international=IBAN format? Kontonummer im freien Format. Account in free format. Formatkennung. Format identification. Bankleitzahl (deutsches Format und/oder international als SWIFT-BIC). Bank code (German and/or international=SWIFT-BIC). Ist die Bankleitzahl im deutschen Format (international=false, BLZ) oder im internationalen Format (international=true, SWIFT-BIC) angegeben? Is the bank code specified using the national=German or the international SWIFT-BIC format? nationales Präfix für Bankleitzahlen. National=German prefix for bank codes. Bankleitzahl im freien Format. Bank code in free format. Formatkennung. Format identification. Name des Kontoinhabers. Name of the account holder. Währungscode für dieses Konto, Default=EUR. Currency code for this account, Default=EUR. Kontobeschreibung. Description of this account. Datentyp für die Rolle eines Zahlungsverkehrskontos innerhalb einer Transaktion. Auftraggeberkonto Empfängerkonto Gebührenkonto andere Kontorolle Datentyp für die Rolle eines Kreditinstituts innerhalb einer Transaktion (repräsentiert durch die Bankleitzahl). Auftraggeberbank Empfängerbank Korrespondenzbank andere Bankrolle Datentyp für die Rolle eines Kontoinhabers innerhalb einer Transaktion. Auftraggeber Empfänger Überbringer, Einreicher andere Rolle Datentyp für Kontoinformationen inkl. der Eigenschaftszuordnung innerhalb einer Zahlungstransaktion. Kontonummer (deutsches Format oder international als IBAN). Kontonummer (Account number (German format and/or international = IBAN). Rolle des Kontos innerhalb der Zahlungstransaktion. Role of the account during the transaction. Textuelle Beschreibung der Funktion, falls role=Other ausgewählt wird. Textual description of the role the account place during the transaction; use only if the corresponding 'role' field is set to 'other'. Ist die Kontonummer im deutschen Format (international=false) oder im internationalen Format (international=true, IBAN) angegeben? Is the account number specified using the national=German or the international=IBAN format? Kontonummer im freien Format. Account in free format. Rolle des Kontos innerhalb der Zahlungstransaktion. Role of the account during the transaction. Textuelle Beschreibung der Funktion, falls role=Other ausgewählt wird. Textual description of the role the account place during the transaction; use only if the corresponding 'role' field is set to 'other'. Formatkennung. Format identification. Bankleitzahl (deutsches Format oder international als SWIFT-BIC). Bank code (German and/or international=SWIFT-BIC). Rolle des kontoführenden Instituts innerhalb der Zahlungstransaktion. Role of the bank during the transaction. Textuelle Beschreibung der Funktion, falls role=Other ausgewählt wird. Textual description of the role the account place during the transaction; use only if the corresponding 'role' field is set to 'other'. Ist die Bankleitzahl im deutschen Format (international=false, BLZ) oder im internationalen Format (international=true, SWIFT-BIC) angegeben? Is the bank code specified using the national=German or the international=SWIFT-BIC format? nationales Präfix für Bankleitzahlen. National=German prefix for bank codes. Bankleitzahl im freien Format. Bank code in free format. Rolle des kontoführenden Instituts innerhalb der Zahlungstransaktion. Role of the bank during the transaction. Textuelle Beschreibung der Funktion, falls role=Other ausgewählt wird. Textual description of the role the account place during the transaction; use only if the corresponding 'role' field is set to 'other'. Formatkennung. Format identification. Name des Kontoinhabers. Name of the account holder. Rolle des Kontoinhabers innerhalb der Zahlungstransaktion. Role of the account holder during the transaction. Textuelle Beschreibung der Rolle, falls role=Other ausgewählt wird. Textual description of the role the account holder place during the transaction; use only if the corresponding 'role' field is set to 'other'. Währungscode für dieses Konto, Default=EUR. Currency code for this account, Default=EUR. Kontobeschreibung. Description of this account. Datentyp für binäre Signaturdaten (komprimiert, verschlüsselt und kodiert). Datentyp für binäre Auftragsdaten (komprimiert, verschlüsselt und kodiert). ISO-Code zur Länderkennzeichnung. ISO-Code to identify the country. Datentyp für das Dateiformat. ISO-Code zur Länderkennzeichnung (EU für Europa) ISO-Code to identify the country (EU for Europe) Datentyp für Berechtigungsklassen zur Elektronischen Unterschrift. Einzelunterschrift Erstunterschrift Zweitunterschrift Transportunterschrift Listentyp für Berechtigungsklassen zur Elektronischen Unterschrift. Datentyp für Hashfunktionen. Datentyp für Hashwerte. Version des Signaturverfahrens. Version of the algorithm used for signature creation. Datentyp für kryptographische Unterschriften. Datentyp für symmetrische Schlüssel. Datentyp für Hashwerte und Attribute von öffentlichen Schlüsseln. Hashalgorithmus. Name of the used hash algorithm. Datentyp für die Exponent-Modulus-Darstellung eines öffentlichen RSA-Schlüssels. Zeitpunkt der Generierung des Schlüssels. Datentyp für die Darstellung eines öffentlichen RSA-Schlüssels als Exponent-Modulus-Kombination oder als X509-Zertifikat. Darstellung als Exponent-Modulus-Kombination. Datentyp für öffentliche Verschlüsselungsschlüssel. Version des Verschlüsselungsverfahrens. Datentyp für öffentlichen Authentfikationsschlüssel. Version des Authentifikationsverfahrens. Datentyp für öffentliche bankfachliche Schlüssel. Data type for public authorisation (ES) key. Version des EU-Signaturverfahrens. ES-Version. Datentyp für öffentlichen Schlüssel zur Authentisierung. Data type for public for identification and authentication. Version des Authentifikationsverfahrens. Authentication version. Datentyp für öffentlichen Verschlüsselungsschlüssel. Data type for encryption key. Version des Verschlüsselungsverfahrens. Encryption Version. Datentyp für die Zertifikate hinsichtlich der "bank-technical signature for authorisation" (ES). Data Type for Certificates for the bank-technical signature for authorisation (ES) Datentyp für Antwortcodes. Datentyp für den Erklärungstext zum Antwortcode. Datentyp für Quittierungscodes. Datentyp für Kunden-, Teilnehmer-, Straßen- oder Ortsnamen. Datentyp für den Transfertyp (Upload/Download). Auftragsdaten werden bei der Anfrage transferiert. Auftragsdaten werden bei der Antwort transferiert. Datentyp für die Beschreibung von Auftragsarten. Datentyp für das Auftragsformat. Datentyp für den Teilnehmerstatus. generische Schlüssel-Wert-Parameter. Generic key value parameters. Name des Parameters. Name of the parameter (= key). Wert des Parameters. Value of the parameter. XML-Typ des Parameterwerts (Vorschlag für default ist string). XML type of the parameter value (Proposal for default is string). Datentyp für die Darstellung von Information zur Verschlüsselung der Auftragsdaten. Data type for the modelling of information regarding the encryption of signature and order data. Hashwert des öffentlichen Verschlüsselungsschlüssels des Empfängers der verschlüsselten Auftragsdaten. Hash value of the public encryption key owned by the receipient of the encrypted order data. Version des Verschlüsselungsverfahrens. Version of the encryption method. Asymmetrisch verschlüsselter symmetrischer Transaktionsschlüssel. The asymmetrically encrypted symmetric transaction key. Authentifikationssignatur. Authentication signature. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_orders_H004.xsd0000664000175000017500000026140015122266731027037 0ustar grothoffgrothoff ebics_orders_H004.xsd enthält auftragsbezogene Referenzelemente und auftragsbezogene Typdefinitionen für EBICS. ebics_orders_H004.xsd contains order-based reference elements and order-based type definitions for EBICS. XML-Klartext-Auftragsdaten für neue EBICS-Auftragsarten. Order data in XML format for new EBICS order types. Auftragsdaten für Auftragsart HAA (Antwort: abrufbare Auftragsarten abholen). Order data for order type HAA (response: receive downloadable order types). Auftragsdaten für Auftragsart HCA (Anfrage: Änderung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung). Order data for order type HCA (request: replace user's keys for authentication and encryption). Auftragsdaten für Auftragsart HCS (Anfrage: Schlüsselwechsel aller Schlüssel). Order data for order type HCS (request: replace all keys). Auftragsdaten für Auftragsart HIA (Anfrage: Initialisierung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung). Order data for order type HIA (request: initialise user's keys for authentication and encryption). Order data for order type H3K (request: initialise all three user's keys). Auftragsdaten für Auftragsart H3K (Anfrage: Initialisierung aller drei Teilnehmerschlüssel). Auftragsdaten für Auftragsart HSA (Anfrage: Initialisierung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung, bankfachlich signiert mit Signaturschlüssel aus FTAM). Order data for order type HSA (request: initialise the user's keys for authentication and encryption; this request is signed using the user's FTAM signature key). Auftragsdaten für Auftragsart HKD (Antwort: Kunden- und Teilnehmerdaten des Kunden abholen). Order data for order type HKD (response: receive customer-based information on the customer and the customer's users). Schlüssel zur Identifikation des Kontos. Key for the identification of the account. Referenz auf die Konten-Identifikationsschlüssel. Reference to the account identification keys. Auftragsdaten für Auftragsart HPB (Antwort: Transfer der Bankschlüssel). Order data for order type HPB (response: receive bank's public keys). Auftragsdaten für Auftragsart HPD (Antwort: Bankparameter abholen). Order data for order type HPD (response: receive bank parameters). Auftragsdaten für Auftragsart HTD (Antwort: Kunden- und Teilnehmerdaten des Teilnehmers abholen). Order data for order type HTD (response: receive user-based information on the user's customer and the user herself/himself). Schlüssel zur Identifikation des Kontos. Key for the identification of the account. Referenz auf die Konten-Identifikationsschlüssel. Reference to the account identification keys. Auftragsdaten für Auftragsart HVD (Antwort: VEU-Status abrufen). Order data for order type HVD (response: receive the status of an order currently stored in the distributed signature processing unit). Auftragsdaten für Auftragsart HVS (Anfrage: VEU-Storno). Order data for order type HVS (request: reject an order currently stored in the distributed signature processing unit). Auftragsdaten für Auftragsart HVT (Antwort: VEU-Transaktionsdetails abrufen). Order data for order type HVT (response: receive transaction details of an order currently stored in the distributed signature processing unit). Auftragsdaten für Auftragsart HVU (Antwort: VEU-Übersicht abholen). Order data for order type HVU (response: receive summary of orders currently stored in the distributed signature processing unit). Auftragsdaten für Auftragsart HVZ (Antwort: VEU-Übersicht mit Zusatzinformationen abholen). Order data for order type HVZ (response: receive summary of orders currently stored in the distributed signature processing unit with additional information). XML-Strukturen für bankfachliche Elektronische Unterschriften (EUs). contains the digital signatures. enthält die EU des Kreditinstituts. contains the digital signatures. zusätzliche Auftragsparameter, die zur Ausführung des Auftrags notwendig sind. additional order parameters required to execute the order. zusätzliche Auftragsparameter für Auftragsart HVD. additional order parameters for order type HVD. zusätzliche Auftragsparameter für Auftragsart HVE. additional order parameters for order type HVE. zusätzliche Auftragsparameter für Auftragsart HVS. additional order parameters for order type HVS. zusätzliche Auftragsparameter für Auftragsart HVT. additional order parameters for order type HVT. zusätzliche Auftragsparameter für Auftragsart HVU. additional order parameters for order type HVU. zusätzliche Auftragsparameter für Auftragsart HVZ. additional order parameters for order type HVZ. zusätzliche Auftragsparameter für Auftragsart FUL. additional order parameters for order type FUL. zusätzliche Auftragsparameter für Auftragsart FDL. additional order parameters for order type FDL. zusätzliche Auftragsparameter für Standard-Auftragsarten. additional order parameters for standard order types. zusätzliche Auftragsparameter für beliebige Auftragsarten. additional order parameters for generic order types. Standard-Requeststruktur für HVx-Aufträge (HVD, HVT, HVE, HVS). Standard request structure for HVx orders (HVD, HVT, HVE, HVS). Standard-Requestdaten. Standard request data. Kunden-ID des Einreichers des ausgewählten Auftrags. Customer ID of the presenter of the selected order. Auftragsart des ausgewählten Auftrags. Order type of the selected order. Identifizierung des Dateiformats im Falle von FUL/FDL Identification of the file format in the case of FUL/FDL Auftragsnummer des ausgewählten Auftrags. Order ID of the selected order. Marker für Elemente und deren Substrukturen, die authentifiziert werden sollen. Marker for elements and their substructures that are to be authenticated. Das zugehörige Element ist mitsamt seinen Unterstrukturen zu authentifizieren. The element (and its substructures) that belongs to this attribute is to be authenticated. optionales Support-Flag, Default = true. optional support flag, default = true. Wird die Funktion unterstützt? Is this function supported? EU-Berechtigungsinformationen. permission information of a user's digital signature. Unterschriftsberechtigung des Teilnehmers, der unterzeichnet hat. Authorisation level of the user that signed the order. Datentyp für Signaturdaten des Kreditinstituts beim EU-Transfer. Data type for digital signature data transferred using EBICS. bankfachliche Elektronische Unterschrift. Digital signature (either autorising an order or applied for transportation). Datentyp für Vorabprüfung (Anfrage). Data type for pre-validation (request). Client sendet den Hashwert der Auftragsdaten und alle weiteren Daten, die er im Rahmen der Vorabprüfung zur Verfügung stellen will Hashwert der zu übertragenden Auftragsdatendatei für die Vorabprüfung. Kontoangabe zur Kontoberechtigung für diesen Zahlungsverkehrsauftrag bei der Vorabprüfung. Datentyp für Kontenberechtigungsdaten zur Vorabprüfung. Summe der Zahlungsverkehrsaufträge dieses Kontos für die Höchstbetragsprüfung der EU. Total sum of the ordered payments regarding this account in order to check the maximum amount limit of the signature permission grades. Datentyp für den Transfer von Auftragsdaten (Anfrage). Transaktionsphase? Initialisierungsphase: Transfer der Signaturdaten (EUs) und des Transaktionsschlüssels. Information zur Verschlüsselung der Signatur- und Auftragsdaten. enthält Signaturdaten (EUs). Transferphase: Transfer von Auftragsdaten. enthält Auftragsdaten. Datentyp für den Transfer von Auftragsdaten (Antwort). Transfer des Sitzungsschlüssels und (optional) der Signaturdaten (EUs); nur in der Initialisierungsphase anzugeben. Information zur Verschlüsselung der Signatur- und Auftragsdaten. enthält Signaturdaten (EUs). enthält Auftragsdaten. Datentyp für den Transfer von Transferquittungen. Quittierungscode für Auftragsdatentransfer. Datentyp für den Transfer von Antwortcodes. Antwortcode für den vorangegangenen Transfer. Zeitstempel der letzten Aktualisierung der Bankparameter. Datentyp für Auftragsdaten für Auftragsart HAA (Antwort: abrufbare Auftragsarten abholen). Liste von Auftragsarten, für die Daten bereit stehen. Datentyp für Auftragsdaten für Auftragsart HCA (Anfrage: Änderung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung). öffentlicher Authentifikationsschlüssel. öffentlicher Verschlüsselungsschlüssel. Kunden-ID. Teilnehmer-ID. Datentyp für Auftragsdaten für Auftragsart HCS (Anfrage: Schlüsselwechsel aller Schlüssel). öffentlicher Authentifikationsschlüssel. öffentlicher Verschlüsselungsschlüssel. Kunden-ID. Teilnehmer-ID. Datentyp für Auftragsdaten für Auftragsart HIA (Anfrage: Initialisierung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung). öffentlicher Authentifikationsschlüssel. öffentlicher Verschlüsselungsschlüssel. Kunden-ID. Teilnehmer-ID. Datentyp für Auftragsdaten für Auftragsart H3K (Anfrage: Initialisierung aller drei Teilnehmerschlüssel). Order type for order data H3K (request: initialise all three user's keys). Key for electronic Signature Signaturschlüssel. Authentication key Authentifikationsschlüssel. Encryption key Verschlüsselungsschlüssel. PartnerID. Kunden-ID. UserID. Teilnehmer-ID. Datentyp für Auftragsdaten für Auftragsart HSA (Anfrage: Initialisierung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung, bankfachlich signiert mit FTAM-Schlüssel). öffentlicher Authentifikationsschlüssel. öffentlicher Verschlüsselungsschlüssel. Kunden-ID. Teilnehmer-ID. Datentyp für Auftragsdaten für Auftragsart HKD (Antwort: Kunden- und Teilnehmerdaten des Kunden abholen). Order data for order type HKD (response: receive customer based information on the customer and the customer's user. Kundendaten. Customer data. Teilnehmerdaten. User data. Datentyp für Auftragsdaten für Auftragsart HPB (Antwort: Transfer der Bankschlüssel). öffentlicher Authentifikationsschlüssel. öffentlicher Verschlüsselungsschlüssel. öffentlicher EU-Signaturschlüssel. Banksystem-ID. Datentyp für Auftragsdaten für Auftragsart HPD (Antwort: Bankparameter abholen). Zugangsparameter. Protokollparameter. Datentyp für HPD-Zugangsparameter. institutsspezifische IP-Adresse/URL. Gültigkeitsbeginn für die angegebene URL/IP. Institutsbezeichnung. Banksystem-ID. Datentyp für HPD-Protokollparameter. Data type for HPD's parameters regarding the EBICS protocol. Spezifikation unterstützter Versionen. Specification of supported versions.. Parameter zur Recovery-Funktion (Wiederaufnahme abgebrochener Übertragungen). Parameter denoting the recovery function (recovery of aborted transmissions). Parameter zur Vorabprüfung (über die Übermittlung der EU hinaus). Parameter denoting the pre-validation (beyond transmission of signatures). Optionales Support-Flag, Default = true. Optional support flag, default = true. Parameter zur X.509-Funktionalität. Parameter denoting the X.509 functionality. Sind die X.509-Daten der Teilnehmer serverseitig persistent gespeichert? Will the user's X.509 data be stored persistently on server side? Parameter zum Download von Kunden- und Teilnehmerdaten (Auftragsarten HKD/HTD). Parameter denoting the download of customer and user data (order types HKD/HTD). Parameter zum Abruf von Auftragsarten, zu denen Auftragsdaten verfügbar sind (Auftragsart HAA). Parameter denoting the reception of order types which provides downloadable order data (order type HAA). Datentyp für HPD-Versionsinformationen. unterstützte EBICS-Protokollversionen (H...). unterstützte Versionen der Authentifikation (X...). unterstützte Versionen der Verschlüsselung (E...). unterstützte EU-Versionen (A...). Datentyp für Auftragsdaten für Auftragsart HTD (Antwort: Kunden- und Teilnehmerdaten des Teilnehmers abholen). Kundendaten. Customer data. Teilnehmerdaten. User data. Datentyp für Auftragsdaten für Auftragsart HVD (Antwort: VEU-Status abrufen). Hashwert der Auftragsdaten. Hash value of the order data. Begleitzettel/"Displaydatei" (entspricht der Dateianzeige im Kundenprotokoll gemäß DFÜ-Abkommen). Accompanying ticket/"display file" (corresponds to the display file of the customer's journal according to the document "DFÜ-Abkommen"). Kann die Auftragsdatei im Originalformat abgeholt werden? (HVT mit completeOrderData=true) Can the order file be downloaded in the original format? (HVT with completeOrderData=true) Größe der unkomprimierten Auftragsdaten in Bytes. Size of the uncompressed order data (byte count). Können die Auftragsdetails als XML-Dokument HVTResponseOrderData abgeholt werden? (HVT mit completeOrderData=false) Can the order details be downloaded as XML document HVTResponseOrderData? (HVT with completeOrderData=false) bankfachliche Elektronische Unterschrift des Kreditinstituts über Hashwert und Displaydatei. Digital Signature issued by the bank, covering the hash value and the accompanying ticket. Informationen zu den bisherigen Unterzeichnern. Information about the already existing signers. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVD. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVE. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVS. Datentyp für Auftragsdaten für Auftragsart HVS (Anfrage: VEU-Storno). Hashwert der Auftragsdaten des stornierten Auftrags. Datentyp für Antwort mit Einzelauftraginfos für Auftragsart HVT (Antwort VEU-Transaktionsdetails abrufen mit completeOrderData="false"). Gesamtanzahl der Einzelaufträge für den Auftrag. Total number of order infos for the order. Einzelauftragsinfos. Particular order content information requested for display matters. Datentyp für HVT-Konteninformationen. Data type for account information regarding order type HVT. Datentyp für HVT-Auftragsinformationen. Auftragsformat (z.B. DTAZV). kontobezogene Details des Auftrags (Auftraggeber, Empfänger etc.). Ausführungsdatum. Betrag. Gutschrift (isCredit = "true") oder Lastschrift (isCredit = "false")? Währungscode. Textfeld zur weiteren Beschreibung der Transaktion (Verwendungszweck, Auftragsdetails, Kommentar). Beschreibungstyp. Verwendungszweck Auftragsdetails Kommentar Datentyp für HVT-Auftragsflags. Sollen die Transaktionsdetails als Einzelauftragsinfos (completeOrderData=false) oder als komplette Originaldaten (completeOrderData=true) übertragen werden? (Vorschlag für Default=false) Are the transaction details so be transmitted as particular order content information requested for display matters or in complete order data file form? (Proposal for Default=false) Limit für die zu liefernden Transaktionsdetails, bei completeOrderData=false maximale Anzahl zu liefernder Einzelauftragsinfos, 0 für unbegrenzt (Vorschlag für Default=100). Limit for the transaction details to be transmitted; if completeOrderData=false, maximum number of details of a particular order; 0 for unlimited number of details (Proposal for Default=100). Offset vom Anfang der Originalauftragsdatei für die zu liefernden Transaktionsdetails, bei completeOrderData=false bezogen auf laufende Nummer des Einzelauftrags (Vorschlag für Default=0). Offset position in the original order file which marks the starting point for the transaction details to be transmitted; applies to the sequential number of a particular order if completeOrderData=false (Proposal for Default=0). Datentyp für zusätzliche Auftragsparameter für Auftragsart HVT. Data type for additional order parameters for order type HVT. spezielle Flags für HVT-Aufträge. Special order flags for orders of type HVT. Generische Schlüssel-Wert-Parameter Generic key-value parameters Datentyp für Auftragsdaten für Auftragsart HVU (Antwort: VEU-Übersicht abholen). Auftragsinformationen. Datentyp für HVU-Auftragsdetails. Auftragsart lt. DFÜ-Abkommen des ausgewählten Auftrags. Type of the order. Identification of the file format in the case of FUL/FDL Auftragsnummer lt. DFÜ-Abkommen des ausgewählten Auftrags. Größe der unkomprimierten Auftragsdaten in Bytes. Informationen zu den Unterschriftsmodalitäten. Informationen zu den bisherigen Unterzeichnern. Informationen zum Einreicher. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVU. Liste von Auftragsarten, für die zur Unterschrift vorliegende Aufträge abgerufen werden sollen; falls nicht angegeben, werden sämtliche für den Teilnehmer unterschriftsfähigen Aufträge abgerufen. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVZ. Liste von Auftragsarten, für die zur Unterschrift vorliegende Aufträge abgerufen werden sollen; falls nicht angegeben, werden sämtliche für den Teilnehmer unterschriftsfähigen Aufträge abgerufen. List of order types that the orders ready to be signed by the requesting user should match; if not specified, a list of all orders ready to be signed by the requesting user is returned. Datentyp für Informationen zu den HVU-Unterschriftsmodalitäten. Ist der Auftrag unterschriftsreif ("true") oder bereits vom Teilnehmer unterschrieben ("false")? Anzahl der insgesamt zur Freigabe erforderlichen EUs. Anzahl der bereits geleisteten EUs. Datentyp für Informationen zum Ersteller eines HVU-Auftrags. Kunden-ID des Einreichers. Teilnehmer-ID des Einreichers. Name des Einreichers. Zeitstempel der Einreichung (d.h. der Übertragung der Auftragsdatei). Datentyp für Auftragsdaten für Auftragsart HVZ (Antwort: VEU-Übersicht mit Zusatzinformationen abholen). Order data for order type HVZ (response: receive summary of orders currently stored in the distributed signature processing unit with additional informations). Auftragsinformationen. Summary of order information. Datentyp für HVZ-Auftragsdetails. Auftragsart lt. DFÜ-Abkommen des ausgewählten Auftrags. Type of the order. Identification of the file format in the case of FUL/FDL Auftragsnummer lt. DFÜ-Abkommen des ausgewählten Auftrags. ID number of the order. Hashwert der Auftragsdaten. Hash value of the order data. Kann die Auftragsdatei im Originalformat abgeholt werden? (HVT mit completeOrderData=true). Can the order file be downloaded in the original format? (HVT with completeOrderData=true) Größe der unkomprimierten Auftragsdaten in Bytes. Size of uncompressed order data in Bytes. Können die Auftragsdetails als XML-Dokument HVTResponseOrderData abgeholt werden? (HVT mit completeOrderData=false). Can the order details be downloaded as XML document HVTResponseOrderData? (HVT with completeOrderData=false) Zusätzliche Auftragsdetails nur für Zahlungsaufträge. Order details related to payment orders only. Informationen zu den Unterschriftsmodalitäten. Information regarding the signing modalities of the order. Informationen zu den bisherigen Unterzeichnern. Information regarding the users who already signed the order. Informationen zum Einreicher. Information regarding the originator of the order. Standard-Requeststruktur für HVx-Aufträge (HVD, HVT, HVE, HVS). Standard structure for HVZ OrderDetails related to payment orders Anzahl der Zahlungssätze über alle logische Dateien entsprechend Dateianzeige. Total transaction number for all logical files (from dispay file). Summe der Beträge über alle logische Dateien entsprechend Dateianzeige. Total transaction amount for all logical files (from dispay file). Nur Gutschriften (isCredit = "true") oder nur Lastschriften (isCredit = "false")? Sonst keine Nutzung des Elements. Auftragswährung (nur bei sortenreinen Zahlungen, sonst keine Angabe). Order currency (only if identical across all transactions, ship otherwise). Informationen aus Dateianzeige der ersten logischen Datei. Order details from display file for first logical file. Auftraggeber entsprechend Dateianzeige. Order party information (from display file). Erstes Auftraggeberkonto entsprechend Dateianzeige. First order party account (from display file). Kontonummer (deutsches Format oder international als IBAN). Account number (German format or international as IBAN). Ist die Kontonummer im deutschen Format (international=false) oder im internationalen Format (international=true, IBAN) angegeben? Account number given in German format (international=false) or in international format (international=true, IBAN)? Kontonummer im freien Format. Account number in free format. Formatkennung. Format type. Bankleitzahl (deutsches Format oder international als SWIFT-BIC). Bank sort code (German format or international as SWIFT-BIC). Ist die Bankleitzahl im deutschen Format (international=false, BLZ) oder im internationalen Format (international=true, SWIFT-BIC) angegeben? Bank sort code given in German format (international=false) or in international format (international=true, SWIFT-BIC)? nationales Präfix für Bankleitzahlen. National prefix for bank sort code. Bankleitzahl im freien Format. Bank sort code in free format. Formatkennung. Format type. Datentyp für Informationen zu einem Unterzeichner eines VEU-Auftrags (HVU, HVD). Kunden-ID des Unterzeichners. Teilnehmer-ID des Unterzeichners. Name des Unterzeichners. Zeitstempel der Unterzeichnung (d.h. der Übertragung der Unterschrift). zusätzliche Informationen zu den Berechtigungen des Teilnehmers, der unterzeichnet hat. Datentyp für VEU-Berechtigungsinformationen des Teilnehmers (HKD, HTD). Liste von Auftragsarten, für die die Berechtigung des Teilnehmers gültig ist. List of order types which the user's permission belongs to. Identifikation des Dateiformats im Falle von FUL/FDL Identification of the file format in the case of FUL/FDL Verweis auf den Identifikationscode des berechtigten Kontos. Identification codes of the affected accounts. Betragshöchstgrenze, bis zu der die Berechtigung des Teilnehmers gültig ist. Maximum total amount which the user's permission is valid for. Unterschriftsklasse, für die der Teilnehmer berechtigt ist; nicht anzugeben bei Download-Auftragsarten. Authorization level of the user who signed the order; to be omitted for orders of type "download". Datentyp für VEU-Partnerdaten (HKD, HTD). Data type for customer data with regard to distributed signatures (order types HKD, HTD). Informationen zur Adresse des Kunden. Information about the customer's adress. Informationen zur Kreditinstitutsanbindung des Kunden. Information about the customer's banking access paramters. Informationen zu den Konten des Kunden. Information about the customer's accounts. Liste der Auftragsartenbeschränkungen; falls nicht angegeben, gibt es keine Auftragsartenbeschränkungen; falls Liste leer, ist das Konto für keine Auftragsart freigegeben. List containing the order types which contain this account is restricted to; if omitted, the account is unrestricted; if the list is empty the account is blocked for any order type. Identifikationscode des Kontos. Informationen zu den Auftragsarten, für die der Kunde berechtigt ist. Information about order types which the customer is authorised to use. Datentyp für VEU-Adressinformationen (HKD, HTD). Data type for address information with regard to distributed signature (order types HKD, HTD). Name des Kunden. Customer's name. Straße und Hausnummer. Street and house number. Postleitzahl. Postal code. Stadt. City. Region / Bundesland / Bundesstaat. Region / province / federal state. Land. Country. Datentyp für VEU-Kreditinstitutsinformationen (HKD, HTD). Banksystem-ID. Datentyp für VEU-Teilnehmerinformationen (HKD, HTD). Teilnehmer-ID. Status des Teilnehmers. Name des Teilnehmers. Informationen zu den Berechtigungen des Teilnehmers. Datentyp für VEU-Berechtigungsinformationen zu Auftragsarten (HKD, HTD). Data type for user permissions with regard to distributed signatures (order types HKD, HTD). Auftragsart. Identifikation des Dateiformats im Falle von FUL/FDL Identification of the file format in the case of FUL/FDL Transfertyp (Upload/Download). Auftragsformat (z.B. DTAZV). Beschreibung der Auftragsart. Anzahl erforderlicher EUs (Default=0). Datentyp für zusätzliche Auftragsparameter bei Standard-Auftragsarten. Datumsbereich (von-bis). Startdatum (inkl.). Enddatum (inkl.). Datentyp für zusätzliche Auftragsparameter für beliebige Auftragsarten. Datentyp für zusätzliche Auftragsparameter für Auftragsart FUL. Bezeichnung des Dateiformats Name of data format Datentyp für zusätzliche Auftragsparameter für Auftragsart FDL. Datumsbereich (von-bis). Range of date (from-to). Startdatum (inkl.). Enddatum (inkl.). Bezeichnung des Dateiformats Name of data format Attribute zur EBICS-Protokollversion und -revision. Attributes regarding the protocol version and revision of EBICS. Version des EBICS-Protokolls (z.B. "H00x"). Version of the EBICS protocol (e.g. "H00x"). Revision des EBICS-Protokolls (z.B. 1). Revision of the EBICS protocol (e.g. 1). libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_keymgmt_response_H005.xsd0000664000175000017500000001331415122266731031134 0ustar grothoffgrothoff ebics_keymgmt_response_H005.xsd ist das EBICS-Protokollschema für Schlüsselmanagement-Antwortnachrichten (HIA, HPB, HSA, INI). XML-Signature. Electronic Banking Internet Communication Standard des Zentralen Kreditausschusses (ZKA): Multibankfähige Schnittstelle zur internetbasierten Kommunikation. enthält die technischen Transaktionsdaten. enhält alle festen Headereinträge. enthält alle variablen Headereinträge. enthält die Auftragsdaten und den fachlichen ReturnCode. Transfer von Auftragsdaten; nur bei Download anzugeben (HPB). Informationen zur Verschlüsselung der Auftragsdaten enthält Auftragsdaten. Antwortcode für den vorangegangenen Transfer. Zeitstempel der letzten Aktualisierung der Bankparameter; nur in der Initialisierungsphase anzugeben. Datentyp für den variablen EBICS-Header. Auftragsnummer von Sendeaufträgen gemäß DFÜ-Abkommen (used for all key management order types except download order type HPB). Rückmeldung des Ausführungsstatus mit einer eindeutigen Fehlernummer. Klartext der Rückmeldung des Ausführungsstatus. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_request_H004.xsd0000664000175000017500000004246415122266731027240 0ustar grothoffgrothoff ebics_request_H004.xsd ist das EBICS-Protokollschema für Anfragen. ebics_request_H004.xsd is the appropriate EBICS protocol schema for standard requests. Electronic Banking Internet Communication Standard of the EBICS SCRL: Multibankfähige Schnittstelle zur internetbasierten Kommunikation. Electronic Banking Internet Communication Standard der EBICS SCRL: multi-bank capable interface for internet-based communication. enthält die technischen Transaktionsdaten. contains the transaction-driven data. enhält alle festen Headereinträge. contains the static header entries. enthält alle variablen Headereinträge. contains the mutable header entries. enthält die Auftragsdaten, EU(s) und weitere Nutzdaten. contains order data, order signature(s) and further data referring to the current order. X.509-Daten des Teilnehmers. X.509 data of the user. Welche Transaktionsphase? Which transaction phase? Initialisierungs- und Transferphase. Initialisation or transfer phase. Daten zur Vorabprüfung; nur anzugeben in der Initialisierungsphase bei Uploads mit Auftragsattribut OZH (EUs + Auftragsdaten). Data sent for pre-validation; mandatory for initialisation phase during uploads using order attribute OZH (order signature(s) + order data). Transfer von Signatur- bzw. Auftragsdaten; nur bei Upload anzugeben. Transfer of signature or order data; mandatory for uploads only. Quittierungsphase nach Download. Receipt phase after download. Quittierung des Transfers. Receipt of transfer. Datentyp für den statischen EBICS-Header. Data type for the static EBICS header. Hostname des Banksystems. Transaktionsphase? Transaction phase? Initialisierungsphase. Initialisation phase. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig. Random value, ensures the uniqueness of the client's message during initialisation phase. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung. current timestamp, used to limit storage space for nonces on the server. Kunden-ID des serverseitig administrierten Kunden. ID of the partner = customer, administered on the server. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. ID of the user that is assigned to the given customer, administered on the server. technische User-ID für Multi-User-Systeme. ID of the system for multi-user systems. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. software ID / manufacturer ID / manufacturer's name of the customer's software package. Sprachkennzeichen der Kundenproduktversion (gemäß ISO 639). Language code of the customer's software package according to ISO 639. Kennung des Herausgebers des Kundenprodukts bzw. des betreuenden Kreditinstituts. ID of the manufacturer / financial institute providing support for the customer's software package. Auftragsdetails. order details. Hashwerte der erwarteten öffentlichen Schlüssel (Verschlüsselung, Signatur, Authentifikation) des Kreditinstituts. Digest values of the expected public keys (authentication, encryption, signature) owned by the financial institute. Hashwert des Authentifikationsschlüssels. Digest value of the public authentication key. Version des Authentifikationsverfahrens. Version of the algorithm used for authentication. Hashwert des Verschlüsselungsschlüssels. Digest value of the public encryption key. Version des Verschlüsselungsverfahrens. Version of the algorithm used for encryption. Hashwert des Signaturschlüssels. Digest value of the public signature key. Version des Signaturverfahrens. Version of the algorithm used for signature creation. Angabe des Sicherheitsmediums, das der Kunde verwendet. Classification of the security medium used by the customer. Gesamtsegmentanzahl für diese Transaktion; nur bei Uploads anzugeben. Total number of segments for this transaction; mandatory for uploads only. Transfer- und Quittierungsphase. Transfer or receipt phase. eindeutige, technische Transaktions-ID; wird vom Server vergeben. unique transaction ID, provided by the server. Datentyp für den variablen EBICS-Header. Data type for the mutable EBICS header. Phase, in der sich die Transaktion gerade befindet; wird bei jedem Transaktionsschritt vom Client gesetzt und vom Server übernommen. Current phase of the transaction; this information is provided by the client for each step of the transaction, and the server adopts the setting. enthält die Nummer des aktuellen Segments, welches gerade übertragen oder angefordert wird; nur anzugeben bei TransactionPhase=Transfer. contains the number of the segment which is currently being transmitted or requested; mandatory for transaction phase 'Transfer' only. Ist dies das letzte Segment der Übertragung? Is this segment meant to be the last one regarding this transmission? Datentyp für Auftragsdetails im statischen EBICS-Header. Data type for order details stored in the static EBICS header. Auftragsart. type code of the order. Auftragsnummer für Sendeaufträge gemäß DFÜ-Abkommen. ID of the (upload) order, formatted in accordance with the document "DFÜ-Abkommen". Auftragsattribut. attribute describing the order contents. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_types_H005.xsd0000664000175000017500000020532615122266731026713 0ustar grothoffgrothoff ebics_types_H005.xsd enthält einfache Typdefinitionen für EBICS. Datentyp für EBICS-Versionsnummern. Datentyp für EBICS-Revisionsnummern. Datentyp für Versionsnummern zur Verschlüsselung. Datentyp für Versionsnummern zur Elektronischen Unterschrift (EU). Datentyp für Versionsnummern zur Authentifikation. Datentyp für Versionsnummern zur Verschlüsselung, Signatur und Authentifkation. Datentyp für Währungen (Grundtyp). dreistelliger Währungscode gemäß ISO 4217. Afghanistan: Afghani Albanien: Lek Armenien: Dram Niederländische Antillen: Gulden Angola: Kwanza Argentinien: Peso Australien: Dollar Aruba: Florin Aserbaidschan: Manat Bosnien und Herzegowina: Konvertible Mark Barbados: Dollar Bangladesch: Taka Bulgarien: Lew Bahrain: Dinar Bermuda: Dollar Brunei: Dollar Bolivien: Boliviano Brasilien: Real Bahamas: Dollar Bhutan: Ngultrum Botswana: Pula Weißrussland (Belarus): Rubel Belize: Dollar Kanada: Dollar Demokratische Republik Kongo: Franc Schweiz: Franken Chile: Peso China (Volksrepublik): Renminbi Yuan Kolumbien: Peso Costa Rica: Colón Serbien: Dinar Kuba: Peso Kap Verde: Escudo Zypern (griechischer Teil): Pfund Tschechien: Krone Dschibuti: Franc Dänemark: Krone Dominikanische Republik: Peso Algerien: Dinar Ecuador (bis 2000): Sucre Estland: Krone Ägypten: Pfund Äthiopien: Birr Europäische Währungsunion: Euro Fidschi: Dollar Falklandinseln: Pfund Vereinigtes Königreich: Pfund Georgien: Lari Ghana: Cedi Gibraltar: Pfund Gambia: Dalasi Guinea: Franc Guatemala: Quetzal Guyana: Dollar Hongkong: Dollar Honduras: Lempira Kroatien: Kuna Haiti: Gourde Ungarn: Forint Indonesien: Rupiah Israel: Schekel Indien: Rupie Irak: Dinar Iran: Rial Island: Krone Jamaika: Dollar Jordanien: Dinar Japan: Yen Kenia: Schilling Kirgisistan: Som Kambodscha: Riel Komoren: Franc Nordkorea: Won Südkorea: Won Kuwait: Dinar Kaimaninseln: Dollar Kasachstan: Tenge Laos: Kip Libanon: Pfund Sri Lanka: Rupie Liberia: Dollar Lesotho: Loti Litauen: Litas Lettland: Lats Libyen: Dinar Marokko: Dirham Moldawien: Leu Madagaskar: Franc Mazedonien: Denar Myanmar: Kyat Mongolei: Tugrik Macau: Pataca Mauretanien: Ouguiya Malta: Lira Mauritius: Rupie Malediven: Rufiyaa Malawi: Kwacha Mexiko: Peso Malaysia: Ringgit Mosambik: Metical Namibia: Dollar Nigeria: Naira Nicaragua: Cordoba Oro Norwegen: Krone Nepal: Rupie Neuseeland: Dollar Oman: Rial Panama: Balboa Peru: Nuevo Sol Papua-Neuguinea: Kina Philippinen: Peso Pakistan: Rupie Polen: Zloty Paraguay: Guaraní Katar: Riyal Rumänien: Leu Russland: Rubel Ruanda: Franc Saudi-Arabien: Riyal Salomonen: Dollar Seychellen: Rupie Sudan: Dinar Schweden: Krone Singapur: Dollar St. Helena: Pfund Slowenien: Tolar Slowakei: Krone Sierra Leone: Leone Somalia: Schilling Suriname: Dollar São Tomé und Príncipe: Dobra El Salvador: Colón Syrien: Pfund Swasiland: Lilangeni Thailand: Baht Tadschikistan: Somoni Turkmenistan: Manat Tunesien: Dinar Tonga: Pa'anga Türkei: Lira Türkei: Neue Lira (ab 2005) Trinidad und Tobago: Dollar Taiwan: Dollar Tansania: Schilling Ukraine: Hrywnja Uganda: Shilling USA: Dollar Uruguay: Peso Usbekistan: Sum Venezuela: Bolivar Vietnam: Dong Vanuatu: Vatu Samoa: Tala Zentralafrikanische Wirtschafts- und Währungsunion: CFA-Franc Ostkaribische Währungsunion: Dollar Westafrikanische Wirtschafts- und Währungsunion: CFA-Franc Neukaledonien: CFP-Franc Spezialcode für Testzwecke; keine existierende Währung keine Währung Jemen: Rial Südafrika: Rand Sambia: Kwacha Simbabwe: Dollar Datentyp für einen Betragswert (ohne Währung). Datentyp für einen Betrag inkl. Währungscode-Attribut (Default = "EUR"). Währungscode, Default="EUR". Currency code, default setting is "EUR". Datentyp für die Transaktions-ID. Datentyp für Nonces. Datentyp für die Instituts-ID. Datentyp für die Host-ID. Datentyp für die Kundenprodukt-ID. Datentyp für das Sprachkennzeichen des Kundenprodukts. Datentyp für allgemeine Auftragsarten (Grundtyp). Datentyp für eine Auftragsnummer lt. DFÜ-Abkommen. Datentyp für das Sicherheitsmedium. Datentyp für die Segmentnummer. Datentyp für die Gesamtsegmentanzahl. Datentyp für die Gesamtanzahl der Einzelauftraginfos. Datentyp für die Transaktionsphase. Transaktionsinitialisierung Auftragsdatentransfer Quittungstransfer Datentyp für Zeitstempel. Datentyp für Datumswerte. Datentyp für eine Teilnehmer-ID. Datentyp für eine Kunden-ID. Datentyp für eine Konten-ID. Datentyp für eine Kontonummer (national/international). Datentyp für eine Bankleitzahl (national/international). Datentyp für ein nationales BLZ-Präfix. Datentyp für eine Kontonummer (freies Format). Datentyp für eine Bankleitzahl (freies Format). Datentyp für den Namen des Kontoinhabers. Datentyp für die Kontobeschreibung. Datentyp für Kontoinformationen. Kontonummer (deutsches Format und/oder international als IBAN). Account number (German format and/or international=IBAN). Ist die Kontonummer im deutschen Format (international=false) oder im internationalen Format (international=true, IBAN) angegeben? Is the account number specified using the national=German or the international=IBAN format? Kontonummer im freien Format. Account in free format. Formatkennung. Format identification. Bankleitzahl (deutsches Format und/oder international als SWIFT-BIC). Bank code (German and/or international=SWIFT-BIC). Ist die Bankleitzahl im deutschen Format (international=false, BLZ) oder im internationalen Format (international=true, SWIFT-BIC) angegeben? Is the bank code specified using the national=German or the international SWIFT-BIC format? nationales Präfix für Bankleitzahlen. National=German prefix for bank codes. Bankleitzahl im freien Format. Bank code in free format. Formatkennung. Format identification. Name des Kontoinhabers. Name of the account holder. Währungscode für dieses Konto, Default=EUR. Currency code for this account, Default=EUR. Kontobeschreibung. Description of this account. Datentyp für die Rolle eines Zahlungsverkehrskontos innerhalb einer Transaktion. Auftraggeberkonto Empfängerkonto Gebührenkonto andere Kontorolle Datentyp für die Rolle eines Kreditinstituts innerhalb einer Transaktion (repräsentiert durch die Bankleitzahl). Auftraggeberbank Empfängerbank Korrespondenzbank andere Bankrolle Datentyp für die Rolle eines Kontoinhabers innerhalb einer Transaktion. Auftraggeber Empfänger Überbringer, Einreicher andere Rolle Datentyp für Kontoinformationen inkl. der Eigenschaftszuordnung innerhalb einer Zahlungstransaktion. Kontonummer (deutsches Format oder international als IBAN). Kontonummer (Account number (German format and/or international = IBAN). Rolle des Kontos innerhalb der Zahlungstransaktion. Role of the account during the transaction. Textuelle Beschreibung der Funktion, falls role=Other ausgewählt wird. Textual description of the role the account place during the transaction; use only if the corresponding 'role' field is set to 'other'. Ist die Kontonummer im deutschen Format (international=false) oder im internationalen Format (international=true, IBAN) angegeben? Is the account number specified using the national=German or the international=IBAN format? Kontonummer im freien Format. Account in free format. Rolle des Kontos innerhalb der Zahlungstransaktion. Role of the account during the transaction. Textuelle Beschreibung der Funktion, falls role=Other ausgewählt wird. Textual description of the role the account place during the transaction; use only if the corresponding 'role' field is set to 'other'. Formatkennung. Format identification. Bankleitzahl (deutsches Format oder international als SWIFT-BIC). Bank code (German and/or international=SWIFT-BIC). Rolle des kontoführenden Instituts innerhalb der Zahlungstransaktion. Role of the bank during the transaction. Textuelle Beschreibung der Funktion, falls role=Other ausgewählt wird. Textual description of the role the account place during the transaction; use only if the corresponding 'role' field is set to 'other'. Ist die Bankleitzahl im deutschen Format (international=false, BLZ) oder im internationalen Format (international=true, SWIFT-BIC) angegeben? Is the bank code specified using the national=German or the international=SWIFT-BIC format? nationales Präfix für Bankleitzahlen. National=German prefix for bank codes. Bankleitzahl im freien Format. Bank code in free format. Rolle des kontoführenden Instituts innerhalb der Zahlungstransaktion. Role of the bank during the transaction. Textuelle Beschreibung der Funktion, falls role=Other ausgewählt wird. Textual description of the role the account place during the transaction; use only if the corresponding 'role' field is set to 'other'. Formatkennung. Format identification. Name des Kontoinhabers. Name of the account holder. Rolle des Kontoinhabers innerhalb der Zahlungstransaktion. Role of the account holder during the transaction. Textuelle Beschreibung der Rolle, falls role=Other ausgewählt wird. Textual description of the role the account holder place during the transaction; use only if the corresponding 'role' field is set to 'other'. Währungscode für dieses Konto, Default=EUR. Currency code for this account, Default=EUR. Kontobeschreibung. Description of this account. Datentyp für binäre Signaturdaten (komprimiert, verschlüsselt und kodiert). Datentyp für binäre Auftragsdaten (komprimiert, verschlüsselt und kodiert). Datentyp für Berechtigungsklassen zur Elektronischen Unterschrift. Einzelunterschrift Erstunterschrift Zweitunterschrift Transportunterschrift Listentyp für Berechtigungsklassen zur Elektronischen Unterschrift. Datentyp für Hashfunktionen. Datentyp für Hashwerte. Version des Signaturverfahrens. Version of the algorithm used for signature creation. Datentyp für kryptographische Unterschriften. Datentyp für symmetrische Schlüssel. Datentyp für Hashwerte und Attribute von öffentlichen Schlüsseln. Hashalgorithmus. Name of the used hash algorithm. Datentyp für die Darstellung eines öffentlichen RSA-Schlüssels als Exponent-Modulus-Kombination oder als X509-Zertifikat. Datentyp für öffentliche Verschlüsselungsschlüssel. Version des Verschlüsselungsverfahrens. Datentyp für öffentlichen Authentfikationsschlüssel. Version des Authentifikationsverfahrens. Datentyp für öffentliche bankfachliche Schlüssel. Data type for public authorisation (ES) key. Version des EU-Signaturverfahrens. ES-Version. Datentyp für öffentlichen Schlüssel zur Authentisierung. Data type for public for identification and authentication. Version des Authentifikationsverfahrens. Authentication version. Datentyp für öffentlichen Verschlüsselungsschlüssel. Data type for encryption key. Version des Verschlüsselungsverfahrens. Encryption Version. Datentyp für die Zertifikate hinsichtlich der "bank-technical signature for authorisation" (ES). Data Type for Certificates for the bank-technical signature for authorisation (ES) Datentyp für Antwortcodes. Datentyp für den Erklärungstext zum Antwortcode. Datentyp für Quittierungscodes. Datentyp für Kunden-, Teilnehmer-, Straßen- oder Ortsnamen. Datentyp für die Beschreibung von Auftragsarten. Datentyp für den Teilnehmerstatus. generic parameter Generic key value parameters. name of parameter Name of the parameter (= key). value of parameter Value of the parameter. XML-Typ des Parameterwerts (Vorschlag für default ist string). XML type of the parameter value (Proposal for default is string). Datentyp für die Darstellung von Information zur Verschlüsselung der Auftragsdaten. Data type for the modelling of information regarding the encryption of signature and order data. Hashwert des öffentlichen Verschlüsselungsschlüssels des Empfängers der verschlüsselten Auftragsdaten. Hash value of the public encryption key owned by the receipient of the encrypted order data. Version des Verschlüsselungsverfahrens. Version of the encryption method. Asymmetrisch verschlüsselter symmetrischer Transaktionsschlüssel. The asymmetrically encrypted symmetric transaction key. Authentifikationssignatur. Authentication signature. String up to 255 characters. Type is used for ISO variant and version Type ist used for original file name Type ist used for name or rather kind of Message Service Code name: External list specified and maintained by EBICS. Basis is the "SWIFT-list" for the field "description" (SCT, DCT, XCT, SDD, DDD, STM, REP...) plus additional codes needed for further services libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_keymgmt_request_H005.xsd0000664000175000017500000005451215122266731030773 0ustar grothoffgrothoff ebics_keymgmt_request_H005.xsd ist das EBICS-Protokollschema für Schlüsselmanagement-Anfragen (HIA, HPB, HSA, INI). XML-Signature. Datentyp für den statischen EBICS-Header (allgemein). Hostname des Banksystems. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig; nur anzugeben, falls Authentifikationssignatur vorhanden. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung; nur anzugeben, falls Authentifikationssignatur vorhanden. Kunden-ID des serverseitig administrierten Kunden. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. technische User-ID für Multi-User-Systeme. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Auftragsdetails. Angabe des Sicherheitsmediums, das der Kunde verwendet. Datentyp für OrderDetails im statischen EBICS-Header (allgemein). Auftragsart. Datentyp für Element mit Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Sprachkennzeichen der Kundenproduktversion (gemäß ISO 639). Kennung des Herausgebers des Kundenprodukts bzw. des betreuenden Kreditinstituts. Datentyp für den leeren variablen EBICS-Header von Key Managemen Aufträgen. Anfragestruktur für ungesicherte Auftragsarten HIA (Authentifikations- und Verschlüsselungsschlüssel senden) und INI (bankfachllichen Schlüssel senden). enthält die technischen Transaktionsdaten. enhält alle festen Headereinträge. enthält alle variablen Headereinträge. enthält die Auftragsdaten. Transfer von Auftragsdaten. enthält Auftragsdaten. Datentyp für den statischen EBICS-Header bei ungesicherten Sendeauftragsarten (Aufträge HIA und INI): kein Nonce, kein Timestamp, keine EU-Datei, keine X001 Authentifizierung, keine Verschlüsselung, keine Digests der öffentlichen Bankschlüssel, Nutzdaten komprimiert Hostname des Banksystems. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig; nicht anzugeben für ebicsUnsecuredRequest. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung; nicht anzugeben für ebicsUnsecuredRequest. Kunden-ID des serverseitig administrierten Kunden. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. technische User-ID für Multi-User-Systeme. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Auftragsdetails. Angabe des Sicherheitsmediums, das der Kunde verwendet. Datentyp für OrderDetails im statischen EBICS-Header von ebicsUnsecuredRequest. Auftragsart. Anfragestruktur für Auftragsarten ohne Übertragung der Digests der öffentlichen Bankschlüssel (HPB Bankschlüssel abholen). enthält die technischen Transaktionsdaten. enhält alle festen Headereinträge. enthält alle variablen Headereinträge. Authentifikationssignatur. enthält optionale Zertifikate (vorgesehen). X.509-Daten des Teilnehmers. Datentyp für den statischen EBICS-Header bei Aufträgen ohne Übertragung der Digests der Bankschlüssel (Auftrag HBP): keine Digests der öffentlichen Bankschlüssel, keine EU-Datei, keine Nutzdaten, OrderId optional!, Nonce, Timestamp, X001 Authentifizierung, Auftragsattribut DZHNN Hostname des Banksystems. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung. Kunden-ID des serverseitig administrierten Kunden. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. technische User-ID für Multi-User-Systeme. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Auftragsdetails. Angabe des Sicherheitsmediums, das der Kunde verwendet. Datentyp für OrderDetails im statischen EBICS-Header von ebicsNoPubKeyDigestsRequest. Auftragsart. The structure for uploads contains order data and the ESs, but without an authentication signature and data digest of bank keys. Anfragestruktur für Sendeaufträge mit EU-Datei und Nutzdaten aber ohne Authentifizierungssignatur und Digests der Bankschlüssel. Contains technical transaction data. enthält die technischen Transaktionsdaten. Contains all fixed header entries. enhält alle festen Headereinträge. Contains all mutable header entries. enthält alle variablen Headereinträge. Contains the order data and the ESs. enthält die Auftragsdaten und EUs. Transfer of order data and the ESs. Transfer von Auftragsdaten und EUs. Contains the ESs. enthält Signaturdaten (EUs). Contains the order data enthält Auftragsdaten. Datentyp für den statischen EBICS-Header für ebicsUnsignedRequest.Datentyp für den statischen EBICS-Header bei Aufträgen ohne Authentifizierungssignatur (Auftrag HSA): keine X001 Authentifizierung, keine Digests der öffentlichen Bankschlüssel, EU-Datei, Nutzdaten, Nonce, Timestamp, OrderId, Auftragsattribut OZNNN Hostname des Banksystems. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig; nicht anzugeben bei ebicsUnsignedRequest. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung; nicht anzugeben bei ebicsUnsignedRequest. Kunden-ID des serverseitig administrierten Kunden. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. technische User-ID für Multi-User-Systeme. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Auftragsdetails. Angabe des Sicherheitsmediums, das der Kunde verwendet. Datentyp für OrderDetails im statischen EBICS-Header von ebicsUnsignedRequest. Auftragsart. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/pain.001.001.03.ch.02.xsd0000664000175000017500000014123215122266731026460 0ustar grothoffgrothoff libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_orders_H005.xsd0000664000175000017500000031411515122266731027042 0ustar grothoffgrothoff ebics_orders_H005.xsd contains order-based reference elements and order-based type definitions for EBICS. ebics_orders_H005.xsd enthält auftragsbezogene Referenzelemente und auftragsbezogene Typdefinitionen für EBICS. XML-Klartext-Auftragsdaten für neue EBICS-Auftragsarten. Order data in XML format for new EBICS order types. Auftragsdaten für Auftragsart HAA (Antwort: abrufbare Auftragsarten abholen). Order data for order type HAA (response: receive downloadable order types). Auftragsdaten für Auftragsart HCA (Anfrage: Änderung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung). Order data for order type HCA (request: replace user's keys for authentication and encryption). Auftragsdaten für Auftragsart HCS (Anfrage: Schlüsselwechsel aller Schlüssel). Order data for order type HCS (request: replace all keys). Auftragsdaten für Auftragsart HIA (Anfrage: Initialisierung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung). Order data for order type HIA (request: initialise user's keys for authentication and encryption). Order data for order type H3K (request: initialise all three user's keys). Auftragsdaten für Auftragsart H3K (Anfrage: Initialisierung aller drei Teilnehmerschlüssel). Auftragsdaten für Auftragsart HKD (Antwort: Kunden- und Teilnehmerdaten des Kunden abholen). Order data for order type HKD (response: receive customer-based information on the customer and the customer's users). Schlüssel zur Identifikation des Kontos. Key for the identification of the account. Referenz auf die Konten-Identifikationsschlüssel. Reference to the account identification keys. Auftragsdaten für Auftragsart HPB (Antwort: Transfer der Bankschlüssel). Order data for order type HPB (response: receive bank's public keys). Auftragsdaten für Auftragsart HPD (Antwort: Bankparameter abholen). Order data for order type HPD (response: receive bank parameters). Auftragsdaten für Auftragsart HTD (Antwort: Kunden- und Teilnehmerdaten des Teilnehmers abholen). Order data for order type HTD (response: receive user-based information on the user's customer and the user herself/himself). Schlüssel zur Identifikation des Kontos. Key for the identification of the account. Referenz auf die Konten-Identifikationsschlüssel. Reference to the account identification keys. Auftragsdaten für Auftragsart HVD (Antwort: VEU-Status abrufen). Order data for order type HVD (response: receive the status of an order currently stored in the distributed signature processing unit). Auftragsdaten für Auftragsart HVS (Anfrage: VEU-Storno). Order data for order type HVS (request: reject an order currently stored in the distributed signature processing unit). Auftragsdaten für Auftragsart HVT (Antwort: VEU-Transaktionsdetails abrufen). Order data for order type HVT (response: receive transaction details of an order currently stored in the distributed signature processing unit). Auftragsdaten für Auftragsart HVU (Antwort: VEU-Übersicht abholen). Order data for order type HVU (response: receive summary of orders currently stored in the distributed signature processing unit). Auftragsdaten für Auftragsart HVZ (Antwort: VEU-Übersicht mit Zusatzinformationen abholen). Order data for order type HVZ (response: receive summary of orders currently stored in the distributed signature processing unit with additional information). XML-Strukturen für bankfachliche Elektronische Unterschriften (EUs). contains the digital signatures. enthält die EU des Kreditinstituts. contains the digital signatures. zusätzliche Auftragsparameter, die zur Ausführung des Auftrags notwendig sind. additional order parameters required to execute the order. zusätzliche Auftragsparameter für Auftragsart HVD. additional order parameters for order type HVD. zusätzliche Auftragsparameter für Auftragsart HVE. additional order parameters for order type HVE. zusätzliche Auftragsparameter für Auftragsart HVS. additional order parameters for order type HVS. zusätzliche Auftragsparameter für Auftragsart HVT. additional order parameters for order type HVT. zusätzliche Auftragsparameter für Auftragsart HVU. additional order parameters for order type HVU. zusätzliche Auftragsparameter für Auftragsart HVZ. additional order parameters for order type HVZ. zusätzliche Auftragsparameter für Standard-Auftragsarten. additional order parameters for standard order types. Standard-Requeststruktur für HVx-Aufträge (HVD, HVT, HVE, HVS). Standard request structure for HVx orders (HVD, HVT, HVE, HVS). Standard-Requestdaten. Standard request data. Kunden-ID des Einreichers des ausgewählten Auftrags. Customer ID of the presenter of the selected order. BTF Service Parameter struktur im Falle von BTU/BTD Identification of the file format in the case of FUL/FDL Auftragsnummer des ausgewählten Auftrags. Order ID of the selected order. Marker für Elemente und deren Substrukturen, die authentifiziert werden sollen. Marker for elements and their substructures that are to be authenticated. Das zugehörige Element ist mitsamt seinen Unterstrukturen zu authentifizieren. The element (and its substructures) that belongs to this attribute is to be authenticated. optionales Support-Flag, Default = true. optional support flag, default = true. Wird die Funktion unterstützt? Is this function supported? EU-Berechtigungsinformationen. permission information of a user's digital signature. Unterschriftsberechtigung des Teilnehmers, der unterzeichnet hat. Authorisation level of the user that signed the order. Datentyp für Signaturdaten des Kreditinstituts beim EU-Transfer. Data type for digital signature data transferred using EBICS. bankfachliche Elektronische Unterschrift. Digital signature (either autorising an order or applied for transportation). Datentyp für Vorabprüfung (Anfrage). Data type for pre-validation (request). Client sendet den Hashwert der Auftragsdaten und alle weiteren Daten, die er im Rahmen der Vorabprüfung zur Verfügung stellen will Hashwert der zu übertragenden Auftragsdatendatei für die Vorabprüfung. Hashvalue of the transmitted order data for the prevalidation. Kontoangabe zur Kontoberechtigung für diesen Zahlungsverkehrsauftrag bei der Vorabprüfung. Account information for authorisation checks for the payment order within the prevalidation. Datentyp für Kontenberechtigungsdaten zur Vorabprüfung. Data type for the account authorisation data for the prevalidation. Summe der Zahlungsverkehrsaufträge dieses Kontos für die Höchstbetragsprüfung der EU. Total sum of the ordered payments regarding this account in order to check the maximum amount limit of the signature permission grades. Datentyp für den Transfer von Auftragsdaten (Anfrage). Data type for the transfer of order data (request). Transaktionsphase? Initialisierungsphase: Transfer der Signaturdaten (EUs) und des Transaktionsschlüssels. Inituialisation phase: Transfer of signatur data (ESs) and transaktion key. Information zur Verschlüsselung der Signatur- und Auftragsdaten. Information regarding the encryption of signature and order data. enthält Signaturdaten (EUs). contains signature data (ESs). Hashwert der Auftragsdaten. Hashvalue of the order data. Additional Information about the order (unstructured, up to 255 characters). Transferphase: Transfer von Auftragsdaten. Transferphase: Transfer of order data. enthält Auftragsdaten. contains order data. Datentyp für den Transfer von Auftragsdaten (Antwort). Transfer des Sitzungsschlüssels und (optional) der Signaturdaten (EUs); nur in der Initialisierungsphase anzugeben. Transfer of the session key and (optional) signature data (ESs); to be specified only in the initialisation phase. Information zur Verschlüsselung der Signatur- und Auftragsdaten. Information regarding the encryption of signature and order data. enthält Signaturdaten (EUs). contains signature data (ESs). enthält Auftragsdaten. contains order data. Datentyp für den Transfer von Transferquittungen. Data type for the transfer of transfer receipts. Quittierungscode für Auftragsdatentransfer. Receipt code fpr transfer of order data. Datentyp für den Transfer von Antwortcodes. Antwortcode für den vorangegangenen Transfer. response code for the foregoing transfer. Zeitstempel der letzten Aktualisierung der Bankparameter. Datentyp für Auftragsdaten für Auftragsart HAA (Antwort: abrufbare Auftragsarten abholen). Data type for order data of order type HAA (Response: Download of available order data). Liste von Auftragsarten, für die Daten bereit stehen. List of order types for which data are available. Datentyp für Auftragsdaten für Auftragsart HCA (Anfrage: Änderung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung). Data type for order data regarding order type HCA (Request: Update of Subscriber's key for authentication and encryption). öffentlicher Authentifikationsschlüssel. public key for authentication. öffentlicher Verschlüsselungsschlüssel. public key for encryption. Kunden-ID. Partner-ID. Teilnehmer-ID. User-ID. Datentyp für Auftragsdaten für Auftragsart HCS (Anfrage: Schlüsselwechsel aller Schlüssel). Data type for order data for order type HCS (Request: Update of all keys). öffentlicher Authentifikationsschlüssel. public key for authentication. öffentlicher Verschlüsselungsschlüssel. public key for encryption. Kunden-ID. Partner-ID. Teilnehmer-ID. User-ID. Datentyp für Auftragsdaten für Auftragsart HIA (Anfrage: Initialisierung der Teilnehmerschlüssel für Authentifikation und Verschlüsselung). Data type for order data for order type HIA (Request: Initialisation of subcriber keys for authentication and encryption). öffentlicher Authentifikationsschlüssel. public key for authentication. öffentlicher Verschlüsselungsschlüssel. public key for encryption. Kunden-ID. Partner-ID. Teilnehmer-ID. User-ID. Datentyp für Auftragsdaten für Auftragsart H3K (Anfrage: Initialisierung aller drei Teilnehmerschlüssel). Order type for order data H3K (request: initialise all three user's keys). Key for electronic Signature Signaturschlüssel. Authentication key Authentifikationsschlüssel. Encryption key Verschlüsselungsschlüssel. PartnerID. Kunden-ID. UserID. Teilnehmer-ID. Datentyp für Auftragsdaten für Auftragsart HKD (Antwort: Kunden- und Teilnehmerdaten des Kunden abholen). Order data for order type HKD (response: receive customer based information on the customer and the customer's user. Kundendaten. Customer data. Teilnehmerdaten. User data. Datentyp für Auftragsdaten für Auftragsart HPB (Antwort: Transfer der Bankschlüssel). Data type for order data for order type HPB (Response: Transfer of bank keys). öffentlicher Authentifikationsschlüssel. public authentication key öffentlicher Verschlüsselungsschlüssel. public encryption key öffentlicher EU-Signaturschlüssel. public ES key. Banksystem-ID. Host-ID. Datentyp für Auftragsdaten für Auftragsart HPD (Antwort: Bankparameter abholen). Data type for order data for order type HPD (Response: Download bank parameters). Zugangsparameter. Access Parameter. Protokollparameter. Protocol Parameter. Datentyp für HPD-Zugangsparameter. data type for HPD Access Parameter. institutsspezifische IP-Adresse/URL. individual IP-address/URL of the bank. Gültigkeitsbeginn für die angegebene URL/IP. Valid-From-Date of the URL/IP. Institutsbezeichnung. Name of the bank. Banksystem-ID. Datentyp für HPD-Protokollparameter. Data type for HPD's parameters regarding the EBICS protocol. Spezifikation unterstützter Versionen. Specification of supported versions.. Parameter zur Recovery-Funktion (Wiederaufnahme abgebrochener Übertragungen). Parameter denoting the recovery function (recovery of aborted transmissions). Parameter zur Vorabprüfung (über die Übermittlung der EU hinaus). Parameter denoting the pre-validation (beyond transmission of signatures). Optionales Support-Flag, Default = true. Optional support flag, default = true. Parameter zum Download von Kunden- und Teilnehmerdaten (Auftragsarten HKD/HTD). Parameter denoting the download of customer and user data (order types HKD/HTD). Parameter zum Abruf von Auftragsarten, zu denen Auftragsdaten verfügbar sind (Auftragsart HAA). Parameter denoting the reception of order types which provides downloadable order data (order type HAA). Datentyp für HPD-Versionsinformationen. Data type for HPD version information. unterstützte EBICS-Protokollversionen (H...). supported EBICS protocol versions. (H...). unterstützte Versionen der Authentifikation (X...). supported version for authentication (X...). unterstützte Versionen der Verschlüsselung (E...). supported version for encryption (E...). unterstützte EU-Versionen (A...). supported version for ES (A...). Datentyp für Auftragsdaten für Auftragsart HTD (Antwort: Kunden- und Teilnehmerdaten des Teilnehmers abholen). Data type for order data for order type HTD (Response: Download partner- and user data). Kundendaten. Customer data. Teilnehmerdaten. User data. Datentyp für Auftragsdaten für Auftragsart HVD (Antwort: VEU-Status abrufen). Data type for order data for order type HVD (Response: EDS-status). Hashwert der Auftragsdaten. Hash value of the order data. Begleitzettel/"Displaydatei" (entspricht der Dateianzeige im Kundenprotokoll gemäß DFÜ-Abkommen). Accompanying ticket/"display file" (corresponds to the display file of the customer's journal according to the document "DFÜ-Abkommen"). Kann die Auftragsdatei im Originalformat abgeholt werden? (HVT mit completeOrderData=true) Can the order file be downloaded in the original format? (HVT with completeOrderData=true) Größe der unkomprimierten Auftragsdaten in Bytes. Size of the uncompressed order data (byte count). Können die Auftragsdetails als XML-Dokument HVTResponseOrderData abgeholt werden? (HVT mit completeOrderData=false) Can the order details be downloaded as XML document HVTResponseOrderData? (HVT with completeOrderData=false) bankfachliche Elektronische Unterschrift des Kreditinstituts über Hashwert und Displaydatei. Digital Signature issued by the bank, covering the hash value and the accompanying ticket. Informationen zu den bisherigen Unterzeichnern. Information about the already existing signers. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVD. Data type for additional order parameters for order type HVD. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVE. Data type for additional order parameters for order type HVE. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVS. Data type for additional order parameters for order type HVS. Datentyp für Auftragsdaten für Auftragsart HVS (Anfrage: VEU-Storno). Data type for order data for order type HVS (request: EDS cancellation). Hashwert der Auftragsdaten des stornierten Auftrags. Hash value of order data of cancelled order. Datentyp für Antwort mit Einzelauftraginfos für Auftragsart HVT (Antwort VEU-Transaktionsdetails abrufen mit completeOrderData="false"). Data type for a response containing information about single transactions for order type HVT (response: EDS transaction details with completeOrderData="false"). Gesamtanzahl der Einzelaufträge für den Auftrag. Total number of order infos for the order. Einzelauftragsinfos. Particular order content information requested for display matters. Datentyp für HVT-Konteninformationen. Data type for account information regarding order type HVT. //MODIFIED - Replaced Element OrderFormat with MsgName// Datentyp für HVT-Auftragsinformationen. kontobezogene Details des Auftrags (Auftraggeber, Empfänger etc.). account related details of the order (ordering party, receiver etc.). Ausführungsdatum. Execution date. Betrag. Amount. Gutschrift (isCredit = "true") oder Lastschrift (isCredit = "false")? Credit (isCredit = "true") or debit (isCredit = "false")? Währungscode. Currency code. Textfeld zur weiteren Beschreibung der Transaktion (Verwendungszweck, Auftragsdetails, Kommentar). text field for additional descriptions regarding the transaction (remittance information, order details, annotations). Beschreibungstyp. Description type. Verwendungszweck remittance information. Auftragsdetails Order details. Kommentar Annotation. Datentyp für HVT-Auftragsflags. Data type for HVT order flags. Sollen die Transaktionsdetails als Einzelauftragsinfos (completeOrderData=false) oder als komplette Originaldaten (completeOrderData=true) übertragen werden? (Vorschlag für Default=false) Are the transaction details so be transmitted as particular order content information requested for display matters or in complete order data file form? (Proposal for Default=false) Limit für die zu liefernden Transaktionsdetails, bei completeOrderData=false maximale Anzahl zu liefernder Einzelauftragsinfos, 0 für unbegrenzt (Vorschlag für Default=100). Limit for the transaction details to be transmitted; if completeOrderData=false, maximum number of details of a particular order; 0 for unlimited number of details (Proposal for Default=100). Offset vom Anfang der Originalauftragsdatei für die zu liefernden Transaktionsdetails, bei completeOrderData=false bezogen auf laufende Nummer des Einzelauftrags (Vorschlag für Default=0). Offset position in the original order file which marks the starting point for the transaction details to be transmitted; applies to the sequential number of a particular order if completeOrderData=false (Proposal for Default=0). Datentyp für zusätzliche Auftragsparameter für Auftragsart HVT. Data type for additional order parameters for order type HVT. spezielle Flags für HVT-Aufträge. Special order flags for orders of type HVT. Generische Schlüssel-Wert-Parameter Generic key-value parameters Datentyp für Auftragsdaten für Auftragsart HVU (Antwort: VEU-Übersicht abholen). Data type for order data for order type HVU (Response: Download EDS overview). Auftragsinformationen. Datentyp für HVU-Auftragsdetails. Data type for HVU order details. Auftragsart lt. DFÜ-Abkommen des ausgewählten Auftrags. Type of the order. Auftragsnummer lt. DFÜ-Abkommen des ausgewählten Auftrags. Order number. Größe der unkomprimierten Auftragsdaten in Bytes. Order data size in bytes. Informationen zu den Unterschriftsmodalitäten. Signing information. Informationen zu den bisherigen Unterzeichnern. Information regarding the signer. Informationen zum Einreicher. Information regarding the originator. Additional Information about the order (unstructured, up to 255 characters). Additional Information about the order (unstructured, up to 255 characters). Datentyp für zusätzliche Auftragsparameter für Auftragsart HVU. Data type for additional order parameters for order type HVU. Liste von Auftragsarten, für die zur Unterschrift vorliegende Aufträge abgerufen werden sollen; falls nicht angegeben, werden sämtliche für den Teilnehmer unterschriftsfähigen Aufträge abgerufen. Datentyp für zusätzliche Auftragsparameter für Auftragsart HVZ. Data type for additional order parameters for order type HVZ. Liste von Auftragsarten, für die zur Unterschrift vorliegende Aufträge abgerufen werden sollen; falls nicht angegeben, werden sämtliche für den Teilnehmer unterschriftsfähigen Aufträge abgerufen. List of order types that the orders ready to be signed by the requesting user should match; if not specified, a list of all orders ready to be signed by the requesting user is returned. Datentyp für Informationen zu den HVU-Unterschriftsmodalitäten. Ist der Auftrag unterschriftsreif ("true") oder bereits vom Teilnehmer unterschrieben ("false")? Anzahl der insgesamt zur Freigabe erforderlichen EUs. Anzahl der bereits geleisteten EUs. Datentyp für Informationen zum Ersteller eines HVU-Auftrags. Kunden-ID des Einreichers. Teilnehmer-ID des Einreichers. Name des Einreichers. Zeitstempel der Einreichung (d.h. der Übertragung der Auftragsdatei). Datentyp für Auftragsdaten für Auftragsart HVZ (Antwort: VEU-Übersicht mit Zusatzinformationen abholen). Order data for order type HVZ (response: receive summary of orders currently stored in the distributed signature processing unit with additional informations). Auftragsinformationen. Summary of order information. Datentyp für HVZ-Auftragsdetails. BTF Service Parameter-Struktur des ausgewählten Auftrags. Type of the order. Auftragsnummer lt. DFÜ-Abkommen des ausgewählten Auftrags. ID number of the order. Hashwert der Auftragsdaten. Hash value of the order data. Kann die Auftragsdatei im Originalformat abgeholt werden? (HVT mit completeOrderData=true). Can the order file be downloaded in the original format? (HVT with completeOrderData=true) Größe der unkomprimierten Auftragsdaten in Bytes. Size of uncompressed order data in Bytes. Können die Auftragsdetails als XML-Dokument HVTResponseOrderData abgeholt werden? (HVT mit completeOrderData=false). Can the order details be downloaded as XML document HVTResponseOrderData? (HVT with completeOrderData=false) Zusätzliche Auftragsdetails nur für Zahlungsaufträge. Order details related to payment orders only. Informationen zu den Unterschriftsmodalitäten. Information regarding the signing modalities of the order. Informationen zu den bisherigen Unterzeichnern. Information regarding the users who already signed the order. Informationen zum Einreicher. Information regarding the originator of the order. Additional Information about the order (unstructured, up to 255 characters). Standard-Requeststruktur für HVx-Aufträge (HVD, HVT, HVE, HVS). Standard structure for HVZ OrderDetails related to payment orders Anzahl der Zahlungssätze über alle logische Dateien entsprechend Dateianzeige. Total transaction number for all logical files (from dispay file). Summe der Beträge über alle logische Dateien entsprechend Dateianzeige. Total transaction amount for all logical files (from dispay file). Nur Gutschriften (isCredit = "true") oder nur Lastschriften (isCredit = "false")? Sonst keine Nutzung des Elements. Auftragswährung (nur bei sortenreinen Zahlungen, sonst keine Angabe). Order currency (only if identical across all transactions, ship otherwise). Informationen aus Dateianzeige der ersten logischen Datei. Order details from display file for first logical file. Auftraggeber entsprechend Dateianzeige. Order party information (from display file). Erstes Auftraggeberkonto entsprechend Dateianzeige. First order party account (from display file). Kontonummer (deutsches Format oder international als IBAN). Account number (German format or international as IBAN). Ist die Kontonummer im deutschen Format (international=false) oder im internationalen Format (international=true, IBAN) angegeben? Account number given in German format (international=false) or in international format (international=true, IBAN)? Kontonummer im freien Format. Account number in free format. Formatkennung. Format type. Bankleitzahl (deutsches Format oder international als SWIFT-BIC). Bank sort code (German format or international as SWIFT-BIC). Ist die Bankleitzahl im deutschen Format (international=false, BLZ) oder im internationalen Format (international=true, SWIFT-BIC) angegeben? Bank sort code given in German format (international=false) or in international format (international=true, SWIFT-BIC)? nationales Präfix für Bankleitzahlen. National prefix for bank sort code. Bankleitzahl im freien Format. Bank sort code in free format. Formatkennung. Format type. Datentyp für Informationen zu einem Unterzeichner eines VEU-Auftrags (HVU, HVD). Kunden-ID des Unterzeichners. Teilnehmer-ID des Unterzeichners. Name des Unterzeichners. Zeitstempel der Unterzeichnung (d.h. der Übertragung der Unterschrift). zusätzliche Informationen zu den Berechtigungen des Teilnehmers, der unterzeichnet hat. Datentyp für VEU-Berechtigungsinformationen des Teilnehmers (HKD, HTD). Liste von Auftragsarten, für die die Berechtigung des Teilnehmers gültig ist. List of order types which the user's permission belongs to. BTF Service Parameter struktur im Falle von BTU/BTD Identification of the file format in the case of FUL/FDL Verweis auf den Identifikationscode des berechtigten Kontos. Identification codes of the affected accounts. Betragshöchstgrenze, bis zu der die Berechtigung des Teilnehmers gültig ist. Maximum total amount which the user's permission is valid for. Unterschriftsklasse, für die der Teilnehmer berechtigt ist; nicht anzugeben bei Download-Auftragsarten. Authorization level of the user who signed the order; to be omitted for orders of type "download". Datentyp für VEU-Partnerdaten (HKD, HTD). Data type for customer data with regard to distributed signatures (order types HKD, HTD). Informationen zur Adresse des Kunden. Information about the customer's adress. Informationen zur Kreditinstitutsanbindung des Kunden. Information about the customer's banking access paramters. Informationen zu den Konten des Kunden. Information about the customer's accounts. //MODIFIED//Liste der Auftragsartenbeschränkungen; falls nicht angegeben, gibt es keine Auftragsartenbeschränkungen; falls das Element ohne Service-Element geliefert wird, ist das Konto für keine Auftragsart freigegeben. List containing the order types which contain this account is restricted to; if omitted, the account is unrestricted; if the list is empty the account is blocked for any order type. Identifikationscode des Kontos. Informationen zu den Auftragsarten, für die der Kunde berechtigt ist. Information about order types which the customer is authorised to use. Datentyp für VEU-Adressinformationen (HKD, HTD). Data type for address information with regard to distributed signature (order types HKD, HTD). Name des Kunden. Customer's name. Straße und Hausnummer. Street and house number. Postleitzahl. Postal code. Stadt. City. Region / Bundesland / Bundesstaat. Region / province / federal state. Land. Country. Datentyp für VEU-Kreditinstitutsinformationen (HKD, HTD). Banksystem-ID. Datentyp für VEU-Teilnehmerinformationen (HKD, HTD). Teilnehmer-ID. Status des Teilnehmers. Name des Teilnehmers. Informationen zu den Berechtigungen des Teilnehmers. Datentyp für VEU-Berechtigungsinformationen zu Auftragsarten (HKD, HTD). Data type for user permissions with regard to distributed signatures (order types HKD, HTD). Administrative EBICS Auftragsart. BTF Service Parameter struktur im Falle von BTU/BTD Identification of the file format in the case of FUL/FDL Beschreibung der Auftragsart. Anzahl erforderlicher EUs (Default=0). Datentyp für zusätzliche Auftragsparameter bei Standard-Auftragsarten. Datumsbereich (von-bis). Startdatum (inkl.). Enddatum (inkl.). Attribute zur EBICS-Protokollversion und -revision. Attributes regarding the protocol version and revision of EBICS. Version des EBICS-Protokolls (z.B. "H00x"). Version of the EBICS protocol (e.g. "H00x"). Revision des EBICS-Protokolls (z.B. 1). Revision of the EBICS protocol (e.g. 1). zusätzliche Auftragsparameter für Auftragsart BTD. additional order parameters for order type BTD. zusätzliche Auftragsparameter für Auftragsart BTU. additional order parameters for order type BTU. Datentyp für BTF Download Parameter Service name - target system for the further processing of the order The file name on the client It can be transmitted optionally Datentyp für BTF Upload Parameter Service name - target system for the further processing of the order If not present the order doesn't contain any ES and shall be authorised outside EBICS If present the order shall be autorised within EBICS: 1. If the attribute VEU is also present the sender desires spooling into the VEU - hence in this case the order is not rejected in the case of not sufficient number of ES 2. If the attribute is not present all necessary ES must be inside the order (else: rejection of the order) The file name on the client It can be transmitted optionally Abstract Type containing all BTF params structures Service name - target system for the further processing of the order If not present the order doesn't contain any ES and shall be authorised outside EBICS If present the order shall be autorised within EBICS: 1. If the attribute VEU is also present the sender desires spooling into the VEU - hence in this case the order is not rejected in the case of not sufficient number of ES 2. If the attribute is not present all necessary ES must be inside the order (else: rejection of the order) The file name on the client It can be transmitted optionally Datentyp für die Angabe eines (Berichts-) Zeitraums Basis-Datentyp für Kennzeichen mit optionalem Attribut Datentyp für Meldungstyp-String mit optionalen Attributen Variant number of the message type (usable for ISO20022 messages) Version number of the message type (usable for ISO20022 messages) Encoding format of the message (e.g. XML, ASN1, JSON, PDF) Basisdatentyp für BTF-Service Parameter Set Service Code name: External list specified and maintained by EBICS. Basis is the "SWIFT-list" for the field "description" (SCT, DCT, XCT, SDD, DDD, STM, REP...) plus additional codes needed for further services Specifies whose rules have to be taken into account for the service. This means which market / comminity has defined the rules. If the element is absent a global definition for the service is assumed. External list specified and maintained by EBICS. In addition the following codes may be used: 2-character ISO country code or a 3-character issuer code (defined by EBICS) Service Option Code Additional option for the service (also depends on used scope) Container flag. If present, data is provided/requested in a container format specified in the attribute of the flag Name of the message, e.g. pain.001 or mt101 National message names (issued by DK, CFONB or SIC are also allowed) Type is arestriction of the generic ServiceType, defining the mandatory elements Service Code name: External list specified and maintained by EBICS. Basis is the "SWIFT-list" for the field "description" (SCT, DCT, XCT, SDD, DDD, STM, REP...) plus additional codes needed for further services Specifies whose rules have to be taken into account for the service. This means which market / comminity has defined the rules. If the element is absent a global definition for the service is assumed. External list specified and maintained by EBICS. In addition the following codes may be used: 2-character ISO country code or a 3-character issuer code (defined by EBICS) Service Option Code Additional option for the service (also depends on used scope) Container flag. If present, data is provided/requested in a container format specified in the attribute of the flag Name of the message, e.g. pain.001 or mt101 National message names (issued by DK, CFONB or SIC are also allowed) Container flag. If present, data is provided/requested in a container format specified in the attribute of the flag Specifies the container type - External Codelist defined by EBICS (starting values: XML, ZIP, SVC) Datentyp für BTF Signatur-Flag (ersetzt Orderkennzeichen) If present the sender desires spooling into EBICS distributed signature queue, only "true" is allowed Datentyp zur Kennzeichnung von Auftragsartenbeschränkungen Service Parameter-Sets von nicht unterstützten BTF-Auftragsarten libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_hev.xsd0000664000175000017500000001456115122266731025634 0ustar grothoffgrothoff ebics_hev.xsd ist das EBICS-Protokollschema entweder für Anfragen oder Rückmeldungen der Bank zu unterstützten EBICS-Versionen. ebics_hev.xsd is the appropriate EBICS protocol schema either for requests or responses according the EBICS versions supported by a bank. Datentyp für die Host-ID. Dataype for Host-ID. Datentyp für allgemeine Auftragsarten (Grundtyp). Datatype for general order types (basic type). Datentyp für Antwortcodes. Datatype for the return code Datentyp für den Erklärungstext zum Antwortcode. Datatype for report text with respect to the return code Datentyp für eine Versionsnummer Datatype for a release number Datentyp für Versionsnummer des EBICS-schemas Datatype for release-number of the EBICS scheme Datentyp für technische Fehler. Datatype for technical error Rückmeldung des Ausführungsstatus mit einer eindeutigen Fehlernummer. Confirmation of the carried out status with a unique error code. Klartext der Rückmeldung des Ausführungsstatus. Clear text of the response (carried out status). Datentyp für die Request-Daten Data type for Request data Datentyp für die Response-Daten Data type for Request data Von der Bank unterstützte EBICS-Versionen, z.B. 2.4 EBICS-releases supported by the bank, e.g. 2.4 der EBICS-Version eindeutig zugeordnete Schema-Version, z.B. H003 EBICS-scheme-version, e.g. H003, well-defined for EBICS-release-Version Requestdaten request data Responsedaten response data libeufin-1.6.8/libeufin-common/src/main/resources/xsd/camt.054.001.02.xsd0000664000175000017500000014505415122266731025661 0ustar grothoffgrothoff libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_response_H004.xsd0000664000175000017500000002145315122266731027401 0ustar grothoffgrothoff ebics_response_H004.xsd ist das EBICS-Protokollschema für Antwortnachrichten. ebics_response_H004.xsd is the appropriate EBICS protocol schema for standard responses. XML-Signature. Electronic Banking Internet Communication Standard des Zentralen Kreditausschusses (ZKA): Multibankfähige Schnittstelle zur internetbasierten Kommunikation. Electronic Banking Internet Communication Standard of the "Zentraler Kreditausschuss (ZKA)": multi-bank capable interface for internet-based communication. enthält die technischen Transaktionsdaten. contains the transaction-driven data. enhält alle festen Headereinträge. contains the static header entries. enthält alle variablen Headereinträge. contains the mutable header entries. Authentifikationssignatur. Authentication signature. enthält die Auftragsdaten, EU(s) und weitere Nutzdaten. contains order data, order signature(s) and further data referring to the current order. Transfer von Auftragsdaten; nur bei Download anzugeben. Transfer of signature or order data; mandatory for downloads only. fachlicher Antwortcode für den vorangegangenen Request. order-related return code of the previous request. Zeitstempel der letzten Aktualisierung der Bankparameter; nur in der Initialisierungsphase anzugeben. timestamp indicating the latest update of the bank parameters; may be set during initialisation phase only. Datentyp für den statischen EBICS-Header. Data type for the static EBICS header. eindeutige, technische Transaktions-ID; wird vom Server vergeben, falls OrderAttribute entweder gleich "OZHNN" oder gleich "DZHNN" ist und falls tatsächlich eine Transaktion erzeugt wurde. unique transaction ID, provided by the server if and only if the order attribute is set to either "OZHNN" or "DZHNN" and if a transaction has been established actually. Gesamtsegmentanzahl für diese Transaktion; nur bei Downloads in der Initialisierungsphase anzugeben. Total number of segments for this transaction; mandatory for downloads in initialisation phase only. Datentyp für den variablen EBICS-Header. Data type for the mutable EBICS header. Phase, in der sich die Transaktion gerade befindet; wird bei jedem Transaktionsschritt vom Client gesetzt und vom Server übernommen. Current phase of the transaction; this information is provided by the client for each step of the transaction, and the server adopts the setting. enthält die Nummer des aktuellen Segments, welches gerade übertragen oder angefordert wird; nur anzugeben bei TransactionPhase=Transfer und (bei Download) TransactionPhase=Initialisation. contains the number of the segment which is currently being transmitted or requested; mandatory for transaction phases 'Transfer' and (for downloads) 'Initialisation' only. Ist dies das letzte Segment der Übertragung? Auftragsnummer von Sendeaufträgen gemäß DFÜ-Abkommen. Rückmeldung des technischen Status mit einer eindeutigen Fehlernummer. Return code indicating the technical status. Klartext der Rückmeldung des technischen Status. Textual interpretation of the returned technical status code. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_H004.xsd0000664000175000017500000000165415122266731025464 0ustar grothoffgrothoff ebics_H004.xsd inkludiert alle Schemadateien des EBICS-Protokolls, um die Eindeutigkeit von Element- und Typnamen im EBCIS Namespace zu erzwingen. ebics_H004.xsd includes all schema files for the EBICS protocol in order to enforce unique element and type names in the EBICS namespace. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/pain.001.001.09.ch.03.xsd0000664000175000017500000022166215122266731026475 0ustar grothoffgrothoff libeufin-1.6.8/libeufin-common/src/main/resources/xsd/pain.001.001.03.xsd0000664000175000017500000010716615122266731025657 0ustar grothoffgrothoff libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_request_H005.xsd0000664000175000017500000004273015122266731027235 0ustar grothoffgrothoff ebics_request_H005.xsd ist das EBICS-Protokollschema für Anfragen. ebics_request_H005.xsd is the appropriate EBICS protocol schema for standard requests. Electronic Banking Internet Communication Standard of the EBICS SCRL: Multibankfähige Schnittstelle zur internetbasierten Kommunikation. Electronic Banking Internet Communication Standard der EBICS SCRL: multi-bank capable interface for internet-based communication. enthält die technischen Transaktionsdaten. contains the transaction-driven data. enhält alle festen Headereinträge. contains the static header entries. enthält alle variablen Headereinträge. contains the mutable header entries. enthält die Auftragsdaten, EU(s) und weitere Nutzdaten. contains order data, order signature(s) and further data referring to the current order. X.509-Daten des Teilnehmers. X.509 data of the user. Welche Transaktionsphase? Which transaction phase? Initialisierungs- und Transferphase. Initialisation or transfer phase. Daten zur Vorabprüfung; nur anzugeben in der Initialisierungsphase bei Uploads mit Auftragsattribut OZH (EUs + Auftragsdaten). Data sent for pre-validation; mandatory for initialisation phase during uploads using order attribute OZH (order signature(s) + order data). Transfer von Signatur- bzw. Auftragsdaten; nur bei Upload anzugeben. Transfer of signature or order data; mandatory for uploads only. Quittierungsphase nach Download. Receipt phase after download. Quittierung des Transfers. Receipt of transfer. Datentyp für den statischen EBICS-Header. Data type for the static EBICS header. Hostname des Banksystems. Transaktionsphase? Transaction phase? Initialisierungsphase. Initialisation phase. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig. Random value, ensures the uniqueness of the client's message during initialisation phase. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung. current timestamp, used to limit storage space for nonces on the server. Kunden-ID des serverseitig administrierten Kunden. ID of the partner = customer, administered on the server. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. ID of the user that is assigned to the given customer, administered on the server. technische User-ID für Multi-User-Systeme. ID of the system for multi-user systems. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. software ID / manufacturer ID / manufacturer's name of the customer's software package. Sprachkennzeichen der Kundenproduktversion (gemäß ISO 639). Language code of the customer's software package according to ISO 639. Kennung des Herausgebers des Kundenprodukts bzw. des betreuenden Kreditinstituts. ID of the manufacturer / financial institute providing support for the customer's software package. Auftragsdetails. order details. Hashwerte der erwarteten öffentlichen Schlüssel (Verschlüsselung, Signatur, Authentifikation) des Kreditinstituts. Digest values of the expected public keys (authentication, encryption, signature) owned by the financial institute. Hashwert des Authentifikationsschlüssels. Digest value of the public authentication key. Version des Authentifikationsverfahrens. Version of the algorithm used for authentication. Hashwert des Verschlüsselungsschlüssels. Digest value of the public encryption key. Version des Verschlüsselungsverfahrens. Version of the algorithm used for encryption. Hashwert des Signaturschlüssels. Digest value of the public signature key. Version des Signaturverfahrens. Version of the algorithm used for signature creation. Angabe des Sicherheitsmediums, das der Kunde verwendet. Classification of the security medium used by the customer. Gesamtsegmentanzahl für diese Transaktion; nur bei Uploads anzugeben. Total number of segments for this transaction; mandatory for uploads only. Transfer- und Quittierungsphase. Transfer or receipt phase. eindeutige, technische Transaktions-ID; wird vom Server vergeben. unique transaction ID, provided by the server. Datentyp für den variablen EBICS-Header. Data type for the mutable EBICS header. Phase, in der sich die Transaktion gerade befindet; wird bei jedem Transaktionsschritt vom Client gesetzt und vom Server übernommen. Current phase of the transaction; this information is provided by the client for each step of the transaction, and the server adopts the setting. enthält die Nummer des aktuellen Segments, welches gerade übertragen oder angefordert wird; nur anzugeben bei TransactionPhase=Transfer. contains the number of the segment which is currently being transmitted or requested; mandatory for transaction phase 'Transfer' only. Ist dies das letzte Segment der Übertragung? Is this segment meant to be the last one regarding this transmission? //MODIFIED - Removed OrderAtribute ELEMENT// Datentyp für Auftragsdetails im statischen EBICS-Header. Data type for order details stored in the static EBICS header. //MODIFIED - Umbenannt von OrderType// Auftragsart. type code of the order. Auftragsnummer für Sendeaufträge gemäß DFÜ-Abkommen. ID of the (upload) order, formatted in accordance with the document "DFÜ-Abkommen". libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_H005.xsd0000664000175000017500000000165415122266731025465 0ustar grothoffgrothoff ebics_H005.xsd inkludiert alle Schemadateien des EBICS-Protokolls, um die Eindeutigkeit von Element- und Typnamen im EBCIS Namespace zu erzwingen. ebics_H005.xsd includes all schema files for the EBICS protocol in order to enforce unique element and type names in the EBICS namespace. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_keymgmt_response_H004.xsd0000664000175000017500000001333115122266731031132 0ustar grothoffgrothoff ebics_keymgmt_response_H004.xsd ist das EBICS-Protokollschema für Schlüsselmanagement-Antwortnachrichten (HIA, HPB, HSA, INI). XML-Signature. Electronic Banking Internet Communication Standard des Zentralen Kreditausschusses (ZKA): Multibankfähige Schnittstelle zur internetbasierten Kommunikation. enthält die technischen Transaktionsdaten. enhält alle festen Headereinträge. enthält alle variablen Headereinträge. enthält die Auftragsdaten und den fachlichen ReturnCode. Transfer von Auftragsdaten; nur bei Download anzugeben (HPB). Informationen zur Verschlüsselung der Auftragsdaten enthält Auftragsdaten. Antwortcode für den vorangegangenen Transfer. Zeitstempel der letzten Aktualisierung der Bankparameter; nur in der Initialisierungsphase anzugeben. Datentyp für den variablen EBICS-Header. Auftragsnummer von Sendeaufträgen gemäß DFÜ-Abkommen (used for all key management order types except download order type HPB). Rückmeldung des Ausführungsstatus mit einer eindeutigen Fehlernummer. Klartext der Rückmeldung des Ausführungsstatus. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_signatures.xsd0000664000175000017500000002334115122266731027232 0ustar grothoffgrothoff ebics_signature enthält Typdefinitionen für elektronische Unterschriften der Versionen A004, A005, A006 und folgende. ebics_EU contains type definitions for electronic signatures: versions A005, A006 and et sqq. XML-Strukturen für bankfachliche Elektronische Unterschriften (EUs). contains the digital signatures. enthält die EUs der Teilnehmer. contains the digital signatures. Datentyp für Signaturdaten des Teilnehmers beim EU-Transfer. Data type for digital signature data transferred using EBICS. bankfachliche Elektronische Unterschrift oder Transportunterschrift (Binärformat). Digital signature (either autorising an order or applied for transportation), binary format. Kunden-ID des Unterzeichners. Customer ID of the signer. bankfachliche Elektronische Unterschrift oder Transportunterschrift (strukturiertes Format). Digital signature (either autorising an order or applied for transportation), structured format. Datentyp für kryptographische Unterschriften. bankfachliche Elektronische Unterschrift oder Transportunterschrift (strukturiertes Format). Digital signature (either autorising an order or applied for transportation), structured format. Datentyp für bankfachliche Elektronische Unterschrift oder Transportunterschrift (strukturiertes Format). Data type according for a digital signature (either autorising an order or applied for transportation), structured format. Version des Signaturverfahrens. Version of the algorithm used for signature creation. Digitale Signatur. Digital signature. Kunden-ID des Unterzeichners. Customer ID of the signer. Teilnehmer-ID. User ID. Parameter zur X.509-Funktionalität Parameter for X509Data Datentyp für eine Kunden-ID. Datentyp für eine Teilnehmer-ID. Datentyp für Versionsnummern zur Elektronischen Unterschrift (EU). Element für Public Key Dateien unabhängig von der Auftragsart / Geschäftsvorfall. Datentyp für Public Key Dateien unabhängig von der Auftragsart / Geschäftsvorfall. öffentlicher Signaturschlüssel. Kunden-ID. Teilnehmer-ID. öffentlicher Signaturschlüssel. Datentyp für öffentliche bankfachliche Schlüssel. Version des EU-Signaturverfahrens. Datentyp für die Darstellung eines öffentlichen RSA-Schlüssels als Exponent-Modulus-Kombination oder als X509-Zertifikat. Darstellung als Exponent-Modulus-Kombination. Datentyp für die Exponent-Modulus-Darstellung eines öffentlichen RSA-Schlüssels. Zeitpunkt der Generierung des Schlüssels. Datentyp für Zeitstempel. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_signature_S002.xsd0000664000175000017500000002022715122266731027553 0ustar grothoffgrothoff ebics_signature enthält Typdefinitionen für elektronische Unterschriften der Versionen A005, A006 und folgende. ebics_EU contains type definitions for electronic signatures: versions A005, A006 and et sqq. XML-Strukturen für bankfachliche Elektronische Unterschriften (EUs). contains the digital signatures. enthält die EUs der Teilnehmer. contains the digital signatures. Datentyp für Signaturdaten des Teilnehmers beim EU-Transfer. Data type for digital signature data transferred using EBICS. bankfachliche Elektronische Unterschrift oder Transportunterschrift (strukturiertes Format). Digital signature (either autorising an order or applied for transportation), structured format. Datentyp für kryptographische Unterschriften. bankfachliche Elektronische Unterschrift oder Transportunterschrift (strukturiertes Format). Digital signature (either autorising an order or applied for transportation), structured format. Datentyp für bankfachliche Elektronische Unterschrift oder Transportunterschrift (strukturiertes Format). Data type according for a digital signature (either autorising an order or applied for transportation), structured format. Version des Signaturverfahrens. Version of the algorithm used for signature creation. Digitale Signatur. Digital signature. Kunden-ID des Unterzeichners. Customer ID of the signer. Teilnehmer-ID. User ID. Parameter zur X.509-Funktionalität Parameter for X509Data Datentyp für eine Kunden-ID. Datentyp für eine Teilnehmer-ID. Datentyp für Versionsnummern zur Elektronischen Unterschrift (EU). Element für Public Key Dateien unabhängig von der Auftragsart / Geschäftsvorfall. Datentyp für Public Key Dateien unabhängig von der Auftragsart / Geschäftsvorfall. öffentlicher Signaturschlüssel. Kunden-ID. Teilnehmer-ID. öffentlicher Signaturschlüssel. Datentyp für öffentliche bankfachliche Schlüssel. Version des EU-Signaturverfahrens. Datentyp für die Darstellung eines öffentlichen RSA-Schlüssels als Exponent-Modulus-Kombination oder als X509-Zertifikat. Datentyp für Zeitstempel. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/camt.052.001.02.xsd0000664000175000017500000015121615122266731025654 0ustar grothoffgrothoff libeufin-1.6.8/libeufin-common/src/main/resources/xsd/xmldsig-core-schema.xsd0000664000175000017500000002454015122266731027536 0ustar grothoffgrothoff libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_response_H005.xsd0000664000175000017500000002170015122266731027375 0ustar grothoffgrothoff ebics_response_H005.xsd ist das EBICS-Protokollschema für Antwortnachrichten. ebics_response_H005.xsd is the appropriate EBICS protocol schema for standard responses. XML-Signature. Electronic Banking Internet Communication Standard des Zentralen Kreditausschusses (ZKA): Multibankfähige Schnittstelle zur internetbasierten Kommunikation. Electronic Banking Internet Communication Standard of the "Zentraler Kreditausschuss (ZKA)": multi-bank capable interface for internet-based communication. enthält die technischen Transaktionsdaten. contains the transaction-driven data. enhält alle festen Headereinträge. contains the static header entries. enthält alle variablen Headereinträge. contains the mutable header entries. Authentifikationssignatur. Authentication signature. enthält die Auftragsdaten, EU(s) und weitere Nutzdaten. contains order data, order signature(s) and further data referring to the current order. Transfer von Auftragsdaten; nur bei Download anzugeben. Transfer of signature or order data; mandatory for downloads only. fachlicher Antwortcode für den vorangegangenen Request. order-related return code of the previous request. Zeitstempel der letzten Aktualisierung der Bankparameter; nur in der Initialisierungsphase anzugeben. timestamp indicating the latest update of the bank parameters; may be set during initialisation phase only. //TODO - Modify anotation TransactionID// Datentyp für den statischen EBICS-Header. Data type for the static EBICS header. eindeutige, technische Transaktions-ID; wird vom Server vergeben, falls OrderAttribute entweder gleich "OZHNN" oder gleich "DZHNN" ist und falls tatsächlich eine Transaktion erzeugt wurde. unique transaction ID, provided by the server if and only if the order attribute is set to either "OZHNN" or "DZHNN" and if a transaction has been established actually. Gesamtsegmentanzahl für diese Transaktion; nur bei Downloads in der Initialisierungsphase anzugeben. Total number of segments for this transaction; mandatory for downloads in initialisation phase only. Datentyp für den variablen EBICS-Header. Data type for the mutable EBICS header. Phase, in der sich die Transaktion gerade befindet; wird bei jedem Transaktionsschritt vom Client gesetzt und vom Server übernommen. Current phase of the transaction; this information is provided by the client for each step of the transaction, and the server adopts the setting. enthält die Nummer des aktuellen Segments, welches gerade übertragen oder angefordert wird; nur anzugeben bei TransactionPhase=Transfer und (bei Download) TransactionPhase=Initialisation. contains the number of the segment which is currently being transmitted or requested; mandatory for transaction phases 'Transfer' and (for downloads) 'Initialisation' only. Ist dies das letzte Segment der Übertragung? Auftragsnummer von Sendeaufträgen gemäß DFÜ-Abkommen. Rückmeldung des technischen Status mit einer eindeutigen Fehlernummer. Return code indicating the technical status. Klartext der Rückmeldung des technischen Status. Textual interpretation of the returned technical status code. libeufin-1.6.8/libeufin-common/src/main/resources/xsd/camt.053.001.02.xsd0000664000175000017500000015117315122266731025657 0ustar grothoffgrothoff libeufin-1.6.8/libeufin-common/src/main/resources/xsd/pain.002.001.13.xsd0000664000175000017500000017553015122266731025661 0ustar grothoffgrothoff libeufin-1.6.8/libeufin-common/src/main/resources/xsd/ebics_keymgmt_request_H004.xsd0000664000175000017500000005627315122266731031000 0ustar grothoffgrothoff ebics_keymgmt_request_H004.xsd ist das EBICS-Protokollschema für Schlüsselmanagement-Anfragen (HIA, HPB, HSA, INI). XML-Signature. Datentyp für den statischen EBICS-Header (allgemein). Hostname des Banksystems. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig; nur anzugeben, falls Authentifikationssignatur vorhanden. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung; nur anzugeben, falls Authentifikationssignatur vorhanden. Kunden-ID des serverseitig administrierten Kunden. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. technische User-ID für Multi-User-Systeme. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Auftragsdetails. Angabe des Sicherheitsmediums, das der Kunde verwendet. Datentyp für OrderDetails im statischen EBICS-Header (allgemein). Auftragsart. Auftragsattribut. Datentyp für Element mit Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Sprachkennzeichen der Kundenproduktversion (gemäß ISO 639). Kennung des Herausgebers des Kundenprodukts bzw. des betreuenden Kreditinstituts. Datentyp für den leeren variablen EBICS-Header von Key Managemen Aufträgen. Anfragestruktur für ungesicherte Auftragsarten HIA (Authentifikations- und Verschlüsselungsschlüssel senden) und INI (bankfachllichen Schlüssel senden). enthält die technischen Transaktionsdaten. enhält alle festen Headereinträge. enthält alle variablen Headereinträge. enthält die Auftragsdaten. Transfer von Auftragsdaten. enthält Auftragsdaten. Datentyp für den statischen EBICS-Header bei ungesicherten Sendeauftragsarten (Aufträge HIA und INI): kein Nonce, kein Timestamp, keine EU-Datei, keine X001 Authentifizierung, keine Verschlüsselung, keine Digests der öffentlichen Bankschlüssel, Nutzdaten komprimiert, Auftragsattribut DZNNN Hostname des Banksystems. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig; nicht anzugeben für ebicsUnsecuredRequest. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung; nicht anzugeben für ebicsUnsecuredRequest. Kunden-ID des serverseitig administrierten Kunden. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. technische User-ID für Multi-User-Systeme. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Auftragsdetails. Angabe des Sicherheitsmediums, das der Kunde verwendet. Datentyp für OrderDetails im statischen EBICS-Header von ebicsUnsecuredRequest. Auftragsart. Auftragsattribut: DZNNN. Anfragestruktur für Auftragsarten ohne Übertragung der Digests der öffentlichen Bankschlüssel (HPB Bankschlüssel abholen). enthält die technischen Transaktionsdaten. enhält alle festen Headereinträge. enthält alle variablen Headereinträge. Authentifikationssignatur. enthält optionale Zertifikate (vorgesehen). X.509-Daten des Teilnehmers. Datentyp für den statischen EBICS-Header bei Aufträgen ohne Übertragung der Digests der Bankschlüssel (Auftrag HBP): keine Digests der öffentlichen Bankschlüssel, keine EU-Datei, keine Nutzdaten, OrderId optional!, Nonce, Timestamp, X001 Authentifizierung, Auftragsattribut DZHNN Hostname des Banksystems. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung. Kunden-ID des serverseitig administrierten Kunden. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. technische User-ID für Multi-User-Systeme. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Auftragsdetails. Angabe des Sicherheitsmediums, das der Kunde verwendet. Datentyp für OrderDetails im statischen EBICS-Header von ebicsNoPubKeyDigestsRequest. Auftragsart. Auftragsattribut: DZHNN. The structure for uploads contains order data and the ESs, but without an authentication signature and data digest of bank keys. Anfragestruktur für Sendeaufträge mit EU-Datei und Nutzdaten aber ohne Authentifizierungssignatur und Digests der Bankschlüssel. Contains technical transaction data. enthält die technischen Transaktionsdaten. Contains all fixed header entries. enhält alle festen Headereinträge. Contains all mutable header entries. enthält alle variablen Headereinträge. Contains the order data and the ESs. enthält die Auftragsdaten und EUs. Transfer of order data and the ESs. Transfer von Auftragsdaten und EUs. Contains the ESs. enthält Signaturdaten (EUs). Contains the order data enthält Auftragsdaten. Datentyp für den statischen EBICS-Header für ebicsUnsignedRequest.Datentyp für den statischen EBICS-Header bei Aufträgen ohne Authentifizierungssignatur (Auftrag HSA): keine X001 Authentifizierung, keine Digests der öffentlichen Bankschlüssel, EU-Datei, Nutzdaten, Nonce, Timestamp, OrderId, Auftragsattribut OZNNN Hostname des Banksystems. Zufallswert; damit wird die Initialisierungsnachricht des Clients einzigartig; nicht anzugeben bei ebicsUnsignedRequest. aktueller Zeitstempel zur Begrenzung der serverseitigen Nonce-Speicherung; nicht anzugeben bei ebicsUnsignedRequest. Kunden-ID des serverseitig administrierten Kunden. Teilnehmer-ID des serverseitig zu diesem Kunden administrierten Teilnehmers. technische User-ID für Multi-User-Systeme. Kennung des Kundenprodukts bzw. Herstellerkennung oder Name. Auftragsdetails. Angabe des Sicherheitsmediums, das der Kunde verwendet. Datentyp für OrderDetails im statischen EBICS-Header von ebicsUnsignedRequest. Auftragsart. Auftragsattribut: OZNNN. libeufin-1.6.8/libeufin-common/src/main/resources/META-INF/0000775000175000017500000000000015236145704023522 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/main/resources/META-INF/services/0000775000175000017500000000000015236145704025345 5ustar grothoffgrothoff././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootlibeufin-1.6.8/libeufin-common/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProviderlibeufin-1.6.8/libeufin-common/src/main/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvid0000664000175000017500000000005115122266731033212 0ustar grothoffgrothofftech.libeufin.common.TalerServiceProviderlibeufin-1.6.8/libeufin-common/src/test/0000775000175000017500000000000015236145704020403 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/test/kotlin/0000775000175000017500000000000015236145704021703 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/test/kotlin/IbanTest.kt0000664000175000017500000000235015122266731023752 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.* import kotlin.test.assertEquals class IbanTest { @Test fun valid() { for ((iban, bban) in VALID_IBAN) { val parsed = IBAN.parse(iban) } } @Test fun roundtrip() { for (country in Country.values()) { val gen = IBAN.rand(country) println("$gen") val parsed = IBAN.parse("$gen") println("$gen $parsed") assertEquals(gen, parsed) } } }libeufin-1.6.8/libeufin-common/src/test/kotlin/TlsTest.kt0000664000175000017500000000326715122266731023653 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.* import io.ktor.client.request.* import io.ktor.client.plugins.* import io.ktor.http.* import org.junit.Test import kotlin.io.path.Path import kotlin.io.path.writeBytes import kotlin.test.assertEquals import kotlin.test.assertFails import java.security.Security import kotlinx.coroutines.runBlocking import tech.libeufin.common.setupSecurityProperties class TlsTest { @Test fun securityCheck() = runBlocking { setupSecurityProperties() val secureClient = HttpClient() val checks = sequenceOf( "expired", "wrong.host", "self-signed", "untrusted-root", "revoked", // "no-sct", TODO when java support this "preact-cli" ) for (check in checks) { println("https://$check.badssl.com") assertFails { secureClient.get("https://$check.badssl.com") } } } }libeufin-1.6.8/libeufin-common/src/test/kotlin/ParamsTest.kt0000664000175000017500000000523015236062741024325 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import org.junit.Test import tech.libeufin.common.* import kotlin.test.* class ParamsTest { @Test fun parse() { fun String.check(timeout_ms: Long, limit: Int, offset: Long) { val parameters = this.parseUrlEncodedParameters() val parsed = HistoryParams.extract(parameters) assertEquals(HistoryParams(PageParams(limit, offset), PollingParams(timeout_ms)), parsed) } fun String.fail(msg: String) { val parameters = this.parseUrlEncodedParameters() val e = assertFailsWith { HistoryParams.extract(parameters) } assertEquals(HttpStatusCode.BadRequest, e.httpStatus) assertEquals(msg, e.message) } sequenceOf( "long_poll_ms=1&delta=2&offset=3", "timeout_ms=1&limit=2&start=3", "long_poll_ms=1&delta=2&offset=3&timeout_ms=1&limit=2&start=3" ).forEach { case -> case.check(1, 2, 3) } "".check(0, -20, Long.MAX_VALUE) "limit=1".check(0, 1, 0) "limit=${MAX_PAGE_SIZE}".check(0, MAX_PAGE_SIZE, 0) "limit=0".fail("Param 'limit' must be non-zero") "limit=${MAX_PAGE_SIZE+1}".fail("Param 'limit' must be <= ${MAX_PAGE_SIZE}") "limit=${-MAX_PAGE_SIZE}".check(0, -MAX_PAGE_SIZE, Long.MAX_VALUE) "limit=${-MAX_PAGE_SIZE-1}".fail("Param 'limit' must be >= ${-MAX_PAGE_SIZE}") "limit=${Int.MIN_VALUE}".fail("Param 'limit' must be >= ${-MAX_PAGE_SIZE}") "offset=-1".fail("Param 'offset' must be a positive number") "long_poll_ms=${MAX_TIMEOUT_MS+1}&limit=10".check(MAX_TIMEOUT_MS, 10, 0) "long_poll_ms=1&timeout_ms=2".fail("Param 'timeout_ms' cannot be used with param 'long_poll_ms'") "limit=1&delta=2".fail("Param 'limit' cannot be used with param 'delta'") "offset=1&start=2".fail("Param 'offset' cannot be used with param 'start'") } }libeufin-1.6.8/libeufin-common/src/test/kotlin/SubjectTest.kt0000664000175000017500000001757515156463305024522 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import tech.libeufin.common.* import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFails class SubjectTest { fun assertFailsMsg(msg: String, lambda: () -> Unit) { val failure = assertFails(lambda) assertEquals(msg, failure.message) } @Test fun parseIncoming() { val key = "4MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0"; val other = "00Q979QSMJ29S7BJT3DDAVC5A0DR5Z05B7N0QT1RCBQ8FXJPZ6RG"; for (ty in sequenceOf(IncomingType.reserve, IncomingType.kyc, IncomingType.map)) { val prefix = when (ty) { IncomingType.reserve -> "" IncomingType.kyc -> "KYC" IncomingType.map -> "MAP" } val standard = "$prefix$key" val (standardL, standardR) = standard.chunked(standard.length / 2 + 1) val mixed = "${prefix}4mzt6RS3rvb3b0e2rdmyw0yra3y0vphyv0cyde6xbb0ympfxceg0" val (mixedL, mixedR) = mixed.chunked(mixed.length / 2 + 1) val other_standard = "$prefix$other" val other_mixed = "${prefix}TEGY6d9mh9pgwvwpgs0z0095z854xegfy7jj202yd0esp8p0za60" val key = when (ty) { IncomingType.reserve -> IncomingSubject.Reserve(EddsaPublicKey(key)) IncomingType.kyc -> IncomingSubject.Kyc(EddsaPublicKey(key)) IncomingType.map -> IncomingSubject.Map(EddsaPublicKey(key)) } // Check succeed if standard or mixed for (case in sequenceOf(standard, mixed)) { for (test in sequenceOf( "noise $case noise", "$case noise to the right", "noise to the left $case", " $case ", "noise\n$case\nnoise", "Test+$case" )) { assertEquals(key, parseIncomingSubject(test)) } } // Check succeed if standard or mixed and split for ((L, R) in sequenceOf(standardL to standardR, mixedL to mixedR)) { for (case in sequenceOf( "left $L$R right", "left $L $R right", "left $L-$R right", "left $L+$R right", "left $L\n$R right", "left $L%20$R right", "left $L-+\n$R right", "left $L - $R right", "left $L + $R right", "left $L \n $R right", "left $L - + \n $R right", )) { assertEquals(key, parseIncomingSubject(case)) } } // Check concat parts for (chunkSize in 1 until standard.length) { val chunked = standard.chunked(chunkSize).joinToString(" ") for (case in sequenceOf(chunked, "left ${chunked} right")) { assertEquals(key, parseIncomingSubject(case)) } } // Check failed when multiple key for (case in sequenceOf( "$standard $other_standard", "$mixed $other_mixed", )) { assertFailsMsg("found multiple reserve public key") { parseIncomingSubject(case) } } // Check accept redundant key for (case in sequenceOf( "$standard $standard $mixed $mixed", // Accept redundant key "$mixedL-$mixedR $standardL-$standardR", "$standard $other_mixed", // Prefer high quality )) { assertEquals(key, parseIncomingSubject(case)) } // Check failure if malformed or missing for (case in sequenceOf( "does not contain any reserve", // Check fail if none standard.substring(1), // Check fail if missing char "2MZT6RS3RVB3B0E2RDMYW0YRA3Y0VPHYV0CYDE6XBB0YMPFXCEG0" // Check fail if not a valid key )) { assertFailsMsg("missing reserve public key") { parseIncomingSubject(case) } } if (ty == IncomingType.kyc) { // Prefer prefixed over unprefixed for (case in sequenceOf( "$other $standard", "$other $mixed" )) { assertEquals(key, parseIncomingSubject(case)) } } } // Admin balance adjust for (subject in sequenceOf( "ADMIN BALANCE ADJUST", "ADMIN:BALANCE:ADJUST", "AdminBalanceAdjust", "ignore aDmIn:BaLaNCe AdJUsT" )) { assertEquals( IncomingSubject.AdminBalanceAdjust, parseIncomingSubject(subject) ) } } /** Test parsing logic using real use case */ @Test fun realIncoming() { // Good reserve cases for ((subject, key) in sequenceOf( "Taler TEGY6d9mh9pgwvwpgs0z0095z854xegfy7j j202yd0esp8p0za60" to "TEGY6d9mh9pgwvwpgs0z0095z854xegfy7jj202yd0esp8p0za60", "00Q979QSMJ29S7BJT3DDAVC5A0DR5Z05B7N 0QT1RCBQ8FXJPZ6RG" to "00Q979QSMJ29S7BJT3DDAVC5A0DR5Z05B7N0QT1RCBQ8FXJPZ6RG", "Taler NDDCAM9XN4HJZFTBD8V6FNE2FJE8G Y734PJ5AGQMY06C8D4HB3Z0" to "NDDCAM9XN4HJZFTBD8V6FNE2FJE8GY734PJ5AGQMY06C8D4HB3Z0", "KYCVEEXTBXBEMCS5R64C24GFNQVWBN5R2F9QSQ7PN8QXAP1NG4NG" to "KYCVEEXTBXBEMCS5R64C24GFNQVWBN5R2F9QSQ7PN8QXAP1NG4NG", "Taler%20NDDCAM9XN4HJZFTBD8V6FNE2FJE8G Y734PJ5AGQMY06C8D4HB3Z0" to "NDDCAM9XN4HJZFTBD8V6FNE2FJE8GY734PJ5AGQMY06C8D4HB3Z0", )) { assertEquals( IncomingSubject.Reserve(EddsaPublicKey(key)), parseIncomingSubject(subject) ) } // Good kyc cases for ((subject, key) in sequenceOf( "KYC JW398X85FWPKKMS0EYB6TQ1799RMY5DDXTZ FPW4YC3WJ2DWSJT70" to "JW398X85FWPKKMS0EYB6TQ1799RMY5DDXTZFPW4YC3WJ2DWSJT70" )) { assertEquals( IncomingSubject.Kyc(EddsaPublicKey(key)), parseIncomingSubject(subject) ) } } @Test fun outgoing() { val key = ShortHashCode.rand() run { // Without metadata val subject = "$key http://exchange.example.com/" val parsed = parseOutgoingSubject(subject) assertEquals(parsed, Triple(key, BaseURL.parse("http://exchange.example.com/"), null)) assertEquals(subject, fmtOutgoingSubject(parsed.first, parsed.second, parsed.third)) } run { // With metadata val subject = "Accounting:id.42 $key http://exchange.example.com/" val parsed = parseOutgoingSubject(subject) assertEquals( parsed, Triple(key, BaseURL.parse("http://exchange.example.com/"), "Accounting:id.42") ) assertEquals(subject, fmtOutgoingSubject(parsed.first, parsed.second, parsed.third)) } } } libeufin-1.6.8/libeufin-common/src/test/kotlin/BaseUrlTest.kt0000664000175000017500000000310715122266731024437 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.* import kotlin.test.* class BaseUrlTest { @Test fun test() { for (valid in listOf( "https://www.example.com/", "http://localhost:8080/", "https://api.example.com/v1/", "https://example.com:3000/path/", )) { val parsed = BaseURL.parse(valid) assertEquals(parsed.toString(), valid) } for (invalid in listOf( "https://example.com?param=value", "https://example.com#section", "https://not.a/base/url", "file://not.http.com/", "not-a-url", "no.transport.com/", "://example.com", "https://", "", " ", )) { assertFails { BaseURL.parse(invalid) } } } }libeufin-1.6.8/libeufin-common/src/test/kotlin/PaytoTest.kt0000664000175000017500000000775515157322161024211 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.BankPaytoCtx import tech.libeufin.common.CommonError import tech.libeufin.common.Payto import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertNull import java.net.URL class PaytoTest { @Test fun wrongCases() { assertFailsWith { Payto.parse("http://iban/BIC123/IBAN123?receiver-name=The%20Name") } assertFailsWith { Payto.parse("payto:iban/BIC123/IBAN123?receiver-name=The%20Name&address=house") } assertFailsWith { Payto.parse("payto://wrong/BIC123/IBAN123?sender-name=Foo&receiver-name=Foo") } } @Test fun parsePaytoTest() { val withBic = Payto.parse("payto://iban/BIC123/CH9300762011623852957?receiver-name=The%20Name").expectIban() assertEquals(withBic.iban.value, "CH9300762011623852957") assertEquals(withBic.receiverName, "The Name") val complete = Payto.parse("payto://iban/BIC123/CH9300762011623852957?receiver-name=The%20Name&amount=EUR:1&message=donation").expectIban() assertEquals(complete.iban.value, "CH9300762011623852957") assertEquals(complete.receiverName, "The Name") assertEquals(complete.message, "donation") assertEquals(complete.amount.toString(), "EUR:1") val plusEncode = Payto.parse("payto://iban/BIC123/CH9300762011623852957?receiver-name=Santa+Claus&amount=EUR:1&message=donation").expectIban() assertEquals(plusEncode.iban.value, "CH9300762011623852957") assertEquals(plusEncode.receiverName, "Santa Claus") val withoutOptionals = Payto.parse("payto://iban/CH9300762011623852957").expectIban() assertNull(withoutOptionals.message) assertNull(withoutOptionals.receiverName) assertNull(withoutOptionals.amount) val malformed = Payto.parse("payto://iban/CH0400766000103138557?receiver-name=NYM%20Technologies%SA").expectIban() assertEquals(malformed.iban.value, "CH0400766000103138557") assertEquals(malformed.receiverName, "NYM Technologies%SA") } @Test fun forms() { val ctx = BankPaytoCtx( bic = "TESTBIC", hostname = "test.com" ) val canonical = "payto://iban/CH9300762011623852957" val bank = "payto://iban/TESTBIC/CH9300762011623852957?receiver-name=Name" val inputs = listOf( "payto://iban/BIC/CH9300762011623852957?receiver-name=NotGiven", "payto://iban/CH9300762011623852957?receiver-name=Grothoff%20Hans", "payto://iban/ch%209300-7620-1162-3852-957", ) val names = listOf( "NotGiven", "Grothoff Hans", null ) val full = listOf( "payto://iban/BIC/CH9300762011623852957?receiver-name=Santa", "payto://iban/CH9300762011623852957?receiver-name=Santa", "payto://iban/CH9300762011623852957?receiver-name=Santa", ) for ((i, input) in inputs.withIndex()) { val payto = Payto.parse(input).expectIban() assertEquals(canonical, payto.canonical) assertEquals(bank, payto.bank("Name", ctx)) assertEquals(full[i], payto.full("Santa")) assertEquals(names[i], payto.receiverName) } } }libeufin-1.6.8/libeufin-common/src/test/kotlin/ConfigTest.kt0000664000175000017500000003051515122266731024312 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import com.github.ajalt.clikt.testing.test import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.db.currentUser import tech.libeufin.common.db.jdbcFromPg import uk.org.webcompere.systemstubs.SystemStubs.withEnvironmentVariable import java.io.ByteArrayOutputStream import java.io.PrintStream import java.time.Duration import kotlin.io.path.* import kotlin.test.assertEquals import kotlin.test.assertFails import kotlin.test.assertFailsWith class ConfigTest { @Test fun cli() { val cmd = CliConfigCmd(ConfigSource("test", "test", "test")) val configPath = Path("tmp/test-conf.conf") val secondPath = Path("tmp/test-second-conf.conf") fun testErr(msg: String) { val prevErr = System.err val tmpErr = ByteArrayOutputStream() System.setErr(PrintStream(tmpErr)) val result = cmd.test("dump -c $configPath") System.setErr(prevErr) val lastLog = tmpErr.asUtf8().substringAfterLast(" - ").trimEnd('\n') assertEquals(1, result.statusCode, lastLog) assertEquals(msg, lastLog, lastLog) } configPath.deleteIfExists() testErr("Could not read config at '$configPath': no such file") configPath.createParentDirectories() configPath.createFile() configPath.toFile().setReadable(false) if (!configPath.isReadable()) { // Skip if root testErr("Could not read config at '$configPath': permission denied") } configPath.toFile().setReadable(true) configPath.writeText("@inline@test-second-conf.conf") secondPath.deleteIfExists() testErr("Could not read config at '$secondPath': no such file") secondPath.createFile() secondPath.toFile().setReadable(false) if (!secondPath.isReadable()) { // Skip if root testErr("Could not read config at '$secondPath': permission denied") } configPath.writeText("@inline-matching@[*") testErr("Malformed glob regex at '$configPath:0': Missing '] near index 1\n[*\n ^") configPath.writeText("@inline-matching@*second-conf.conf") if (!secondPath.isReadable()) { // Skip if root testErr("Could not read config at '$secondPath': permission denied") } secondPath.toFile().setReadable(true) configPath.writeText("\n@inline-matching@*.conf") testErr("Recursion limit in config inlining at '$secondPath:1'") configPath.writeText("\n\n@inline@test-conf.conf") testErr("Recursion limit in config inlining at '$configPath:2'") } fun checkErr(msg: String, block: () -> Unit) { val exception = assertFailsWith(null, block) println(exception.message) assertEquals(msg, exception.message) } @Test fun parsing() { checkErr("expected section header at 'mem:1'") { ConfigSource("test", "test", "test").fromMem( """ key=value """ ) } checkErr("expected section header, option assignment or directive at 'mem:2'") { ConfigSource("test", "test", "test").fromMem( """ [section] bad-line """ ) } ConfigSource("test", "test", "test").fromMem( """ [section-a] bar = baz [section-b] first_value = 1 second_value = "test" """.trimIndent() ).let { conf -> // Missing section checkErr("Missing string option 'value' in section 'unknown'") { conf.section("unknown").string("value").require() } // Missing value checkErr("Missing string option 'value' in section 'section-a'") { conf.section("section-a").string("value").require() } } } fun testConfigValue( type: String, lambda: TalerConfigSection.(String) -> TalerConfigOption, wellformed: List, T>>, malformed: List, (String) -> String>>, conf: String = "" ) { fun conf(content: String) = ConfigSource("test", "test", "test").fromMem("$conf\n$content") // Check missing msg val conf = conf("") checkErr("Missing $type option 'value' in section 'section'") { conf.section("section").lambda("value").require() } // Check wellformed options are properly parsed for ((raws, expected) in wellformed) { for (raw in raws) { val conf = conf("[section]\nvalue=$raw") assertEquals(expected, conf.section("section").lambda("value").require()) } } // Check malformed options have proper error message for ((raws, errorFmt) in malformed) { for (raw in raws) { val conf = conf("[section]\nvalue=$raw") checkErr("Expected $type option 'value' in section 'section': ${errorFmt(raw)}") { conf.section("section").lambda("value").require() } } } } fun testConfigValue( type: String, lambda: TalerConfigSection.(String) -> TalerConfigOption, wellformed: List, T>>, malformed: Pair, (String) -> String> ) = testConfigValue(type, lambda, wellformed, listOf(malformed)) @Test fun string() = testConfigValue( "string", TalerConfigSection::string, listOf( listOf("1", "\"1\"") to "1", listOf("test", "\"test\"") to "test", listOf("\"") to "\"", ), listOf() ) @Test fun number() = testConfigValue( "number", TalerConfigSection::number, listOf( listOf("1") to 1, listOf("42") to 42 ), listOf("true", "YES") to { "'$it' not a valid number" } ) @Test fun boolean() = testConfigValue( "boolean", TalerConfigSection::boolean, listOf( listOf("yes", "YES", "Yes") to true, listOf("no", "NO", "No") to false ), listOf("true", "1") to { "expected 'YES' or 'NO' got '$it'" } ) @Test fun path() = testConfigValue( "path", TalerConfigSection::path, listOf( listOf("path") to Path("path"), listOf("foo/\$DATADIR/bar", "foo/\${DATADIR}/bar") to Path("foo/mydir/bar"), listOf("foo/\$DATADIR\$DATADIR/bar") to Path("foo/mydirmydir/bar"), listOf("foo/pre_\$DATADIR/bar", "foo/pre_\${DATADIR}/bar") to Path("foo/pre_mydir/bar"), listOf("foo/\${DATADIR}_next/bar", "foo/\${UNKNOWN:-\$DATADIR}_next/bar") to Path("foo/mydir_next/bar"), listOf("foo/\${UNKNOWN:-default}_next/bar", "foo/\${UNKNOWN:-\${UNKNOWN:-default}}_next/bar") to Path("foo/default_next/bar"), listOf("foo/\${UNKNOWN:-pre_\${UNKNOWN:-default}_next}_next/bar") to Path("foo/pre_default_next_next/bar"), ), listOf( listOf("foo/\${A/bar") to { "bad substitution '\${A/bar'" }, listOf("foo/\${A:-pre_\${B}/bar") to { "unbalanced variable expression 'pre_\${B}/bar'" }, listOf("foo/\${A:-\${B\${C}/bar") to { "unbalanced variable expression '\${B\${C}/bar'" }, listOf("foo/\$UNKNOWN/bar", "foo/\${UNKNOWN}/bar") to { "unbound variable 'UNKNOWN'" }, listOf("foo/\$RECURSIVE/bar") to { "recursion limit in path substitution exceeded for '\$RECURSIVE'" } ), "[PATHS]\nDATADIR=mydir\nRECURSIVE=\$RECURSIVE" ) @Test fun duration() = testConfigValue( "temporal", TalerConfigSection::duration, listOf( listOf("1s", "1 s") to Duration.ofSeconds(1), listOf("10m", "10 m") to Duration.ofMinutes(10), listOf("1h") to Duration.ofHours(1), listOf("1h10m12s", "1h 10m 12s", "1 h 10 m 12 s", "1h10'12\"") to Duration.ofHours(1).plus(Duration.ofMinutes(10)).plus(Duration.ofSeconds(12)), ), listOf( listOf("test", "42") to { "'$it' not a valid temporal" }, listOf("42t") to { "'t' not a valid temporal unit" }, listOf("9223372036854775808s") to { "'9223372036854775808' not a valid temporal amount" }, ) ) @Test fun date() = testConfigValue( "date", TalerConfigSection::date, listOf( listOf("2024-12-12") to dateToInstant("2024-12-12"), ), listOf( listOf("test", "42") to { "'$it' not a valid date" }, listOf("2024-12-32") to { "'$it' not a valid date: Invalid value for DayOfMonth (valid values 1 - 28/31): 32" }, listOf("2024-42-12") to { "'$it' not a valid date: Invalid value for MonthOfYear (valid values 1 - 12): 42" }, listOf("2024-12-32s") to { "'$it' not a valid date at index 10" }, ) ) @Test fun jsonMap() = testConfigValue( "json key/value map", TalerConfigSection::jsonMap, listOf( listOf("{\"a\": \"12\", \"b\": \"test\"}") to mapOf("a" to "12", "b" to "test"), ), listOf("test", "12", "{\"a\": 12}", "{\"a\": \"12\",") to { "'$it' is malformed" } ) @Test fun amount() = testConfigValue( "amount", { amount(it, "KUDOS") }, listOf( listOf("KUDOS:12", "KUDOS:12.0", "KUDOS:012.0") to TalerAmount("KUDOS:12"), ), listOf( listOf("test", "42", "KUDOS:0.3ABC") to { "'$it' is malformed: Invalid amount format" }, listOf("KUDOS:999999999999999999") to { "'$it' is malformed: Value specified in amount is too large" }, listOf("EUR:12") to { "expected currency KUDOS got EUR" }, ) ) @Test fun map() = testConfigValue( "map", { map(it, "map", mapOf("one" to 1, "two" to 2, "three" to 3)) }, listOf( listOf("one") to 1, listOf("two") to 2, listOf("three") to 3, ), listOf( listOf("test", "42") to { "expected 'one', 'two' or 'three' got '$it'" }, ) ) @Test fun mapLambda() = testConfigValue( "lambda", { map(it, "lambda", mapOf("ok" to 1, "fail" to { throw Exception("Never executed") })) }, listOf( listOf("ok") to 1, ), listOf( listOf("test", "42") to { "expected 'ok' or 'fail' got '$it'" } ) ) @Test fun jdbcParsing() { val user = currentUser() assertFails { jdbcFromPg("test") } assertEquals("jdbc:test", jdbcFromPg("jdbc:test")) assertEquals("jdbc:postgresql://localhost/?user=$user&socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432", jdbcFromPg("postgresql:///")) assertEquals("jdbc:postgresql://?host=args%2Dhost&user=arg%23%24User&password=%21%22%23%24%25%26%27%28%29", jdbcFromPg("postgresql://?host=args%2Dhost&user=arg%23%24User&password=%21%22%23%24%25%26%27%28%29")) withEnvironmentVariable("PGPORT", "1234").execute { assertEquals("jdbc:postgresql://localhost/?user=$user&socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.1234", jdbcFromPg("postgresql:///")) } withEnvironmentVariable("PGPORT", "1234").and("PGHOST", "/tmp").execute { assertEquals("jdbc:postgresql://localhost/?user=$user&socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=/tmp/.s.PGSQL.1234", jdbcFromPg("postgresql:///")) } } } libeufin-1.6.8/libeufin-common/src/test/kotlin/AmountTest.kt0000664000175000017500000000552115122266731024347 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.TalerAmount import kotlin.test.assertEquals class AmountTest { @Test fun parse() { assertEquals(TalerAmount("EUR:4"), TalerAmount(4L, 0, "EUR")) assertEquals(TalerAmount("EUR:0.02"), TalerAmount(0L, 2000000, "EUR")) assertEquals(TalerAmount("EUR:4.12"), TalerAmount(4L, 12000000, "EUR")) assertEquals(TalerAmount("LOCAL:4444.1000"), TalerAmount(4444L, 10000000, "LOCAL")) assertEquals(TalerAmount("EUR:${TalerAmount.MAX_VALUE}.99999999"), TalerAmount(TalerAmount.MAX_VALUE, 99999999, "EUR")) assertException("Invalid amount format") {TalerAmount("")} assertException("Invalid amount format") {TalerAmount("EUR")} assertException("Invalid amount format") {TalerAmount("eur:12")} assertException("Invalid amount format") {TalerAmount(" EUR:12")} assertException("Invalid amount format") {TalerAmount("EUR:1.")} assertException("Invalid amount format") {TalerAmount("EUR:.1")} assertException("Invalid amount format") {TalerAmount("AZERTYUIOPQSD:12")} assertException("Value specified in amount is too large") {TalerAmount("EUR:${Long.MAX_VALUE}")} assertException("Invalid amount format") {TalerAmount("EUR:4.000000000")} assertException("Invalid amount format") {TalerAmount("EUR:4.4a")} } @Test fun parseRoundTrip() { for (amount in sequenceOf("EUR:4", "EUR:0.02", "EUR:4.12")) { assertEquals(amount, TalerAmount(amount).toString()) } } @Test fun subCent() { for (ok in sequenceOf("EUR:1", "EUR:0.1", "EUR:0.01", "EUR:1.23")) { assert(!TalerAmount(ok).isSubCent()) } for (subCent in sequenceOf("EUR:0.001", "EUR:1.001", "EUR:99.991", "EUR:0.0000012")) { assert(TalerAmount(subCent).isSubCent()) } } fun assertException(msg: String, lambda: () -> Unit) { try { lambda() throw Exception("Expected failure") } catch (e: Exception) { assert(e.message!!.startsWith(msg)) { "${e.message}" } } } }libeufin-1.6.8/libeufin-common/src/test/kotlin/CryptoUtilTest.kt0000664000175000017500000001234515122266731025224 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.common.crypto.PasswordHashCheck import tech.libeufin.common.crypto.PwCrypto import tech.libeufin.common.decodeUpHex import tech.libeufin.common.encodeBase64 import tech.libeufin.common.encodeHex import tech.libeufin.common.encodeUpHex import kotlin.test.assertEquals import kotlin.test.assertTrue class CryptoUtilTest { @Test fun loadFromModulusAndExponent() { val public = CryptoUtil.genRSAPublic(1024) val pub2 = CryptoUtil.RSAPublicFromComponents( public.modulus.toByteArray(), public.publicExponent.toByteArray() ) assertEquals(public, pub2) } @Test fun testCryptoUtilBasics() { val (private, public) = CryptoUtil.genRSAPair(1024) assertEquals(private, CryptoUtil.loadRSAPrivate(private.encoded)) assertEquals(public, CryptoUtil.loadRSAPublic(public.encoded)) } @Test fun testEbicsE002() { val data = "Hello, World!".toByteArray() val (private, public) = CryptoUtil.genRSAPair(1024) val (txKey, encryptedKey) = CryptoUtil.genEbicsE002Key(public) val enc = CryptoUtil.encryptEbicsE002(txKey, data.inputStream()) val txKey2 = CryptoUtil.decryptEbicsE002Key(private, encryptedKey) val dec = CryptoUtil.decryptEbicsE002(txKey2, enc).readBytes() assertTrue(data.contentEquals(dec)) } @Test fun testEbicsA006() { val (private, public) = CryptoUtil.genRSAPair(1024) val data = "Hello, World".toByteArray(Charsets.UTF_8) val sig = CryptoUtil.signEbicsA006(data, private) assertTrue(CryptoUtil.verifyEbicsA006(sig, data, public)) } @Test fun testEbicsPublicKeyHashing() { val exponentStr = "01 00 01".replace(" ", "") val moduloStr = """ EB BD B8 E3 73 45 60 06 44 A1 AD 6A 25 33 65 F5 9C EB E5 93 E0 51 72 77 90 6B F0 58 A8 89 EB 00 C6 0B 37 38 F3 3C 55 F2 4D 83 D0 33 C3 A8 F0 3C 82 4E AF 78 51 D6 F4 71 6A CC 9C 10 2A 58 C9 5F 3D 30 B4 31 D7 1B 79 6D 43 AA F9 75 B5 7E 0B 4A 55 52 1D 7C AC 8F 92 B0 AE 9F CF 5F 16 5C 6A D1 88 DB E2 48 E7 78 43 F9 18 63 29 45 ED 6C 08 6C 16 1C DE F3 02 01 23 8A 58 35 43 2B 2E C5 3F 6F 33 B7 A3 46 E1 75 BD 98 7C 6D 55 DE 71 11 56 3D 7A 2C 85 42 98 42 DF 94 BF E8 8B 76 84 13 3E CA 0E 8D 12 57 D6 8A CF 82 DE B7 D7 BB BC 45 AE 25 95 76 00 19 08 AA D2 C8 A7 D8 10 37 88 96 B9 98 14 B4 B0 65 F3 36 CE 93 F7 46 12 58 9F E7 79 33 D5 BE 0D 0E F8 E7 E0 A9 C3 10 51 A1 3E A4 4F 67 5E 75 8C 9D E6 FE 27 B6 3C CF 61 9B 31 D4 D0 22 B9 2E 4C AF 5F D6 4B 1F F0 4D 06 5F 68 EB 0B 71 """.trimIndent().replace(" ", "").replace("\n", "") val expectedHashStr = """ 72 71 D5 83 B4 24 A6 DA 0B 7B 22 24 3B E2 B8 8C 6E A6 0F 9F 76 11 FD 18 BE 2C E8 8B 21 03 A9 41 """.trimIndent() val expectedHash = expectedHashStr.replace(" ", "").replace("\n", "") val pub = CryptoUtil.RSAPublicFromComponents(moduloStr.decodeUpHex(), exponentStr.decodeUpHex()) println("echoed pub exp: ${pub.publicExponent.encodeHex()}") println("echoed pub mod: ${pub.modulus.encodeHex()}") val pubHash = CryptoUtil.getEbicsPublicKeyHash(pub) println("our pubHash: ${pubHash.encodeUpHex()}") println("expected pubHash: ${expectedHash}") assertEquals(expectedHash, pubHash.encodeUpHex()) } @Test fun passwordHashing() { val password = "myinsecurepw" val pwCrypto = PwCrypto.Bcrypt(cost = 4) // Check roundtrip val hash = pwCrypto.hashpw(password) assertEquals(pwCrypto.checkpw(password, hash), PasswordHashCheck(true, false)) assertEquals(pwCrypto.checkpw("other", hash), PasswordHashCheck(false, false)) // Check outdated algorithm val pwh = CryptoUtil.hashStringSHA256(password).encodeBase64() val outdatedHash = "sha256\$$pwh" assertEquals(pwCrypto.checkpw(password, outdatedHash), PasswordHashCheck(true, true)) assertEquals(pwCrypto.checkpw("other", outdatedHash), PasswordHashCheck(false, true)) // Check outdated options val betterCrypto = pwCrypto.copy(cost = 5) assertEquals(betterCrypto.checkpw(password, hash), PasswordHashCheck(true, true)) assertEquals(betterCrypto.checkpw("other", hash), PasswordHashCheck(false, true)) } } libeufin-1.6.8/libeufin-common/src/test/kotlin/EncodingTest.kt0000664000175000017500000001064715122266731024637 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.Base32Crockford import tech.libeufin.common.rand import kotlin.test.assertContentEquals import kotlin.test.assertEquals import kotlin.test.assertFailsWith class EncodingTest { @Test fun base32() { fun roundTripBytes(data: ByteArray) { val encoded = Base32Crockford.encode(data) val decoded = Base32Crockford.decode(encoded) assertContentEquals(data, decoded) } // Empty assert(Base32Crockford.encode(ByteArray(0)).isEmpty()) assert(Base32Crockford.decode("").isEmpty()) roundTripBytes(ByteArray(0)) // Many size for (size in 0..100) { roundTripBytes(ByteArray(size).rand()) } val ORIGINAL = "00111VVBASE32TESTXRST7M8J4H2VY3E0N561BAFWDCPKQG9ZNTG" val LOWERCASE = "00111vvbase32testxrst7m8j4h2vy3e0n561bafwdcpkqg9zntg" val ALT = "0O1ILVUBASE32TESTXRST7M8J4H2VY3E0N561BAFWDCPKQG9ZNTG" val ALT_LOWER = "0o1ilvubase32testxrst7m8j4h2vy3e0n561bafwdcpkqg9zntg" val specialCases = listOf(LOWERCASE, ALT, ALT_LOWER) // Common case val decoded = Base32Crockford.decode(ORIGINAL) assertEquals(ORIGINAL, Base32Crockford.encode(decoded)) // Special cases for (case in specialCases) { assertContentEquals(decoded, Base32Crockford.decode(case)) } // Bad cases for (case in listOf('(', '\n', '@')) { val err = assertFailsWith { Base32Crockford.decode("CROCKFORDBASE32${case}TESTDATA") } assertEquals("invalid Base32 character: $case", err.message) } assertFailsWith { Base32Crockford.decode("CROCKFORDBASE32🤯TESTDATA") } // Gnunet check val gnunetInstalled = try { val exitValue = ProcessBuilder("gnunet-base32", "-v").start().waitFor() exitValue == 0 } catch (e: java.io.IOException) { false } if (gnunetInstalled) { for (size in 0..100) { // Generate random blob val blob = ByteArray(size).rand() // Encode with kotlin val encoded = Base32Crockford.encode(blob) // Encode with gnunet val gnunetEncoded = ProcessBuilder("gnunet-base32").start().run { outputStream.use { it.write(blob) } waitFor() inputStream.readBytes().decodeToString() } // Check match assertEquals(encoded, gnunetEncoded) // Decode with kotlin val decoded = Base32Crockford.decode(encoded) // Decode with gnunet val gnunetDecoded = ProcessBuilder("gnunet-base32", "-d").start().run { outputStream.use { it.write(encoded.toByteArray()) } waitFor() inputStream.readBytes() } // Check match assertContentEquals(decoded, gnunetDecoded) } for (case in specialCases) { // Decode with kotlin val decoded = Base32Crockford.decode(case) // Decode with gnunet val gnunetDecoded = ProcessBuilder("gnunet-base32", "-d").start().run { outputStream.use { it.write(case.toByteArray()) } waitFor() inputStream.readBytes() } // Check match assertContentEquals(decoded, gnunetDecoded) } } } } libeufin-1.6.8/libeufin-common/src/test/resources/0000775000175000017500000000000015236145704022415 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/test/resources/hpb_request.xml0000664000175000017500000000433615122266731025464 0ustar grothoffgrothoff EBIXQUAL 0749134D19E160DA4ACA366180113D44 2018-11-01T11:10:35Z EXCHANGE TALER HPB DZHNN 0000 yuwpcvmVrNrc1t58aulF6TiqKO+CNe7Dhwaa6V/cKws= chhF4/yxSz2WltTR0/DPf01WyncNx3P1XJDr0SylVMVWWSY9S1dYyJKgGOW+g7C/ HYzrGcFwKrejf79DH3F2Ek8NJLsAFzf/0oxff2eYEe0SlxjXmgsubeMOy5PKB9Ag ZiQYMiNy9gaatqcW79E3n/r1nD/lwLsped/4jzWdY+Gfj3z6d18vymmGymbHqIaR hawk/Iu/tpMQ3dbvIFbzn9LLMmzfQzG2ZPy3BiQNVWr3aSLl9qG4U9zeK6OyH2/Z g1EEnjfJa/+pTCeJmyoDBwgaJWcuCRQmWjvxvbM4ckYnrFkhvLf24on2ydmUeipp sMl8q1khyWUC0P0h6otZhD1SUdf1rt14r16bdy1r0ieTVm6m3qXhcX5MXagvFci0 0OE2mOgf/GXE2WiJLAbRh06s9OvAzHUq4QGQwbkprMBMFw4uxONyNzYl+F9aA5Ic Awebf7/dfDJIHZc8XkwY1jNJrmCTzRyTP5eDN4bDPoHqTotDo1CMFaHtnkygg/Lg qoirV8mHfqnO4XQBOCUiHZ6mzz81l+O7dYg65cYx9Z76q2cv1PxsMb7Eo4nvux5S QPuuid0G5lomHXM/uM3mu4vXcDluCoffgTDimxs0I9X+PB7a2vgSMezwYkj8dA69 vszH1hwek7DRbRfKUo6HUxl49Gsk0XYG/K30M5fS5JE= libeufin-1.6.8/libeufin-common/src/test/resources/ebics_ini_request_sample.xml0000664000175000017500000000314715122266731030177 0ustar grothoffgrothoff
    myhost k1 u1 INI DZNNN 0000
    eJx9U1tzmkAUfu9M/wNDH524XIINjprBaOIFCopg8CWzyHK/GHaR1V9fhtg0bWrf9nzfdy57LoN7mqXMEZU4KvIhy3c5lkH5vvCiPBiyFfFv7tj70dcvAzMKckiqEhmVu0QnvfRQOYEEMo1/jvsUR0M2JOTQB6Cu624tdosyAALH8eBZU819iDJ4E+WYwHyPWKbR93ELqsUekjb5B3fkRnvcRjCbCMxVBrTmC/5VXJdij72U5OErFXGAk0Gj8Rq3bxf1f7KzzfcZ5u8GzHO/aImGekNsmFboAjWgh/trU/mEvzFa4VVphUdYSsghEOlT7O52gb1xyLbDoR7F24C/Faz6WGhi5lda57VM5lByDetppc5647Uqz1HsFNgIC6UX19rYpPqd6kMYoNNuQQRNqmdJunDOoq9MyKq0eTeR1rKgQwfIu503o7VIHVkkmbTw7VKbbOXJdCmN+dA6O49eXP0Ar5UAsDeVszqkghM7de2Zq/Oxp4UuMZeyrixi46kQ/YTikPQyaGbrBy+gh3Sum7qQZQZfx9bZtS1tX64TeTnRjrkrJg802mQddDzS597itj44vKtsq6RIFy5U1Fn6SIJNwat5lVoIjGm0pPLskFVTBRo4uUsCr3rGZ0l/nQkBsE/1d4lKPFzaBtU3Y+NkdG6T1XA4AB+a/Gfrp/RQ5CgnI2WljFvdO/I+O/DP4Q3A50H/Xgv77YZGCsf1BuAT3O4QuLZEAwOWJEflfDJK+CbPu9WSFm7fVcNcns1BgmsXOfoJ1l5CIg==
    libeufin-1.6.8/libeufin-common/src/test/resources/hia_request.xml0000664000175000017500000000533715122266731025456 0ustar grothoffgrothoff
    LIBEUFIN-SANDBOX CUSTM001 u1 HIA DZNNN 0000
    eJzNlsmyo0YWhvf1FBW3l0SZZBY3VHIwCwESM0g7ZpCYxAxPb/mWh7ZdrlUvmhX8Z/gzyPNl5P7npSo/T0nXF0399Q35Cbz9fPi0P8qMmTzHpB8uXZx0fDAEn1+Jdf8e91/f8mFo32F4nuefZuynpstgFAAAAxp+5cR9kf3n7dPn7z0fLb6+jV39/qp6T8Ii6t+PAOA/yn9PXh3/YvpR9+FrAYD8sHbpi39ZLwL7mmpFeVIFX4q6H4I6St4Or157ZhzypB6KKBheP0UfQyVZ5TptDh9G+2+CG5RjcvjNeh/376bF/F3+FtCaeCzH/sCccjF6CEpIHO9qNg7sk6vEJqcu5+zCjy3Te4YaE00r3WCcLidQGGEqJ4uoRMrcaQFlAnAK2xDVb1T2KGFMbW87hbMe9m5XzjCb6kuIareAuStQx66uzs+PUlk5oQim7B6eoNW2qo4Ljxu4jbFWLM4M7n4geL2ZNSiMnxum8+d+YTntqIqVV3eS06KTHYeBuOmqaXA1Ar/csDRAAFFNmr8cGc07u8ZC9TidnjhurtHURIQpvLBIf6Uj/5xQT2pGj62hFy2jbldl1wQtTkKbBKm0d2pWZIxX6Q6brViRT8Hl5UeW6FnsgIC1YQslccVX8AhjALHjgHF/ENYD8+3O7ZLOjPhJWvOeMniZ3ayU8F9rAxgdA9xMO1mN0ITDKKWuzZ23hRWH6P3ZKRn3FBhahVPVUOgmF1Br6mWEGkoWQ9h1eXcWlHsA5sGwVg6PurNwXCdWaw70kceyi3Gye6IjoQTPmksNZ5SAyYFlYQD2HLzenvaur+j7YOw20fN9ZEQK+yYyl0AYctO+tL7HmmVR6lw3hpVuLQpfJxvUcjJfsQ+pQCzmVCuiBpbg+DR1uktRiLu3+LHTSiTqQrWN+QF3a4lGdo/NMirzSlakYYUsCgekexluTTKjt4LKV65gMNMX5fIM3xBPu3PUGepNk19iM6yPa4K3z9m8X4KU3gVayt7E+jGR7DWwoZlcyj38X4P7l2kWlrapX3QcGINhP9L+UH6HAf4+DXu7qBJrCKr2gAJk9wVBvgDERpB3BLxjxG0P/xn/Bhr8D9L+hqb77dg6+ACge/j7sV+Bhn9E9F6oo25t/7eoqyBWNpkKhBnWdoKGuhmCBRJ82aiLXKO+c69WObdyykqpGrcg2A+PPp8it7LPdjNhK5BiMEIn6h6QgJHjEWsmk3Jz+9arzzIBzYNz3qj0mNT8xVTYUR8xVxXWklfOR9nz6FQ6z/gI7Gwkg6kTjx2OnisyF3DN823VzoSr4g5ryJwbHMquYT4NDSEM0PbsLwYsRRPq9lvpA5nnoqlXi9vTCYT4FkyoE7QDt5aBImu2fMdO5d0bBJftAd5cSFpop0IvJKXEH4KxYVdK8B7lsp0JfSmIiwiriH9a+plTZiGxZc8hezlARdah8KgLdshknHN6xLyi0SWHjCm6cYu2J4n6VkCYMjfdzMMxRs1sRCsAt9LXlrr01YT4jeM2RE95x8qg+zShwUrm7MyWCdonrmK+SL8U8gsGwbCZbECR3PP5ihjNrA6ryssn9bR6BnTlRnBkNYmdG6aEuzBLGnrk1WxY2VwBGH5S6tCp/VFGBobwT2FY2JSrPquMjHjlFnGFWDCutPVlcNIwljSFU34Ws5h4bdgq2eKUHV+jcHVQx5v74z2uToGp3xmRjGxpTkTEnnnaf7zQb+rdLpo0DlJL7ZwxCJ8OJIRM6iQvetZRo4sQoCTSbQp1HVovaZ95jUK/zljDup8ehRVrEBGCRGZmzukmaSZn61EXF/pRszUNjc8sVSdM9+Wuq1WA6f+vqP+J5e8oCx+Y/1P/QPzfKN7rQTfUSSfzB8HnjsxZEl5uf2i/Zjj9x6vNqIK5h3/7+rSHv3MJOnz6BXLJ7gw=
    libeufin-1.6.8/libeufin-common/src/test/resources/ebics_ini_inner_key.xml0000664000175000017500000000173615122266731027133 0ustar grothoffgrothoff s5ktpg3xGjbZZgVTYtW+0e6xsWg142UwvoM3mfuM+qrkIa5bPUGQLH6BRL9IejYosPhoA6jwMBSxO8LfaageyZJt2M5wHklJYz3fADtQrV1bk5R92OaY/9ZZdHxw3xY93tm5JfVrMDW9DEK5B1hUzYFdjuN/qu2/sdE9mwhx2YjYwwdSQzv6MhbtSK9OAJjPGo3fkxsht6maSmRCdgxplIOSO2mmP1wjUzbVUMcrRk9KDMvnb3kCxiTm+evvxX6J4wpY1bAWukolJbaALHlFtgTo1LnulUe/BxiKx9HpmuEAaPsk8kgduXsz5OqH2g/Vyw75x51aKVPxOTBPyP+4kQ== AQAB A006 flo-kid flo-uid libeufin-1.6.8/libeufin-common/src/test/resources/signature1/0000775000175000017500000000000015236145704024477 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/src/test/resources/signature1/public_key.txt0000664000175000017500000000061015122266731027361 0ustar grothoffgrothoffMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqpUpetHZYdMjnaG544iSLZ5SnxlV4F/eQsIckG3mvMaXCQsY4rUTfJyle/fTZ0xGbjCUXCsbl1wkz8eB6chaX2LsHYDGiu/xNnU1nddAVB+5kkA5AIGncT9NVhdOgmpnZY/tae9qtZfCPAvbI0sGYQHea0pwyJ/hUnRJiMOjSRgIXALIvGVNqxe4U5ffLXFIUapTK2hOuhUH9BwDSK+mVR6gw0vDT05Z38sEpTeKUqJywL5cPSFIV+AN4ErSvsXNkTKUcbDxhGzOh/oTjTkz1kFFKe4ijPkSRkpK2sJMyAIretBKOK8SDICnsSrIh0YAcd6yTHQ3CeEjW4t0ZBULOQIDAQABlibeufin-1.6.8/libeufin-common/src/test/resources/signature1/doc.xml0000664000175000017500000000236115122266731025766 0ustar grothoffgrothoff qiFUoCn9kE0zSidyraO2Br/wn3/XyvWObJZ0aLIBXyA=LupLyRUJIuk0kCRwpFj4fpen2MI7Jw0BI944agwzXHfSDfq0Pp8h3sub6eSsKIAq7ekT3z+mlfMc VFaKRi4B7kv4ja/URiYCKKbChQU2+kMGDvsncx9VcpcFrqAbWPmE9JXD2W2YW9OSkJ1tAZxZlZwS A8KcvluV1wGEBuakHL2t3GqFPQEfKW4l8GYTjHh/w9jBve5d8tvMOjGtoyNemZGrVlzBxO9+hwbw 8UFUCDA00dCjFDUHOnyAbBYsGzoaQyZprDn3iYDvlBz243zAN98PIKDclxlUEmkuF+JhrhCRjT9l +JJxrELGHaDkFVadR4kaPdWPsbDaV0/2Fzc4Qg== Hello World libeufin-1.6.8/libeufin-common/src/test/resources/hia_request_order_data.xml0000664000175000017500000000315115122266731027632 0ustar grothoffgrothoff 0Ekicvrcj2+8tsF+DZsWihl9W7AyVwtMLxq3qefSWagpfnV7BVsKYIJ/OhiWpvr3dz6K5lHSatzhG1x//jrZt6VHn5Wkkb0M0vayPUiZbe5s2aLabqfOTrt8TPnHwjZMChDHRmGoKI0OzLyQJ6MIfQrHZ5t61ccWubYO/bgbSnP9H39k8QEp0kmW4Tf4u+28GTLgueNAaaPTdCozZjrST4fH9nyhBUZ3nl+vZ+AiUNdl5UfV109CXhCm3safLboUus6ZcYLm6gTaiwJEdRX7HYbnAQZ5gcoXVz/oyxJqTkicVOLPrTAfi3UmFrnIVF8XBtOPdIXHzSpxZ3yT8gH4zQ== AQAB X002 0Ekicvrcj2+8tsF+DZsWihl9W7AyVwtMLxq3qefSWagpfnV7BVsKYIJ/OhiWpvr3dz6K5lHSatzhG1x//jrZt6VHn5Wkkb0M0vayPUiZbe5s2aLabqfOTrt8TPnHwjZMChDHRmGoKI0OzLyQJ6MIfQrHZ5t61ccWubYO/bgbSnP9H39k8QEp0kmW4Tf4u+28GTLgueNAaaPTdCozZjrST4fH9nyhBUZ3nl+vZ+AiUNdl5UfV109CXhCm3safLboUus6ZcYLm6gTaiwJEdRX7HYbnAQZ5gcoXVz/oyxJqTkicVOLPrTAfi3UmFrnIVF8XBtOPdIXHzSpxZ3yT8gH4zQ== AQAB E002 PARTNER1 USER1 libeufin-1.6.8/libeufin-common/src/test/resources/ebics_hev.xml0000664000175000017500000000025215122266731025063 0ustar grothoffgrothoff EBIXQUAL libeufin-1.6.8/libeufin-common/build.gradle0000664000175000017500000000506015221677432021117 0ustar grothoffgrothoffplugins { id("kotlin") id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version" } version = rootProject.version java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } compileKotlin.kotlinOptions.jvmTarget = "17" compileTestKotlin.kotlinOptions.jvmTarget = "17" task versionConstant { def outputDir = file("$buildDir/generated/constants") def outputFile = new File(outputDir, "CompileConstants.kt") outputs.dir outputDir doLast { // Ensure output directory exists outputDir.mkdirs() // Generate the Kotlin constants file outputFile.text = """ package tech.libeufin.common val VERSION: String = "${getVersionWithGitHash()}" """.stripIndent() } } dokkaGenerateModuleHtml { dependsOn versionConstant } clean { delete "$buildDir/generated" } sourceSets.main.java.srcDirs = ["src/main/kotlin", "$buildDir/generated/constants"] compileKotlin { dependsOn versionConstant } dependencies { implementation("org.slf4j:slf4j-api:2.0.18") // Crypto implementation("org.bouncycastle:bcprov-jdk18on:1.84") implementation("org.bouncycastle:bcpkix-jdk18on:1.84") // Database helper implementation("org.postgresql:postgresql:$postgres_version") implementation("com.zaxxer:HikariCP:7.0.2") implementation("io.ktor:ktor-server-core:$ktor_version") implementation("io.ktor:ktor-server-call-logging:$ktor_version") implementation("io.ktor:ktor-server-content-negotiation:$ktor_version") implementation("io.ktor:ktor-server-status-pages:$ktor_version") implementation("io.ktor:ktor-server-cio:$ktor_version") implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") implementation("io.ktor:ktor-server-forwarded-header:$ktor_version") implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") implementation("io.ktor:ktor-server-test-host:$ktor_version") implementation("io.ktor:ktor-server-call-id:$ktor_version") // OpenAPI spec generation implementation("io.github.smiley4:ktor-openapi:5.6.0") implementation("io.github.smiley4:schema-kenerator-core:2.6.0") implementation("io.github.smiley4:schema-kenerator-serialization:2.6.0") implementation("io.github.smiley4:schema-kenerator-swagger:2.6.0") implementation("com.github.ajalt.clikt:clikt:$clikt_version") implementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version") testImplementation("uk.org.webcompere:system-stubs-core:2.1.8") }libeufin-1.6.8/libeufin-common/tmp/0000775000175000017500000000000015236145704017435 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/tmp/test-second-conf.conf0000664000175000017500000000000015122266731023443 0ustar grothoffgrothofflibeufin-1.6.8/libeufin-common/tmp/test-conf.conf0000664000175000017500000000003015122266731022175 0ustar grothoffgrothoff @inline@test-conf.conflibeufin-1.6.8/.gitattributes0000644000175000017500000000022214674637415016451 0ustar grothoffgrothoffcontrib/wallet-core/* export-ignore contrib/wallet-core/bank -export-ignore doc/prebuilt/* export-ignore doc/prebuilt/man/libeufin* -export-ignorelibeufin-1.6.8/libeufin-ebisync/0000775000175000017500000000000015236145704017001 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/0000775000175000017500000000000015236145704017570 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/0000775000175000017500000000000015236145704020514 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/kotlin/0000775000175000017500000000000015236145704022014 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/0000775000175000017500000000000015236145704022737 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/0000775000175000017500000000000015236145704024534 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/0000775000175000017500000000000015236145704026170 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/constants.kt0000664000175000017500000000156415122266731030550 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync // KV val CHECKPOINT_KEY = "checkpoint" val SUBMIT_TASK_KEY = "submit_task" val FETCH_TASK_KEY = "fetch_task"libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/api/0000775000175000017500000000000015236145704026741 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/api/SyncApi.kt0000664000175000017500000000760315122266731030653 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.api import kotlinx.serialization.Serializable import tech.libeufin.common.* import tech.libeufin.common.api.* import tech.libeufin.ebics.* import tech.libeufin.ebisync.* import tech.libeufin.ebisync.db.Database import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.server.http.content.* import io.ktor.http.content.* import io.ktor.http.* import io.ktor.utils.io.* import java.nio.file.Path import tech.libeufin.common.VERSION @Serializable class TalerEbiSyncConfig() { val name: String = "taler-ebisync" val version: String = "0:0:0" val spa_version: String = VERSION } @Serializable data class ListSubmitOrders( val orders: List ) @Serializable data class SubmitOrder( val id: String, val description: String ) @Serializable data class SyncSubmit( val order: String ) fun Routing.syncApi(auth: AuthMethod, client: EbicsClient, spa: Path) { suspend fun orders() = client.download(EbicsOrder.V3.HKD) { stream -> val hkd = EbicsAdministrative.parseHKD(stream) hkd.partner.orders .filter { it.order.isUpload() } } get("/config") { call.respond(TalerEbiSyncConfig()) } apiAuth(auth) { get("/") { call.respondRedirect("/webui/") } staticFiles("/webui/", spa.toFile()) get("/submit") { call.respond(ListSubmitOrders(orders().map { SubmitOrder(it.order.description(), it.description) })) } post("/submit") { call.attributes.set(BODY_LIMIT, 10 * 1024 * 1024) val multipart = call.receiveMultipart() var orderId: String? = null var xml: ByteArray? = null multipart.forEachPart { part -> when (part) { is PartData.FormItem -> { if (part.name == "order") { orderId = part.value } } is PartData.FileItem -> { xml = part.provider().toByteArray() } else -> {} } part.dispose() } if (xml == null) { throw badRequest("Missing file", TalerErrorCode.GENERIC_PARAMETER_MISSING) } else if (orderId == null) { throw badRequest("Missing orderId", TalerErrorCode.GENERIC_PARAMETER_MISSING) } val match = orders().find { it.order.description() == orderId } ?: throw notFound( "Unknown order '$orderId'", TalerErrorCode.END ) val order = try { client.upload(match.order, xml) } catch (e: Exception) { if (e is EbicsError.Code) { throw conflict(e.fmt(), TalerErrorCode.END) } else if (e is EbicsError) { throw badGateway(e.fmt(), TalerErrorCode.END) } else { throw e } } call.respond(SyncSubmit(order)) } } }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/db/0000775000175000017500000000000015236145704026555 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/db/KvDAO.kt0000664000175000017500000000603115122266731030017 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.db import tech.libeufin.common.* import tech.libeufin.common.db.* import java.sql.* import java.time.Instant import kotlinx.serialization.Contextual import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.descriptors.PrimitiveKind import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encodeToString import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModule object InstantSerialize : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Instant", PrimitiveKind.LONG) override fun serialize(encoder: Encoder, value: Instant) = encoder.encodeLong(value.micros()) override fun deserialize(decoder: Decoder): Instant = decoder.decodeLong().asInstant() } val JSON = Json { this.serializersModule = SerializersModule { contextual(Instant::class) { InstantSerialize } } } inline fun ResultSet.getJson(name: String): T? { val value = this.getString(name) if (value == null) { return value } return JSON.decodeFromString(value) } /** Data access logic for key value */ class KvDAO(val db: Database) { /** Get current value for [key] */ suspend inline fun get(key: String): T? = db.serializable( "SELECT value FROM kv WHERE key=?" ) { bind(key) oneOrNull { it.getJson("value") } } /** Update a TaskStatus timestamp */ suspend fun updateTaskStatus(key: String, timestamp: Instant, success: Boolean) = db.serializable( if (success) { "INSERT INTO kv (key, value) VALUES (?, jsonb_build_object('last_successfull', ?, 'last_trial', ?)) ON CONFLICT (key) DO UPDATE SET value=EXCLUDED.value" } else { "INSERT INTO kv (key, value) VALUES (?, jsonb_build_object('last_trial', ?)) ON CONFLICT (key) DO UPDATE SET value=jsonb_set(EXCLUDED.value, '{last_trial}'::text[], to_jsonb(?))" } ) { bind(key) bind(timestamp) bind(timestamp) executeUpdate() } }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/db/Database.kt0000664000175000017500000000263315122266731030623 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.db import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import org.slf4j.LoggerFactory import tech.libeufin.common.TalerAmount import tech.libeufin.common.TransferStatusState import tech.libeufin.common.IbanPayto import tech.libeufin.common.db.DatabaseConfig import tech.libeufin.common.db.DbPool import tech.libeufin.common.db.watchNotifications import tech.libeufin.ebics.EbicsDAO import java.time.Instant /** Collects database connection steps and any operation on the EbiSync tables */ class Database(dbConfig: DatabaseConfig): DbPool(dbConfig, "libeufin_ebisync") { val ebics = EbicsDAO(this) val kv = KvDAO(this) }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/azure.kt0000664000175000017500000001404115122266731027654 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.request.* import io.ktor.client.plugins.* import io.ktor.client.plugins.api.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.util.* import tech.libeufin.common.setupSecurityProperties import tech.libeufin.common.BaseURL import tech.libeufin.ebics.httpClient import java.security.Key import java.time.* import java.time.format.DateTimeFormatter import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec import kotlinx.coroutines.runBlocking import java.util.Base64 data class AzureStorageConfig( var accountName: String = "ACCOUNT_NAME", var accountKey: String = "ACCOUNT_KEY" ) const val API_VERSION = "2025-11-05" val LINEAR_WHITESPACE = Regex("\\s+") /** * Ktor Client Plugin for Azure Storage Shared Key Authorization. */ val AzureSharedKeyAuth = createClientPlugin("AzureSharedKeyAuth", ::AzureStorageConfig) { val config = pluginConfig val keyBytes = Base64.getDecoder().decode(config.accountKey) val signingKey: Key = SecretKeySpec(keyBytes, "HmacSHA256") // Intercepts the request before it is sent onRequest { req, _ -> // 1. Set required headers (x-ms-date and x-ms-version) val dateHeaderValue = Instant.now().atZone(ZoneOffset.ofHours(0)).format(DateTimeFormatter.RFC_1123_DATE_TIME) req.headers.apply { // Azure uses x-ms-date instead of the standard Date header for signing set("x-ms-date", dateHeaderValue) set("x-ms-version", API_VERSION) } // 2. Build the StringToSign val stringToSign = createStringToSign(req, config.accountName) // 3. Calculate the HMAC-SHA256 signature val signature = run { val mac = Mac.getInstance("HmacSHA256") mac.init(signingKey) val hash = mac.doFinal(stringToSign.toByteArray(Charsets.UTF_8)) Base64.getEncoder().encodeToString(hash) } // 4. Add the Authorization header val authHeader = "SharedKey ${config.accountName}:$signature" req.headers.set(HttpHeaders.Authorization, authHeader) } } /** * Constructs the StringToSign based on the Azure Storage Shared Key specification. */ private fun createStringToSign( req: HttpRequestBuilder, accountName: String ): String = buildString { val h = req.headers; fun add(value: Any?) { append(value ?: "") append('\n') } // 1. VERB add(req.method.value) // 2. Content-Encoding add(h[HttpHeaders.ContentEncoding]) // 3. Content-Language add(h[HttpHeaders.ContentLanguage]) // 4. Content-Length (empty string if zero for modern versions) val length = req.contentLength() add(if (length != null && length != 0L) "$length" else null) // 5. Content-MD5 add(h["Content-MD5"]) // 6. Content-Type add(h[HttpHeaders.ContentType]) // 7. Date add("") // Must be empty as x-ms-date is used) // 8. If-Modified-Since add(h[HttpHeaders.IfModifiedSince]) // 9. If-Match add(h[HttpHeaders.IfMatch]) // 10. If-None-Match add(h[HttpHeaders.IfNoneMatch]) // 11. If-Unmodified-Since add(h[HttpHeaders.IfUnmodifiedSince]) // 12. Range add(h[HttpHeaders.Range]) // 13. CanonicalizedHeaders // This includes all x-ms- headers, converted to lowercase, sorted, and concatenated. for (entry in h.entries().sortedBy { it.key }) { val k = entry.key if (k.startsWith("x-ms-")) { append(k) append(':') append(entry.value.joinToString(" ").replace(LINEAR_WHITESPACE, " ").trim()) append('\n') } } // 14. CanonicalizedResource // This includes the account name, the path, and canonicalized query parameters. append('/') append(accountName) append(req.url.encodedPath.trimEnd('/')) for (entry in req.url.encodedParameters.entries().sortedBy { it.key }) { append('\n') append(entry.key) append(':') append(entry.value.sorted().joinToString(",")) } } data class AzureError(val status: HttpStatusCode, val code: String?): Exception("${status.value} ${code}") class AzureBlogStorage( name: String, key: String, url: BaseURL, client: HttpClient ) { private val client = client.config { defaultRequest { url(url.toString()) } install(AzureSharedKeyAuth) { accountName = name accountKey = key } install(HttpCallValidator) { validateResponse { res -> if (res.status.value >= 300) { throw AzureError(res.status, res.headers["x-ms-error-code"]) } } } } suspend fun createContainer(name: String) { client.put("$name?restype=container") } suspend fun getContainterMetadata(container: String) { client.get("$container?restype=container&comp=metadata") } suspend fun putBlob(container: String, name: String, content: ByteArray, contentType: ContentType) { client.put("$container/$name") { setBody(content) contentType(contentType) headers.set(HttpHeaders.ContentLength, "${content.size}") headers.set("x-ms-blob-type", "BlockBlob") } } }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/cli/0000775000175000017500000000000015236145704026737 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/cli/Setup.kt0000664000175000017500000001156415122266731030404 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import io.ktor.client.* import tech.libeufin.ebics.* import tech.libeufin.ebisync.* import tech.libeufin.common.* import tech.libeufin.common.crypto.CryptoUtil import java.nio.file.FileAlreadyExistsException import java.nio.file.Path import java.nio.file.StandardOpenOption import java.time.Instant import kotlin.io.path.Path import kotlin.io.path.writeBytes fun expectFullKeys(cfg: EbicsKeysConfig): Pair = expectFullKeys(cfg, "libeufin-ebisync setup") class Setup: TalerCmd() { override fun help(context: Context) = "Set up the EBICS subscriber" private val forceKeysResubmission by option( help = "Resubmits all the keys to the bank" ).flag(default = false) private val autoAcceptKeys by option( help = "Accepts the bank keys without interactively asking the user" ).flag(default = false) private val generateRegistrationPdf by option( help = "Generates the PDF with the client public keys to send to the bank" ).flag(default = false) private val ebicsLog by ebicsLogOption() /** * This function collects the main steps of setting up an EBICS access. */ override fun run() = cliCmd(logger) { val cfg = ebisyncConfig(config) val httpClient = httpClient() val ebicsLogger = EbicsLogger(ebicsLog) logger.info("Check EBICS setup") val (clientKeys, bankKeys) = ebicsSetup( httpClient, ebicsLogger, cfg, cfg, cfg.setup, forceKeysResubmission, generateRegistrationPdf, autoAcceptKeys, true ) // Check account information logger.info("Doing administrative request HKD") cfg.withDb { db, _ -> EbicsClient( cfg, httpClient, db.ebics, ebicsLogger, clientKeys, bankKeys ).download(EbicsOrder.V3.HKD) { stream -> val (partner, users) = EbicsAdministrative.parseHKD(stream) // Debug logging logger.debug { buildString { if (partner.name != null || partner.accounts.isNotEmpty()) { append("Partner Info: ") if (partner.name != null) { append("'") append(partner.name) append("'") } for ((currency, iban, bic) in partner.accounts) { append(' ') append(currency) append('-') append(iban) append('-') append(bic) } append('\n') } append("Supported orders:\n") for ((order, description) in partner.orders) { append("- ") append(order.description()) append(": ") append(description) append('\n') } } } } } logger.info("EBICS ready") logger.info("Check fetch destination setup") when (val dest = DestinationClient.prepare(cfg.fetch.destination, httpClient)) { null -> logger.warn("No destination configured") is DestinationClient.AzureBlobStorage -> { dest.client.getContainterMetadata(dest.container) } } logger.info("Fetch destination ready") println("setup ready") } }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/cli/Serve.kt0000664000175000017500000000525315122266731030366 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.cli import io.ktor.server.application.* import org.slf4j.Logger import org.slf4j.LoggerFactory import tech.libeufin.ebics.* import tech.libeufin.ebisync.* import tech.libeufin.ebisync.db.Database import tech.libeufin.ebisync.api.* import tech.libeufin.common.* import tech.libeufin.common.api.* import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import java.nio.file.Path class Serve : TalerCmd() { override fun help(context: Context) = "Run libeufin-ebisync HTTP server" private val check by option( help = "Check whether an API is in use (if it's useful to start the HTTP server). Exit with 0 if at least one API is enabled, otherwise 1" ).flag() val ebicsLog by ebicsLogOption() override fun run() = cliCmd(logger) { val cfg = ebisyncConfig(config) val auth = when (val source = cfg.submit.source) { Source.None -> null is Source.SyncAPI -> source.auth } if (check) { if (auth == null) { logger.info("No source api, not starting the server") throw ProgramResult(1) } else { throw ProgramResult(0) } } else if (auth == null) { throw ProgramResult(0) } cfg.withDb { db, cfg -> val (clientKeys, bankKeys) = expectFullKeys(cfg) val client = EbicsClient( cfg, httpClient(), db.ebics, EbicsLogger(ebicsLog), clientKeys, bankKeys ) serve(cfg.serverCfg, logger) { ebisyncApi(auth, client, cfg.spa) } } } }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/cli/LibeufinEbisync.kt0000664000175000017500000000354115140725607032354 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025, 2026 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.versionOption import com.github.ajalt.clikt.parameters.types.path import tech.libeufin.common.* import tech.libeufin.ebisync.EBISYNC_CONFIG_SOURCE import tech.libeufin.ebics.ebicsLogOption import org.slf4j.Logger import org.slf4j.LoggerFactory internal val logger: Logger = LoggerFactory.getLogger("libeufin-ebisync") fun CliktCommand.transientOption() = option( "--transient", help = "Execute once and return, ignoring the 'FREQUENCY' configuration value" ).flag(default = false) abstract class EbicsCmd(name: String? = null): TalerCmd(name) { val ebicsLog by ebicsLogOption() val transient by transientOption() } class LibeufinEbisync : CliktCommand() { init { versionOption(VERSION) subcommands(DbInit(), Setup(), Fetch(), Serve(), CliConfigCmd(EBISYNC_CONFIG_SOURCE)) } override fun run() = Unit }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/cli/DbInit.kt0000664000175000017500000000313715122266731030452 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.cli import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import tech.libeufin.common.TalerCmd import tech.libeufin.common.db.dbInit import tech.libeufin.common.db.pgDataSource import tech.libeufin.ebisync.dbConfig class DbInit : TalerCmd("dbinit") { override fun help(context: Context) = "Initialize the libeufin-ebisync database" private val reset by option( "--reset", "-r", help = "Reset database (DANGEROUS: All existing data is lost)" ).flag() override fun run() = cliCmd(logger) { val cfg = dbConfig(config) pgDataSource(cfg.dbConnStr).dbInit(cfg, "libeufin-ebisync", reset) } }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/cli/Fetch.kt0000664000175000017500000002333215122266731030331 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2023-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync.cli import io.ktor.client.HttpClient import io.ktor.http.ContentType import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.ProgramResult import com.github.ajalt.clikt.parameters.arguments.* import com.github.ajalt.clikt.parameters.groups.provideDelegate import com.github.ajalt.clikt.parameters.options.* import com.github.ajalt.clikt.parameters.types.enum import kotlin.math.min import kotlinx.coroutines.* import tech.libeufin.common.* import tech.libeufin.ebics.* import tech.libeufin.ebisync.* import tech.libeufin.ebisync.db.Database import java.time.* import java.time.temporal.* import java.io.IOException import kotlin.time.toKotlinDuration sealed interface DestinationClient { data class AzureBlobStorage(val client: AzureBlogStorage, val container: String): DestinationClient companion object { fun prepare(dest: Destination, client: HttpClient): DestinationClient? { return when (dest) { Destination.None -> null is Destination.AzureBlobStorage -> DestinationClient.AzureBlobStorage( AzureBlogStorage(dest.accountName, dest.accountKey, dest.apiUrl, client), dest.container ) } } } suspend fun uploadFile(name: String, xml: ByteArray) { when (this) { is DestinationClient.AzureBlobStorage -> this.client.putBlob(this.container, name, xml, ContentType.Application.Xml) } } } suspend fun submit(dest: DestinationClient, ebics: EbicsClient, db: Database, orders: List) { for (order in orders) { try { ebics.download(order) { payload -> val doc = order.doc(); if (doc == OrderDoc.acknowledgement) { // TODO HAC } else { payload.unzipEach { fileName, xml -> val bytes = xml.use { it.readBytes() } logger.info("upload $fileName") dest.uploadFile(fileName, bytes) } } } } catch (e: EbicsError.Code) { when (e.bankCode) { EbicsReturnCode.EBICS_NO_DOWNLOAD_DATA_AVAILABLE -> continue else -> throw e } } } } class Fetch : EbicsCmd() { override fun help(context: Context) = "Downloads EBICS files from the bank and store them in the configured destination" private val pinnedStart by option( help = "Only supported in --transient mode, this option lets specify the earliest timestamp of the downloaded documents", metavar = "YYYY-MM-DD" ).convert { dateToInstant(it) } private val peek by option("--peek", help = "Only supported in --transient mode, do not consume fetched documents" ).flag() private val transientCheckpoint by option("--checkpoint", help = "Only supported in --transient mode, run a checkpoint" ).flag() private val check by option( help = "Check whether a destination is configured. Exit with 0 if at destination is configured, otherwise 1" ).flag() override fun run() = cliCmd(logger) { ebisyncConfig(config).withDb { db, cfg -> val (clientKeys, bankKeys) = expectFullKeys(cfg) val httpClient = httpClient(); val dest = DestinationClient.prepare(cfg.fetch.destination, httpClient) if (check) { if (dest == null) { logger.info("No destination configured, not starting the fetcher") throw ProgramResult(1) } else { throw ProgramResult(0) } } else if (dest == null) { throw ProgramResult(0) } val client = EbicsClient( cfg, httpClient, db.ebics, EbicsLogger(ebicsLog), clientKeys, bankKeys ) // Try to obtain real-time notification channel if not transient val wssNotification = if (transient) { logger.info("Transient mode: fetching once and returning") null } else { val tmp = listenForNotification(client) logger.info("Running with a frequency of ${cfg.fetch.frequencyRaw}") tmp } var lastFetch = Instant.EPOCH while (true) { val checkpoint = db.kv.get(CHECKPOINT_KEY) ?: TaskStatus() var nextFetch = lastFetch + cfg.fetch.frequency var nextCheckpoint = run { // We never ran, we must checkpoint now if (checkpoint.last_trial == null) { Instant.EPOCH } else { // We run today at checkpointTime val checkpointDate = OffsetDateTime.now().with(cfg.fetch.checkpointTime) val checkpointToday = checkpointDate.toInstant() // If we already ran today we ruAn tomorrow if (checkpoint.last_trial > checkpointToday) { checkpointDate.plusDays(1).toInstant() } else { checkpointToday } } } val now = Instant.now() var success: Boolean = true if ( // Run transient checkpoint at request (transient && transientCheckpoint) || // Or run recurrent checkpoint (!transient && now > nextCheckpoint) ) { logger.info("Running checkpoint") val since = if (transient && pinnedStart != null && (checkpoint.last_successfull == null || pinnedStart!!.isBefore(checkpoint.last_successfull))) { pinnedStart } else { checkpoint.last_successfull } success = try { /// We fetch HKD to only fetch supported EBICS orders and get the document versions val orders = client.download(EbicsOrder.V3.HKD) { stream -> val hkd = EbicsAdministrative.parseHKD(stream) val supportedOrder = hkd.partner.orders.map { it.order } logger.debug { val fmt = supportedOrder.map(EbicsOrder::description).joinToString(" ") "HKD: ${fmt}" } supportedOrder.filter { it.isDownload() } } submit(dest, client, db, orders) true } catch (e: Exception) { e.fmtLog(logger) false } db.kv.updateTaskStatus(CHECKPOINT_KEY, now, success) lastFetch = now } else if (transient || now > nextFetch) { if (!transient) logger.info("Running at frequency") success = try { /// We fetch HAA to only fetch pending & supported EBICS orders and get the document versions val orders = client.download(EbicsOrder.V3.HAA) { stream -> val haa = EbicsAdministrative.parseHAA(stream) logger.debug { val orders = haa.orders.map(EbicsOrder::description).joinToString(" ") "HAA: ${orders}" } haa.orders } // TODO pinned starts submit(dest, client, db, orders) true } catch (e: Exception) { e.fmtLog(logger) false } lastFetch = now } db.kv.updateTaskStatus(SUBMIT_TASK_KEY, now, success) if (transient) throw ProgramResult(if (!success) 1 else 0) val delay = min(ChronoUnit.MILLIS.between(now, nextFetch), ChronoUnit.MILLIS.between(now, nextCheckpoint)) if (wssNotification == null) { delay(delay) } else { val notifications = withTimeoutOrNull(delay) { wssNotification.receive() } if (notifications != null) { logger.info("Running at real-time notifications reception") submit(dest, client, db, notifications) } } } } } }libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/Main.kt0000664000175000017500000000413715122266731027417 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.request.* import io.ktor.client.plugins.* import io.ktor.client.plugins.api.* import io.ktor.client.statement.* import io.ktor.server.application.* import io.ktor.http.* import io.ktor.util.* import tech.libeufin.ebics.* import tech.libeufin.ebisync.* import tech.libeufin.ebisync.db.Database import tech.libeufin.ebisync.api.* import tech.libeufin.ebisync.cli.* import tech.libeufin.common.* import tech.libeufin.common.api.* import java.security.Key import java.time.* import java.time.format.DateTimeFormatter import javax.crypto.Mac import javax.crypto.spec.SecretKeySpec import kotlinx.coroutines.runBlocking import java.util.Base64 import com.github.ajalt.clikt.core.main import kotlinx.serialization.Serializable import kotlinx.serialization.Contextual import java.nio.file.Path import org.slf4j.Logger import org.slf4j.LoggerFactory fun main(args: Array) { setupSecurityProperties() setupSecurityProperties() LibeufinEbisync().main(args) } fun Application.ebisyncApi(auth: AuthMethod, client: EbicsClient, spa: Path) = talerApi(LoggerFactory.getLogger("libeufin-ebisync-api")) { syncApi(auth, client, spa) } @Serializable data class TaskStatus( @Contextual val last_successfull: Instant? = null, @Contextual val last_trial: Instant? = null )libeufin-1.6.8/libeufin-ebisync/src/main/kotlin/tech/libeufin/ebisync/config.kt0000664000175000017500000001153415122266731027777 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ package tech.libeufin.ebisync import tech.libeufin.common.* import tech.libeufin.common.db.DatabaseConfig import tech.libeufin.ebics.EbicsSetupConfig import tech.libeufin.ebics.EbicsHostConfig import tech.libeufin.ebics.EbicsKeysConfig import tech.libeufin.ebisync.db.Database import java.nio.file.Path import org.slf4j.Logger import org.slf4j.LoggerFactory private val logger: Logger = LoggerFactory.getLogger("libeufin-config") val EBISYNC_CONFIG_SOURCE = ConfigSource("libeufin-ebisync", "ebisync", "libeufin-ebisync") class EbisyncSetupConfig(cfg: TalerConfig): EbicsSetupConfig { private val sect = cfg.section("ebisync-setup") override val bankAuthPubKey = sect.hex("bank_authentication_pub_key_hash").orNull() override val bankEncPubKey = sect.hex("bank_encryption_pub_key_hash").orNull() } class EbisyncConfig internal constructor (val cfg: TalerConfig): EbicsKeysConfig, EbicsHostConfig { private val sect = cfg.section("ebisync") /** The bank base URL */ override val baseUrl = sect.string("host_base_url").require() /** The bank EBICS host ID */ override val hostId = sect.string("host_id").require() /** EBICS user ID */ override val userId = sect.string("user_id").require() /** EBICS partner ID */ override val partnerId = sect.string("partner_id").require() /** Path where we store the bank public keys */ override val bankPublicKeysPath = sect.path("bank_public_keys_file").require() /** Path where we store our private keys */ override val clientPrivateKeysPath = sect.path("client_private_keys_file").require() val setup by lazy { EbisyncSetupConfig(cfg) } val dbCfg by lazy { cfg.dbConfig() } val fetch by lazy { EbisyncFetchConfig(cfg) } val submit by lazy { EbisyncSubmitConfig(cfg) } val serverCfg by lazy { cfg.loadServerConfig("ebisync-httpd") } val spa by lazy { val sect = cfg.section("ebisync-httpd") sect.path("SPA").require() } } class EbisyncFetchConfig(cfg: TalerConfig) { private val sect = cfg.section("ebisync-fetch") val frequency = sect.duration("frequency").require() val frequencyRaw = sect.string("frequency").require() val checkpointTime = sect.time("checkpoint_time_of_day").require() val destination = sect.mapLambda("destination", "ebics file destination", mapOf( "none" to { Destination.None }, "azure-blob-storage" to { Destination.AzureBlobStorage( apiUrl = sect.baseURL("azure_api_url").require(), accountName = sect.string("azure_account_name").require(), accountKey = sect.string("azure_account_key").require(), container = sect.string("azure_container").require() ) } )).require() } class EbisyncSubmitConfig(cfg: TalerConfig) { private val sect = cfg.section("ebisync-submit") val source = sect.mapLambda("source", "ebics file source", mapOf( "none" to { Source.None }, "ebisync-api" to { Source.SyncAPI(sect.requireAuthMethod()) } )).require() } private fun TalerConfig.dbConfig(): DatabaseConfig { val sect = section("ebisyncdb-postgres") return DatabaseConfig( dbConnStr = sect.string("config").require(), sqlDir = sect.path("sql_dir").require() ) } /** Load ebisync cfg at [configPath] */ fun ebisyncConfig(configPath: Path?): EbisyncConfig { val cfg = EBISYNC_CONFIG_SOURCE.fromFile(configPath) return EbisyncConfig(cfg) } /** Load ebisync db cfg at [configPath] */ fun dbConfig(configPath: Path?): DatabaseConfig = EBISYNC_CONFIG_SOURCE.fromFile(configPath).dbConfig() /** Run [lambda] with access to a database conn pool */ suspend fun EbisyncConfig.withDb(lambda: suspend (Database, EbisyncConfig) -> Unit) { Database(dbCfg).use { lambda(it, this) } } sealed interface Destination { data object None: Destination data class AzureBlobStorage( val apiUrl: BaseURL, val accountName: String, val accountKey: String, val container: String, ): Destination } sealed interface Source { data object None: Source data class SyncAPI(val auth: AuthMethod): Source }libeufin-1.6.8/libeufin-ebisync/src/test/0000775000175000017500000000000015236145704020547 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/test/kotlin/0000775000175000017500000000000015236145704022047 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/test/kotlin/EbicsTest.kt0000664000175000017500000000401715122266731024274 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.w3c.dom.Document import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.testing.test import kotlinx.coroutines.runBlocking import io.ktor.http.* import io.ktor.http.content.* import org.junit.Test import tech.libeufin.ebisync.cli.LibeufinEbisync import tech.libeufin.ebisync.CHECKPOINT_KEY import tech.libeufin.common.* import tech.libeufin.common.test.* import tech.libeufin.common.crypto.CryptoUtil import tech.libeufin.ebics.test.* import tech.libeufin.ebics.* import kotlin.io.path.* import kotlin.test.* import java.time.LocalDate @OptIn(kotlin.io.path.ExperimentalPathApi::class) class EbicsTest { private val cmd = LibeufinEbisync() private val bank = EbicsState() private val args = "-L TRACE -c conf/test.conf" private fun ebicsSetup() { // Reset current keys val dir = Path("/tmp/ebics-test") dir.deleteRecursively() dir.createDirectories() // Set setup mock setMock(sequence { yield(bank::hev) yield(bank::ini) yield(bank::hia) yield(bank::hpb) yield(bank::hkd) yield(bank::receiptOk) }) // Run setup cmd.succeed("setup $args --auto-accept-keys") } @Test fun setup() { ebicsSetup() } }libeufin-1.6.8/libeufin-ebisync/src/test/kotlin/SyncApiTest.kt0000664000175000017500000000642015122266731024615 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.http.* import io.ktor.server.testing.* import io.ktor.client.request.* import io.ktor.client.request.forms.* import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.test.* import tech.libeufin.ebics.test.* import tech.libeufin.ebics.* import tech.libeufin.ebisync.api.* import kotlin.test.* class SynApiTest { // GET /config @Test fun config() = serverSetup { db, bank -> client.get("/config").assertOkJson() } // GET /submit @Test fun orders() = serverSetup { db, bank -> setMock(sequence { yield(bank::hkd) yield(bank::receiptOk) }) val date = client.get("/submit").assertOkJson() assertContentEquals(date.orders, listOf( SubmitOrder("BTU-SCT-pain.001", "Direct Debit"), SubmitOrder("BTU-SCI-DE-pain.001", "Instant Direct Debit"), )) } // POST /submit @Test fun submit() = serverSetup { db, bank -> client.submitFormWithBinaryData( url = "/submit", formData = formData { } ).assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MISSING) client.submitFormWithBinaryData( url = "/submit", formData = formData { append("order", "UNKNOWN") } ).assertBadRequest(TalerErrorCode.GENERIC_PARAMETER_MISSING) setMock(sequence { yield(bank::hkd) yield(bank::receiptOk) }) client.submitFormWithBinaryData( url = "/submit", formData = formData { append("order", "UNKNOWN") append("file", "test", Headers.build { append(HttpHeaders.ContentType, "application/xml") append(HttpHeaders.ContentDisposition, "filename=\"content.xml\"") }) } ).assertNotFound(TalerErrorCode.END) setMock(sequence { yield(bank::hkd) yield(bank::receiptOk) yield(bank::btuInit) yield(bank::btuPayload) }) client.submitFormWithBinaryData( url = "/submit", formData = formData { append("order", "BTU-SCI-DE-pain.001") append("file", "test", Headers.build { append(HttpHeaders.ContentType, "application/xml") append(HttpHeaders.ContentDisposition, "filename=\"content.xml\"") }) } ).assertOkJson() } }libeufin-1.6.8/libeufin-ebisync/src/test/kotlin/DatabaseTest.kt0000664000175000017500000000255115122266731024754 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2024-2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import org.junit.Test import tech.libeufin.common.* import tech.libeufin.common.db.* import tech.libeufin.ebics.* import tech.libeufin.ebisync.db.* import java.time.Instant import java.util.UUID; import kotlin.test.* class EbicsTxTest { // Test pending transaction's id @Test fun pending() = setup { db, _ -> val ids = setOf("first", "second", "third") for (id in ids) { db.ebics.register(id) } repeat(ids.size) { val id = db.ebics.first() assert(ids.contains(id)) db.ebics.remove(id!!) } assertNull(db.ebics.first()) } }libeufin-1.6.8/libeufin-ebisync/src/test/kotlin/helpers.kt0000664000175000017500000000552215122266731024053 0ustar grothoffgrothoff/* * This file is part of LibEuFin. * Copyright (C) 2025 Taler Systems S.A. * LibEuFin is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3, or * (at your option) any later version. * LibEuFin is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General * Public License for more details. * You should have received a copy of the GNU Affero General Public * License along with LibEuFin; see the file COPYING. If not, see * */ import io.ktor.client.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import kotlinx.coroutines.runBlocking import tech.libeufin.ebics.* import tech.libeufin.ebics.test.* import tech.libeufin.ebisync.* import tech.libeufin.ebisync.db.* import tech.libeufin.common.* import tech.libeufin.common.test.* import tech.libeufin.common.db.dbInit import tech.libeufin.common.db.pgDataSource import java.nio.file.NoSuchFileException import kotlin.io.path.* import java.nio.file.FileAlreadyExistsException import java.nio.file.Path import java.nio.file.StandardOpenOption import kotlin.random.Random import kotlin.test.assertEquals import kotlin.test.assertIs import kotlin.test.assertNotNull /* ----- Setup ----- */ fun setup( conf: String = "test.conf", lambda: suspend (Database, EbisyncConfig) -> Unit ) = runBlocking { val cfg = ebisyncConfig(Path("conf/$conf")) pgDataSource(cfg.dbCfg.dbConnStr).run { dbInit(cfg.dbCfg, "libeufin-ebisync", true) } cfg.withDb(lambda) } @OptIn(kotlin.io.path.ExperimentalPathApi::class) fun serverSetup( conf: String = "test.conf", lambda: suspend ApplicationTestBuilder.(Database, EbicsState) -> Unit ) = setup(conf) { db, cfg -> val bank = EbicsState() // Reset current keys val dir = Path("/tmp/ebics-test") dir.deleteRecursively() dir.createDirectories() // Set setup mock setMock(sequence { yield(bank::hev) yield(bank::ini) yield(bank::hia) yield(bank::hpb) }) val client = httpClient() val ebicsLogger = EbicsLogger(null) val (clientKeys, bankKeys) = ebicsSetup( client, ebicsLogger, cfg, cfg, cfg.setup, false, false, true, true ) val ebics = EbicsClient( cfg, client, db.ebics, ebicsLogger, clientKeys, bankKeys ) testApplication { application { ebisyncApi((cfg.submit.source as Source.SyncAPI).auth, ebics, cfg.spa) } lambda(db, bank) } }libeufin-1.6.8/libeufin-ebisync/src/spa/0000775000175000017500000000000015236145704020353 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/src/spa/index.html0000664000175000017500000003641515122266731022357 0ustar grothoffgrothoff LibEuFin EbiSync - File Submission Portal
    LibEuFin EbiSync

    File Submission Portal

    Initializing...

    Choose Order

    Loading orders...

    Submit File

    📄
    Drop XML file here or click to browse
    Accepts .xml files only
    libeufin-1.6.8/libeufin-ebisync/build.gradle0000664000175000017500000000461115140725607021262 0ustar grothoffgrothoffplugins { id("kotlin") id("application") id("com.gradleup.shadow") version "$shadow_version" id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version" } version = rootProject.version java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } compileKotlin.kotlinOptions.jvmTarget = "17" compileTestKotlin.kotlinOptions.jvmTarget = "17" sourceSets.main.java.srcDirs = ["src/main/kotlin"] dependencies { // Core language libraries implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") implementation(project(":libeufin-common")) implementation(project(":libeufin-ebics")) // Metrics implementation("io.prometheus:prometheus-metrics-core:$prometheus_version") implementation("io.prometheus:prometheus-metrics-instrumentation-jvm:$prometheus_version") implementation("io.prometheus:prometheus-metrics-exposition-formats:$prometheus_version") // Command line parsing implementation("com.github.ajalt.clikt:clikt:$clikt_version") implementation("org.postgresql:postgresql:$postgres_version") // Ktor client library implementation("io.ktor:ktor-server-core:$ktor_version") implementation("io.ktor:ktor-client-cio:$ktor_version") implementation("io.ktor:ktor-client-websockets:$ktor_version") // UNIX domain sockets support (used to connect to PostgreSQL) implementation("com.kohlschutter.junixsocket:junixsocket-core:$junixsocket_version") // Serialization implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") // Unit testing testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version") testImplementation("io.ktor:ktor-server-test-host:$ktor_version") testImplementation("io.ktor:ktor-server-cio:$ktor_version") } application { mainClass = "tech.libeufin.ebisync.MainKt" } shadowJar { version = "" minimize { // Kotlin serialization exclude(dependency("io.ktor:ktor-serialization-kotlinx-json:.*")) // Postgres unix socket driver exclude(dependency("com.kohlschutter.junixsocket:junixsocket-core:.*")) // CIO engine exclude(dependency("io.ktor:ktor-client-cio:.*")) // Crypto exclude(dependency("org.bouncycastle:.*")) // CLI exclude(dependency("com.github.ajalt.mordant:mordant:.*")) // PDF exclude(dependency("com.itextpdf:itext-core:.*")) } }libeufin-1.6.8/libeufin-ebisync/ebisync.conf0000664000175000017500000000511115122266731021300 0ustar grothoffgrothoff[paths] EBISYNC_HOME = /var/lib/libeufin-ebisync/ [ebisync] # Base URL of the bank server. HOST_BASE_URL = # EBICS host ID. HOST_ID = # EBICS user ID, as assigned by the bank. USER_ID = # EBICS partner ID, as assigned by the bank. PARTNER_ID = # EBICS partner ID, as assigned by the bank. SYSTEM_ID = # File that holds the bank EBICS keys. BANK_PUBLIC_KEYS_FILE = ${EBISYNC_HOME}/bank-ebics-keys.json # File that holds the client EBICS keys. CLIENT_PRIVATE_KEYS_FILE = ${EBISYNC_HOME}/client-ebics-keys.json [ebisync-setup] # Bank encryption public key hash # BANK_ENCRYPTION_PUB_KEY_HASH = # Bank authentication public key hash # BANK_AUTHENTICATION_PUB_KEY_HASH = [ebisync-fetch] # How often should ebics-fetch run when the bank does not support real time notification FREQUENCY = 30m # At what time of day should ebics-fetch perform a checkpoint CHECKPOINT_TIME_OF_DAY = 19:00 # Where should the ebics file be stored? This his can either can be azure-blob-storage or none DESTINATION = none # Azure API account base url for azure-blob-storage # AZURE_API_URL = https://myaccount.blob.core.windows.net/ # Azure API account name for azure-blob-storage # AZURE_ACCOUNT_NAME = myaccount # Azure API account key for azure-blob-storage # AZURE_ACCOUNT_KEY = Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw== # Which Azure Blob Storage container to use for azure-blob-storage # AZURE_COUNTAINER = mycontainer [ebisync-submit] # Where does the ebics file come from? This his can either can be ebisync-api or none SOURCE = none # Authentication scheme used by the API, this can either can be basic, bearer or none. # AUTH_METHOD = bearer # User name for basic authentication scheme # USERNAME = # Password for basic authentication scheme # PASSWORD = # Token for bearer authentication scheme # TOKEN = [ebisync-httpd] # How "libeufin-ebisync serve" serves its API, this can either be tcp or unix SERVE = tcp # Port on which the HTTP server listens, e.g. 9967. Only used if SERVE is tcp. PORT = 8080 # Which IP address should we bind to? E.g. ``127.0.0.1`` or ``::1``for loopback. Can also be given as a hostname. Only used if SERVE is tcp. BIND_TO = 0.0.0.0 # Which unix domain path should we bind to? Only used if SERVE is unix. # UNIXPATH = libeufin-ebisync.sock # What should be the file access permissions for UNIXPATH? Only used if SERVE is unix. # UNIXPATH_MODE = 660 # Path to spa files SPA = $DATADIR/spa [ebisyncdb-postgres] # Where are the SQL files to setup our tables? SQL_DIR = $DATADIR/sql/ # DB connection string CONFIG = postgres:///libeufin-ebisynclibeufin-1.6.8/libeufin-ebisync/conf/0000775000175000017500000000000015236145704017726 5ustar grothoffgrothofflibeufin-1.6.8/libeufin-ebisync/conf/test.conf0000664000175000017500000000053315122266731021553 0ustar grothoffgrothoff[ebisync] HOST_BASE_URL = http://localhost:8080/ebicsweb BANK_PUBLIC_KEYS_FILE = /tmp/ebics-test/bank-keys.json CLIENT_PRIVATE_KEYS_FILE = /tmp/ebics-test/client-keys.json HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 [ebisyncdb-postgres] CONFIG = postgresql:///libeufincheck [ebisync-submit] SOURCE = ebisync-api AUTH_METHOD = nonelibeufin-1.6.8/configure0000775000175000017500000000404515236144536015466 0ustar grothoffgrothoff#!/bin/sh # This file is part of GNU Taler. # (C) 2020 Taler Systems S.A. # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE # LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF # THIS SOFTWARE. # # SPDX-License-Identifier: 0BSD # This script checks if a suitable python3 executable is installed and then # executes the actual configure logic written in Python. build_system_dir=build-system if ! test -d "$build_system_dir"; then # Maybe this is not a top-level configure invocation # For monorepos, try location from top-level build_system_dir=../../build-system fi if ! test -d "$build_system_dir"; then echo "fatal error: build-system directory not found" >&2 echo "hint: are you running this script from the right directory?" >&2 exit 1 fi scriptpath=$build_system_dir/taler-build-scripts if ! test -d "$build_system_dir"; then echo "fatal error: taler-build-scripts directory not found at $scriptpath" >&2 echo "hint: did you run './bootstrap'?" >&2 exit 1 fi export TALERBUILDSYSTEMDIR=$build_system_dir # Check that the python3 executable is on the PATH. # This follows PEP 394 (https://www.python.org/dev/peps/pep-0394/). if ! python3 --version >/dev/null 2>&1; then echo "error: python3 not found" >&2 exit 1 fi # Let python3 check that its own version is okay for us. python3 "$scriptpath/pyvercheck.py" || exit $? # Allow Python to find libraries that are checked into the build system git. export PYTHONPATH="$scriptpath:${PYTHONPATH:-}" # Call configure.py, assuming all went well. python3 $TALERBUILDSYSTEMDIR/configure.py "$@" libeufin-1.6.8/docker-compose.yml0000664000175000017500000000043515122266731017207 0ustar grothoffgrothoffservices: azurite: image: mcr.microsoft.com/azure-storage/azurite command: azurite --blobHost 0.0.0.0 --debug /data/debug.log container_name: azurite ports: - 10000:10000 volumes: - ./azurite:/data restart: unless-stopped volumes: azurite-data:libeufin-1.6.8/debian/0000775000175000017500000000000015236145704014774 5ustar grothoffgrothofflibeufin-1.6.8/debian/changelog0000664000175000017500000003065215236113342016645 0ustar grothoffgrothofflibeufin (1.6.8) unstable; urgency=low * Release version 1.6.8 -- Christian Grothoff Sun, 09 Aug 2026 17:04:02 +0200 libeufin (1.6.7) unstable; urgency=low * Release version 1.6.7 -- Florian Dold Thu, 09 Jul 2026 15:52:21 +0200 libeufin (1.6.6) unstable; urgency=low * Release version 1.6.6 -- Florian Dold Thu, 02 Jul 2026 17:36:08 +0200 libeufin (1.6.5) unstable; urgency=low * Release version 1.6.5 -- Florian Dold Wed, 10 Jun 2026 11:22:39 +0200 libeufin (1.6.4) unstable; urgency=low * Release version 1.6.4 -- Florian Dold Tue, 02 Jun 2026 19:13:36 +0200 libeufin (1.6.3) unstable; urgency=low * Release version 1.6.3 -- Florian Dold Tue, 02 Jun 2026 17:42:19 +0200 libeufin (1.6.2) unstable; urgency=low * Release version 1.6.2 -- Florian Dold Tue, 02 Jun 2026 14:49:17 +0200 libeufin (1.6.1) unstable; urgency=low * Release version 1.6.1 -- Florian Dold Tue, 02 Jun 2026 12:56:12 +0200 libeufin (1.6.0) unstable; urgency=low * Release version 1.6.0 -- Florian Dold Fri, 29 May 2026 12:55:57 +0200 libeufin (1.5.0) unstable; urgency=low * Release version 1.5.0 -- Christian Grothoff Sat, 21 Mar 2026 18:24:34 +0100 libeufin (1.4.4) unstable; urgency=low * Release version 1.4.4 -- Florian Dold Wed, 18 Mar 2026 18:04:12 +0100 libeufin (1.4.3) unstable; urgency=low * Release version 1.4.3 -- Florian Dold Wed, 18 Mar 2026 16:28:20 +0100 libeufin (1.4.2) unstable; urgency=low * Release version 1.4.2 -- Florian Dold Wed, 18 Mar 2026 15:16:47 +0100 libeufin (1.4.0) unstable; urgency=low * Release version 1.4.0 -- Christian Grothoff Wed, 04 Feb 2026 21:33:00 +0100 libeufin (1.3.1) unstable; urgency=low * Release version 1.3.1 -- Florian Dold Fri, 23 Jan 2026 19:43:34 +0100 libeufin (1.3.0) unstable; urgency=low * Release version 1.3.0 -- Christian Grothoff Mon, 22 Dec 2025 21:20:55 +0100 libeufin (1.2.4) unstable; urgency=low * Release version 1.2.4 -- Florian Dold Thu, 18 Dec 2025 18:44:36 +0100 libeufin (1.2.3) unstable; urgency=low * Release version 1.2.3 -- Florian Dold Thu, 11 Dec 2025 12:59:49 +0100 libeufin (1.2.2) unstable; urgency=low * Release version 1.2.2 -- Florian Dold Sun, 07 Dec 2025 15:17:09 +0100 libeufin (1.1.1) unstable; urgency=low * Release version 1.1.1 -- Florian Dold Thu, 30 Oct 2025 15:25:27 +0100 libeufin (1.1.0) unstable; urgency=low * Release version 1.1.0 -- Florian Dold Tue, 28 Oct 2025 13:23:56 +0100 libeufin (1.0.8) unstable; urgency=low * Release version 1.0.8 -- Christian Grothoff Tue, 22 Jul 2025 15:23:03 +0200 libeufin (1.0.7) unstable; urgency=low * Release version 1.0.7 -- Florian Dold Tue, 22 Jul 2025 15:22:03 +0200 libeufin (1.0.6) unstable; urgency=low * Release version 1.0.6 -- Florian Dold Wed, 16 Jul 2025 15:22:03 +0200 libeufin (1.0.5) unstable; urgency=low * Release version 1.0.5 -- Florian Dold Tue, 08 Jul 2025 23:56:48 +0200 libeufin (1.0.4) unstable; urgency=low * Release version 1.0.4 -- Florian Dold Tue, 24 Jun 2025 00:37:44 +0200 libeufin (1.0.3) unstable; urgency=low * Release version 1.0.3 -- Florian Dold Tue, 10 Jun 2025 20:07:44 +0200 libeufin (1.0.2) unstable; urgency=low * Release version 1.0.2 -- Florian Dold Wed, 28 May 2025 12:40:51 +0200 libeufin (1.0.1) unstable; urgency=low * Release version 1.0.1 -- Florian Dold Mon, 26 May 2025 18:56:28 +0200 libeufin (1.0.0) unstable; urgency=low * Release version 1.0.0 -- Christian Grothoff Sat, 10 May 2025 00:27:18 +0200 libeufin (0.14.9) unstable; urgency=low * Release version 0.14.9 -- Christian Grothoff Fri, 18 Apr 2025 13:50:23 +0200 libeufin (0.14.8) unstable; urgency=low * Release version 0.14.8 -- Florian Dold Fri, 24 Jan 2025 10:12:32 +0100 libeufin (0.14.7) unstable; urgency=low * Release version 0.14.7 -- Florian Dold Thu, 23 Jan 2025 20:30:58 +0100 libeufin (0.14.6) unstable; urgency=low * Release version 0.14.6 -- Florian Dold Mon, 16 Dec 2024 16:03:27 +0100 libeufin (0.14.4) unstable; urgency=low * Release version 0.14.4 -- Florian Dold Fri, 08 Nov 2024 16:03:27 +0100 libeufin (0.14.3) unstable; urgency=low * Release version 0.14.3 -- Florian Dold Tue, 22 Oct 2024 10:34:49 +0200 libeufin (0.14.2) unstable; urgency=low * Release version 0.14.2 -- Florian Dold Wed, 16 Oct 2024 19:42:19 +0200 libeufin (0.14.1) unstable; urgency=low * Release version 0.14.1 -- Christian Grothoff Tue, 17 Sep 2024 16:45:24 +0200 libeufin (0.13.0) unstable; urgency=low * Release version 0.13.0 -- Florian Dold Wed, 28 Aug 2024 22:45:24 +0200 libeufin (0.12.0) unstable; urgency=low * Release version 0.12.0 -- Florian Dold Wed, 24 Jul 2024 06:53:07 +0200 libeufin (0.11.3) unstable; urgency=low * Update to latest bank SPA. -- Florian Dold Mon, 10 Jun 2024 00:20:31 +0200 libeufin (0.11.2) unstable; urgency=low * Package v0.11.2. -- Sebastian Marchano Mon, 03 Jun 2024 13:27:25 -0300 libeufin (0.11.1) unstable; urgency=low * Package v0.11.1. -- Florian Dold Mon, 27 May 2024 19:27:25 +0200 libeufin (0.11.0) unstable; urgency=low * Package v0.11.0. -- Christian Grothoff Wed, 15 May 2024 11:18:26 +0200 libeufin (0.10.3) unstable; urgency=low * Package v0.10.3 with support for instant payments. -- Christian Grothoff Mon, 6 May 2024 11:18:26 +0200 libeufin (0.10.2) unstable; urgency=low * Package v0.10.2 -- Florian Dold Wed, 24 Apr 2024 09:18:26 +0200 libeufin (0.10.1) unstable; urgency=low * Package v0.10.1 -- Christian Grothoff Fri, 12 Apr 2024 13:18:43 +0100 libeufin (0.10.0) unstable; urgency=low * Package v0.10.0 -- Christian Grothoff Thu, 09 Apr 2024 13:18:43 +0100 libeufin (0.9.4a) unstable; urgency=low * Package v0.9.4a -- Florian Dold Thu, 07 Mar 2024 23:48:43 +0100 libeufin (0.9.4) unstable; urgency=low * Package v0.9.4 -- Florian Dold Thu, 07 Mar 2024 22:29:35 +0100 libeufin (0.9.4~dev.30) unstable; urgency=low * Package v0.9.4-dev.30 -- Florian Dold Tue, 05 Mar 2024 22:29:35 +0100 libeufin (0.9.4~dev.29) unstable; urgency=low * Package v0.9.4-dev.29 -- Florian Dold Tue, 27 Feb 2024 16:33:25 +0100 libeufin (0.9.4~dev.28) unstable; urgency=low * Package v0.9.4-dev.28 -- Florian Dold Mon, 26 Feb 2024 17:09:51 +0100 libeufin (0.9.4~dev.27) unstable; urgency=low * Package v0.9.4-dev.27 -- Florian Dold Wed, 21 Feb 2024 11:43:56 +0100 libeufin (0.9.4~dev.26) unstable; urgency=low * Package v0.9.4-dev.26 -- Florian Dold Tue, 20 Feb 2024 17:19:54 +0100 libeufin (0.9.4~dev.25) unstable; urgency=low * Package v0.9.4-dev.25 -- Florian Dold Mon, 19 Feb 2024 18:33:22 +0100 libeufin (0.9.4~dev.22) unstable; urgency=low * Package git tag v0.9.4-dev.22 -- Florian Dold Fri, 16 Feb 2024 00:43:38 +0100 libeufin (0.9.4~dev.20) unstable; urgency=low * Package git tag v0.9.4-dev.20 -- Florian Dold Wed, 14 Feb 2024 10:22:09 +0100 libeufin (0.9.4~dev.18) unstable; urgency=low * Package git tag v0.9.4-dev.18 -- Florian Dold Fri, 09 Feb 2024 21:50:18 +0100 libeufin (0.9.3-11) unstable; urgency=low * Package v0.9.3-dev.7 -- Florian Dold Mon, 29 Jan 2024 12:55:33 +0100 libeufin (0.9.3-9) unstable; urgency=low * Package v0.9.3-dev.4 -- Florian Dold Fri, 19 Jan 2024 23:35:45 +0100 libeufin (0.9.3-8) unstable; urgency=low * Misc. bugfixes. -- Christian Grothoff Tue, 13 Dec 2023 18:50:12 -0700 libeufin (0.9.3-7) unstable; urgency=low * Improvements to account creation. * Return more configuration data in /config. -- Christian Grothoff Thu, 7 Dec 2023 00:50:12 -0800 libeufin (0.9.3-6) unstable; urgency=medium * Add CLI for account creation, minor bugfixes. -- Christian Grothoff Mon, 4 Dec 2023 14:13:55 -0600 libeufin (0.9.3-5) unstable; urgency=medium * Add fix for idempotency of account creation. -- Christian Grothoff Sat, 2 Dec 2023 16:13:55 -0600 libeufin (0.9.3-4) unstable; urgency=medium * Avoid conflicting double-initialization of DB versioning by bank and nexus. -- Christian Grothoff Fri, 1 Dec 2023 19:47:55 -0600 libeufin (0.9.3-3) unstable; urgency=medium * Proper setup for database sharing needed for currency conversion * Coherent nginx configuration with default libeufin-bank configuration -- Christian Grothoff Wed, 30 Nov 2023 15:47:55 -0600 libeufin (0.9.3-2) unstable; urgency=medium * Improved currency conversion implementation -- Florian Dold Wed, 29 Nov 2023 20:57:55 +0100 libeufin (0.9.3-1) unstable; urgency=medium * Also package libeufin-nexus * Various other packaging improvements -- Florian Dold Mon, 27 Nov 2023 21:54:22 +0100 libeufin (0.9.3) unstable; urgency=medium * Starting to package for v0.9.3. -- Christian Grothoff Sat, 4 Mar 2023 14:47:04 +0200 libeufin (0.9.2-2) unstable; urgency=medium * Try to fix DB setup rules. -- Christian Grothoff Sat, 4 Mar 2023 14:47:04 +0200 libeufin (0.9.2-1) unstable; urgency=medium * Add SPA. -- Christian Grothoff Sat, 4 Mar 2023 14:46:04 +0200 libeufin (0.9.2) unstable; urgency=medium * New upstream release. -- Christian Grothoff Tue, 21 Feb 2023 14:46:04 +0200 libeufin (0.9.1) unstable; urgency=medium * Prepare for first proper release. -- Christian Grothoff Sat, 21 Jan 2023 14:46:04 +0200 libeufin (0.0.1-12) unstable; urgency=medium * Fix key letter generation. -- Florian Dold Thu, 14 Oct 2021 14:46:04 +0200 libeufin (0.0.1-11) unstable; urgency=medium * Add anastasis facade to the nexus. -- Florian Dold Tue, 24 Aug 2021 18:40:11 +0200 libeufin (0.0.1-10) unstable; urgency=medium * Add BIC validation to nexus and sandbox. -- Florian Dold Sat, 07 Aug 2021 21:40:28 +0200 libeufin (0.0.1-9) unstable; urgency=medium * Various bugfixes. -- Florian Dold Sat, 07 Aug 2021 16:09:59 +0200 libeufin (0.0.1-8) unstable; urgency=medium * Various bugfixes. -- Florian Dold Sat, 07 Aug 2021 14:32:14 +0200 libeufin (0.0.1-7) unstable; urgency=medium * New sandbox simulate-incoming-transaction command. -- Florian Dold Fri, 06 Aug 2021 00:08:52 +0200 libeufin (0.0.1-6) unstable; urgency=medium * Fix trailing slash in facade URL. -- Florian Dold Tue, 03 Aug 2021 14:43:33 +0200 libeufin (0.0.1-5) unstable; urgency=medium * Fix facade URL. -- Florian Dold Tue, 03 Aug 2021 14:43:33 +0200 libeufin (0.0.1-4) unstable; urgency=medium * Bugfixes in libeufin-cli and libeufin-nexus. -- Florian Dold Tue, 03 Aug 2021 13:59:52 +0200 libeufin (0.0.1-3) unstable; urgency=medium * Sandbox bugfixes. * Packaging: Install tmpfiles properly. -- Florian Dold Mon, 02 Aug 2021 19:53:44 +0200 libeufin (0.0.1-2) unstable; urgency=medium * Support debhelper-compat level 12. -- Florian Dold Sun, 01 Aug 2021 18:50:25 +0200 libeufin (0.0.1-1) unstable; urgency=medium * Packaging fixes. -- Florian Dold Sat, 31 Jul 2021 16:34:40 +0200 libeufin (0.0.1) unstable; urgency=low * Initial Release. -- Christian Grothoff Sun, 17 Jan 2021 07:03:45 +0100 libeufin-1.6.8/debian/libeufin-ebisync.libeufin-ebisync-fetch.service0000664000175000017500000000124115156463305026121 0ustar grothoffgrothoff[Unit] Description=LibEuFin EbiSync fetch service. After=postgres.service network.target PartOf=libeufin-ebisync.target [Service] User=libeufin-ebisync Type=exec ExecStart=/usr/bin/libeufin-ebisync fetch -c /etc/libeufin-ebisync/libeufin-ebisync.conf ExecCondition=/usr/bin/libeufin-ebisync fetch -c /etc/libeufin-ebisync/libeufin-ebisync.conf --check Restart=always RestartMode=direct RestartSec=10ms RestartSteps=5 RestartPreventExitStatus=9 StartLimitBurst=5 StartLimitInterval=5s RuntimeMaxSec=4d StandardOutput=journal StandardError=journal PrivateTmp=yes PrivateDevices=yes ProtectSystem=full Slice=libeufin-ebisync.slice [Install] WantedBy=multi-user.target libeufin-1.6.8/debian/libeufin-ebisync.postinst0000664000175000017500000000036715122266731022034 0ustar grothoffgrothoff#!/bin/sh set -e if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then if [ -x "$(command -v systemd-sysusers)" ]; then systemd-sysusers fi fi #DEBHELPER# exit 0libeufin-1.6.8/debian/libeufin-ebisync.libeufin-ebisync.slice0000664000175000017500000000026415122266731024472 0ustar grothoffgrothoff[Unit] Description=Slice for GNU Taler LibEuFin EbiSync processes Before=slices.target [Slice] # Add settings that should affect all GNU Taler LibEuFin EbiSync # components here. libeufin-1.6.8/debian/libeufin-nexus.install0000664000175000017500000000107615122266731021323 0ustar grothoffgrothoffdebian/etc/libeufin/libeufin-nexus.conf etc/libeufin/ libeufin-nexus/build/install/libeufin-nexus-shadow/bin/libeufin-nexus usr/bin/ contrib/libeufin-nexus-dbinit usr/bin/ database-versioning/libeufin-nexus*.sql usr/share/libeufin/sql/ contrib/nexus.conf usr/share/libeufin/config.d/ # FIXME: This name should be prefixed! libeufin-nexus/build/install/libeufin-nexus-shadow/lib/libeufin-nexus-all.jar usr/lib/ doc/prebuilt/man/libeufin-nexus.1 usr/share/man/man1 doc/prebuilt/man/libeufin-nexus.conf.5 usr/share/man/man5 debian/libeufin-nexus.conf /usr/lib/sysusers.d/libeufin-1.6.8/debian/rules0000775000175000017500000000275215140725607016062 0ustar grothoffgrothoff#!/usr/bin/make -f include /usr/share/dpkg/default.mk SHELL := sh -e export GRADLE_USER_HOME = .gradle LIBEUFIN_HOME = /usr/share/libeufin DEV = FULLVER = $(DEB_VERSION_UPSTREAM)$(DEV) %: dh ${@} --no-parallel override_dh_auto_test: true override_dh_auto_configure: true override_dh_auto_install: true override_dh_auto_build: make build # Override this step because it's very slow and likely # unnecessary for us. override_dh_strip_nondeterminism: true override_dh_installsystemd: # Need to specify units manually, since we have multiple # and dh_installsystemd by default only looks for ".service". dh_installsystemd -p libeufin-bank --no-start --no-enable --no-stop-on-upgrade --name=libeufin-bank-gc dh_installsystemd -p libeufin-bank --no-start --no-enable --no-stop-on-upgrade --name=libeufin-bank dh_installsystemd -p libeufin-nexus --no-start --no-enable --no-stop-on-upgrade --name=libeufin-nexus-ebics-submit dh_installsystemd -p libeufin-nexus --no-start --no-enable --no-stop-on-upgrade --name=libeufin-nexus-ebics-fetch dh_installsystemd -p libeufin-nexus --no-start --no-enable --no-stop-on-upgrade --name=libeufin-nexus-httpd dh_installsystemd -p libeufin-ebisync --no-start --no-enable --no-stop-on-upgrade --name=libeufin-ebisync-fetch dh_installsystemd -p libeufin-ebisync --no-start --no-enable --no-stop-on-upgrade --name=libeufin-ebisync-httpd # final invocation to generate daemon reload dh_installsystemd get-orig-source: uscan --force-download --rename libeufin-1.6.8/debian/libeufin-ebisync.conf0000664000175000017500000000007715156463305021077 0ustar grothoffgrothoff# Create service user u libeufin-ebisync - "LibEuFin EbiSync" -libeufin-1.6.8/debian/libeufin-bank.target0000644000175000017500000000021114674637415020714 0ustar grothoffgrothoff[Unit] Description=LibEuFin Bank After=postgres.service network.target Wants=libeufin-bank.service [Install] WantedBy=multi-user.targetlibeufin-1.6.8/debian/watch0000644000175000017500000000015314674637415016034 0ustar grothoffgrothoffversion=4 opts=uversionmangle=s/^/0\./ \ https://ftp.gnu.org/gnu/taler/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@ libeufin-1.6.8/debian/libeufin-ebisync.target0000664000175000017500000000027215122266731021432 0ustar grothoffgrothoff[Unit] Description=LibEuFin EbiSync After=postgres.service network.target Wants=libeufin-ebisync-fetch.service Wants=libeufin-ebisync-httpd.service [Install] WantedBy=multi-user.targetlibeufin-1.6.8/debian/libeufin-bank.tmpfiles0000644000175000017500000000015614674637415021261 0ustar grothoffgrothoff# Type Path Mode UID GID Age Argument d /var/lib/libeufin-bank 0700 libeufin-bank libeufin-bank - - libeufin-1.6.8/debian/libeufin-nexus.tmpfiles0000664000175000017500000000013215110141204021450 0ustar grothoffgrothoff# Create home directory d$ /var/lib/libeufin-nexus 0700 libeufin-nexus libeufin-nexus - -libeufin-1.6.8/debian/libeufin-nexus.conf0000664000175000017500000000012115156463305020573 0ustar grothoffgrothoff# Create service user u libeufin-nexus - "LibEuFin Nexus" /var/lib/libeufin-nexuslibeufin-1.6.8/debian/libeufin-bank.libeufin-bank.service0000664000175000017500000000104215140725607023566 0ustar grothoffgrothoff[Unit] Description=LibEuFin Bank Server Service After=postgres.service network.target PartOf=libeufin-bank.target [Service] User=libeufin-bank Type=exec ExecStart=/usr/bin/libeufin-bank serve -c /etc/libeufin/libeufin-bank.conf Restart=always RestartMode=direct RestartSec=10ms RestartSteps=5 RestartPreventExitStatus=9 StartLimitBurst=5 StartLimitInterval=5s RuntimeMaxSec=4d StandardOutput=journal StandardError=journal PrivateTmp=yes PrivateDevices=yes ProtectSystem=full Slice=libeufin-bank.slice [Install] WantedBy=multi-user.target libeufin-1.6.8/debian/libeufin-common.install0000664000175000017500000000033015122266731021441 0ustar grothoffgrothoffcontrib/currencies.conf usr/share/libeufin/config.d/ database-versioning/versioning.sql usr/share/libeufin/sql/ database-versioning/libeufin-conversion*.sql usr/share/libeufin/sql/ contrib/libeufin-dbconfig usr/bin/ libeufin-1.6.8/debian/README0000644000175000017500000000047514674637415015672 0ustar grothoffgrothoffThis is NOT a 'clean' Debian package, as it is not using the proper Javahelper tooling (https://wiki.debian.org/Java/Packaging#Gradle). It also requires an external run of the configure command. To build the package, you must run: $ ./bootstrap $ ./configure --prefix=/usr $ dpkg-buildpackage -rfakeroot -b -uc -us libeufin-1.6.8/debian/libeufin-nexus.postinst0000664000175000017500000000036715110141204021522 0ustar grothoffgrothoff#!/bin/sh set -e if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then if [ -x "$(command -v systemd-sysusers)" ]; then systemd-sysusers fi fi #DEBHELPER# exit 0libeufin-1.6.8/debian/libeufin-nexus.target0000644000175000017500000000034414674637415021152 0ustar grothoffgrothoff[Unit] Description=LibEuFin Nexus After=postgres.service network.target Wants=libeufin-nexus-ebics-fetch.service Wants=libeufin-nexus-ebics-submit.service Wants=libeufin-nexus-httpd.service [Install] WantedBy=multi-user.targetlibeufin-1.6.8/debian/libeufin-ebisync.install0000664000175000017500000000155115122266731021613 0ustar grothoffgrothoffdebian/etc/libeufin-ebisync/* etc/libeufin-ebisync/ debian/etc/nginx/sites-available/libeufin-ebisync etc/nginx/sites-available/ debian/etc/apache2/sites-available/libeufin-ebisync.conf etc/apache2/sites-available/ libeufin-ebisync/build/install/libeufin-ebisync-shadow/bin/libeufin-ebisync usr/bin/ contrib/libeufin-ebisync-dbconfig usr/bin/ database-versioning/versioning.sql usr/share/libeufin-ebisync/sql/ database-versioning/libeufin-ebisync*.sql usr/share/libeufin-ebisync/sql/ libeufin-ebisync/src/spa/* usr/share/libeufin-ebisync/spa libeufin-ebisync/ebisync.conf usr/share/libeufin-ebisync/config.d/ libeufin-ebisync/build/install/libeufin-ebisync-shadow/lib/libeufin-ebisync-all.jar usr/lib/ doc/prebuilt/man/libeufin-ebisync.1 usr/share/man/man1 doc/prebuilt/man/libeufin-ebisync.conf.5 usr/share/man/man5 debian/libeufin-ebisync.conf /usr/lib/sysusers.d/libeufin-1.6.8/debian/libeufin-bank.conf0000664000175000017500000000007115156463305020350 0ustar grothoffgrothoff# Create service user u libeufin-bank - "LibEuFin Bank" -libeufin-1.6.8/debian/libeufin-bank.libeufin-bank-gc.service0000664000175000017500000000052315140725607024160 0ustar grothoffgrothoff[Unit] Description=LibEuFin Bank Garbage Collection Service After=postgres.service PartOf=libeufin-bank.target [Service] User=libeufin-bank ExecStart=/usr/bin/libeufin-bank gc -c /etc/libeufin/libeufin-bank.conf StandardOutput=journal StandardError=journal PrivateTmp=yes PrivateDevices=yes ProtectSystem=full Slice=libeufin-bank.slicelibeufin-1.6.8/debian/etc/0000775000175000017500000000000015236145704015547 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/nginx/0000775000175000017500000000000015236145704016672 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/nginx/sites-available/0000775000175000017500000000000015236145704021737 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/nginx/sites-available/libeufin-bank0000644000175000017500000000140114674637415024374 0ustar grothoffgrothoffserver { include /etc/nginx/mime.types; # NOTE: # - urgently consider configuring TLS instead # - maybe keep a forwarder from HTTP to HTTPS listen 80; # NOTE: # - Comment out this line if you have no IPv6 listen [::]:80; # NOTE: # - replace with your actual server name. server_name localhost; access_log /var/log/nginx/libeufin-bank.log; error_log /var/log/nginx/libeufin-bank.err; location / { # NOTE: urgently change to 'https' once TLS has been configured. proxy_set_header X-Forwarded-Proto "$scheme"; proxy_set_header X-Forwarded-Host "localhost"; proxy_set_header X-Forwarded-Prefix /; # FIXME: should use UNIX domain socket once # supported by libeufin-bank! proxy_pass http://localhost:9099; } } libeufin-1.6.8/debian/etc/nginx/sites-available/libeufin-ebisync0000664000175000017500000000141215122266731025105 0ustar grothoffgrothoffserver { include /etc/nginx/mime.types; # NOTE: # - urgently consider configuring TLS instead # - maybe keep a forwarder from HTTP to HTTPS listen 80; # NOTE: # - Comment out this line if you have no IPv6 listen [::]:80; # NOTE: # - replace with your actual server name. server_name localhost; access_log /var/log/nginx/libeufin-ebisync.log; error_log /var/log/nginx/libeufin-ebisync.err; location / { # NOTE: urgently change to 'https' once TLS has been configured. proxy_set_header X-Forwarded-Proto "$scheme"; proxy_set_header X-Forwarded-Host "localhost"; proxy_set_header X-Forwarded-Prefix /; # FIXME: should use UNIX domain socket once # supported by libeufin-ebisync! proxy_pass http://localhost:8080; } } libeufin-1.6.8/debian/etc/libeufin/0000775000175000017500000000000015236145704017344 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/libeufin/libeufin-nexus.conf0000644000175000017500000000010414760713600023136 0ustar grothoffgrothoff# This is the main configuration entrypoint for the libeufin-nexus. libeufin-1.6.8/debian/etc/libeufin/libeufin-bank.conf0000644000175000017500000000044014760713600022712 0ustar grothoffgrothoff# This is the main configuration entrypoint for the libeufin-bank. [libeufin-bank] # Where "libeufin-bank serve" serves its API SERVE = tcp # The default port for libeufin-bank on Debian is different than the default # for historical reason. Might be merged in the future. PORT = 9099 libeufin-1.6.8/debian/etc/libeufin/settings.json0000644000175000017500000000233514674637415022112 0ustar grothoffgrothoff// This file is an example of configuration of Bank SPA // Remove all the comments to make the file a valid // JSON file, otherwise no value here will make any // effect. // All the settings are optionals. { // Where libeufin backend is localted // default: window.origin without "webui/" "backendBaseURL": "http://bank.taler.test:1180/", // Shows a button "create random account" in the registration form // Useful for testing // default: false "allowRandomAccountCreation": false, // Create all random accounts with password "123" // Useful for testing // default: false "simplePasswordForRandomAccounts": false, // Bank name shown in the header // default: "Taler Bank" "bankName": "Taler TESTING Bank", // URL where the user is going to be redirected after // clicking in Taler Logo // default: home page "iconLinkURL": "#", // Mapping for every link shown in the top navitation bar // - key: link label, what the user will read // - value: link target, where the user is going to be redirected // default: empty list "topNavSites": { "Exchange": "http://exchange.taler.test:1180/", "Bank": "http://bank-ui.taler.test:1180/", "Merchant": "http://merchant.taler.test:1180/" } } libeufin-1.6.8/debian/etc/apache2/0000775000175000017500000000000015236145704017052 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/apache2/sites-available/0000775000175000017500000000000015236145704022117 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/apache2/sites-available/libeufin-ebisync.conf0000664000175000017500000000033715122266731026216 0ustar grothoffgrothoff ProxyPass "http://localhost:8080/" # RequestHeader add "X-Forwarded-Proto" "https" # RequestHeader add "X-Forwarded-Host" "localhost" # RequestHeader add "X-Forwarded-Prefix" "/" libeufin-1.6.8/debian/etc/apache2/sites-available/libeufin-bank.conf0000644000175000017500000000033414760713600025467 0ustar grothoffgrothoff ProxyPass "http://localhost:9099/" # RequestHeader add "X-Forwarded-Proto" "https" # RequestHeader add "X-Forwarded-Host" "localhost" # RequestHeader add "X-Forwarded-Prefix" "/" libeufin-1.6.8/debian/etc/libeufin-ebisync/0000775000175000017500000000000015236145704020776 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/libeufin-ebisync/libeufin-ebisync.conf0000664000175000017500000000316315122266731025075 0ustar grothoffgrothoff# Main entry point for the LibEuFin EbiSync configuration. # # Structure: # - libeufin-ebisync.conf is the main configuration entry point # used by all LibEuFin EbiSync components (the file you are currently # looking at. # - overrides.conf contains configuration overrides that are # set by some tools that help with the configuration, # and should not be edited by humans. Comments in this file # are not preserved. # - conf.d/ contains configuration files for # LibEuFin EbiSync components, which can be read by all # users of the system and are included by the main # configuration. # - secrets/ contains configuration snippets # with secrets for particular services. # These files should have restrictive permissions # so that only users of the relevant services # can read it. All files in it should end with # ".secret.conf". [ebisync] # Base URL of the bank server. HOST_BASE_URL = # EBICS host ID. HOST_ID = # EBICS user ID, as assigned by the bank. USER_ID = # EBICS partner ID, as assigned by the bank. PARTNER_ID = # EBICS partner ID, as assigned by the bank. SYSTEM_ID = [ebisync-setup] # Bank encryption public key hash # BANK_ENCRYPTION_PUB_KEY_HASH = # Bank authentication public key hash # BANK_AUTHENTICATION_PUB_KEY_HASH = # Inline configurations from all LibEuFin EbiSync components. @inline-matching@ conf.d/*.conf # Overrides from tools that help with configuration. @inline@ overrides.conf [paths] # Paths for the system-wide installation of the LibEuFin EbyiSync. Do not remove # or change these unless you are very sure of what you are doing. EBISYNC_HOME = /var/lib/libeufin-ebisync/libeufin-1.6.8/debian/etc/libeufin-ebisync/conf.d/0000775000175000017500000000000015236145704022145 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/libeufin-ebisync/conf.d/ebisync-submit.conf0000664000175000017500000000036215122266731025750 0ustar grothoffgrothoff# Configuration for the EbiSync submitter. [ebisync-submit] # Where does the ebics file come from? This his can either can be ebisync-api or none # SOURCE = ebisync-api @inline-secret@ ebisync-submit ../secrets/ebisync-submit.secret.conf libeufin-1.6.8/debian/etc/libeufin-ebisync/conf.d/ebisync-fetch.conf0000664000175000017500000000040215122266731025531 0ustar grothoffgrothoff# Configuration for the EbiSync fetcher. [ebisync-fetch] # Where should the ebics file be stored? This his can either can be azure-blob-storage or none # DESTINATION = azure-blob-storage @inline-secret@ ebisync-fetch ../secrets/ebisync-fetch.secret.conf libeufin-1.6.8/debian/etc/libeufin-ebisync/secrets/0000775000175000017500000000000015236145704022446 5ustar grothoffgrothofflibeufin-1.6.8/debian/etc/libeufin-ebisync/secrets/ebisync-submit.secret.conf0000664000175000017500000000040415122266731027532 0ustar grothoffgrothoff[ebisync-submit] # Authentication scheme used by the API, this can either can be basic, bearer or none. # AUTH_METHOD = basic # User name for basic authentication scheme # USERNAME = username # Password for basic authentication scheme # PASSWORD = passwordlibeufin-1.6.8/debian/etc/libeufin-ebisync/secrets/ebisync-db.secret.conf0000664000175000017500000000034415122266731026617 0ustar grothoffgrothoff [ebisyncdb-postgres] # Typically, there should only be a single line here, of the form: CONFIG=postgres:///libeufin-ebisync # The details of the URI depend on where the database lives and how # access control was configured.libeufin-1.6.8/debian/etc/libeufin-ebisync/secrets/ebisync-fetch.secret.conf0000664000175000017500000000072715122266731027330 0ustar grothoffgrothoff[ebisync-fetch] # Azure API account base url for azure-blob-storage # AZURE_API_URL = https://myaccount.blob.core.windows.net/ # Azure API account name for azure-blob-storage # AZURE_ACCOUNT_NAME = myaccount # Azure API account key for azure-blob-storage # AZURE_ACCOUNT_KEY = Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw== # Which Azure Blob Storage container to use for azure-blob-storage # AZURE_COUNTAINER = mycontainer libeufin-1.6.8/debian/etc/libeufin-ebisync/overrides.conf0000664000175000017500000000011315122266731023640 0ustar grothoffgrothoff# This configuration will be changed by tooling. Do not touch it manually.libeufin-1.6.8/debian/libeufin-nexus.libeufin-nexus-ebics-submit.service0000664000175000017500000000106615140725607026636 0ustar grothoffgrothoff[Unit] Description=LibEuFin Nexus EBICS submit service. After=postgres.service network.target PartOf=libeufin-nexus.target [Service] User=libeufin-nexus Type=exec ExecStart=/usr/bin/libeufin-nexus ebics-submit -c /etc/libeufin/libeufin-nexus.conf Restart=always RestartMode=direct RestartSec=10ms RestartSteps=5 RestartPreventExitStatus=9 StartLimitBurst=5 StartLimitInterval=5s RuntimeMaxSec=4d StandardOutput=journal StandardError=journal PrivateTmp=yes PrivateDevices=yes ProtectSystem=full Slice=libeufin-nexus.slice [Install] WantedBy=multi-user.target libeufin-1.6.8/debian/libeufin-nexus.libeufin-nexus-ebics-fetch.service0000664000175000017500000000106415140725607026422 0ustar grothoffgrothoff[Unit] Description=LibEuFin Nexus EBICS fetch service. After=postgres.service network.target PartOf=libeufin-nexus.target [Service] User=libeufin-nexus Type=exec ExecStart=/usr/bin/libeufin-nexus ebics-fetch -c /etc/libeufin/libeufin-nexus.conf Restart=always RestartMode=direct RestartSec=10ms RestartSteps=5 RestartPreventExitStatus=9 StartLimitBurst=5 StartLimitInterval=5s RuntimeMaxSec=4d StandardOutput=journal StandardError=journal PrivateTmp=yes PrivateDevices=yes ProtectSystem=full Slice=libeufin-nexus.slice [Install] WantedBy=multi-user.target libeufin-1.6.8/debian/libeufin-nexus.libeufin-nexus.slice0000644000175000017500000000026014730107742023700 0ustar grothoffgrothoff[Unit] Description=Slice for GNU Taler LibEuFin Nexus processes Before=slices.target [Slice] # Add settings that should affect all GNU Taler LibEuFin Nexus # components here. libeufin-1.6.8/debian/libeufin-bank.install0000664000175000017500000000152415122266731021072 0ustar grothoffgrothoffdebian/etc/libeufin/libeufin-bank.conf etc/libeufin/ debian/etc/nginx/sites-available/libeufin-bank etc/nginx/sites-available/ debian/etc/apache2/sites-available/libeufin-bank.conf etc/apache2/sites-available/ debian/etc/libeufin/settings.json etc/libeufin/ libeufin-bank/build/install/libeufin-bank-shadow/bin/libeufin-bank usr/bin/ contrib/libeufin-bank-dbinit usr/bin/ contrib/libeufin-tan-*.sh usr/bin/ database-versioning/libeufin-bank*.sql usr/share/libeufin/sql/ contrib/wallet-core/bank/* usr/share/libeufin/spa contrib/bank.conf usr/share/libeufin/config.d/ # FIXME: This name should be prefixed! libeufin-bank/build/install/libeufin-bank-shadow/lib/libeufin-bank-all.jar usr/lib/ doc/prebuilt/man/libeufin-bank.1 usr/share/man/man1 doc/prebuilt/man/libeufin-bank.conf.5 usr/share/man/man5 debian/libeufin-bank.conf /usr/lib/sysusers.d/libeufin-1.6.8/debian/control0000664000175000017500000000247415122266731016404 0ustar grothoffgrothoffSource: libeufin Section: net Priority: optional Maintainer: Taler Systems SA Uploaders: Christian Grothoff , Florian Dold Build-Depends: debhelper-compat (= 13), default-jdk-headless | java-runtime-headless (>= 17) Standards-Version: 4.7.2 Vcs-Git: https://git.taler.net/libeufin.git Homepage: https://taler.net/ Package: libeufin-common Architecture: all Depends: ${misc:Depends} Description: Common files for other libeufin packages. Package: libeufin-bank Architecture: all Depends: default-jre-headless | java-runtime-headless (>= 17), libeufin-common (= ${binary:Version}), ${misc:Depends} Recommends: nginx | apache2 | httpd, postgresql (>= 14.0) Description: Software package to provide a regional bank with optional EBICS access. Package: libeufin-nexus Architecture: all Depends: default-jre-headless | java-runtime-headless (>= 17), libeufin-common (= ${binary:Version}), ${misc:Depends} Recommends: nginx | apache2 | httpd, postgresql (>= 14.0) Description: Software package to access a bank accounts via the EBICS protocol. Package: libeufin-ebisync Architecture: all Depends: default-jre-headless | java-runtime-headless (>= 17), ${misc:Depends} Recommends: postgresql (>= 14.0) Description: Software package to sync ISO20022 files via the EBICS protocol. libeufin-1.6.8/debian/libeufin-bank.postinst0000664000175000017500000000036715110141204021273 0ustar grothoffgrothoff#!/bin/sh set -e if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then if [ -x "$(command -v systemd-sysusers)" ]; then systemd-sysusers fi fi #DEBHELPER# exit 0libeufin-1.6.8/debian/libeufin-ebisync.libeufin-ebisync-httpd.service0000664000175000017500000000124115140725607026152 0ustar grothoffgrothoff[Unit] Description=LibEuFin EbiSync Server Service After=postgres.service network.target PartOf=libeufin-ebisync.target [Service] User=libeufin-ebisync Type=exec ExecStart=/usr/bin/libeufin-ebisync serve -c /etc/libeufin-ebisync/libeufin-ebisync.conf ExecCondition=/usr/bin/libeufin-ebisync serve -c /etc/libeufin-ebisync/libeufin-ebisync.conf --check Restart=always RestartMode=direct RestartSec=10ms RestartSteps=5 RestartPreventExitStatus=9 StartLimitBurst=5 StartLimitInterval=5s RuntimeMaxSec=4d StandardOutput=journal StandardError=journal PrivateTmp=yes PrivateDevices=yes ProtectSystem=full Slice=libeufin-ebisync.slice [Install] WantedBy=multi-user.target libeufin-1.6.8/debian/libeufin-bank.libeufin-bank-gc.timer0000644000175000017500000000026014674637415023646 0ustar grothoffgrothoff[Unit] Description=Run garbage collection every 15min PartOf=libeufin-bank.target [Timer] OnCalendar=*:0/15 Unit=libeufin-bank-gc.service [Install] WantedBy=multi-user.targetlibeufin-1.6.8/debian/libeufin-nexus.libeufin-nexus-httpd.service0000664000175000017500000000120115140725607025362 0ustar grothoffgrothoff[Unit] Description=LibEuFin Nexus Server Service After=postgres.service network.target PartOf=libeufin-nexus.target [Service] User=libeufin-nexus Type=exec ExecStart=/usr/bin/libeufin-nexus serve -c /etc/libeufin/libeufin-nexus.conf ExecCondition=/usr/bin/libeufin-nexus serve -c /etc/libeufin/libeufin-nexus.conf --check Restart=always RestartMode=direct RestartSec=10ms RestartSteps=5 RestartPreventExitStatus=9 StartLimitBurst=5 StartLimitInterval=5s RuntimeMaxSec=4d StandardOutput=journal StandardError=journal PrivateTmp=yes PrivateDevices=yes ProtectSystem=full Slice=libeufin-nexus.slice [Install] WantedBy=multi-user.target libeufin-1.6.8/debian/libeufin-ebisync.tmpfiles0000664000175000017500000000074315122266731021772 0ustar grothoffgrothoff# Create home directory d$ /var/lib/libeufin-ebisync 0700 libeufin-ebisync libeufin-ebisync - - # Update secret files permissions z /etc/libeufin-ebisync/secrets/libeufin-ebisync-db.secret.conf 0640 libeufin-ebisync libeufin-ebisync - - z /etc/libeufin-ebisync/secrets/libeufin-ebisync-fetch.secret.conf 0640 libeufin-ebisync libeufin-ebisync - - z /etc/libeufin-ebisync/secrets/libeufin-ebisync-submit.secret.conf 0640 libeufin-ebisync libeufin-ebisync - - libeufin-1.6.8/debian/copyright0000644000175000017500000010665514674637415016754 0ustar grothoffgrothoffFormat: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: GNU Taler Upstream-Contact: Christian Grothoff Source: https://taler.net/ Files: * Copyright: (C) 2013-2020 Taler Systems SA License: AGPL-3+ Comment: Many contributors are mentioned in AUTHORS Files: debian/* Copyright: (C) 2020 Christian Grothoff License: GPL-3+ Files: debian/po/* Copyright: License: GPL-3+ License: GPL-3+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . . The complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL-3 file. License: AGPL-3+ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 . Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. . Preamble . The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. . The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. . When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. . Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. . A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. . The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. . An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. . The precise terms and conditions for copying, distribution and modification follow. . TERMS AND CONDITIONS . 0. Definitions. . "This License" refers to version 3 of the GNU Affero General Public License. . "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. . "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. . To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. . A "covered work" means either the unmodified Program or a work based on the Program. . To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. . To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. . An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. . 1. Source Code. . The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. . A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. . The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. . The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. . The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. . The Corresponding Source for a work in source code form is that same work. . 2. Basic Permissions. . All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. . You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. . Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. . 3. Protecting Users' Legal Rights From Anti-Circumvention Law. . No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. . When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. . 4. Conveying Verbatim Copies. . You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. . You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. . 5. Conveying Modified Source Versions. . You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: . a) The work must carry prominent notices stating that you modified it, and giving a relevant date. . b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". . c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. . d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. . A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. . 6. Conveying Non-Source Forms. . You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: . a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. . b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. . c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. . d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. . e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. . A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. . A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. . "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. . If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). . The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. . Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. . 7. Additional Terms. . "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. . When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. . Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: . a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or . b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or . c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or . d) Limiting the use for publicity purposes of names of licensors or authors of the material; or . e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or . f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. . All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. . If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. . Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. . 8. Termination. . You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). . However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. . Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. . Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. . 9. Acceptance Not Required for Having Copies. . You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. . 10. Automatic Licensing of Downstream Recipients. . Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. . An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. . You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. . 11. Patents. . A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". . A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. . Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. . In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. . If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. . If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. . A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. . Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. . 12. No Surrender of Others' Freedom. . If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. . 13. Remote Network Interaction; Use with the GNU General Public License. . Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. . Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. . 14. Revised Versions of this License. . The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. . Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. . If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. . Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. . 15. Disclaimer of Warranty. . THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. . 16. Limitation of Liability. . IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. . 17. Interpretation of Sections 15 and 16. . If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. . END OF TERMS AND CONDITIONS . How to Apply These Terms to Your New Programs . If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. . To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. . Copyright (C) . This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. . You should have received a copy of the GNU Affero General Public License along with this program. If not, see . . Also add information on how to contact you by electronic and paper mail. . If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. . You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . libeufin-1.6.8/debian/libeufin-bank.libeufin-bank.slice0000644000175000017500000000025614730107742023227 0ustar grothoffgrothoff[Unit] Description=Slice for GNU Taler LibEuFin Bank processes Before=slices.target [Slice] # Add settings that should affect all GNU Taler LibEuFin Bank # components here.